Skip to content

Commit

Permalink
Better approach (dotnet#66902)
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorBo authored and radekdoulik committed Mar 30, 2022
1 parent c6d693f commit c3194a4
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 17 deletions.
8 changes: 5 additions & 3 deletions src/coreclr/jit/codegenarm64.cpp
Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down
42 changes: 33 additions & 9 deletions src/coreclr/jit/codegencommon.cpp
Expand Up @@ -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;
Expand All @@ -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?

/*
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/jit/codegenlinear.cpp
Expand Up @@ -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())
{
Expand Down
21 changes: 16 additions & 5 deletions src/coreclr/jit/emitarm64.cpp
Expand Up @@ -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
{
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/jit/lower.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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)))
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/lsraarm64.cpp
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/jit/lsrabuild.cpp
Expand Up @@ -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;
Expand Down

0 comments on commit c3194a4

Please sign in to comment.