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