Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[arm64] JIT: Better addressing modes around bytes #66902

Merged
merged 1 commit into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10103,7 +10103,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 @@ -10129,13 +10129,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -1607,6 +1607,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -5238,7 +5238,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 @@ -5378,6 +5385,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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