| 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.
|
|
|