Title: [144973] trunk/Source/_javascript_Core
Revision
144973
Author
[email protected]
Date
2013-03-06 13:23:39 -0800 (Wed, 06 Mar 2013)

Log Message

DFG should not run full CSE after the optimization fixpoint, since it really just wants store elimination
https://bugs.webkit.org/show_bug.cgi?id=111536

Reviewed by Oliver Hunt and Mark Hahnenberg.
        
The fixpoint will do aggressive load elimination and pure CSE. There's no need to do it after the fixpoint.
On the other hand, the fixpoint does not profit from doing store elimination (except for SetLocal/Flush).
Previously we had CSE do both, and had it avoid doing some store elimination during the fixpoint by querying
the fixpoint state. This changes CSE to be templated on mode - either NormalCSE or StoreElimination - so
that we explicitly put it into one of those modes depending on where we call it from. The goal is to reduce
time spent doing load elimination after the fixpoint, since that is just wasted cycles.

* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::CSEPhase):
(JSC::DFG::CSEPhase::run):
(JSC::DFG::CSEPhase::performNodeCSE):
(JSC::DFG::CSEPhase::performBlockCSE):
(JSC::DFG::performCSE):
(DFG):
(JSC::DFG::performStoreElimination):
* dfg/DFGCSEPhase.h:
(DFG):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (144972 => 144973)


