diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index e918607827cac..69fc1885da3e9 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -10120,7 +10120,7 @@ void CodeGen::genCodeForBfiz(GenTreeOp* tree) // void CodeGen::genCodeForAddEx(GenTreeOp* tree) { - assert(tree->OperIs(GT_ADDEX) && !(tree->gtFlags & GTF_SET_FLAGS)); + assert(tree->OperIs(GT_ADDEX)); genConsumeOperands(tree); GenTree* op; @@ -10146,13 +10146,15 @@ void CodeGen::genCodeForAddEx(GenTreeOp* tree) GenTreeCast* cast = containedOp->AsCast(); assert(varTypeIsLong(cast->CastToType())); insOpts opts = cast->IsUnsigned() ? INS_OPTS_UXTW : INS_OPTS_SXTW; - GetEmitter()->emitIns_R_R_R(INS_add, emitActualTypeSize(tree), dstReg, op1Reg, op2Reg, opts); + GetEmitter()->emitIns_R_R_R(tree->gtSetFlags() ? INS_adds : INS_add, emitActualTypeSize(tree), dstReg, op1Reg, + op2Reg, opts); } else { assert(containedOp->OperIs(GT_LSH)); ssize_t cns = containedOp->gtGetOp2()->AsIntCon()->IconValue(); - GetEmitter()->emitIns_R_R_R_I(INS_add, emitActualTypeSize(tree), dstReg, op1Reg, op2Reg, cns, INS_OPTS_LSL); + GetEmitter()->emitIns_R_R_R_I(tree->gtSetFlags() ? INS_adds : INS_add, emitActualTypeSize(tree), dstReg, op1Reg, + op2Reg, cns, INS_OPTS_LSL); } genProduceReg(tree); } diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 8e74e648983b3..87de50188d24d 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1062,17 +1062,16 @@ bool CodeGen::genCreateAddrMode( /* All indirect address modes require the address to be an addition */ - if (addr->gtOper != GT_ADD) - { - return false; - } - - // Can't use indirect addressing mode as we need to check for overflow. - // Also, can't use 'lea' as it doesn't set the flags. - - if (addr->gtOverflow()) + if (!addr->OperIs(GT_ADD)) { +#if TARGET_ARM64 + if (!addr->OperIs(GT_ADDEX)) + { + return false; + } +#else return false; +#endif } GenTree* rv1 = nullptr; @@ -1099,6 +1098,31 @@ bool CodeGen::genCreateAddrMode( op2 = addr->AsOp()->gtOp2; } +#if TARGET_ARM64 + if (addr->OperIs(GT_ADDEX)) + { + if (op2->isContained() && op2->OperIs(GT_CAST)) + { + *rv1Ptr = op1; + *rv2Ptr = op2; + *mulPtr = 1; + *cnsPtr = 0; + *revPtr = false; // op2 is never a gc type + assert(!varTypeIsGC(op2)); + return true; + } + return false; + } +#endif + + // Can't use indirect addressing mode as we need to check for overflow. + // Also, can't use 'lea' as it doesn't set the flags. + + if (addr->gtOverflow()) + { + return false; + } + bool rev = false; // Is op2 first in the evaluation order? /* diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 5ae82589f4851..deb9e42a176d2 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1600,6 +1600,13 @@ void CodeGen::genConsumeRegs(GenTree* tree) assert(cast->isContained()); genConsumeAddress(cast->CastOp()); } + else if (tree->OperIs(GT_CAST)) + { + // Can be contained as part of LEA on ARM64 + GenTreeCast* cast = tree->AsCast(); + assert(cast->isContained()); + genConsumeAddress(cast->CastOp()); + } #endif else if (tree->OperIsLocalRead()) { diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index f5e272ff036ab..63e8b3bb3ab08 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -13548,17 +13548,28 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR } else // no scale { - if (index->OperIs(GT_BFIZ) && index->isContained()) + if (index->OperIs(GT_BFIZ, GT_CAST) && index->isContained()) { // Then load/store dataReg from/to [memBase + index*scale with sign/zero extension] - GenTreeCast* cast = index->gtGetOp1()->AsCast(); + GenTreeCast* cast; + int cns; + + if (index->OperIs(GT_BFIZ)) + { + cast = index->gtGetOp1()->AsCast(); + cns = (int)index->gtGetOp2()->AsIntCon()->IconValue(); + } + else + { + cast = index->AsCast(); + cns = 0; + } // For now, this code only supports extensions from i32/u32 - assert(cast->isContained() && varTypeIsInt(cast->CastFromType())); + assert(cast->isContained()); emitIns_R_R_R_Ext(ins, attr, dataReg, memBase->GetRegNum(), cast->CastOp()->GetRegNum(), - cast->IsUnsigned() ? INS_OPTS_UXTW : INS_OPTS_SXTW, - (int)index->gtGetOp2()->AsIntCon()->IconValue()); + cast->IsUnsigned() ? INS_OPTS_UXTW : INS_OPTS_SXTW, cns); } else { diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index bd7c0b7b5e0bf..c9ab4fa81a63a 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5257,7 +5257,14 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* par { if (!addr->OperIs(GT_ADD) || addr->gtOverflow()) { +#ifdef TARGET_ARM64 + if (!addr->OperIs(GT_ADDEX)) + { + return false; + } +#else return false; +#endif } #ifdef TARGET_ARM64 @@ -5397,6 +5404,11 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* par } #ifdef TARGET_ARM64 + if ((index != nullptr) && index->OperIs(GT_CAST) && (scale == 1) && (offset == 0) && varTypeIsByte(targetType)) + { + MakeSrcContained(addrMode, index); + } + // Check if we can "contain" LEA(BFIZ) in order to extend 32bit index to 64bit as part of load/store. if ((index != nullptr) && index->OperIs(GT_BFIZ) && index->gtGetOp1()->OperIs(GT_CAST) && index->gtGetOp2()->IsCnsIntOrI() && (varTypeIsIntegral(targetType) || varTypeIsFloating(targetType))) diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index bc067bb544770..3a3d0ee23241f 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -701,6 +701,12 @@ int LinearScan::BuildNode(GenTree* tree) assert(cast->isContained() && (cns == 0)); BuildUse(cast->CastOp()); } + else if (index->OperIs(GT_CAST) && index->isContained()) + { + GenTreeCast* cast = index->AsCast(); + assert(cast->isContained() && (cns == 0)); + BuildUse(cast->CastOp()); + } else { BuildUse(index); diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 325f333688188..04df846e367e7 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -3076,6 +3076,13 @@ int LinearScan::BuildAddrUses(GenTree* addr, regMaskTP candidates) BuildUse(cast->CastOp(), candidates); srcCount++; } + else if (addrMode->Index()->OperIs(GT_CAST)) + { + GenTreeCast* cast = addrMode->Index()->AsCast(); + assert(cast->isContained()); + BuildUse(cast->CastOp(), candidates); + srcCount++; + } #endif } return srcCount;