Update conservative value numbers during CSE
authorJoseph Tremoulet <jotrem@microsoft.com>
Tue, 7 Feb 2017 19:43:29 +0000 (11:43 -0800)
committerJoseph Tremoulet <jotrem@microsoft.com>
Thu, 9 Feb 2017 18:00:34 +0000 (10:00 -0800)
When a CSE candidate's defs all share the same conservative value number,
its uses can be updated to share that conservative value number as well
when CSE is performed, because we are removing any reloads that may have
been the cause of the divergence.  Performing this update can improve
subsequent range check elimination when the CSE use is array length or
index in a bounds check.

src/jit/compiler.h
src/jit/optcse.cpp

index d10d34b..4239cf6 100644 (file)
@@ -5388,6 +5388,9 @@ protected:
 
         treeStmtLstPtr csdTreeList; // list of matching tree nodes: head
         treeStmtLstPtr csdTreeLast; // list of matching tree nodes: tail
+
+        ValueNum defConservativeVN; // if all def occurrences share the same conservative value
+                                    // number, this will reflect it; otherwise, NoVN.
     };
 
     static const size_t s_optCSEhashSize;
index 3ff4cea..5ee6d84 100644 (file)
@@ -996,6 +996,17 @@ void Compiler::optValnumCSE_Availablity()
 
                         /* This is a CSE def */
 
+                        if (desc->csdDefCount == 0)
+                        {
+                            // This is the first def visited, so copy its conservative VN
+                            desc->defConservativeVN = tree->gtVNPair.GetConservative();
+                        }
+                        else if (tree->gtVNPair.GetConservative() != desc->defConservativeVN)
+                        {
+                            // This candidate has defs with differing conservative VNs
+                            desc->defConservativeVN = ValueNumStore::NoVN;
+                        }
+
                         desc->csdDefCount += 1;
                         desc->csdDefWtCnt += stmw;
 
@@ -1778,6 +1789,8 @@ public:
         m_addCSEcount++; // Record that we created a new LclVar for use as a CSE temp
         m_pCompiler->optCSEcount++;
 
+        ValueNum defConservativeVN = successfulCandidate->CseDsc()->defConservativeVN;
+
         /*  Walk all references to this CSE, adding an assignment
             to the CSE temp to all defs and changing all refs to
             a simple use of the CSE temp.
@@ -1890,6 +1903,13 @@ public:
                 //
                 cse           = m_pCompiler->gtNewLclvNode(cseLclVarNum, cseLclVarTyp);
                 cse->gtVNPair = exp->gtVNPair; // assign the proper Value Numbers
+                if (defConservativeVN != ValueNumStore::NoVN)
+                {
+                    // All defs of this CSE share the same conservative VN, and we are rewriting this
+                    // use to fetch the same value with no reload, so we can safely propagate that
+                    // conservative VN to this use.  This can help range check elimination later on.
+                    cse->gtVNPair.SetConservative(defConservativeVN);
+                }
 #ifdef DEBUG
                 cse->gtDebugFlags |= GTF_DEBUG_VAR_CSE_REF;
 #endif // DEBUG