diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 391682418ed1e2..e6ed66846b3ba7 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -825,6 +825,7 @@ LinearScan::LinearScan(Compiler* theCompiler) blockSequenceWorkList = nullptr; curBBSeqNum = 0; bbSeqCount = 0; + recentKillLocation = 0; // Information about each block, including predecessor blocks used for variable locations at block entry. blockInfo = nullptr; @@ -9668,6 +9669,10 @@ void Interval::dump(Compiler* compiler) printf(" Preferences="); compiler->dumpRegMask(this->registerPreferences); + if (preferCalleeSave) + { + printf("(prefer-callee-save)"); + } if (relatedInterval) { diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index d0f7aeb8369695..bd93a42f6e729b 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -449,6 +449,7 @@ class Referenceable firstRefPosition = nullptr; recentRefPosition = nullptr; lastRefPosition = nullptr; + recentDefRefPosition = nullptr; } // A linked list of RefPositions. These are only traversed in the forward @@ -458,6 +459,7 @@ class Referenceable RefPosition* firstRefPosition; RefPosition* recentRefPosition; RefPosition* lastRefPosition; + RefPosition* recentDefRefPosition; // Get the position of the next reference which is at or greater than // the current location (relies upon recentRefPosition being updated @@ -1626,6 +1628,8 @@ class LinearScan : public LinearScanInterface unsigned int bbSeqCount; // The Location of the start of the current block. LsraLocation curBBStartLocation; + // Most recent kill location + LsraLocation recentKillLocation; // True if the method contains any critical edges. bool hasCriticalEdges; diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 7d9803c645799d..1df45f1b46ea0f 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -377,6 +377,15 @@ void LinearScan::applyCalleeSaveHeuristics(RefPosition* rp) Interval* theInterval = rp->getInterval(); + //if ((theInterval->recentDefRefPosition != nullptr) && RefTypeIsUse(rp->refType) && !theInterval->isWriteThru && + // !theInterval->isLocalVar) + //{ + // if (theInterval->recentDefRefPosition->nodeLocation < recentKillLocation) + // { + // theInterval->preferCalleeSave = true; + // } + //} + #ifdef DEBUG if (!doReverseCallerCallee()) #endif // DEBUG @@ -482,6 +491,16 @@ void LinearScan::associateRefPosWithInterval(RefPosition* rp) if (prevRP != nullptr) { prevRP->nextRefPosition = rp; + if (rp->isIntervalRef() && RefTypeIsDef(rp->refType)) + { + Interval* theInterval = rp->getInterval(); + if (theInterval->recentDefRefPosition != nullptr && theInterval->recentDefRefPosition->nodeLocation < + recentKillLocation && + recentKillLocation < prevRP->nodeLocation) + { + theInterval->preferCalleeSave = true; + } + } } else { @@ -639,6 +658,7 @@ RefPosition* LinearScan::newRefPosition(Interval* theInterval, { assert(theInterval != nullptr); theInterval->isSingleDef = theInterval->firstRefPosition == newRP; + theInterval->recentDefRefPosition = newRP; } DBEXEC(VERBOSE, newRP->dump(this)); @@ -1159,6 +1179,12 @@ bool LinearScan::buildKillPositionsForNode(GenTree* tree, LsraLocation currentLo { addRefsForPhysRegMask(killMask, currentLoc, RefTypeKill, true); + const bool isCallKill = ((killMask == RBM_INT_CALLEE_TRASH) || (killMask == RBM_CALLEE_TRASH)); + if (isCallKill) + { + recentKillLocation = currentLoc; + } + // TODO-CQ: It appears to be valuable for both fp and int registers to avoid killing the callee // save regs on infrequently executed paths. However, it results in a large number of asmDiffs, // many of which appear to be regressions (because there is more spill on the infrequently path), @@ -1189,8 +1215,7 @@ bool LinearScan::buildKillPositionsForNode(GenTree* tree, LsraLocation currentLo { continue; } - Interval* interval = getIntervalForLocalVar(varIndex); - const bool isCallKill = ((killMask == RBM_INT_CALLEE_TRASH) || (killMask == RBM_CALLEE_TRASH)); + Interval* interval = getIntervalForLocalVar(varIndex); if (isCallKill) { @@ -1228,6 +1253,7 @@ bool LinearScan::buildKillPositionsForNode(GenTree* tree, LsraLocation currentLo { RefPosition* pos = newRefPosition((Interval*)nullptr, currentLoc, RefTypeKillGCRefs, tree, (availableIntRegs & ~RBM_ARG_REGS)); + insertedKills = true; }