--- trunk/Source/_javascript_Core/ChangeLog	2013-03-06 21:21:48 UTC (rev 144972)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-03-06 21:23:39 UTC (rev 144973)
@@ -1,3 +1,30 @@
+2013-03-06  Filip Pizlo  <[email protected]>
+
+        DFG should not run full CSE after the optimization fixpoint, since it really just wants store elimination
+        https://bugs.webkit.org/show_bug.cgi?id=111536
+
+        Reviewed by Oliver Hunt and Mark Hahnenberg.
+        
+        The fixpoint will do aggressive load elimination and pure CSE. There's no need to do it after the fixpoint.
+        On the other hand, the fixpoint does not profit from doing store elimination (except for SetLocal/Flush).
+        Previously we had CSE do both, and had it avoid doing some store elimination during the fixpoint by querying
+        the fixpoint state. This changes CSE to be templated on mode - either NormalCSE or StoreElimination - so
+        that we explicitly put it into one of those modes depending on where we call it from. The goal is to reduce
+        time spent doing load elimination after the fixpoint, since that is just wasted cycles.
+
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::CSEPhase):
+        (JSC::DFG::CSEPhase::run):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        (JSC::DFG::CSEPhase::performBlockCSE):
+        (JSC::DFG::performCSE):
+        (DFG):
+        (JSC::DFG::performStoreElimination):
+        * dfg/DFGCSEPhase.h:
+        (DFG):
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compile):
+
 2013-03-06  Andreas Kling  <[email protected]>
 
         Pack Structure members better.

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (144972 => 144973)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2013-03-06 21:21:48 UTC (rev 144972)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2013-03-06 21:23:39 UTC (rev 144973)
@@ -35,15 +35,21 @@
 
 namespace JSC { namespace DFG {
 
+enum CSEMode { NormalCSE, StoreElimination };
+
+template<CSEMode cseMode>
 class CSEPhase : public Phase {
 public:
     CSEPhase(Graph& graph)
-        : Phase(graph, "common subexpression elimination")
+        : Phase(graph, cseMode == NormalCSE ? "common subexpression elimination" : "store elimination")
     {
     }
     
     bool run()
     {
+        ASSERT((cseMode == NormalCSE) == (m_graph.m_fixpointState == FixpointNotConverged));
+        ASSERT(m_graph.m_fixpointState != BeforeFixpoint);
+        
         m_changed = false;
         
         for (unsigned block = 0; block < m_graph.m_blocks.size(); ++block)
@@ -1011,7 +1017,8 @@
     
     void performNodeCSE(Node* node)
     {
-        m_graph.performSubstitution(node);
+        if (cseMode == NormalCSE)
+            m_graph.performSubstitution(node);
         
         if (node->op() == SetLocal)
             node->child1()->mergeFlags(NodeRelevantToOSR);
@@ -1032,6 +1039,8 @@
         switch (node->op()) {
         
         case Identity:
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(node->child1().node());
             break;
             
@@ -1069,19 +1078,27 @@
         case TypeOf:
         case CompareEqConstant:
         case ValueToInt32:
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(pureCSE(node));
             break;
             
         case Int32ToDouble:
         case ForwardInt32ToDouble:
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(int32ToDoubleCSE(node));
             break;
             
         case GetCallee:
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(getCalleeLoadElimination(node->codeOrigin.inlineCallFrame));
             break;
 
         case GetLocal: {
+            if (cseMode == StoreElimination)
+                break;
             VariableAccessData* variableAccessData = node->variableAccessData();
             if (!variableAccessData->isCaptured())
                 break;
@@ -1108,6 +1125,8 @@
         }
             
         case GetLocalUnlinked: {
+            if (cseMode == StoreElimination)
+                break;
             Node* relevantLocalOpIgnored;
             setReplacement(getLocalLoadElimination(node->unlinkedLocal(), relevantLocalOpIgnored, true));
             break;
@@ -1122,7 +1141,7 @@
             ASSERT(replacement->variableAccessData() == variableAccessData);
             // FIXME: We should be able to remove SetLocals that can exit; we just need
             // to replace them with appropriate type checks.
-            if (m_graph.m_fixpointState == FixpointNotConverged) {
+            if (cseMode == NormalCSE) {
                 // Need to be conservative at this time; if the SetLocal has any chance of performing
                 // any speculations then we cannot do anything.
                 if (variableAccessData->isCaptured()) {
@@ -1159,21 +1178,29 @@
         }
             
         case JSConstant:
+            if (cseMode == StoreElimination)
+                break;
             // This is strange, but necessary. Some phases will convert nodes to constants,
             // which may result in duplicated constants. We use CSE to clean this up.
             setReplacement(constantCSE(node));
             break;
             
         case WeakJSConstant:
+            if (cseMode == StoreElimination)
+                break;
             // FIXME: have CSE for weak constants against strong constants and vice-versa.
             setReplacement(weakConstantCSE(node));
             break;
             
         case GetArrayLength:
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(getArrayLengthElimination(node->child1().node()));
             break;
 
         case GetMyScope:
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(getMyScopeLoadElimination(node->codeOrigin.inlineCallFrame));
             break;
             
@@ -1185,6 +1212,8 @@
         case CompareGreater:
         case CompareGreaterEq:
         case CompareEq: {
+            if (cseMode == StoreElimination)
+                break;
             if (m_graph.isPredictedNumerical(node)) {
                 Node* replacement = pureCSE(node);
                 if (replacement && m_graph.isPredictedNumerical(replacement))
@@ -1196,39 +1225,49 @@
         // Finally handle heap accesses. These are not quite pure, but we can still
         // optimize them provided that some subtle conditions are met.
         case GetGlobalVar:
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(globalVarLoadElimination(node->registerPointer()));
             break;
 
         case GetScopedVar: {
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(scopedVarLoadElimination(node->child1().node(), node->varNumber()));
             break;
         }
 
         case GlobalVarWatchpoint:
+            if (cseMode == StoreElimination)
+                break;
             if (globalVarWatchpointElimination(node->registerPointer()))
                 eliminate();
             break;
             
         case PutGlobalVar:
         case PutGlobalVarCheck:
-            if (m_graph.m_fixpointState == FixpointNotConverged)
+            if (cseMode == NormalCSE)
                 break;
             eliminate(globalVarStoreElimination(node->registerPointer()));
             break;
             
         case PutScopedVar: {
-            if (m_graph.m_fixpointState == FixpointNotConverged)
+            if (cseMode == NormalCSE)
                 break;
             eliminate(scopedVarStoreElimination(node->child1().node(), node->child2().node(), node->varNumber()));
             break;
         }
 
         case GetByVal:
+            if (cseMode == StoreElimination)
+                break;
             if (m_graph.byValIsPure(node))
                 setReplacement(getByValLoadElimination(node->child1().node(), node->child2().node()));
             break;
             
         case PutByVal: {
+            if (cseMode == StoreElimination)
+                break;
             Edge child1 = m_graph.varArgChild(node, 0);
             Edge child2 = m_graph.varArgChild(node, 1);
             if (node->arrayMode().canCSEStorage()) {
@@ -1242,52 +1281,68 @@
             
         case CheckStructure:
         case ForwardCheckStructure:
+            if (cseMode == StoreElimination)
+                break;
             if (checkStructureElimination(node->structureSet(), node->child1().node()))
                 eliminate();
             break;
             
         case StructureTransitionWatchpoint:
         case ForwardStructureTransitionWatchpoint:
+            if (cseMode == StoreElimination)
+                break;
             if (structureTransitionWatchpointElimination(node->structure(), node->child1().node()))
                 eliminate();
             break;
             
         case PutStructure:
-            if (m_graph.m_fixpointState == FixpointNotConverged)
+            if (cseMode == NormalCSE)
                 break;
             eliminate(putStructureStoreElimination(node->child1().node()), PhantomPutStructure);
             break;
 
         case CheckFunction:
+            if (cseMode == StoreElimination)
+                break;
             if (checkFunctionElimination(node->function(), node->child1().node()))
                 eliminate();
             break;
                 
         case CheckExecutable:
+            if (cseMode == StoreElimination)
+                break;
             if (checkExecutableElimination(node->executable(), node->child1().node()))
                 eliminate();
             break;
                 
         case CheckArray:
+            if (cseMode == StoreElimination)
+                break;
             if (checkArrayElimination(node->child1().node(), node->arrayMode()))
                 eliminate();
             break;
             
         case GetIndexedPropertyStorage: {
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(getIndexedPropertyStorageLoadElimination(node->child1().node(), node->arrayMode()));
             break;
         }
 
         case GetButterfly:
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(getPropertyStorageLoadElimination(node->child1().node()));
             break;
 
         case GetByOffset:
+            if (cseMode == StoreElimination)
+                break;
             setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child1().node()));
             break;
             
         case PutByOffset:
-            if (m_graph.m_fixpointState == FixpointNotConverged)
+            if (cseMode == NormalCSE)
                 break;
             eliminate(putByOffsetStoreElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child1().node()));
             break;
@@ -1350,6 +1405,12 @@
             m_currentNode = block->at(m_indexInBlock);
             performNodeCSE(m_currentNode);
         }
+        
+        if (!ASSERT_DISABLED && cseMode == StoreElimination) {
+            // Nobody should have replacements set.
+            for (unsigned i = 0; i < block->size(); ++i)
+                ASSERT(!block->at(i)->replacement);
+        }
     }
     
     BasicBlock* m_currentBlock;
@@ -1362,9 +1423,15 @@
 bool performCSE(Graph& graph)
 {
     SamplingRegion samplingRegion("DFG CSE Phase");
-    return runPhase<CSEPhase>(graph);
+    return runPhase<CSEPhase<NormalCSE> >(graph);
 }
 
+bool performStoreElimination(Graph& graph)
+{
+    SamplingRegion samplingRegion("DFG Store Elimination Phase");
+    return runPhase<CSEPhase<StoreElimination> >(graph);
+}
+
 } } // namespace JSC::DFG
 
 #endif // ENABLE(DFG_JIT)

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.h (144972 => 144973)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.h	2013-03-06 21:21:48 UTC (rev 144972)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.h	2013-03-06 21:23:39 UTC (rev 144973)
@@ -40,9 +40,11 @@
 // it is rather profitable. It has fairly accurate heap modeling and will match
 // a wide range of subexpression similarities. It's known to produce big wins
 // on a few benchmarks, and is relatively cheap to run.
-
 bool performCSE(Graph&);
 
+// Perform just block-local store elimination.
+bool performStoreElimination(Graph&);
+
 } } // namespace JSC::DFG
 
 #endif // ENABLE(DFG_JIT)

Modified: trunk/Source/_javascript_Core/dfg/DFGDriver.cpp (144972 => 144973)


--- trunk/Source/_javascript_Core/dfg/DFGDriver.cpp	2013-03-06 21:21:48 UTC (rev 144972)
+++ trunk/Source/_javascript_Core/dfg/DFGDriver.cpp	2013-03-06 21:23:39 UTC (rev 144973)
@@ -152,8 +152,8 @@
         dataLogF("DFG optimization fixpoint converged in %u iterations.\n", cnt);
 
     dfg.m_fixpointState = FixpointConverged;
-    performCSE(dfg);
-    performCPSRethreading(dfg); // This should usually be a no-op since CSE rarely dethreads the graph.
+    performStoreElimination(dfg);
+    performCPSRethreading(dfg); // This should usually be a no-op since store elimination rarely dethreads the graph.
     performDCE(dfg);
     performVirtualRegisterAllocation(dfg);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to