summaryrefslogtreecommitdiff
path: root/src/jit
diff options
context:
space:
mode:
authorCarol Eidt <carol.eidt@microsoft.com>2018-04-09 17:07:03 -0700
committerCarol Eidt <carol.eidt@microsoft.com>2018-04-09 17:07:03 -0700
commitd62569872457dff731fa3ae4c2888e8182c03190 (patch)
treedb56e1de026968ed8631e44b88cd0c6370c37ef5 /src/jit
parentefb6e48dd977fae49089eef19c1368c81fb10f3d (diff)
downloadcoreclr-d62569872457dff731fa3ae4c2888e8182c03190.tar.gz
coreclr-d62569872457dff731fa3ae4c2888e8182c03190.tar.bz2
coreclr-d62569872457dff731fa3ae4c2888e8182c03190.zip
Handle last uses that become contained
Diffstat (limited to 'src/jit')
-rw-r--r--src/jit/lsra.h22
-rw-r--r--src/jit/lsraxarch.cpp16
2 files changed, 37 insertions, 1 deletions
diff --git a/src/jit/lsra.h b/src/jit/lsra.h
index d3d3f99b00..22e3ead7ec 100644
--- a/src/jit/lsra.h
+++ b/src/jit/lsra.h
@@ -1683,6 +1683,28 @@ private:
bool isRMWRegOper(GenTree* tree);
void BuildMul(GenTree* tree);
void SetContainsAVXFlags(bool isFloatingPointType = true, unsigned sizeOfSIMDVector = 0);
+ // Move the last use bit, if any, from 'fromTree' to 'toTree'; 'fromTree' must be contained.
+ void CheckAndMoveRMWLastUse(GenTree* fromTree, GenTree* toTree)
+ {
+ // If 'fromTree' is not a last-use lclVar, there's nothing to do.
+ if ((fromTree == nullptr) || !fromTree->OperIs(GT_LCL_VAR) || ((fromTree->gtFlags & GTF_VAR_DEATH) == 0))
+ {
+ return;
+ }
+ // If 'fromTree' was a lclVar, it must be contained and 'toTree' must match.
+ if (!fromTree->isContained() || (toTree == nullptr) || !toTree->OperIs(GT_LCL_VAR) ||
+ (toTree->AsLclVarCommon()->gtLclNum != toTree->AsLclVarCommon()->gtLclNum))
+ {
+ assert(!"Unmatched RMW indirections");
+ return;
+ }
+ // This is probably not necessary, but keeps things consistent.
+ fromTree->gtFlags &= ~GTF_VAR_DEATH;
+ if (toTree != nullptr) // Just to be conservative
+ {
+ toTree->gtFlags |= GTF_VAR_DEATH;
+ }
+ }
#endif // defined(_TARGET_XARCH_)
#ifdef FEATURE_SIMD
diff --git a/src/jit/lsraxarch.cpp b/src/jit/lsraxarch.cpp
index 09cc9ca96e..f72403d0e3 100644
--- a/src/jit/lsraxarch.cpp
+++ b/src/jit/lsraxarch.cpp
@@ -2515,7 +2515,8 @@ void LinearScan::BuildIndir(GenTreeIndir* indirTree)
// Because 'source' is contained, we haven't yet determined its special register requirements, if any.
// As it happens, the Shift or Rotate cases are the only ones with special requirements.
assert(source->isContained() && source->OperIsRMWMemOp());
- GenTree* nonMemSource = nullptr;
+ GenTree* nonMemSource = nullptr;
+ GenTreeIndir* otherIndir = nullptr;
if (source->OperIsShiftOrRotate())
{
@@ -2527,6 +2528,7 @@ void LinearScan::BuildIndir(GenTreeIndir* indirTree)
}
if (indirTree->AsStoreInd()->IsRMWDstOp1())
{
+ otherIndir = source->gtGetOp1()->AsIndir();
if (source->OperIsBinary())
{
nonMemSource = source->gtOp.gtOp2;
@@ -2534,8 +2536,20 @@ void LinearScan::BuildIndir(GenTreeIndir* indirTree)
}
else if (indirTree->AsStoreInd()->IsRMWDstOp2())
{
+ otherIndir = source->gtGetOp2()->AsIndir();
nonMemSource = source->gtOp.gtOp1;
}
+ if (otherIndir != nullptr)
+ {
+ // Any lclVars in the addressing mode of this indirection are contained.
+ // If they are marked as lastUse, transfer the last use flag to the store indir.
+ GenTree* base = otherIndir->Base();
+ GenTree* dstBase = indirTree->Base();
+ CheckAndMoveRMWLastUse(base, dstBase);
+ GenTree* index = otherIndir->Index();
+ GenTree* dstIndex = indirTree->Index();
+ CheckAndMoveRMWLastUse(index, dstIndex);
+ }
if (nonMemSource != nullptr)
{
assert(!nonMemSource->isContained() || (!nonMemSource->isMemoryOp() && !nonMemSource->IsLocal()));