From 24dd4c84da33350801fb47678031f9a4e744807b Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Wed, 26 Apr 2023 12:25:27 -0700 Subject: [PATCH] Optimize buildIntervals() --- src/coreclr/jit/lsra.cpp | 2 ++ src/coreclr/jit/lsra.h | 4 ++- src/coreclr/jit/lsrabuild.cpp | 61 ++++++++++++++++++++++++----------- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 20c4997552556..53d93ffed0d4f 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -1298,7 +1298,9 @@ PhaseStatus LinearScan::doLinearScan() #ifdef TARGET_ARM64 nextConsecutiveRefPositionMap = nullptr; #endif + buildIntervals(); + DBEXEC(VERBOSE, TupleStyleDump(LSRA_DUMP_REFPOS)); compiler->EndPhase(PHASE_LINEAR_SCAN_BUILD); diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index 1a2d431d2e025..47a1160c8eb1b 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -642,7 +642,9 @@ class LinearScan : public LinearScanInterface virtual void recordVarLocationsAtStartOfBB(BasicBlock* bb); // This does the dataflow analysis and builds the intervals - void buildIntervals(); + template + void buildIntervals(); + void buildIntervals(); // This is where the actual assignment is done #ifdef TARGET_ARM64 diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 9ff7f83b3ab6f..8e2c80a3273b2 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -2131,6 +2131,23 @@ void LinearScan::updateRegStateForArg(LclVarDsc* argDsc) // which we will do register allocation. // void LinearScan::buildIntervals() +{ + if (enregisterLocalVars) + { + buildIntervals(); + } + else + { + buildIntervals(); + } +} + +//------------------------------------------------------------------------ +// buildIntervals: The main entry point for building the data structures over +// which we will do register allocation. +// +template +void LinearScan::buildIntervals() { BasicBlock* block; @@ -2331,7 +2348,7 @@ void LinearScan::buildIntervals() blockInfo[block->bbNum].predBBNum = predBlock->bbNum; } - if (enregisterLocalVars) + if (localVarsEnregistered) { VarSetOps::AssignNoCopy(compiler, currentLiveVars, VarSetOps::Intersection(compiler, registerCandidateVars, block->bbLiveIn)); @@ -2464,12 +2481,12 @@ void LinearScan::buildIntervals() currentLoc += 2; } -#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE - // At the end of each block, create upperVectorRestores for any largeVectorVars that may be - // partiallySpilled (during the build phase all intervals will be marked isPartiallySpilled if - // they *may) be partially spilled at any point. - if (enregisterLocalVars) + if (localVarsEnregistered) { +#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE + // At the end of each block, create upperVectorRestores for any largeVectorVars that may be + // partiallySpilled (during the build phase all intervals will be marked isPartiallySpilled if + // they *may) be partially spilled at any point. VarSetOps::Iter largeVectorVarsIter(compiler, largeVectorVars); unsigned largeVectorVarIndex = 0; while (largeVectorVarsIter.NextElem(&largeVectorVarIndex)) @@ -2477,19 +2494,16 @@ void LinearScan::buildIntervals() Interval* lclVarInterval = getIntervalForLocalVar(largeVectorVarIndex); buildUpperVectorRestoreRefPosition(lclVarInterval, currentLoc, nullptr, false); } - } #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE - // Note: the visited set is cleared in LinearScan::doLinearScan() - markBlockVisited(block); - if (!defList.IsEmpty()) - { - INDEBUG(dumpDefList()); - assert(!"Expected empty defList at end of block"); - } + // Note: the visited set is cleared in LinearScan::doLinearScan() + markBlockVisited(block); + if (!defList.IsEmpty()) + { + INDEBUG(dumpDefList()); + assert(!"Expected empty defList at end of block"); + } - if (enregisterLocalVars) - { // Insert exposed uses for a lclVar that is live-out of 'block' but not live-in to the // next block, or any unvisited successors. // This will address lclVars that are live on a backedge, as well as those that are kept @@ -2557,7 +2571,8 @@ void LinearScan::buildIntervals() LclVarDsc* const varDsc = compiler->lvaGetDesc(varNum); assert(isCandidateVar(varDsc)); RefPosition* const lastRP = getIntervalForLocalVar(varIndex)->lastRefPosition; - // We should be able to assert that lastRP is non-null if it is live-out, but sometimes liveness lies. + // We should be able to assert that lastRP is non-null if it is live-out, but sometimes liveness + // lies. if ((lastRP != nullptr) && (lastRP->bbNum == block->bbNum)) { lastRP->lastUse = false; @@ -2577,11 +2592,21 @@ void LinearScan::buildIntervals() } #endif // DEBUG } + else + { + // Note: the visited set is cleared in LinearScan::doLinearScan() + markBlockVisited(block); + if (!defList.IsEmpty()) + { + INDEBUG(dumpDefList()); + assert(!"Expected empty defList at end of block"); + } + } prevBlock = block; } - if (enregisterLocalVars) + if (localVarsEnregistered) { if (compiler->lvaKeepAliveAndReportThis()) {