JIT: remove incremental ref count updates (#19345)
authorAndy Ayers <andya@microsoft.com>
Mon, 20 Aug 2018 22:03:29 +0000 (15:03 -0700)
committerGitHub <noreply@github.com>
Mon, 20 Aug 2018 22:03:29 +0000 (15:03 -0700)
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.

19 files changed:
src/jit/assertionprop.cpp
src/jit/codegencommon.cpp
src/jit/compiler.cpp
src/jit/compiler.h
src/jit/compiler.hpp
src/jit/copyprop.cpp
src/jit/decomposelongs.cpp
src/jit/earlyprop.cpp
src/jit/flowgraph.cpp
src/jit/gentree.cpp
src/jit/lclvars.cpp
src/jit/lir.cpp
src/jit/liveness.cpp
src/jit/lower.cpp
src/jit/morph.cpp
src/jit/optcse.cpp
src/jit/optimizer.cpp
src/jit/rationalize.cpp
src/jit/regalloc.cpp

index d4153a2..0cc35a9 100644 (file)
@@ -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;
-    }
 }
index 0f6beec..67faf40 100644 (file)
@@ -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
                 {
index b66236b..ded0920 100644 (file)
@@ -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();
index 09ff104..6015cf3 100644 (file)
@@ -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);
 
index c1b050c..2063d55 100644 (file)
@@ -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:
index c09fa91..98671c1 100644 (file)
@@ -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);
index 9e6da62..74863ad 100644 (file)
@@ -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);
index f97c0ac..325f85d 100644 (file)
@@ -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)
index d98cf2f..b06b16c 100644 (file)
@@ -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
     //
index c3ce836..5a5d2e1 100644 (file)
@@ -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)
index 324896b..5f51739 100644 (file)
@@ -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;
+            }
+        }
     }
 }
 
index 0ba18a2..480a5d3 100644 (file)
@@ -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.
index 9f8910f..c749152 100644 (file)
@@ -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
index 13780ca..4098c6e 100644 (file)
@@ -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);
index 7c093c4..83707b0 100644 (file)
@@ -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;
 
index f389aa5..3abab60 100644 (file)
@@ -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.
     }
 };
 
index 9a1e015..dbf13a3 100644 (file)
@@ -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);
index 89e4167..cbbeaea 100644 (file)
@@ -931,7 +931,6 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, ArrayStack<G
     {
         if (use.IsDummyUse())
         {
-            comp->lvaDecRefCnts(node);
             BlockRange().Remove(node);
         }
         else
index f80c81b..eb6ddf8 100644 (file)
@@ -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;