The CleanUp after LICM is erroneously removing a Check
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGLICMPhase.cpp
index a28127f..ef7d647 100644 (file)
@@ -220,7 +220,7 @@ public:
                     changed |= attemptHoist(block, nodeRef, loopStack[stackIndex]);
             }
         }
-        
+
         return changed;
     }
 
@@ -297,15 +297,28 @@ private:
                 "\n");
         }
 
-        // FIXME: We should adjust the Check: flags on the edges of node. There are phases that assume
-        // that those flags are correct even if AI is stale.
-        // https://bugs.webkit.org/show_bug.cgi?id=148544
         data.preHeader->insertBeforeTerminal(node);
         node->owner = data.preHeader;
         NodeOrigin terminalOrigin = data.preHeader->terminal()->origin;
         node->origin = terminalOrigin.withSemantic(node->origin.semantic);
         node->origin.wasHoisted |= addsBlindSpeculation;
         
+        // We can trust what AI proves about edge proof statuses when hoisting to the preheader.
+        m_state.trustEdgeProofs();
+        m_state.initializeTo(data.preHeader);
+        m_interpreter.execute(node);
+        // However, when walking various inner loops below, the proof status of
+        // an edge may be trivially true, even if it's not true in the preheader
+        // we hoist to. We don't allow the below node executions to change the
+        // state of edge proofs. An example of where a proof is trivially true
+        // is if we have two loops, L1 and L2, where L2 is nested inside L1. The
+        // header for L1 dominates L2. We hoist a Check from L1's header into L1's
+        // preheader. However, inside L2's preheader, we can't trust that AI will
+        // tell us this edge is proven. It's proven in L2's preheader because L2
+        // is dominated by L1's header. However, the edge is not guaranteed to be
+        // proven inside L1's preheader.
+        m_state.dontTrustEdgeProofs();
+
         // Modify the states at the end of the preHeader of the loop we hoisted to,
         // and all pre-headers inside the loop. This isn't a stability bottleneck right now
         // because most loops are small and most blocks belong to few loops.
@@ -323,10 +336,13 @@ private:
             // The pre-header's tail may be unreachable, in which case we have nothing to do.
             if (!subPreHeader->cfaDidFinish)
                 continue;
+            // We handled this above.
+            if (subPreHeader == data.preHeader)
+                continue;
             m_state.initializeTo(subPreHeader);
             m_interpreter.execute(node);
         }
-        
+
         // It just so happens that all of the nodes we currently know how to hoist
         // don't have var-arg children. That may change and then we can fix this
         // code. But for now we just assert that's the case.