diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index a04b8ab1280d..0ba2750a7091 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -6170,8 +6170,9 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, #ifdef DEBUG if (JitConfig.DumpJittedMethods() == 1 && !compIsForInlining()) { - printf("Compiling %4d %s::%s, IL size = %u, hash=%08x %s\n", Compiler::jitTotalMethodCompiled, info.compClassName, - info.compMethodName, info.compILCodeSize, info.compMethodHash(), compGetTieringName()); + printf("Compiling %4d %s::%s, IL size = %u, hash=%08x %s\n", Compiler::jitTotalMethodCompiled, + info.compClassName, info.compMethodName, info.compILCodeSize, info.compMethodHash(), + compGetTieringName()); } if (compIsForInlining()) { diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp index 470d6ce66c59..63ea9171c9e8 100644 --- a/src/jit/lclvars.cpp +++ b/src/jit/lclvars.cpp @@ -4113,8 +4113,20 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) case GT_STORE_LCL_VAR: case GT_STORE_LCL_FLD: { - const unsigned lclNum = node->AsLclVarCommon()->GetLclNum(); - lvaTable[lclNum].incRefCnts(weight, this); + LclVarDsc* varDsc = lvaGetDesc(node->AsLclVarCommon()); + // If this is an EH var, use a zero weight for defs, so that we don't + // count those in our heuristic for register allocation, since they always + // must be stored, so there's no value in enregistering them at defs; only + // if there are enough uses to justify it. + if (varDsc->lvLiveInOutOfHndlr && !varDsc->lvDoNotEnregister && + ((node->gtFlags & GTF_VAR_DEF) != 0)) + { + varDsc->incRefCnts(0, this); + } + else + { + varDsc->incRefCnts(weight, this); + } break; } diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp index fd7db2aefea0..981291bd90b9 100644 --- a/src/jit/lsra.cpp +++ b/src/jit/lsra.cpp @@ -186,7 +186,16 @@ unsigned LinearScan::getWeight(RefPosition* refPos) if (refPos->getInterval()->isSpilled) { // Decrease the weight if the interval has already been spilled. - weight -= BB_UNITY_WEIGHT; + if (varDsc->lvLiveInOutOfHndlr) + { + // An EH var is always spilled at defs, and we'll decrease the weight by half, + // since only the reload is needed. + weight = weight / 2; + } + else + { + weight -= compiler->fgFirstBB->getBBWeight(compiler); + } } } else @@ -4798,17 +4807,17 @@ void LinearScan::processBlockStartLocations(BasicBlock* currentBlock) #if DEBUG if (blockInfo[currentBlock->bbNum].hasEHBoundaryIn) { -#if DEBUG - // This should still be in its initialized empty state. - for (unsigned varIndex = 0; varIndex < compiler->lvaTrackedCount; varIndex++) - { - // In the case where we're extending lifetimes for stress, we are intentionally modeling variables - // as live when they really aren't to create extra register pressure & constraints. - // However, this means that non-EH-vars will be live into EH regions. We can and should ignore the - // locations of these. Note that they aren't reported to codegen anyway. - if (!getLsraExtendLifeTimes() || VarSetOps::IsMember(compiler, currentBlock->bbLiveIn, varIndex)) + // This should still be in its initialized empty state. + for (unsigned varIndex = 0; varIndex < compiler->lvaTrackedCount; varIndex++) { - assert(inVarToRegMap[varIndex] == REG_STK); + // In the case where we're extending lifetimes for stress, we are intentionally modeling variables + // as live when they really aren't to create extra register pressure & constraints. + // However, this means that non-EH-vars will be live into EH regions. We can and should ignore the + // locations of these. Note that they aren't reported to codegen anyway. + if (!getLsraExtendLifeTimes() || VarSetOps::IsMember(compiler, currentBlock->bbLiveIn, varIndex)) + { + assert(inVarToRegMap[varIndex] == REG_STK); + } } } #endif // DEBUG @@ -8236,7 +8245,7 @@ void LinearScan::handleOutgoingCriticalEdges(BasicBlock* block) // so if we have only EH vars, we'll do that instead of splitting the edge. if ((compiler->compHndBBtabCount > 0) && VarSetOps::IsSubset(compiler, edgeResolutionSet, exceptVars)) { - GenTree* insertionPoint = LIR::AsRange(succBlock).FirstNonPhiNode(); + GenTree* insertionPoint = LIR::AsRange(succBlock).FirstNonPhiNode(); VarSetOps::Iter edgeSetIter(compiler, edgeResolutionSet); unsigned edgeVarIndex = 0; while (edgeSetIter.NextElem(&edgeVarIndex)) diff --git a/src/jit/lsrabuild.cpp b/src/jit/lsrabuild.cpp index d6cfce072761..ac85370da3fc 100644 --- a/src/jit/lsrabuild.cpp +++ b/src/jit/lsrabuild.cpp @@ -2399,7 +2399,9 @@ void LinearScan::buildIntervals() // Given that we also don't have a good way to tell whether the variable is live // across a call in the non-EH code, we'll be extra conservative about this. // Note that for writeThru intervals we don't update the preferences to be only callee-save. - if (weight <= (BB_UNITY_WEIGHT * 7)) + unsigned calleeSaveCount = + (varTypeIsFloating(interval->registerType)) ? CNT_CALLEE_SAVED_FLOAT : CNT_CALLEE_ENREG; + if ((weight <= (BB_UNITY_WEIGHT * 7)) || varDsc->lvVarIndex >= calleeSaveCount) { // If this is relatively low weight, don't prefer callee-save at all. interval->preferCalleeSave = false;