Put single-def CSEs into SSA (dotnet/coreclr#26986)
authorAndy Ayers <andya@microsoft.com>
Sat, 5 Oct 2019 14:22:09 +0000 (07:22 -0700)
committerGitHub <noreply@github.com>
Sat, 5 Oct 2019 14:22:09 +0000 (07:22 -0700)
If we create a single-def temp during SSE, add it into SSA so uses of the temp
can benefit from assertion prop and similar.

Follow-up from some work proposed for dotnet/coreclr#21973.

Commit migrated from https://github.com/dotnet/coreclr/commit/863b40ec595bc1db58d7000255d72180a43deacb

src/coreclr/src/jit/optcse.cpp

index 2bceb57..dffd1f7 100644 (file)
@@ -2012,6 +2012,7 @@ public:
     // It will replace all of the CSE defs with assignments to a new "cse0" LclVar
     // and will replace all of the CSE uses with reads of the "cse0" LclVar
     //
+    // It will also put cse0 into SSA if there is just one def.
     void PerformCSE(CSE_Candidate* successfulCandidate)
     {
         unsigned cseRefCnt = (successfulCandidate->DefCount() * 2) + successfulCandidate->UseCount();
@@ -2072,6 +2073,21 @@ public:
         Compiler::CSEdsc*      dsc = successfulCandidate->CseDsc();
         Compiler::treeStmtLst* lst;
 
+        // If there's just a single def for the CSE, we'll put this
+        // CSE into SSA form on the fly. We won't need any PHIs.
+        unsigned cseSsaNum = SsaConfig::RESERVED_SSA_NUM;
+
+        if (dsc->csdDefCount == 1)
+        {
+            JITDUMP("CSE #%02u is single-def, so associated cse temp V%02u will be in SSA\n", dsc->csdIndex,
+                    cseLclVarNum);
+            m_pCompiler->lvaTable[cseLclVarNum].lvInSsa = true;
+
+            // Allocate the ssa num
+            CompAllocator allocator = m_pCompiler->getAllocator(CMK_SSA);
+            cseSsaNum               = m_pCompiler->lvaTable[cseLclVarNum].lvPerSsaData.AllocSsaNum(allocator);
+        }
+
 #ifdef DEBUG
         // Verify that all of the ValueNumbers in this list are correct as
         // Morph will change them when it performs a mutating operation.
@@ -2185,6 +2201,9 @@ public:
                 ValueNumStore* vnStore = m_pCompiler->vnStore;
                 cse                    = m_pCompiler->gtNewLclvNode(cseLclVarNum, cseLclVarTyp);
 
+                // Assign the ssa num for the use. Note it may be the reserved num.
+                cse->gtLclVarCommon.SetSsaNum(cseSsaNum);
+
                 // assign the proper ValueNumber, A CSE use discards any exceptions
                 cse->gtVNPair = vnStore->VNPNormalPair(exp->gtVNPair);
 
@@ -2348,10 +2367,30 @@ public:
 
                 noway_assert(asg->gtOp.gtOp1->gtOper == GT_LCL_VAR);
 
+                // Backpatch the SSA def, if we're putting this cse temp into ssa.
+                asg->gtOp.gtOp1->AsLclVar()->SetSsaNum(cseSsaNum);
+
+                if (cseSsaNum != SsaConfig::RESERVED_SSA_NUM)
+                {
+                    LclSsaVarDsc* ssaVarDsc = m_pCompiler->lvaTable[cseLclVarNum].GetPerSsaData(cseSsaNum);
+
+                    // These should not have been set yet, since this is the first and
+                    // only def for this CSE.
+                    assert(ssaVarDsc->m_defLoc.m_blk == nullptr);
+                    assert(ssaVarDsc->m_defLoc.m_tree == nullptr);
+
+                    ssaVarDsc->m_vnPair        = val->gtVNPair;
+                    ssaVarDsc->m_defLoc.m_blk  = blk;
+                    ssaVarDsc->m_defLoc.m_tree = asg;
+                }
+
                 /* Create a reference to the CSE temp */
                 GenTree* ref  = m_pCompiler->gtNewLclvNode(cseLclVarNum, cseLclVarTyp);
                 ref->gtVNPair = val->gtVNPair; // The new 'ref' is the same as 'val'
 
+                // Assign the ssa num for the ref use. Note it may be the reserved num.
+                ref->gtLclVarCommon.SetSsaNum(cseSsaNum);
+
                 // If it has a zero-offset field seq, copy annotation to the ref
                 if (hasZeroMapAnnotation)
                 {