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: Avoid LEA for volatile IND #64354

Merged
merged 6 commits into from
Jan 27, 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
25 changes: 18 additions & 7 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4891,20 +4891,29 @@ bool Lowering::AreSourcesPossiblyModifiedLocals(GenTree* addr, GenTree* base, Ge
// addressing mode and transform them to a GT_LEA
//
// Arguments:
// use - the use of the address we want to transform
// addr - the use of the address we want to transform
// isContainable - true if this addressing mode can be contained
// targetType - on arm we can use "scale" only for appropriate target type
// parent - the node that consumes the given addr (most likely it's an IND)
//
// Returns:
// true if the address node was changed to a LEA, false otherwise.
//
bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, var_types targetType)
bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* parent)
{
if (!addr->OperIs(GT_ADD) || addr->gtOverflow())
{
return false;
}

#ifdef TARGET_ARM64
if (parent->OperIsIndir() && parent->AsIndir()->IsVolatile())
{
// For Arm64 we avoid using LEA for volatile INDs
// because we won't be able to use ldar/star
return false;
}
#endif

GenTree* base = nullptr;
GenTree* index = nullptr;
unsigned scale = 0;
Expand All @@ -4920,6 +4929,8 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, var_types ta
&scale, // scaling
&offset); // displacement

var_types targetType = parent->OperIsIndir() ? parent->TypeGet() : TYP_UNDEF;

#ifdef TARGET_ARMARCH
// Multiplier should be a "natural-scale" power of two number which is equal to target's width.
//
Expand Down Expand Up @@ -5109,7 +5120,7 @@ GenTree* Lowering::LowerAdd(GenTreeOp* node)
GenTree* parent = use.User();
if (!parent->OperIsIndir() && !parent->OperIs(GT_ADD))
{
TryCreateAddrMode(node, false);
TryCreateAddrMode(node, false, parent);
}
}
#endif // !TARGET_ARMARCH
Expand Down Expand Up @@ -6778,7 +6789,7 @@ void Lowering::ContainCheckBitCast(GenTree* node)
void Lowering::LowerStoreIndirCommon(GenTreeStoreInd* ind)
{
assert(ind->TypeGet() != TYP_STRUCT);
TryCreateAddrMode(ind->Addr(), true, ind->TypeGet());
TryCreateAddrMode(ind->Addr(), true, ind);
if (!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind))
{
if (varTypeIsFloating(ind) && ind->Data()->IsCnsFltOrDbl())
Expand Down Expand Up @@ -6846,7 +6857,7 @@ void Lowering::LowerIndir(GenTreeIndir* ind)
// TODO-Cleanup: We're passing isContainable = true but ContainCheckIndir rejects
// address containment in some cases so we end up creating trivial (reg + offfset)
// or (reg + reg) LEAs that are not necessary.
TryCreateAddrMode(ind->Addr(), true, ind->TypeGet());
TryCreateAddrMode(ind->Addr(), true, ind);
ContainCheckIndir(ind);

if (ind->OperIs(GT_NULLCHECK) || ind->IsUnusedValue())
Expand All @@ -6859,7 +6870,7 @@ void Lowering::LowerIndir(GenTreeIndir* ind)
// If the `ADDR` node under `STORE_OBJ(dstAddr, IND(struct(ADDR))`
// is a complex one it could benefit from an `LEA` that is not contained.
const bool isContainable = false;
TryCreateAddrMode(ind->Addr(), isContainable, ind->TypeGet());
TryCreateAddrMode(ind->Addr(), isContainable, ind);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/lower.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ class Lowering final : public Phase
void ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenTree* addr);
void LowerPutArgStk(GenTreePutArgStk* tree);

bool TryCreateAddrMode(GenTree* addr, bool isContainable, var_types targetType = TYP_UNDEF);
bool TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* parent);

bool TryTransformStoreObjAsStoreInd(GenTreeBlk* blkNode);

Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/jit/lowerxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* binOp)
//
void Lowering::LowerBlockStore(GenTreeBlk* blkNode)
{
TryCreateAddrMode(blkNode->Addr(), false);
TryCreateAddrMode(blkNode->Addr(), false, blkNode);

GenTree* dstAddr = blkNode->Addr();
GenTree* src = blkNode->Data();
Expand Down Expand Up @@ -408,7 +408,7 @@ void Lowering::ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenT
return;
}

if (!addr->OperIsAddrMode() && !TryCreateAddrMode(addr, true))
if (!addr->OperIsAddrMode() && !TryCreateAddrMode(addr, true, blkNode))
{
return;
}
Expand Down Expand Up @@ -5799,7 +5799,7 @@ bool Lowering::TryGetContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode
void Lowering::ContainCheckHWIntrinsicAddr(GenTreeHWIntrinsic* node, GenTree* addr)
{
assert((addr->TypeGet() == TYP_I_IMPL) || (addr->TypeGet() == TYP_BYREF));
TryCreateAddrMode(addr, true);
TryCreateAddrMode(addr, true, node);
if ((addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR, GT_LEA) ||
(addr->IsCnsIntOrI() && addr->AsIntConCommon()->FitsInAddrBase(comp))) &&
IsSafeToContainMem(node, addr))
Expand Down