summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2018-08-20 15:03:29 -0700
committerGitHub <noreply@github.com>2018-08-20 15:03:29 -0700
commit895bfa452da4aeeda52447e76d9e9e987d68f331 (patch)
tree4a677c86c579f45feeb6cf6775b6dc833fc5aec3
parentab8023d9e2d70072d0017191eacca449c4e1c33b (diff)
downloadcoreclr-895bfa452da4aeeda52447e76d9e9e987d68f331.tar.gz
coreclr-895bfa452da4aeeda52447e76d9e9e987d68f331.tar.bz2
coreclr-895bfa452da4aeeda52447e76d9e9e987d68f331.zip
JIT: remove incremental ref count updates (#19345)
Remove almost all of the code in the jit that tries to maintain local ref counts incrementally. Also remove `lvaSortAgain` and related machinery. Explicitly sort locals before post-lower-liveness when optimizing to get the best set of tracked locals. Explicitly recount after post-lower liveness to get accurate counts after dead stores. This can lead to tracked unreferenced arguments; tolerate this during codegen.
-rw-r--r--src/jit/assertionprop.cpp43
-rw-r--r--src/jit/codegencommon.cpp7
-rw-r--r--src/jit/compiler.cpp3
-rw-r--r--src/jit/compiler.h21
-rw-r--r--src/jit/compiler.hpp184
-rw-r--r--src/jit/copyprop.cpp2
-rw-r--r--src/jit/decomposelongs.cpp43
-rw-r--r--src/jit/earlyprop.cpp2
-rw-r--r--src/jit/flowgraph.cpp56
-rw-r--r--src/jit/gentree.cpp28
-rw-r--r--src/jit/lclvars.cpp234
-rw-r--r--src/jit/lir.cpp35
-rw-r--r--src/jit/liveness.cpp32
-rw-r--r--src/jit/lower.cpp62
-rw-r--r--src/jit/morph.cpp83
-rw-r--r--src/jit/optcse.cpp37
-rw-r--r--src/jit/optimizer.cpp40
-rw-r--r--src/jit/rationalize.cpp1
-rw-r--r--src/jit/regalloc.cpp11
19 files changed, 89 insertions, 835 deletions
diff --git a/src/jit/assertionprop.cpp b/src/jit/assertionprop.cpp
index d4153a287e..0cc35a9ceb 100644
--- a/src/jit/assertionprop.cpp
+++ b/src/jit/assertionprop.cpp
@@ -430,12 +430,6 @@ void Compiler::optAddCopies()
{
stmt = fgInsertStmtNearEnd(bestBlock, copyAsgn);
}
-
- /* Increment its lvRefCnt and lvRefCntWtd */
- lvaTable[lclNum].incRefCnts(fgFirstBB->getBBWeight(this), this);
-
- /* Increment its lvRefCnt and lvRefCntWtd */
- lvaTable[copyLclNum].incRefCnts(fgFirstBB->getBBWeight(this), this);
}
else
{
@@ -461,10 +455,6 @@ void Compiler::optAddCopies()
/* TODO-Review: BB_UNITY_WEIGHT is not the correct block weight */
unsigned blockWeight = BB_UNITY_WEIGHT;
- /* Increment its lvRefCnt and lvRefCntWtd twice */
- lvaTable[copyLclNum].incRefCnts(blockWeight, this);
- lvaTable[copyLclNum].incRefCnts(blockWeight, this);
-
/* Assign the old expression into the new temp */
GenTree* newAsgn = gtNewTempAssign(copyLclNum, tree->gtOp.gtOp2);
@@ -2698,10 +2688,6 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion,
gtDispTree(newTree, nullptr, nullptr, true);
}
#endif
- if (lvaLocalVarRefCounted())
- {
- lvaTable[lclNum].decRefCnts(compCurBB->getBBWeight(this), this);
- }
return optAssertionProp_Update(newTree, tree, stmt);
}
@@ -2811,13 +2797,7 @@ GenTree* Compiler::optCopyAssertionProp(AssertionDsc* curAssertion,
return nullptr;
}
- // If global assertion prop, by now we should have ref counts, fix them.
- if (lvaLocalVarRefCounted())
- {
- lvaTable[lclNum].decRefCnts(compCurBB->getBBWeight(this), this);
- lvaTable[copyLclNum].incRefCnts(compCurBB->getBBWeight(this), this);
- tree->gtLclVarCommon.SetSsaNum(copySsaNum);
- }
+ tree->gtLclVarCommon.SetSsaNum(copySsaNum);
tree->gtLclVarCommon.SetLclNum(copyLclNum);
#ifdef DEBUG
@@ -3097,9 +3077,6 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, Gen
gtDispTree(tree, nullptr, nullptr, true);
}
#endif
- // Decrement the ref counts, before we change the oper.
- lvaTable[op1->gtLclVar.gtLclNum].decRefCnts(compCurBB->getBBWeight(this), this);
-
// Change the oper to const.
if (genActualType(op1->TypeGet()) == TYP_INT)
{
@@ -3158,8 +3135,6 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, Gen
gtDispTree(tree, nullptr, nullptr, true);
}
#endif
- lvaTable[op1->gtLclVar.gtLclNum].decRefCnts(compCurBB->getBBWeight(this), this);
-
// If floating point, don't just substitute op1 with op2, this won't work if
// op2 is NaN. Just turn it into a "true" or "false" yielding expression.
if (op1->TypeGet() == TYP_DOUBLE || op1->TypeGet() == TYP_FLOAT)
@@ -3169,7 +3144,6 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, Gen
// point only on JTrue nodes, so if the condition held earlier, it will hold
// now. We don't create OAK_EQUAL assertion on floating point from GT_ASG
// because we depend on value num which would constant prop the NaN.
- lvaTable[op2->gtLclVar.gtLclNum].decRefCnts(compCurBB->getBBWeight(this), this);
op1->ChangeOperConst(GT_CNS_DBL);
op1->gtDblCon.gtDconVal = 0;
op2->ChangeOperConst(GT_CNS_DBL);
@@ -3179,7 +3153,6 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, Gen
else
{
noway_assert(varTypeIsIntegralOrI(op1->TypeGet()));
- lvaTable[op2->gtLclVar.gtLclNum].incRefCnts(compCurBB->getBBWeight(this), this);
op1->AsLclVarCommon()->SetLclNum(op2->AsLclVarCommon()->GetLclNum());
op1->AsLclVarCommon()->SetSsaNum(op2->AsLclVarCommon()->GetSsaNum());
}
@@ -4631,13 +4604,11 @@ GenTree* Compiler::optPrepareTreeForReplacement(GenTree* oldTree, GenTree* newTr
gtExtractSideEffList(oldTree, &sideEffList, GTF_SIDE_EFFECT, ignoreRoot);
}
+
if (sideEffList != nullptr)
{
noway_assert((sideEffList->gtFlags & GTF_SIDE_EFFECT) != 0);
- // Increment the ref counts as we want to keep the side effects.
- lvaRecursiveIncRefCounts(sideEffList);
-
if (newTree != nullptr)
{
newTree = gtNewOperNode(GT_COMMA, newTree->TypeGet(), sideEffList, newTree);
@@ -4648,8 +4619,6 @@ GenTree* Compiler::optPrepareTreeForReplacement(GenTree* oldTree, GenTree* newTr
}
}
- // Decrement the ref counts as the oldTree is going to be dropped.
- lvaRecursiveDecRefCounts(oldTree);
return newTree;
}
@@ -5169,12 +5138,4 @@ void Compiler::optAssertionPropMain()
fgDebugCheckBBlist();
fgDebugCheckLinks();
#endif
-
- // Assertion propagation may have changed the reference counts
- // We need to resort the variable table
-
- if (optAssertionPropagated)
- {
- lvaSortAgain = true;
- }
}
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp
index 0f6beec574..67faf40095 100644
--- a/src/jit/codegencommon.cpp
+++ b/src/jit/codegencommon.cpp
@@ -3668,7 +3668,12 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
{
if (varDsc->lvTrackedNonStruct())
{
- noway_assert(!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex));
+ // We may now see some tracked locals with zero refs.
+ // See Lowering::DoPhase. Tolerate these.
+ if (varDsc->lvRefCnt() > 0)
+ {
+ noway_assert(!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex));
+ }
}
else
{
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index b66236b032..ded0920c3d 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -4912,8 +4912,7 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, JitFlags
StackLevelSetter stackLevelSetter(this); // PHASE_STACK_LEVEL_SETTER
stackLevelSetter.Run();
- assert(lvaSortAgain == false); // We should have re-run fgLocalVarLiveness() in lower.Run()
- lvaTrackedFixed = true; // We can not add any new tracked variables after this point.
+ lvaTrackedFixed = true; // We can not add any new tracked variables after this point.
/* Now that lowering is completed we can proceed to perform register allocation */
m_pLinearScan->doLinearScan();
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 09ff104d7a..6015cf327e 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -613,12 +613,10 @@ private:
public:
unsigned short lvRefCnt(RefCountState state = RCS_NORMAL) const;
void incLvRefCnt(unsigned short delta, RefCountState state = RCS_NORMAL);
- void decLvRefCnt(unsigned short delta, RefCountState state = RCS_NORMAL);
void setLvRefCnt(unsigned short newValue, RefCountState state = RCS_NORMAL);
BasicBlock::weight_t lvRefCntWtd(RefCountState state = RCS_NORMAL) const;
void incLvRefCntWtd(BasicBlock::weight_t delta, RefCountState state = RCS_NORMAL);
- void decLvRefCntWtd(BasicBlock::weight_t delta, RefCountState state = RCS_NORMAL);
void setLvRefCntWtd(BasicBlock::weight_t newValue, RefCountState state = RCS_NORMAL);
int lvStkOffs; // stack offset of home
@@ -711,11 +709,6 @@ public:
!(lvIsParam || lvAddrExposed || lvIsStructField);
}
- void lvaResetSortAgainFlag(Compiler* pComp, RefCountState = RCS_NORMAL);
- void decRefCnts(BasicBlock::weight_t weight,
- Compiler* pComp,
- RefCountState state = RCS_NORMAL,
- bool propagate = true);
void incRefCnts(BasicBlock::weight_t weight,
Compiler* pComp,
RefCountState state = RCS_NORMAL,
@@ -2541,7 +2534,6 @@ public:
return lvaRefCountState == RCS_NORMAL;
}
- bool lvaSortAgain; // true: We need to sort the lvaTable
bool lvaTrackedFixed; // true: We cannot add new 'tracked' variable
unsigned lvaCount; // total number of locals
@@ -2798,13 +2790,6 @@ public:
VARSET_VALRET_TP lvaStmtLclMask(GenTree* stmt);
- void lvaIncRefCnts(GenTree* tree);
- void lvaDecRefCnts(GenTree* tree);
-
- void lvaDecRefCnts(BasicBlock* basicBlock, GenTree* tree);
- void lvaRecursiveDecRefCounts(GenTree* tree);
- void lvaRecursiveIncRefCounts(GenTree* tree);
-
#ifdef DEBUG
struct lvaStressLclFldArgs
{
@@ -3970,10 +3955,6 @@ public:
void fgLiveVarAnalysis(bool updateInternalOnly = false);
- void fgUpdateRefCntForClone(BasicBlock* addedToBlock, GenTree* clonedTree);
-
- void fgUpdateRefCntForExtract(GenTree* wholeTree, GenTree* keptTree);
-
void fgComputeLifeCall(VARSET_TP& life, GenTreeCall* call);
void fgComputeLifeTrackedLocalUse(VARSET_TP& life, LclVarDsc& varDsc, GenTreeLclVarCommon* node);
@@ -4488,7 +4469,7 @@ public:
void fgRemoveEmptyBlocks();
- void fgRemoveStmt(BasicBlock* block, GenTree* stmt, bool updateRefCnt = true);
+ void fgRemoveStmt(BasicBlock* block, GenTree* stmt);
bool fgCheckRemoveStmt(BasicBlock* block, GenTree* stmt);
diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp
index c1b050cc4f..2063d55bd8 100644
--- a/src/jit/compiler.hpp
+++ b/src/jit/compiler.hpp
@@ -1685,18 +1685,25 @@ inline unsigned Compiler::lvaGrabTemp(bool shortLifetime DEBUGARG(const char* re
const unsigned tempNum = lvaCount;
lvaCount++;
- lvaTable[tempNum].lvType = TYP_UNDEF; // Initialize lvType, lvIsTemp and lvOnFrame
+ // Initialize lvType, lvIsTemp and lvOnFrame
+ lvaTable[tempNum].lvType = TYP_UNDEF;
lvaTable[tempNum].lvIsTemp = shortLifetime;
lvaTable[tempNum].lvOnFrame = true;
- // If we've started normal ref counting and are in minopts or debug
- // mark this variable as implictly referenced.
+ // If we've started normal ref counting, bump the ref count of this
+ // local, as we no longer do any incremental counting, and we presume
+ // this new local will be referenced.
if (lvaLocalVarRefCounted())
{
if (opts.MinOpts() || opts.compDbgCode)
{
lvaTable[tempNum].lvImplicitlyReferenced = 1;
}
+ else
+ {
+ lvaTable[tempNum].setLvRefCnt(1);
+ lvaTable[tempNum].setLvRefCntWtd(BB_UNITY_WEIGHT);
+ }
}
#ifdef DEBUG
@@ -1732,6 +1739,9 @@ inline unsigned Compiler::lvaGrabTemps(unsigned cnt DEBUGARG(const char* reason)
}
#endif
+ // Could handle this...
+ assert(!lvaLocalVarRefCounted());
+
// You cannot allocate more space after frame layout!
noway_assert(lvaDoneFrameLayout < Compiler::TENTATIVE_FRAME_LAYOUT);
@@ -1814,124 +1824,6 @@ inline unsigned Compiler::lvaGrabTempWithImplicitUse(bool shortLifetime DEBUGARG
/*****************************************************************************
*
- * If lvaTrackedFixed is false then set the lvaSortAgain flag
- * (this allows us to grow the number of tracked variables)
- * and zero lvRefCntWtd when lvRefCnt is zero
- */
-
-inline void LclVarDsc::lvaResetSortAgainFlag(Compiler* comp, RefCountState state)
-{
- if (!comp->lvaTrackedFixed && !comp->opts.MinOpts() && !comp->opts.compDbgCode)
- {
- /* Flag this change, set lvaSortAgain to true */
- comp->lvaSortAgain = true;
- }
- /* Set weighted ref count to zero if ref count is zero */
- if (lvRefCnt(state) == 0)
- {
- setLvRefCntWtd(0, state);
- }
-}
-
-/*****************************************************************************
- *
- * Decrement the ref counts for a local variable
- */
-
-inline void LclVarDsc::decRefCnts(BasicBlock::weight_t weight, Compiler* comp, RefCountState state, bool propagate)
-{
- // In minopts and debug codegen, we don't maintain normal ref counts.
- if ((state == RCS_NORMAL) && (comp->opts.MinOpts() || comp->opts.compDbgCode))
- {
- return;
- }
-
- /* Decrement lvRefCnt and lvRefCntWtd */
- Compiler::lvaPromotionType promotionType = DUMMY_INIT(Compiler::PROMOTION_TYPE_NONE);
- if (varTypeIsStruct(lvType))
- {
- promotionType = comp->lvaGetPromotionType(this);
- }
-
- //
- // Decrement counts on the local itself.
- //
- if (lvType != TYP_STRUCT || promotionType != Compiler::PROMOTION_TYPE_INDEPENDENT)
- {
- assert(lvRefCnt(state)); // Can't decrement below zero
-
- // TODO: Well, the assert above could be bogus.
- // If lvRefCnt has overflowed before, then might drop to 0.
- // Therefore we do need the following check to keep lvRefCnt from underflow:
- if (lvRefCnt(state) > 0)
- {
- //
- // Decrement lvRefCnt
- //
- decLvRefCnt(1, state);
-
- //
- // Decrement lvRefCntWtd
- //
- if (weight != 0)
- {
- if (lvIsTemp && (weight * 2 > weight))
- {
- weight *= 2;
- }
-
- if (lvRefCntWtd(state) <= weight)
- { // Can't go below zero
- setLvRefCntWtd(0, state);
- }
- else
- {
- decLvRefCntWtd(weight, state);
- }
- }
- }
- }
-
- if (varTypeIsStruct(lvType) && propagate)
- {
- // For promoted struct locals, decrement lvRefCnt on its field locals as well.
- if (promotionType == Compiler::PROMOTION_TYPE_INDEPENDENT ||
- promotionType == Compiler::PROMOTION_TYPE_DEPENDENT)
- {
- for (unsigned i = lvFieldLclStart; i < lvFieldLclStart + lvFieldCnt; ++i)
- {
- comp->lvaTable[i].decRefCnts(weight, comp, state, false); // Don't propagate
- }
- }
- }
-
- if (lvIsStructField && propagate)
- {
- // Depending on the promotion type, decrement the ref count for the parent struct as well.
- promotionType = comp->lvaGetParentPromotionType(this);
- LclVarDsc* parentvarDsc = &comp->lvaTable[lvParentLcl];
- assert(!parentvarDsc->lvRegStruct);
- if (promotionType == Compiler::PROMOTION_TYPE_DEPENDENT)
- {
- parentvarDsc->decRefCnts(weight, comp, state, false); // Don't propagate
- }
- }
-
- lvaResetSortAgainFlag(comp, state);
-
-#ifdef DEBUG
- if (comp->verbose)
- {
- unsigned varNum = (unsigned)(this - comp->lvaTable);
- assert(&comp->lvaTable[varNum] == this);
- printf("New refCnts for V%02u: refCnt = %2u, refCntWtd = %s\n", varNum, lvRefCnt(state),
- refCntWtd2str(lvRefCntWtd(state)));
- }
-#endif
-}
-
-/*****************************************************************************
- *
* Increment the ref counts for a local variable
*/
@@ -2014,8 +1906,6 @@ inline void LclVarDsc::incRefCnts(BasicBlock::weight_t weight, Compiler* comp, R
}
}
- lvaResetSortAgainFlag(comp, state);
-
#ifdef DEBUG
if (comp->verbose)
{
@@ -4917,30 +4807,6 @@ inline void LclVarDsc::incLvRefCnt(unsigned short delta, RefCountState state)
}
//------------------------------------------------------------------------------
-// decLvRefCnt: decrement reference count for this local var
-//
-// Arguments:
-// delta: the amount of the decrement
-// state: the requestor's expected ref count state; defaults to RCS_NORMAL
-//
-// Notes:
-// It is currently the caller's responsibilty to ensure this decrement
-// will not cause underflow.
-
-inline void LclVarDsc::decLvRefCnt(unsigned short delta, RefCountState state)
-{
-
-#if defined(DEBUG)
- assert(state != RCS_INVALID);
- Compiler* compiler = JitTls::GetCompiler();
- assert(compiler->lvaRefCountState == state);
-#endif
-
- assert(m_lvRefCnt >= delta);
- m_lvRefCnt -= delta;
-}
-
-//------------------------------------------------------------------------------
// setLvRefCnt: set the reference count for this local var
//
// Arguments:
@@ -5015,30 +4881,6 @@ inline void LclVarDsc::incLvRefCntWtd(BasicBlock::weight_t delta, RefCountState
}
//------------------------------------------------------------------------------
-// decLvRefCntWtd: decrement weighted reference count for this local var
-//
-// Arguments:
-// delta: the amount of the decrement
-// state: the requestor's expected ref count state; defaults to RCS_NORMAL
-//
-// Notes:
-// It is currently the caller's responsibilty to ensure this decrement
-// will not cause underflow.
-
-inline void LclVarDsc::decLvRefCntWtd(BasicBlock::weight_t delta, RefCountState state)
-{
-
-#if defined(DEBUG)
- assert(state != RCS_INVALID);
- Compiler* compiler = JitTls::GetCompiler();
- assert(compiler->lvaRefCountState == state);
-#endif
-
- assert(m_lvRefCntWtd >= delta);
- m_lvRefCntWtd -= delta;
-}
-
-//------------------------------------------------------------------------------
// setLvRefCntWtd: set the weighted reference count for this local var
//
// Arguments:
diff --git a/src/jit/copyprop.cpp b/src/jit/copyprop.cpp
index c09fa91509..98671c1b32 100644
--- a/src/jit/copyprop.cpp
+++ b/src/jit/copyprop.cpp
@@ -266,8 +266,6 @@ void Compiler::optCopyProp(BasicBlock* block, GenTree* stmt, GenTree* tree, LclN
}
#endif
- lvaTable[lclNum].decRefCnts(block->getBBWeight(this), this);
- lvaTable[newLclNum].incRefCnts(block->getBBWeight(this), this);
tree->gtLclVarCommon.SetLclNum(newLclNum);
tree->AsLclVarCommon()->SetSsaNum(newSsaNum);
gtUpdateSideEffects(stmt, tree);
diff --git a/src/jit/decomposelongs.cpp b/src/jit/decomposelongs.cpp
index 9e6da62c86..74863ade63 100644
--- a/src/jit/decomposelongs.cpp
+++ b/src/jit/decomposelongs.cpp
@@ -141,10 +141,8 @@ GenTree* DecomposeLongs::DecomposeNode(GenTree* tree)
m_compiler->gtDispTreeRange(Range(), tree);
}
#endif // DEBUG
- m_compiler->lvaDecRefCnts(tree);
unsigned loVarNum = varDsc->lvFieldLclStart;
tree->AsLclVarCommon()->SetLclNum(loVarNum);
- m_compiler->lvaIncRefCnts(tree);
return tree->gtNext;
}
}
@@ -343,13 +341,11 @@ GenTree* DecomposeLongs::DecomposeLclVar(LIR::Use& use)
assert(use.IsInitialized());
assert(use.Def()->OperGet() == GT_LCL_VAR);
- GenTree* tree = use.Def();
- unsigned varNum = tree->AsLclVarCommon()->gtLclNum;
- LclVarDsc* varDsc = m_compiler->lvaTable + varNum;
- m_compiler->lvaDecRefCnts(tree);
-
- GenTree* loResult = tree;
- loResult->gtType = TYP_INT;
+ GenTree* tree = use.Def();
+ unsigned varNum = tree->AsLclVarCommon()->gtLclNum;
+ LclVarDsc* varDsc = m_compiler->lvaTable + varNum;
+ GenTree* loResult = tree;
+ loResult->gtType = TYP_INT;
GenTree* hiResult = m_compiler->gtNewLclLNode(varNum, TYP_INT);
Range().InsertAfter(loResult, hiResult);
@@ -373,9 +369,6 @@ GenTree* DecomposeLongs::DecomposeLclVar(LIR::Use& use)
hiResult->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();
}
- m_compiler->lvaIncRefCnts(loResult);
- m_compiler->lvaIncRefCnts(hiResult);
-
return FinalizeDecomposition(use, loResult, hiResult, hiResult);
}
@@ -400,8 +393,6 @@ GenTree* DecomposeLongs::DecomposeLclFld(LIR::Use& use)
GenTree* hiResult = m_compiler->gtNewLclFldNode(loResult->gtLclNum, TYP_INT, loResult->gtLclOffs + 4);
Range().InsertAfter(loResult, hiResult);
- m_compiler->lvaIncRefCnts(hiResult);
-
return FinalizeDecomposition(use, loResult, hiResult, hiResult);
}
@@ -472,8 +463,6 @@ GenTree* DecomposeLongs::DecomposeStoreLclVar(LIR::Use& use)
}
assert(varDsc->lvFieldCnt == 2);
- m_compiler->lvaDecRefCnts(tree);
-
GenTreeOp* value = rhs->AsOp();
Range().Remove(value);
@@ -489,9 +478,6 @@ GenTree* DecomposeLongs::DecomposeStoreLclVar(LIR::Use& use)
hiStore->gtOp.gtOp1 = value->gtOp2;
hiStore->gtFlags |= GTF_VAR_DEF;
- m_compiler->lvaIncRefCnts(loStore);
- m_compiler->lvaIncRefCnts(hiStore);
-
Range().InsertAfter(tree, hiStore);
return hiStore->gtNext;
@@ -529,9 +515,6 @@ GenTree* DecomposeLongs::DecomposeStoreLclFld(LIR::Use& use)
hiStore->gtOp1 = value->gtOp2;
hiStore->gtFlags |= (GTF_VAR_DEF | GTF_VAR_USEASG);
- // Bump the ref count for the destination.
- m_compiler->lvaIncRefCnts(hiStore);
-
Range().InsertAfter(loStore, hiStore);
return hiStore->gtNext;
@@ -653,8 +636,6 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use)
hiResult = m_compiler->gtNewOperNode(GT_RSH, TYP_INT, loCopy, shiftBy);
Range().InsertAfter(cast, loCopy, shiftBy, hiResult);
- m_compiler->lvaIncRefCnts(loCopy);
-
Range().Remove(cast);
}
}
@@ -830,8 +811,6 @@ GenTree* DecomposeLongs::DecomposeStoreInd(LIR::Use& use)
GenTree* storeIndHigh = new (m_compiler, GT_STOREIND) GenTreeStoreInd(TYP_INT, addrHigh, dataHigh);
storeIndHigh->gtFlags = (storeIndLow->gtFlags & (GTF_ALL_EFFECT | GTF_LIVENESS_MASK));
- m_compiler->lvaIncRefCnts(addrBaseHigh);
-
Range().InsertAfter(storeIndLow, dataHigh, addrBaseHigh, addrHigh, storeIndHigh);
return storeIndHigh;
@@ -884,8 +863,6 @@ GenTree* DecomposeLongs::DecomposeInd(LIR::Use& use)
GenTree* indHigh = new (m_compiler, GT_IND) GenTreeIndir(GT_IND, TYP_INT, addrHigh, nullptr);
indHigh->gtFlags |= (indLow->gtFlags & (GTF_GLOB_REF | GTF_EXCEPT | GTF_IND_FLAGS));
- m_compiler->lvaIncRefCnts(addrBaseHigh);
-
Range().InsertAfter(indLow, addrBaseHigh, addrHigh, indHigh);
return FinalizeDecomposition(use, indLow, indHigh, indHigh);
@@ -1149,8 +1126,6 @@ GenTree* DecomposeLongs::DecomposeShift(LIR::Use& use)
GenTree* hiOp = new (m_compiler, GT_LONG) GenTreeOp(GT_LONG, TYP_LONG, loCopy, hiOp1);
hiResult = m_compiler->gtNewOperNode(GT_LSH_HI, TYP_INT, hiOp, shiftByHi);
- m_compiler->lvaIncRefCnts(loCopy);
-
Range().InsertBefore(shift, loOp1, shiftByLo, loResult);
Range().InsertBefore(shift, loCopy, hiOp, shiftByHi, hiResult);
@@ -1226,8 +1201,6 @@ GenTree* DecomposeLongs::DecomposeShift(LIR::Use& use)
GenTree* shiftByHi = m_compiler->gtNewIconNode(count, TYP_INT);
GenTree* shiftByLo = m_compiler->gtNewIconNode(count, TYP_INT);
- m_compiler->lvaIncRefCnts(hiCopy);
-
hiResult = m_compiler->gtNewOperNode(GT_RSZ, TYP_INT, hiOp1, shiftByHi);
// Create a GT_LONG that contains loOp1 and hiCopy. This will be used in codegen to
@@ -1298,7 +1271,6 @@ GenTree* DecomposeLongs::DecomposeShift(LIR::Use& use)
GenTree* shiftByHi = m_compiler->gtNewIconNode(count, TYP_INT);
GenTree* shiftByLo = m_compiler->gtNewIconNode(count, TYP_INT);
- m_compiler->lvaIncRefCnts(hiCopy);
hiResult = m_compiler->gtNewOperNode(GT_RSH, TYP_INT, hiOp1, shiftByHi);
@@ -1349,8 +1321,6 @@ GenTree* DecomposeLongs::DecomposeShift(LIR::Use& use)
GenTree* shiftBy = m_compiler->gtNewIconNode(31, TYP_INT);
hiResult = m_compiler->gtNewOperNode(GT_RSH, TYP_INT, hiCopy, shiftBy);
Range().InsertBefore(shift, shiftBy, hiCopy, hiResult);
-
- m_compiler->lvaIncRefCnts(hiCopy);
}
insertAfter = hiResult;
@@ -1543,9 +1513,6 @@ GenTree* DecomposeLongs::DecomposeRotate(LIR::Use& use)
GenTree* hiOp = new (m_compiler, GT_LONG) GenTreeOp(GT_LONG, TYP_LONG, loCopy, hiOp1);
hiResult = m_compiler->gtNewOperNode(oper, TYP_INT, hiOp, rotateByHi);
- m_compiler->lvaIncRefCnts(loCopy);
- m_compiler->lvaIncRefCnts(hiCopy);
-
Range().InsertBefore(tree, hiCopy, loOp1, loOp);
Range().InsertBefore(tree, rotateByLo, loResult);
Range().InsertBefore(tree, loCopy, hiOp1, hiOp);
diff --git a/src/jit/earlyprop.cpp b/src/jit/earlyprop.cpp
index f97c0ac448..325f85df55 100644
--- a/src/jit/earlyprop.cpp
+++ b/src/jit/earlyprop.cpp
@@ -361,10 +361,8 @@ GenTree* Compiler::optEarlyPropRewriteTree(GenTree* tree)
actualValClone->LabelIndex(this);
}
- DecLclVarRefCountsVisitor::WalkTree(this, tree);
// actualValClone has small tree node size, it is safe to use CopyFrom here.
tree->ReplaceWith(actualValClone, this);
- IncLclVarRefCountsVisitor::WalkTree(this, tree);
#ifdef DEBUG
if (verbose)
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp
index d98cf2f389..b06b16c527 100644
--- a/src/jit/flowgraph.cpp
+++ b/src/jit/flowgraph.cpp
@@ -9670,41 +9670,6 @@ void Compiler::fgSimpleLowering()
#endif
}
-/*****************************************************************************
- */
-
-void Compiler::fgUpdateRefCntForClone(BasicBlock* addedToBlock, GenTree* clonedTree)
-{
- assert(clonedTree->gtOper != GT_STMT);
-
- if (lvaLocalVarRefCounted())
- {
- compCurBB = addedToBlock;
- IncLclVarRefCountsVisitor::WalkTree(this, clonedTree);
- }
-}
-
-/*****************************************************************************
- */
-
-void Compiler::fgUpdateRefCntForExtract(GenTree* wholeTree, GenTree* keptTree)
-{
- if (lvaLocalVarRefCounted())
- {
- /* Update the refCnts of removed lcl vars - The problem is that
- * we have to consider back the side effects trees so we first
- * increment all refCnts for side effects then decrement everything
- * in the statement
- */
- if (keptTree)
- {
- IncLclVarRefCountsVisitor::WalkTree(this, keptTree);
- }
-
- DecLclVarRefCountsVisitor::WalkTree(this, wholeTree);
- }
-}
-
VARSET_VALRET_TP Compiler::fgGetVarBits(GenTree* tree)
{
VARSET_TP varBits(VarSetOps::MakeEmpty(this));
@@ -9875,14 +9840,10 @@ void Compiler::fgRemoveEmptyBlocks()
/*****************************************************************************
*
* Remove a useless statement from a basic block.
- * The default is to decrement ref counts of included vars
*
*/
-void Compiler::fgRemoveStmt(BasicBlock* block,
- GenTree* node,
- // whether to decrement ref counts for tracked vars in statement
- bool updateRefCount)
+void Compiler::fgRemoveStmt(BasicBlock* block, GenTree* node)
{
noway_assert(node);
assert(fgOrder == FGOrderTree);
@@ -9940,14 +9901,6 @@ void Compiler::fgRemoveStmt(BasicBlock* block,
noway_assert(!optValnumCSE_phase);
- if (updateRefCount)
- {
- if (fgStmtListThreaded)
- {
- DecLclVarRefCountsVisitor::WalkTree(this, stmt->gtStmtExpr);
- }
- }
-
fgStmtRemoved = true;
#ifdef DEBUG
@@ -14142,9 +14095,7 @@ bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block)
if (fgStmtListThreaded)
{
- /* Update the lclvar ref counts */
compCurBB = block;
- fgUpdateRefCntForExtract(switchTree, sideEffList);
/* Update ordering, costs, FP levels, etc. */
gtSetStmtInfo(switchStmt);
@@ -14553,9 +14504,7 @@ bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, Basi
if (fgStmtListThreaded)
{
- /* Update the lclvar ref counts */
compCurBB = block;
- fgUpdateRefCntForExtract(cond->gtStmtExpr, sideEffList);
/* Update ordering, costs, FP levels, etc. */
gtSetStmtInfo(cond);
@@ -14836,9 +14785,6 @@ bool Compiler::fgOptimizeBranch(BasicBlock* bJump)
return false;
}
- // Bump up the ref-counts of any variables in 'stmt'
- fgUpdateRefCntForClone(bJump, stmt->gtStmtExpr);
-
//
// Find the last statement in the bJump block
//
diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp
index c3ce836da4..5a5d2e1a3c 100644
--- a/src/jit/gentree.cpp
+++ b/src/jit/gentree.cpp
@@ -12017,9 +12017,6 @@ GenTree* Compiler::gtFoldExpr(GenTree* tree)
GenTree* sideEffList = nullptr;
gtExtractSideEffList(op1, &sideEffList);
- fgUpdateRefCntForExtract(op1, sideEffList); // Decrement refcounts for op1, Keeping any side-effects
- fgUpdateRefCntForExtract(colon_op1, nullptr); // Decrement refcounts for colon_op1
-
// Clear colon flags only if the qmark itself is not conditionaly executed
if ((tree->gtFlags & GTF_COLON_COND) == 0)
{
@@ -12230,10 +12227,7 @@ GenTree* Compiler::gtFoldExprCompare(GenTree* tree)
cons->gtNext = tree->gtNext;
cons->gtPrev = tree->gtPrev;
}
- if (lvaLocalVarRefCounted())
- {
- lvaRecursiveDecRefCounts(tree);
- }
+
return cons;
}
@@ -12671,10 +12665,6 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
/* Multiply by zero - return the 'zero' node, but not if side effects */
if (!(op->gtFlags & GTF_SIDE_EFFECT))
{
- if (lvaLocalVarRefCounted())
- {
- lvaRecursiveDecRefCounts(op);
- }
op = cons;
goto DONE_FOLD;
}
@@ -12703,10 +12693,6 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
if (!(op->gtFlags & GTF_SIDE_EFFECT))
{
- if (lvaLocalVarRefCounted())
- {
- lvaRecursiveDecRefCounts(op);
- }
op = cons;
goto DONE_FOLD;
}
@@ -12743,10 +12729,6 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
if (!(op->gtFlags & GTF_SIDE_EFFECT))
{
- if (lvaLocalVarRefCounted())
- {
- lvaRecursiveDecRefCounts(op);
- }
op = cons;
goto DONE_FOLD;
}
@@ -12766,10 +12748,6 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
}
else if (!(op->gtFlags & GTF_SIDE_EFFECT))
{
- if (lvaLocalVarRefCounted())
- {
- lvaRecursiveDecRefCounts(op);
- }
op = cons;
goto DONE_FOLD;
}
@@ -12794,10 +12772,6 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
op = op2->AsColon()->ElseNode();
opToDelete = op2->AsColon()->ThenNode();
}
- if (lvaLocalVarRefCounted())
- {
- lvaRecursiveDecRefCounts(opToDelete);
- }
// Clear colon flags only if the qmark itself is not conditionaly executed
if ((tree->gtFlags & GTF_COLON_COND) == 0)
diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp
index 324896b1ad..5f51739cf1 100644
--- a/src/jit/lclvars.cpp
+++ b/src/jit/lclvars.cpp
@@ -41,7 +41,6 @@ void Compiler::lvaInit()
lvaTrackedToVarNum = nullptr;
- lvaSortAgain = false; // false: We don't need to call lvaSortOnly()
lvaTrackedFixed = false; // false: We can still add new tracked variables
lvaDoneFrameLayout = NO_FRAME_LAYOUT;
@@ -2798,188 +2797,6 @@ BasicBlock::weight_t BasicBlock::getBBWeight(Compiler* comp)
}
}
-// Decrement the ref counts for all locals contained in the tree and its children.
-void Compiler::lvaRecursiveDecRefCounts(GenTree* tree)
-{
- assert(lvaLocalVarRefCounted());
-
- // We could just use the recursive walker for all cases but that is a
- // fairly heavyweight thing to spin up when we're usually just handling a leaf.
- if (tree->OperIsLeaf())
- {
- if (tree->OperIsLocal())
- {
- lvaDecRefCnts(tree);
- }
- }
- else
- {
- DecLclVarRefCountsVisitor::WalkTree(this, tree);
- }
-}
-
-DecLclVarRefCountsVisitor::DecLclVarRefCountsVisitor(Compiler* compiler)
- : GenTreeVisitor<DecLclVarRefCountsVisitor>(compiler)
-{
-}
-
-Compiler::fgWalkResult DecLclVarRefCountsVisitor::PreOrderVisit(GenTree** use, GenTree* user)
-{
- m_compiler->lvaDecRefCnts(*use);
- return fgWalkResult::WALK_CONTINUE;
-}
-
-Compiler::fgWalkResult DecLclVarRefCountsVisitor::WalkTree(Compiler* compiler, GenTree* tree)
-{
- DecLclVarRefCountsVisitor visitor(compiler);
- return static_cast<GenTreeVisitor<DecLclVarRefCountsVisitor>*>(&visitor)->WalkTree(&tree, nullptr);
-}
-
-/*****************************************************************************
- *
- * Helper passed to the tree walker to decrement the refCnts for
- * all local variables in an expression
- */
-void Compiler::lvaDecRefCnts(GenTree* tree)
-{
- assert(compCurBB != nullptr);
- lvaDecRefCnts(compCurBB, tree);
-}
-
-void Compiler::lvaDecRefCnts(BasicBlock* block, GenTree* tree)
-{
- assert(block != nullptr);
- assert(tree != nullptr);
-
- unsigned lclNum;
- LclVarDsc* varDsc;
-
- noway_assert(lvaLocalVarRefCounted());
-
- if ((tree->gtOper == GT_CALL) && (tree->gtFlags & GTF_CALL_UNMANAGED))
- {
- assert((!opts.ShouldUsePInvokeHelpers()) || (info.compLvFrameListRoot == BAD_VAR_NUM));
- if (!opts.ShouldUsePInvokeHelpers())
- {
- /* Get the special variable descriptor */
-
- lclNum = info.compLvFrameListRoot;
-
- assert(lclNum <= lvaCount);
- varDsc = lvaTable + lclNum;
-
- /* Decrement the reference counts twice */
-
- varDsc->decRefCnts(block->getBBWeight(this), this);
- varDsc->decRefCnts(block->getBBWeight(this), this);
- }
- }
- else
- {
- /* This must be a local variable */
-
- noway_assert(tree->OperIsLocal());
-
- /* Get the variable descriptor */
-
- lclNum = tree->gtLclVarCommon.gtLclNum;
-
- assert(lclNum < lvaCount);
- varDsc = lvaTable + lclNum;
-
- /* Decrement its lvRefCnt and lvRefCntWtd */
-
- varDsc->decRefCnts(block->getBBWeight(this), this);
- }
-}
-
-// Increment the ref counts for all locals contained in the tree and its children.
-void Compiler::lvaRecursiveIncRefCounts(GenTree* tree)
-{
- assert(lvaLocalVarRefCounted());
-
- // We could just use the recursive walker for all cases but that is a
- // fairly heavyweight thing to spin up when we're usually just handling a leaf.
- if (tree->OperIsLeaf())
- {
- if (tree->OperIsLocal())
- {
- lvaIncRefCnts(tree);
- }
- }
- else
- {
- IncLclVarRefCountsVisitor::WalkTree(this, tree);
- }
-}
-
-IncLclVarRefCountsVisitor::IncLclVarRefCountsVisitor(Compiler* compiler)
- : GenTreeVisitor<IncLclVarRefCountsVisitor>(compiler)
-{
-}
-
-Compiler::fgWalkResult IncLclVarRefCountsVisitor::PreOrderVisit(GenTree** use, GenTree* user)
-{
- m_compiler->lvaIncRefCnts(*use);
- return fgWalkResult::WALK_CONTINUE;
-}
-
-Compiler::fgWalkResult IncLclVarRefCountsVisitor::WalkTree(Compiler* compiler, GenTree* tree)
-{
- IncLclVarRefCountsVisitor visitor(compiler);
- return static_cast<GenTreeVisitor<IncLclVarRefCountsVisitor>*>(&visitor)->WalkTree(&tree, nullptr);
-}
-
-/*****************************************************************************
- *
- * Helper passed to the tree walker to increment the refCnts for
- * all local variables in an expression
- */
-void Compiler::lvaIncRefCnts(GenTree* tree)
-{
- unsigned lclNum;
- LclVarDsc* varDsc;
-
- noway_assert(lvaLocalVarRefCounted());
-
- if ((tree->gtOper == GT_CALL) && (tree->gtFlags & GTF_CALL_UNMANAGED))
- {
- assert((!opts.ShouldUsePInvokeHelpers()) || (info.compLvFrameListRoot == BAD_VAR_NUM));
- if (!opts.ShouldUsePInvokeHelpers())
- {
- /* Get the special variable descriptor */
-
- lclNum = info.compLvFrameListRoot;
-
- assert(lclNum <= lvaCount);
- varDsc = lvaTable + lclNum;
-
- /* Increment the reference counts twice */
-
- varDsc->incRefCnts(compCurBB->getBBWeight(this), this);
- varDsc->incRefCnts(compCurBB->getBBWeight(this), this);
- }
- }
- else
- {
- /* This must be a local variable */
-
- noway_assert(tree->gtOper == GT_LCL_VAR || tree->gtOper == GT_LCL_FLD || tree->gtOper == GT_STORE_LCL_VAR ||
- tree->gtOper == GT_STORE_LCL_FLD);
-
- /* Get the variable descriptor */
-
- lclNum = tree->gtLclVarCommon.gtLclNum;
-
- assert(lclNum < lvaCount);
- varDsc = lvaTable + lclNum;
-
- /* Increment its lvRefCnt and lvRefCntWtd */
-
- varDsc->incRefCnts(compCurBB->getBBWeight(this), this);
- }
-}
-
/*****************************************************************************
*
* Compare function passed to qsort() by Compiler::lclVars.lvaSortByRefCount().
@@ -3239,9 +3056,6 @@ void Compiler::lvaSortOnly()
/* Now sort the variable table by ref-count */
qsort(lvaRefSorted, lvaCount, sizeof(*lvaRefSorted), (compCodeOpt() == SMALL_CODE) ? RefCntCmp : WtdRefCntCmp);
-
- lvaSortAgain = false;
-
lvaDumpRefCounts();
}
@@ -3311,24 +3125,6 @@ void Compiler::lvaSortByRefCount()
*refTab++ = varDsc;
- /* If we have JMP, all arguments must have a location
- * even if we don't use them inside the method */
-
- if (compJmpOpUsed && varDsc->lvIsParam)
- {
- /* ...except when we have varargs and the argument is
- passed on the stack. In that case, it's important
- for the ref count to be zero, so that we don't attempt
- to track them for GC info (which is not possible since we
- don't know their offset in the stack). See the assert at the
- end of raMarkStkVars and bug #28949 for more info. */
-
- if (!raIsVarargsStackArg(lclNum))
- {
- varDsc->incRefCnts(1, this);
- }
- }
-
/* For now assume we'll be able to track all locals */
varDsc->lvTracked = 1;
@@ -4080,6 +3876,7 @@ void Compiler::lvaMarkLocalVars()
void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers)
{
+ JITDUMP("\n*** lvaComputeRefCounts ***\n");
unsigned lclNum = 0;
LclVarDsc* varDsc = nullptr;
@@ -4093,11 +3890,8 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers)
{
#if defined(DEBUG)
- // All local vars should be marked as implicitly referenced.
- //
- // This happens today for temps introduced after lvMarkRefs via
- // incremental ref count updates. If/when we remove that we'll need
- // to do something else to ensure late temps are considered.
+ // All local vars should be marked as implicitly referenced
+ // and not tracked.
for (lclNum = 0, varDsc = lvaTable; lclNum < lvaCount; lclNum++, varDsc++)
{
const bool isSpecialVarargsParam = varDsc->lvIsParam && raIsVarargsStackArg(lclNum);
@@ -4110,6 +3904,8 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers)
{
assert(varDsc->lvImplicitlyReferenced);
}
+
+ assert(!varDsc->lvTracked);
}
#endif // defined (DEBUG)
@@ -4168,6 +3964,8 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers)
}
}
+ JITDUMP("\n*** lvaComputeRefCounts -- explicit counts ***\n");
+
// Second, account for all explicit local variable references
for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
{
@@ -4203,6 +4001,8 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers)
}
}
+ JITDUMP("\n*** lvaComputeRefCounts -- implicit counts ***\n");
+
// Third, bump ref counts for some implicit prolog references
for (lclNum = 0, varDsc = lvaTable; lclNum < lvaCount; lclNum++, varDsc++)
{
@@ -4225,6 +4025,22 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers)
varDsc->incRefCnts(BB_UNITY_WEIGHT, this);
}
}
+
+ // If we have JMP, all arguments must have a location
+ // even if we don't use them inside the method
+ if (compJmpOpUsed && varDsc->lvIsParam && (varDsc->lvRefCnt() == 0))
+ {
+ // except when we have varargs and the argument is
+ // passed on the stack. In that case, it's important
+ // for the ref count to be zero, so that we don't attempt
+ // to track them for GC info (which is not possible since we
+ // don't know their offset in the stack). See the assert at the
+ // end of raMarkStkVars and bug #28949 for more info.
+ if (!raIsVarargsStackArg(lclNum))
+ {
+ varDsc->lvImplicitlyReferenced = 1;
+ }
+ }
}
}
diff --git a/src/jit/lir.cpp b/src/jit/lir.cpp
index 0ba18a2d6d..480a5d3e95 100644
--- a/src/jit/lir.cpp
+++ b/src/jit/lir.cpp
@@ -265,10 +265,6 @@ unsigned LIR::Use::ReplaceWithLclVar(Compiler* compiler, unsigned blockWeight, u
lclNum = compiler->lvaGrabTemp(true DEBUGARG("ReplaceWithLclVar is creating a new local variable"));
}
- // Increment its lvRefCnt and lvRefCntWtd twice, one for the def and one for the use
- compiler->lvaTable[lclNum].incRefCnts(blockWeight, compiler);
- compiler->lvaTable[lclNum].incRefCnts(blockWeight, compiler);
-
GenTreeLclVar* const store = compiler->gtNewTempAssign(lclNum, node)->AsLclVar();
assert(store != nullptr);
assert(store->gtOp1 == node);
@@ -1083,8 +1079,7 @@ LIR::Range LIR::Range::Remove(ReadOnlyRange&& range)
// LIR::Range::Delete: Deletes a node from this range.
//
// Note that the deleted node must not be used after this function has
-// been called. If the deleted node is part of a block, this function also
-// calls `Compiler::lvaDecRefCnts` as necessary.
+// been called.
//
// Arguments:
// node - The node to delete. Must be part of this range.
@@ -1097,16 +1092,6 @@ void LIR::Range::Delete(Compiler* compiler, BasicBlock* block, GenTree* node)
assert((block == nullptr) == (compiler == nullptr));
Remove(node);
-
- if (block != nullptr)
- {
- if (((node->OperGet() == GT_CALL) && ((node->gtFlags & GTF_CALL_UNMANAGED) != 0)) ||
- (node->OperIsLocal() && !node->IsPhiNode()))
- {
- compiler->lvaDecRefCnts(block, node);
- }
- }
-
DEBUG_DESTROY_NODE(node);
}
@@ -1115,8 +1100,7 @@ void LIR::Range::Delete(Compiler* compiler, BasicBlock* block, GenTree* node)
//
// Both the start and the end of the subrange must be part of this range.
// Note that the deleted nodes must not be used after this function has
-// been called. If the deleted nodes are part of a block, this function
-// also calls `Compiler::lvaDecRefCnts` as necessary.
+// been called.
//
// Arguments:
// firstNode - The first node in the subrange.
@@ -1134,18 +1118,6 @@ void LIR::Range::Delete(Compiler* compiler, BasicBlock* block, GenTree* firstNod
assert(lastNode->gtNext == nullptr);
- if (block != nullptr)
- {
- for (GenTree* node = firstNode; node != nullptr; node = node->gtNext)
- {
- if (((node->OperGet() == GT_CALL) && ((node->gtFlags & GTF_CALL_UNMANAGED) != 0)) ||
- (node->OperIsLocal() && !node->IsPhiNode()))
- {
- compiler->lvaDecRefCnts(block, node);
- }
- }
- }
-
#ifdef DEBUG
// We can't do this in the loop above because it causes `IsPhiNode` to return a false negative
// for `GT_STORE_LCL_VAR` nodes that participate in phi definitions.
@@ -1161,8 +1133,7 @@ void LIR::Range::Delete(Compiler* compiler, BasicBlock* block, GenTree* firstNod
//
// Both the start and the end of the subrange must be part of this range.
// Note that the deleted nodes must not be used after this function has
-// been called. If the deleted nodes are part of a block, this function
-// also calls `Compiler::lvaDecRefCnts` as necessary.
+// been called.
//
// Arguments:
// range - The subrange to delete.
diff --git a/src/jit/liveness.cpp b/src/jit/liveness.cpp
index 9f8910f1e3..c749152da3 100644
--- a/src/jit/liveness.cpp
+++ b/src/jit/liveness.cpp
@@ -134,7 +134,6 @@ void Compiler::fgLocalVarLiveness()
// Init liveness data structures.
fgLocalVarLivenessInit();
- assert(lvaSortAgain == false); // Set to false by lvaSortOnly()
EndPhase(PHASE_LCLVARLIVENESS_INIT);
@@ -157,25 +156,18 @@ void Compiler::fgLocalVarLiveness()
fgInterBlockLocalVarLiveness();
} while (fgStmtRemoved && fgLocalVarLivenessChanged);
- // If we removed any dead code we will have set 'lvaSortAgain' via decRefCnts
- if (lvaSortAgain)
- {
- JITDUMP("In fgLocalVarLiveness, setting lvaSortAgain back to false (set during dead-code removal)\n");
- lvaSortAgain = false; // We don't re-Sort because we just performed LclVar liveness.
- }
-
EndPhase(PHASE_LCLVARLIVENESS_INTERBLOCK);
}
/*****************************************************************************/
void Compiler::fgLocalVarLivenessInit()
{
- // If necessary, re-sort the variable table by ref-count...before creating any varsets using this sorting.
- if (lvaSortAgain)
+ JITDUMP("In fgLocalVarLivenessInit\n");
+
+ // Sort locals first, if we're optimizing
+ if (!opts.MinOpts() && !opts.compDbgCode)
{
- JITDUMP("In fgLocalVarLivenessInit, sorting locals\n");
lvaSortByRefCount();
- assert(lvaSortAgain == false); // Set to false by lvaSortOnly()
}
// We mark a lcl as must-init in a first pass of local variable
@@ -1025,10 +1017,7 @@ void Compiler::fgExtendDbgLifetimes()
{
printf("Created zero-init of V%02u in BB%02u\n", varNum, block->bbNum);
}
-#endif // DEBUG
-
- varDsc->incRefCnts(block->getBBWeight(this), this);
-
+#endif // DEBUG
block->bbFlags |= BBF_CHANGED; // indicates that the contents of the block have changed.
}
@@ -1888,8 +1877,6 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR
// Remove the store. DCE will iteratively clean up any ununsed operands.
lclVarNode->gtOp1->SetUnusedValue();
- lvaDecRefCnts(block, node);
-
// If the store is marked as a late argument, it is referenced by a call. Instead of removing
// it, bash it to a NOP.
if ((node->gtFlags & GTF_LATE_ARG) != 0)
@@ -2192,7 +2179,6 @@ bool Compiler::fgRemoveDeadStore(GenTree** pTree,
printf("\n");
}
#endif // DEBUG
- fgUpdateRefCntForExtract(asgNode, sideEffList);
/* Replace the assignment statement with the list of side effects */
noway_assert(sideEffList->gtOper != GT_STMT);
@@ -2285,7 +2271,6 @@ bool Compiler::fgRemoveDeadStore(GenTree** pTree,
#endif // DEBUG
if (sideEffList->gtOper == asgNode->gtOper)
{
- fgUpdateRefCntForExtract(asgNode, sideEffList);
#ifdef DEBUG
*treeModf = true;
#endif // DEBUG
@@ -2295,7 +2280,6 @@ bool Compiler::fgRemoveDeadStore(GenTree** pTree,
}
else
{
- fgUpdateRefCntForExtract(asgNode, sideEffList);
#ifdef DEBUG
*treeModf = true;
#endif // DEBUG
@@ -2330,11 +2314,7 @@ bool Compiler::fgRemoveDeadStore(GenTree** pTree,
printf("\n");
}
#endif // DEBUG
- /* No side effects - Remove the interior statement */
- fgUpdateRefCntForExtract(asgNode, nullptr);
-
- /* Change the assignment to a GT_NOP node */
-
+ /* No side effects - Change the assignment to a GT_NOP node */
asgNode->gtBashToNOP();
#ifdef DEBUG
diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp
index 13780ca188..4098c6e826 100644
--- a/src/jit/lower.cpp
+++ b/src/jit/lower.cpp
@@ -480,9 +480,7 @@ GenTree* Lowering::LowerSwitch(GenTree* node)
GenTree* rhs = node->gtOp.gtOp1;
unsigned lclNum = comp->lvaGrabTemp(true DEBUGARG("Lowering is creating a new local variable"));
- comp->lvaSortAgain = true;
comp->lvaTable[lclNum].lvType = rhs->TypeGet();
- comp->lvaTable[lclNum].setLvRefCnt(1);
GenTreeLclVar* store =
new (comp, GT_STORE_LCL_VAR) GenTreeLclVar(GT_STORE_LCL_VAR, rhs->TypeGet(), lclNum, BAD_IL_OFFSET);
@@ -549,9 +547,6 @@ GenTree* Lowering::LowerSwitch(GenTree* node)
// is now less than zero 0 (that would also hit the default case).
gtDefaultCaseCond->gtFlags |= GTF_UNSIGNED;
- /* Increment the lvRefCnt and lvRefCntWtd for temp */
- tempVarDsc->incRefCnts(blockWeight, comp);
-
GenTree* gtDefaultCaseJump = comp->gtNewOperNode(GT_JTRUE, TYP_VOID, gtDefaultCaseCond);
gtDefaultCaseJump->gtFlags = node->gtFlags;
@@ -724,9 +719,6 @@ GenTree* Lowering::LowerSwitch(GenTree* node)
// |____ (ICon) (The actual case constant)
GenTree* gtCaseCond = comp->gtNewOperNode(GT_EQ, TYP_INT, comp->gtNewLclvNode(tempLclNum, tempLclType),
comp->gtNewIconNode(i, tempLclType));
- /* Increment the lvRefCnt and lvRefCntWtd for temp */
- tempVarDsc->incRefCnts(blockWeight, comp);
-
GenTree* gtCaseBranch = comp->gtNewOperNode(GT_JTRUE, TYP_VOID, gtCaseCond);
LIR::Range caseRange = LIR::SeqTree(comp, gtCaseBranch);
currentBBRange->InsertAtEnd(std::move(caseRange));
@@ -761,7 +753,6 @@ GenTree* Lowering::LowerSwitch(GenTree* node)
// switch variants need the switch value so create the necessary LclVar node here.
GenTree* switchValue = comp->gtNewLclvNode(tempLclNum, tempLclType);
LIR::Range& switchBlockRange = LIR::AsRange(afterDefaultCondBlock);
- tempVarDsc->incRefCnts(blockWeight, comp);
switchBlockRange.InsertAtEnd(switchValue);
// Try generating a bit test based switch first,
@@ -2055,9 +2046,7 @@ void Lowering::LowerFastTailCall(GenTreeCall* call)
tmpLclNum = comp->lvaGrabTemp(
true DEBUGARG("Fast tail call lowering is creating a new local variable"));
- comp->lvaSortAgain = true;
- comp->lvaTable[tmpLclNum].lvType = tmpType;
- comp->lvaTable[tmpLclNum].setLvRefCnt(1);
+ comp->lvaTable[tmpLclNum].lvType = tmpType;
comp->lvaTable[tmpLclNum].lvDoNotEnregister = comp->lvaTable[lcl->gtLclNum].lvDoNotEnregister;
}
@@ -2472,11 +2461,6 @@ GenTree* Lowering::DecomposeLongCompare(GenTree* cmp)
if (loSrc1->OperIs(GT_CNS_INT, GT_LCL_VAR, GT_LCL_FLD))
{
BlockRange().Remove(loSrc1);
-
- if (loSrc1->OperIs(GT_LCL_VAR, GT_LCL_FLD))
- {
- comp->lvaDecRefCnts(m_block, loSrc1);
- }
}
else
{
@@ -3953,9 +3937,6 @@ GenTree* Lowering::LowerVirtualVtableCall(GenTreeCall* call)
lclNum = vtableCallTemp;
}
- // We'll introduce another use of this local so increase its ref count.
- comp->lvaTable[lclNum].incRefCnts(comp->compCurBB->getBBWeight(comp), comp);
-
// Get hold of the vtable offset (note: this might be expensive)
unsigned vtabOffsOfIndirection;
unsigned vtabOffsAfterIndirection;
@@ -4001,11 +3982,8 @@ GenTree* Lowering::LowerVirtualVtableCall(GenTreeCall* call)
// tmp2 = tmp1 + vtabOffsOfIndirection + vtabOffsAfterIndirection + [tmp1 + vtabOffsOfIndirection]
// result = tmp2 + [tmp2]
//
- unsigned lclNumTmp = comp->lvaGrabTemp(true DEBUGARG("lclNumTmp"));
- comp->lvaTable[lclNumTmp].incRefCnts(comp->compCurBB->getBBWeight(comp), comp);
-
+ unsigned lclNumTmp = comp->lvaGrabTemp(true DEBUGARG("lclNumTmp"));
unsigned lclNumTmp2 = comp->lvaGrabTemp(true DEBUGARG("lclNumTmp2"));
- comp->lvaTable[lclNumTmp2].incRefCnts(comp->compCurBB->getBBWeight(comp), comp);
GenTree* lclvNodeStore = comp->gtNewTempAssign(lclNumTmp, result);
@@ -4598,7 +4576,6 @@ bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)
GenTree* dividend = comp->gtNewLclvNode(dividendLclNum, type);
GenTree* sub = comp->gtNewOperNode(GT_SUB, type, dividend, mulhi);
BlockRange().InsertBefore(divMod, dividend, sub);
- comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp);
GenTree* one = comp->gtNewIconNode(1, TYP_INT);
GenTree* rsz = comp->gtNewOperNode(GT_RSZ, type, sub, one);
@@ -4610,7 +4587,6 @@ bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)
GenTree* mulhiCopy = comp->gtNewLclvNode(mulhiLclNum, type);
GenTree* add = comp->gtNewOperNode(GT_ADD, type, rsz, mulhiCopy);
BlockRange().InsertBefore(divMod, mulhiCopy, add);
- comp->lvaTable[mulhiLclNum].incRefCnts(curBBWeight, comp);
mulhi = add;
shift -= 1;
@@ -4639,7 +4615,6 @@ bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)
divMod->gtOp2 = mul;
BlockRange().InsertBefore(divMod, div, divisor, mul, dividend);
- comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp);
}
ContainCheckRange(firstNode, divMod);
@@ -4783,8 +4758,6 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
if (requiresAddSubAdjust)
{
dividend = comp->gtNewLclvNode(dividendLclNum, type);
- comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp);
-
adjusted = comp->gtNewOperNode(divisorValue > 0 ? GT_ADD : GT_SUB, type, mulhi, dividend);
BlockRange().InsertBefore(divMod, dividend, adjusted);
}
@@ -4800,7 +4773,6 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
LIR::Use adjustedUse(BlockRange(), &signBit->gtOp.gtOp1, signBit);
unsigned adjustedLclNum = ReplaceWithLclVar(adjustedUse);
adjusted = comp->gtNewLclvNode(adjustedLclNum, type);
- comp->lvaTable[adjustedLclNum].incRefCnts(curBBWeight, comp);
BlockRange().InsertBefore(divMod, adjusted);
if (requiresShiftAdjust)
@@ -4821,7 +4793,6 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
GenTree* div = comp->gtNewOperNode(GT_ADD, type, adjusted, signBit);
dividend = comp->gtNewLclvNode(dividendLclNum, type);
- comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp);
// divisor % dividend = dividend - divisor x div
GenTree* divisor = comp->gtNewIconNode(divisorValue, type);
@@ -4878,8 +4849,6 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
GenTree* adjustedDividend =
comp->gtNewOperNode(GT_ADD, type, adjustment, comp->gtNewLclvNode(dividendLclNum, type));
- comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp);
-
GenTree* newDivMod;
if (isDiv)
@@ -4907,8 +4876,6 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
newDivMod = comp->gtNewOperNode(GT_SUB, type, comp->gtNewLclvNode(dividendLclNum, type),
comp->gtNewOperNode(GT_AND, type, adjustedDividend, divisor));
ContainCheckBinary(newDivMod->AsOp());
-
- comp->lvaTable[dividendLclNum].incRefCnts(curBBWeight, comp);
}
// Remove the divisor and dividend nodes from the linear order,
@@ -5141,7 +5108,6 @@ GenTree* Lowering::LowerArrElem(GenTree* node)
else
{
idxArrObjNode = comp->gtClone(arrObjNode);
- varDsc->incRefCnts(blockWeight, comp);
BlockRange().InsertBefore(insertionPoint, idxArrObjNode);
}
@@ -5152,7 +5118,6 @@ GenTree* Lowering::LowerArrElem(GenTree* node)
BlockRange().InsertBefore(insertionPoint, arrMDIdx);
GenTree* offsArrObjNode = comp->gtClone(arrObjNode);
- varDsc->incRefCnts(blockWeight, comp);
BlockRange().InsertBefore(insertionPoint, offsArrObjNode);
GenTreeArrOffs* arrOffs =
@@ -5182,7 +5147,6 @@ GenTree* Lowering::LowerArrElem(GenTree* node)
}
GenTree* leaBase = comp->gtClone(arrObjNode);
- varDsc->incRefCnts(blockWeight, comp);
BlockRange().InsertBefore(insertionPoint, leaBase);
GenTree* leaNode = new (comp, GT_LEA) GenTreeAddrMode(arrElem->TypeGet(), leaBase, leaIndexNode, scale, offset);
@@ -5249,40 +5213,32 @@ void Lowering::DoPhase()
}
#endif
- // Recompute local var ref counts before potentially sorting.
+ // Recompute local var ref counts before potentially sorting for liveness.
// Note this does minimal work in cases where we are not going to sort.
const bool isRecompute = true;
const bool setSlotNumbers = false;
comp->lvaComputeRefCounts(isRecompute, setSlotNumbers);
- // TODO-Throughput: We re-sort local variables to get the goodness of enregistering recently
- // introduced local variables both by Rationalize and Lower; downside is we need to
- // recompute standard local variable liveness in order to get Linear CodeGen working.
- // For now we'll take the throughput hit of recomputing local liveness but in the long term
- // we're striving to use the unified liveness computation (fgLocalVarLiveness) and stop
- // computing it separately in LSRA.
- if ((comp->lvaCount != 0) && comp->backendRequiresLocalVarLifetimes())
- {
- comp->lvaSortAgain = true;
- }
- comp->EndPhase(PHASE_LOWERING_DECOMP);
-
comp->fgLocalVarLiveness();
// local var liveness can delete code, which may create empty blocks
if (!comp->opts.MinOpts() && !comp->opts.compDbgCode)
{
comp->optLoopsMarked = false;
bool modified = comp->fgUpdateFlowGraph();
- if (modified || comp->lvaSortAgain)
+ if (modified)
{
JITDUMP("had to run another liveness pass:\n");
comp->fgLocalVarLiveness();
}
}
+ // Recompute local var ref counts again after liveness to reflect
+ // impact of any dead code removal. Note this may leave us with
+ // tracked vars that have zero refs.
+ comp->lvaComputeRefCounts(isRecompute, setSlotNumbers);
+
#ifdef DEBUG
JITDUMP("Liveness pass finished after lowering, IR:\n");
- JITDUMP("lvasortagain = %d\n", comp->lvaSortAgain);
if (VERBOSE)
{
comp->fgDispBasicBlocks(true);
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 7c093c4b46..83707b0a2f 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -2333,18 +2333,9 @@ void fgArgInfo::EvalArgsToTemps()
{
setupArg = compiler->gtNewTempAssign(tmpVarNum, argx);
- LclVarDsc* varDsc = compiler->lvaTable + tmpVarNum;
-
- if (compiler->fgOrder == Compiler::FGOrderLinear)
- {
- // We'll reference this temporary variable just once
- // when we perform the function call after
- // setting up this argument.
- varDsc->setLvRefCnt(1);
- }
-
- var_types lclVarType = genActualType(argx->gtType);
- var_types scalarType = TYP_UNKNOWN;
+ LclVarDsc* varDsc = compiler->lvaTable + tmpVarNum;
+ var_types lclVarType = genActualType(argx->gtType);
+ var_types scalarType = TYP_UNKNOWN;
if (setupArg->OperIsCopyBlkOp())
{
@@ -2628,28 +2619,11 @@ GenTree* Compiler::fgMakeMultiUse(GenTree** pOp)
GenTree* tree = *pOp;
if (tree->IsLocal())
{
- auto result = gtClone(tree);
- if (lvaLocalVarRefCounted())
- {
- lvaTable[tree->gtLclVarCommon.gtLclNum].incRefCnts(compCurBB->getBBWeight(this), this);
- }
- return result;
+ return gtClone(tree);
}
else
{
- GenTree* result = fgInsertCommaFormTemp(pOp);
-
- // At this point, *pOp is GT_COMMA(GT_ASG(V01, *pOp), V01) and result = V01
- // Therefore, the ref count has to be incremented 3 times for *pOp and result, if result will
- // be added by the caller.
- if (lvaLocalVarRefCounted())
- {
- lvaTable[result->gtLclVarCommon.gtLclNum].incRefCnts(compCurBB->getBBWeight(this), this);
- lvaTable[result->gtLclVarCommon.gtLclNum].incRefCnts(compCurBB->getBBWeight(this), this);
- lvaTable[result->gtLclVarCommon.gtLclNum].incRefCnts(compCurBB->getBBWeight(this), this);
- }
-
- return result;
+ return fgInsertCommaFormTemp(pOp);
}
}
@@ -5913,13 +5887,6 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree)
bndsChk = arrBndsChk;
- // Make sure to increment ref-counts if already ref-counted.
- if (lvaLocalVarRefCounted())
- {
- lvaRecursiveIncRefCounts(index);
- lvaRecursiveIncRefCounts(arrRef);
- }
-
// Now we'll switch to using the second copies for arrRef and index
// to compute the address expression
@@ -12576,21 +12543,6 @@ DONE_MORPHING_CHILDREN:
DEBUG_DESTROY_NODE(asg->gtOp.gtOp1);
DEBUG_DESTROY_NODE(lcl);
-
- /* This local variable should never be used again */
- // <BUGNUM>
- // VSW 184221: Make RefCnt to zero to indicate that this local var
- // is not used any more. (Keey the lvType as is.)
- // Otherwise lvOnFrame will be set to true in Compiler::raMarkStkVars
- // And then emitter::emitEndCodeGen will assert in the following line:
- // noway_assert( dsc->lvTracked);
- // </BUGNUM>
- noway_assert(varDsc->lvRefCnt() == 0 || // lvRefCnt may not have been set yet.
- varDsc->lvRefCnt() == 2 // Or, we assume this tmp should only be used here,
- // and it only shows up twice.
- );
- lvaTable[lclNum].setLvRefCnt(0);
- lvaTable[lclNum].lvaResetSortAgainFlag(this);
}
if (op1->OperIsCompare())
@@ -12599,9 +12551,9 @@ DONE_MORPHING_CHILDREN:
//
// EQ/NE -> RELOP/!RELOP
// / \ / \
- // RELOP CNS 0/1
+ // RELOP CNS 0/1
// / \
- //
+ //
// Note that we will remove/destroy the EQ/NE node and move
// the RELOP up into it's location.
@@ -13755,11 +13707,6 @@ DONE_MORPHING_CHILDREN:
}
else
{
- /* The left operand is worthless, throw it away */
- if (lvaLocalVarRefCounted())
- {
- lvaRecursiveDecRefCounts(op1);
- }
op2->gtFlags |= (tree->gtFlags & (GTF_DONT_CSE | GTF_LATE_ARG));
DEBUG_DESTROY_NODE(tree);
DEBUG_DESTROY_NODE(op1);
@@ -14328,21 +14275,11 @@ GenTree* Compiler::fgMorphModToSubMulDiv(GenTreeOp* tree)
{
numerator = fgMakeMultiUse(&tree->gtOp1);
}
- else if (lvaLocalVarRefCounted() && numerator->OperIsLocal())
- {
- // Morphing introduces new lclVar references. Increase ref counts
- lvaIncRefCnts(numerator);
- }
if (!denominator->OperIsLeaf())
{
denominator = fgMakeMultiUse(&tree->gtOp2);
}
- else if (lvaLocalVarRefCounted() && denominator->OperIsLocal())
- {
- // Morphing introduces new lclVar references. Increase ref counts
- lvaIncRefCnts(denominator);
- }
// The numerator and denominator may have been assigned to temps, in which case
// their defining assignments are in the current tree. Therefore, we need to
@@ -15698,12 +15635,6 @@ bool Compiler::fgMorphBlockStmt(BasicBlock* block, GenTreeStmt* stmt DEBUGARG(co
stmt->gtStmtExpr = morph;
- if (lvaLocalVarRefCounted())
- {
- // fgMorphTree may have introduced new lclVar references. Bump the ref counts if requested.
- lvaRecursiveIncRefCounts(stmt->gtStmtExpr);
- }
-
// Can the entire tree be removed?
bool removedStmt = false;
diff --git a/src/jit/optcse.cpp b/src/jit/optcse.cpp
index f389aa5bee..3abab600b1 100644
--- a/src/jit/optcse.cpp
+++ b/src/jit/optcse.cpp
@@ -283,28 +283,6 @@ Compiler::fgWalkResult Compiler::optUnmarkCSEs(GenTree** pTree, fgWalkData* data
// The call to optUnmarkCSE(tree) should have cleared any CSE info
//
assert(!IS_CSE_INDEX(tree->gtCSEnum));
-
- // This node is to be removed from the graph of GenTree*
- // next decrement any LclVar references.
- //
- if (tree->gtOper == GT_LCL_VAR)
- {
- unsigned lclNum;
- LclVarDsc* varDsc;
-
- // This variable ref is going away, decrease its ref counts
-
- lclNum = tree->gtLclVarCommon.gtLclNum;
- assert(lclNum < comp->lvaCount);
- varDsc = comp->lvaTable + lclNum;
-
- // make sure it's been initialized
- assert(comp->optCSEweight <= BB_MAX_WEIGHT);
-
- // Decrement its lvRefCnt and lvRefCntWtd
-
- varDsc->decRefCnts(comp->optCSEweight, comp);
- }
}
else // optUnmarkCSE(tree) returned false
{
@@ -2337,15 +2315,6 @@ public:
// cannot add any new exceptions
}
- // Increment ref count for the CSE ref
- m_pCompiler->lvaTable[cseLclVarNum].incRefCnts(blk->getBBWeight(m_pCompiler), m_pCompiler);
-
- if (isDef)
- {
- // Also increment ref count for the CSE assignment
- m_pCompiler->lvaTable[cseLclVarNum].incRefCnts(blk->getBBWeight(m_pCompiler), m_pCompiler);
- }
-
// Walk the statement 'stm' and find the pointer
// in the tree is pointing to 'exp'
//
@@ -2462,11 +2431,7 @@ public:
//
void Cleanup()
{
- if (m_addCSEcount > 0)
- {
- /* We've added new local variables to the lvaTable so note that we need to recreate the sorted table */
- m_pCompiler->lvaSortAgain = true;
- }
+ // Nothing to do, currently.
}
};
diff --git a/src/jit/optimizer.cpp b/src/jit/optimizer.cpp
index 9a1e015969..dbf13a3101 100644
--- a/src/jit/optimizer.cpp
+++ b/src/jit/optimizer.cpp
@@ -6225,16 +6225,10 @@ void Compiler::optPerformHoistExpr(GenTree* origExpr, unsigned lnum)
BasicBlock* preHead = optLoopTable[lnum].lpHead;
assert(preHead->bbJumpKind == BBJ_NONE);
- // fgMorphTree and lvaRecursiveIncRefCounts requires that compCurBB be the block that contains
+ // fgMorphTree requires that compCurBB be the block that contains
// (or in this case, will contain) the expression.
compCurBB = preHead;
-
- // Increment the ref counts of any local vars appearing in "hoist".
- // Note that we need to do this before fgMorphTree() as fgMorph() could constant
- // fold away some of the lcl vars referenced by "hoist".
- lvaRecursiveIncRefCounts(hoist);
-
- hoist = fgMorphTree(hoist);
+ hoist = fgMorphTree(hoist);
GenTree* hoistStmt = gtNewStmt(hoist);
hoistStmt->gtFlags |= GTF_STMT_CMPADD;
@@ -7937,32 +7931,6 @@ Compiler::fgWalkResult Compiler::optRemoveTreeVisitor(GenTree** pTree, fgWalkDat
}
}
- // This node is being removed from the graph of GenTree*
-
- // Look for any local variable references
-
- if (tree->gtOper == GT_LCL_VAR && comp->lvaLocalVarRefCounted())
- {
- unsigned lclNum;
- LclVarDsc* varDsc;
-
- /* This variable ref is going away, decrease its ref counts */
-
- lclNum = tree->gtLclVarCommon.gtLclNum;
- assert(lclNum < comp->lvaCount);
- varDsc = comp->lvaTable + lclNum;
-
- // make sure it's been initialized
- assert(comp->compCurBB != nullptr);
- assert(comp->compCurBB->bbWeight <= BB_MAX_WEIGHT);
-
- /* Decrement its lvRefCnt and lvRefCntWtd */
-
- // Use getBBWeight to determine the proper block weight.
- // This impacts the block weights when we have IBC data.
- varDsc->decRefCnts(comp->compCurBB->getBBWeight(comp), comp);
- }
-
return WALK_CONTINUE;
}
@@ -8784,10 +8752,6 @@ void Compiler::optOptimizeBoolsGcStress(BasicBlock* condBlock)
GenTree* comparandClone = gtCloneExpr(comparand);
- // Bump up the ref-counts of any variables in 'comparandClone'
- compCurBB = condBlock;
- IncLclVarRefCountsVisitor::WalkTree(this, comparandClone);
-
noway_assert(relop->gtOp.gtOp1 == comparand);
genTreeOps oper = compStressCompile(STRESS_OPT_BOOLS_GC, 50) ? GT_OR : GT_AND;
relop->gtOp.gtOp1 = gtNewOperNode(oper, TYP_I_IMPL, comparand, comparandClone);
diff --git a/src/jit/rationalize.cpp b/src/jit/rationalize.cpp
index 89e41679bb..cbbeaeaded 100644
--- a/src/jit/rationalize.cpp
+++ b/src/jit/rationalize.cpp
@@ -931,7 +931,6 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStack<G
{
if (use.IsDummyUse())
{
- comp->lvaDecRefCnts(node);
BlockRange().Remove(node);
}
else
diff --git a/src/jit/regalloc.cpp b/src/jit/regalloc.cpp
index f80c81bbe1..eb6ddf8921 100644
--- a/src/jit/regalloc.cpp
+++ b/src/jit/regalloc.cpp
@@ -335,18 +335,19 @@ void Compiler::raMarkStkVars()
/*
For Debug Code, we have to reserve space even if the variable is never
in scope. We will also need to initialize it if it is a GC var.
- So we set lvMustInit and artifically bump up the ref-cnt.
+ So we set lvMustInit and verify it has a nonzero ref-cnt.
*/
if (opts.compDbgCode && !stkFixedArgInVarArgs && lclNum < info.compLocalsCount)
{
- needSlot |= true;
-
- if (lvaTypeIsGC(lclNum))
+ if (varDsc->lvRefCnt() == 0)
{
- varDsc->setLvRefCnt(1);
+ assert(!"unreferenced local in debug codegen");
+ varDsc->lvImplicitlyReferenced = 1;
}
+ needSlot |= true;
+
if (!varDsc->lvIsParam)
{
varDsc->lvMustInit = true;