JIT: don't allocate promoted struct death vars map for clear or lookup (#19753)
authorAndy Ayers <andya@microsoft.com>
Fri, 31 Aug 2018 15:20:53 +0000 (08:20 -0700)
committerGitHub <noreply@github.com>
Fri, 31 Aug 2018 15:20:53 +0000 (08:20 -0700)
Only allocate this map if we're adding something. Refactor clearing and
lookup to do minimal work if the map hasn't been allocated (and it won't
have been in debug / minopts).

Saves a tiny bit of throughput and memory.

src/jit/compiler.h
src/jit/liveness.cpp
src/jit/treelifeupdater.cpp

index 24ade25..d46e571 100644 (file)
@@ -7105,12 +7105,16 @@ public:
     // node, else NULL.
     static GenTree* fgIsIndirOfAddrOfLocal(GenTree* tree);
 
-    // This is indexed by GT_OBJ nodes that are address of promoted struct variables, which
+    // This map is indexed by GT_OBJ nodes that are address of promoted struct variables, which
     // have been annotated with the GTF_VAR_DEATH flag.  If such a node is *not* mapped in this
-    // table, one may assume that all the (tracked) field vars die at this point.  Otherwise,
+    // table, one may assume that all the (tracked) field vars die at this GT_OBJ.  Otherwise,
     // the node maps to a pointer to a VARSET_TP, containing set bits for each of the tracked field
     // vars of the promoted struct local that go dead at the given node (the set bits are the bits
     // for the tracked var indices of the field vars, as in a live var set).
+    //
+    // The map is allocated on demand so all map operations should use one of the following three
+    // wrapper methods.
+
     NodeToVarsetPtrMap* m_promotedStructDeathVars;
 
     NodeToVarsetPtrMap* GetPromotedStructDeathVars()
@@ -7122,6 +7126,27 @@ public:
         return m_promotedStructDeathVars;
     }
 
+    void ClearPromotedStructDeathVars()
+    {
+        if (m_promotedStructDeathVars != nullptr)
+        {
+            m_promotedStructDeathVars->RemoveAll();
+        }
+    }
+
+    bool LookupPromotedStructDeathVars(GenTree* tree, VARSET_TP** bits)
+    {
+        bits        = nullptr;
+        bool result = false;
+
+        if (m_promotedStructDeathVars != nullptr)
+        {
+            result = m_promotedStructDeathVars->Lookup(tree, bits);
+        }
+
+        return result;
+    }
+
 /*
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
index 35edbfc..a92cc34 100644 (file)
@@ -138,7 +138,7 @@ void Compiler::fgLocalVarLiveness()
     EndPhase(PHASE_LCLVARLIVENESS_INIT);
 
     // Make sure we haven't noted any partial last uses of promoted structs.
-    GetPromotedStructDeathVars()->RemoveAll();
+    ClearPromotedStructDeathVars();
 
     // Initialize the per-block var sets.
     fgInitBlockVarSets();
@@ -1340,7 +1340,7 @@ VARSET_VALRET_TP Compiler::fgUpdateLiveSet(VARSET_VALARG_TP liveSet, GenTree* tr
                 // We maintain the invariant that if the lclVarTree is a promoted struct, but the
                 // the lookup fails, then all the field vars (i.e., "varBits") are dying.
                 VARSET_TP* deadVarBits = nullptr;
-                if (varTypeIsStruct(lclVarTree) && GetPromotedStructDeathVars()->Lookup(lclVarTree, &deadVarBits))
+                if (varTypeIsStruct(lclVarTree) && LookupPromotedStructDeathVars(lclVarTree, &deadVarBits))
                 {
                     VarSetOps::DiffD(this, newLiveSet, *deadVarBits);
                 }
index 5b5165e..ecfdaee 100644 (file)
@@ -85,9 +85,6 @@ void TreeLifeUpdater<ForCodeGen>::UpdateLifeVar(GenTree* tree)
 
     if (isBorn || isDying)
     {
-        bool hasDeadTrackedFieldVars = false; // If this is true, then, for a LDOBJ(ADDR(<promoted struct local>)),
-        VARSET_TP* deadTrackedFieldVars =
-            nullptr; // *deadTrackedFieldVars indicates which tracked field vars are dying.
         VarSetOps::ClearD(compiler, varDeltaSet);
 
         if (varDsc->lvTracked)
@@ -111,11 +108,16 @@ void TreeLifeUpdater<ForCodeGen>::UpdateLifeVar(GenTree* tree)
         }
         else if (varDsc->lvPromoted)
         {
+            // If hasDeadTrackedFieldVars is true, then, for a LDOBJ(ADDR(<promoted struct local>)),
+            // *deadTrackedFieldVars indicates which tracked field vars are dying.
+            bool hasDeadTrackedFieldVars = false;
+
             if (indirAddrLocal != nullptr && isDying)
             {
                 assert(!isBorn); // GTF_VAR_DEATH only set for LDOBJ last use.
+                VARSET_TP* deadTrackedFieldVars = nullptr;
                 hasDeadTrackedFieldVars =
-                    compiler->GetPromotedStructDeathVars()->Lookup(indirAddrLocal, &deadTrackedFieldVars);
+                    compiler->LookupPromotedStructDeathVars(indirAddrLocal, &deadTrackedFieldVars);
                 if (hasDeadTrackedFieldVars)
                 {
                     VarSetOps::Assign(compiler, varDeltaSet, *deadTrackedFieldVars);