Avoid recursion in some of our SSA optimizations, and cache computed block.dominates(other) operations.

R=kasperl@google.com

Review URL: https://codereview.chromium.org//23721009

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@27471 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index ff83098..c7770c8 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -737,14 +737,20 @@
     return validator.isValid;
   }
 
-  // TODO(ngeoffray): Cache the information if this method ends up
-  // being hot.
+  Map<HBasicBlock, bool> dominatesCache;
+
   bool dominates(HBasicBlock other) {
+    if (dominatesCache == null) {
+      dominatesCache = new Map<HBasicBlock, bool>();
+    } else {
+      bool res = dominatesCache[other];
+      if (res != null) return res;
+    }
     do {
-      if (identical(this, other)) return true;
+      if (identical(this, other)) return dominatesCache[other] = true;
       other = other.dominator;
     } while (other != null && other.id >= id);
-    return false;
+    return dominatesCache[other] = false;
   }
 }
 
@@ -2416,24 +2422,26 @@
 
   void addBackEdge(HBasicBlock predecessor) {
     backEdges.add(predecessor);
-    addBlock(predecessor);
+    List<HBasicBlock> workQueue = <HBasicBlock>[predecessor];
+    do {
+      HBasicBlock current = workQueue.removeLast();
+      addBlock(current, workQueue);
+    } while (!workQueue.isEmpty);
   }
 
   // Adds a block and transitively all its predecessors in the loop as
   // loop blocks.
-  void addBlock(HBasicBlock block) {
+  void addBlock(HBasicBlock block, List<HBasicBlock> workQueue) {
     if (identical(block, header)) return;
     HBasicBlock parentHeader = block.parentLoopHeader;
     if (identical(parentHeader, header)) {
       // Nothing to do in this case.
     } else if (parentHeader != null) {
-      addBlock(parentHeader);
+      workQueue.add(parentHeader);
     } else {
       block.parentLoopHeader = header;
       blocks.add(block);
-      for (int i = 0, length = block.predecessors.length; i < length; i++) {
-        addBlock(block.predecessors[i]);
-      }
+      workQueue.addAll(block.predecessors);
     }
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index e433676..463e198 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -1153,6 +1153,12 @@
   }
 }
 
+class GvnWorkItem {
+  final HBasicBlock block;
+  final ValueSet valueSet;
+  GvnWorkItem(this.block, this.valueSet);
+}
+
 class SsaGlobalValueNumberer implements OptimizationPhase {
   final String name = "SsaGlobalValueNumberer";
   final Compiler compiler;
@@ -1166,7 +1172,12 @@
   void visitGraph(HGraph graph) {
     computeChangesFlags(graph);
     moveLoopInvariantCode(graph);
-    visitBasicBlock(graph.entry, new ValueSet());
+    List<GvnWorkItem> workQueue =
+        <GvnWorkItem>[new GvnWorkItem(graph.entry, new ValueSet())];
+    do {
+      GvnWorkItem item = workQueue.removeLast();
+      visitBasicBlock(item.block, item.valueSet, workQueue);
+    } while (!workQueue.isEmpty);
   }
 
   void moveLoopInvariantCode(HGraph graph) {
@@ -1243,7 +1254,8 @@
     return input.block.id > dominator.id;
   }
 
-  void visitBasicBlock(HBasicBlock block, ValueSet values) {
+  void visitBasicBlock(
+      HBasicBlock block, ValueSet values, List<GvnWorkItem> workQueue) {
     HInstruction instruction = block.first;
     if (block.isLoopHeader()) {
       int flags = loopChangesFlags[block.id];
@@ -1280,10 +1292,16 @@
       assert(block.id < dominated.id);
       if (!successorValues.isEmpty && block.id + 1 < dominated.id) {
         visited.clear();
-        int changesFlags = getChangesFlagsForDominatedBlock(block, dominated);
+        List<HBasicBlock> workQueue = <HBasicBlock>[dominated];
+        int changesFlags = 0;
+        do {
+          HBasicBlock current = workQueue.removeLast();
+          changesFlags |=
+              getChangesFlagsForDominatedBlock(block, current, workQueue);
+        } while (!workQueue.isEmpty);
         successorValues.kill(changesFlags);
       }
-      visitBasicBlock(dominated, successorValues);
+      workQueue.add(new GvnWorkItem(dominated, successorValues));
     }
   }
 
@@ -1329,7 +1347,8 @@
   }
 
   int getChangesFlagsForDominatedBlock(HBasicBlock dominator,
-                                       HBasicBlock dominated) {
+                                       HBasicBlock dominated,
+                                       List<HBasicBlock> workQueue) {
     int changesFlags = 0;
     List<HBasicBlock> predecessors = dominated.predecessors;
     for (int i = 0, length = predecessors.length; i < length; i++) {
@@ -1344,7 +1363,7 @@
         // Loop bodies might not be on the path from dominator to dominated,
         // but they can invalidate values.
         changesFlags |= loopChangesFlags[id];
-        changesFlags |= getChangesFlagsForDominatedBlock(dominator, block);
+        workQueue.add(block);
       }
     }
     return changesFlags;