Index: pkg/compiler/lib/src/cps_ir/let_sinking.dart |
diff --git a/pkg/compiler/lib/src/cps_ir/let_sinking.dart b/pkg/compiler/lib/src/cps_ir/let_sinking.dart |
index 8844ae6632d86ef122500fbb6793b765fe449518..7432837d805dd6bc231656f8f172ffa306f81d98 100644 |
--- a/pkg/compiler/lib/src/cps_ir/let_sinking.dart |
+++ b/pkg/compiler/lib/src/cps_ir/let_sinking.dart |
@@ -30,7 +30,12 @@ class LetSinker extends RecursiveVisitor implements Pass { |
LoopHierarchy loopHierarchy; |
List<Continuation> stack = <Continuation>[]; |
- Set<LetPrim> sunkNodes = new Set<LetPrim>(); |
+ |
+ /// Maps a sinkable primitive to its loop header. |
+ Map<Primitive, Continuation> loopHeaderForPrimitive = |
+ <Primitive, Continuation>{}; |
+ |
+ Continuation currentLoopHeader; |
void rewrite(FunctionDefinition node) { |
new ParentVisitor().visit(node); |
@@ -40,22 +45,40 @@ class LetSinker extends RecursiveVisitor implements Pass { |
@override |
Expression traverseLetPrim(LetPrim node) { |
- pushAction(() { |
- if (node.primitive != null) { |
- // The primitive could not be sunk. Sink dependencies to this location. |
- visit(node.primitive); |
- } else { |
- // The primitive was sunk. Destroy the old LetPrim. |
- InteriorNode parent = node.parent; |
- parent.body = node.body; |
- node.body.parent = parent; |
- } |
- }); |
+ Primitive prim = node.primitive; |
+ if (prim.hasExactlyOneUse && prim.isSafeForReordering) { |
+ // This can potentially be sunk. Register the loop header, so when we |
+ // find the use site, we can check if they are in the same loop. |
+ loopHeaderForPrimitive[prim] = currentLoopHeader; |
+ pushAction(() { |
+ if (node.primitive != null) { |
+ // The primitive could not be sunk. Try to sink dependencies here. |
+ visit(node.primitive); |
+ } else { |
+ // The primitive was sunk. Destroy the old LetPrim. |
+ InteriorNode parent = node.parent; |
+ parent.body = node.body; |
+ node.body.parent = parent; |
+ } |
+ }); |
+ } else { |
+ visit(node.primitive); |
+ } |
// Visit the body, wherein this primitive may be sunk to its use site. |
return node.body; |
} |
+ @override |
+ Expression traverseContinuation(Continuation cont) { |
+ Continuation oldLoopHeader = currentLoopHeader; |
+ pushAction(() { |
+ currentLoopHeader = oldLoopHeader; |
+ }); |
+ currentLoopHeader = loopHierarchy.getLoopHeader(cont); |
+ return cont.body; |
+ } |
+ |
void processReference(Reference ref) { |
Definition definition = ref.definition; |
if (definition is Primitive && |
@@ -63,13 +86,12 @@ class LetSinker extends RecursiveVisitor implements Pass { |
definition.hasExactlyOneUse && |
definition.isSafeForReordering) { |
// Check if use is in the same loop. |
- LetPrim binding = definition.parent; |
- Continuation bindingLoop = loopHierarchy.getLoopHeader(binding); |
- Expression use = getEnclosingExpression(ref.parent); |
- Continuation useLoop = loopHierarchy.getLoopHeader(use); |
- if (bindingLoop == useLoop || definition is Constant) { |
+ Continuation bindingLoop = loopHeaderForPrimitive.remove(definition); |
+ if (bindingLoop == currentLoopHeader || definition is Constant) { |
// Sink the definition. |
+ Expression use = getEnclosingExpression(ref.parent); |
+ LetPrim binding = definition.parent; |
binding.primitive = null; // Mark old binding for deletion. |
LetPrim newBinding = new LetPrim(definition); |
definition.parent = newBinding; |
@@ -130,20 +152,9 @@ class LoopHierarchy { |
_processBlock(node.body, null); |
} |
- /// Returns the innermost loop which [node] is effectively part of. |
- Continuation getLoopHeader(Expression exp) { |
- Node node = exp.parent; |
- while (node != null && node is! Continuation) { |
- node = node.parent; |
- } |
- if (node is Continuation) { |
- if (node.isRecursive) { |
- return node; |
- } else { |
- return loopTarget[node]; |
- } |
- } |
- return null; |
+ /// Returns the innermost loop which [cont] is effectively part of. |
+ Continuation getLoopHeader(Continuation cont) { |
+ return cont.isRecursive ? cont : loopTarget[cont]; |
} |
/// Marks the innermost loop as a subloop of the other loop. |