diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index d19e1460c4a03..ed71bb09c4aa5 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -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; @@ -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. // @@ -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 @@ -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()) @@ -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()) @@ -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); } } diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index 624cc1372dc5a..95843b6bded47 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -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); diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 1331644a0a992..37459907558a0 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -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(); @@ -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; } @@ -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))