anchor.diff:      }
     }
   
  -  SubGraph buildCondition(void doCondition()) {
  -    HBasicBlock conditionStartBlock = builder.openNewBlock();
  -    doCondition();
  +  void buildCondition(void visitCondition(),
  +                      SsaBranch conditionBranch,
  +                      SsaBranch thenBranch,
  +                      SsaBranch elseBranch) {
  +    startBranch(conditionBranch);
  +    visitCondition();
       checkNotAborted();
       assert(builder.current === builder.lastOpenedBlock);
  -    HInstruction condition = builder.popBoolified();
  -    HIf branch = new HIf(condition);
  +    HInstruction conditionValue = builder.popBoolified();
  +    HIf branch = new HIf(conditionValue);
  +    HBasicBlock conditionExitBlock = builder.current;
       builder.close(branch);
  -
  -    conditionGraph =
  -        new SubExpression(conditionStartBlock, builder.lastOpenedBlock);
  -    conditionLocals = builder.localsHandler;
  -    return conditionGraph;
  -  }
  -
  -  SubGraph buildThen(void visitThen(), LocalsHandler locals) {
  -    builder.localsHandler = locals;
  -    HBasicBlock thenBlock = builder.addNewBlock();
  -    conditionGraph.end.addSuccessor(thenBlock);
  -    builder.open(thenBlock);
  -    visitThen();
  -    if (branchesHaveValues) {
  +    conditionBranch.exitLocals = builder.localsHandler;
  +    conditionExitBlock.addSuccessor(thenBranch.block);
  +    conditionExitBlock.addSuccessor(elseBranch.block);
  +    bool conditionBranchLocalsCanBeReused =
  +        mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true);
  +    mergeLocals(conditionBranch, elseBranch,
  +                mayReuseFromLocals: conditionBranchLocalsCanBeReused);
  +
  +    conditionBranch.graph =
  +        new SubExpression(conditionBranch.block, conditionExitBlock);
  +  }
  +
  +  /**
  +   * Returns true if the locals of the [fromBranch] may be reused. A [:true:]
  +   * return value implies that [mayReuseFromLocals] was set to [:true:].
  +   */
  +  bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch,
  +                   [bool mayReuseFromLocals]) {
  +    LocalsHandler fromLocals = fromBranch.exitLocals;
  +    if (toBranch.startLocals == null) {
  +      if (mayReuseFromLocals) {
  +        toBranch.startLocals = fromLocals;
  +        return false;
  +      } else {
  +        toBranch.startLocals = new LocalsHandler.from(fromLocals);
  +        return true;
  +      }
  +    } else {
  +      toBranch.startLocals.mergeWith(fromLocals, toBranch.block);
  +      return true;
  +    }
  +  }
  +
  +  void startBranch(SsaBranch branch) {
  +    builder.graph.addBlock(branch.block);
  +    builder.localsHandler = branch.startLocals;
  +    builder.open(branch.block);
  +  }
  +
  +  HInstruction buildBranch(SsaBranch branch,
  +                           void visitBranch(),
  +                           SsaBranch joinBranch,
  +                           bool isExpression) {
  +    startBranch(branch);
  +    visitBranch();
  +    branch.graph = new SubGraph(branch.block, builder.lastOpenedBlock);
  +    branch.exitLocals = builder.localsHandler;
  +    if (!builder.isAborted()) {
  +      builder.goto(builder.current, joinBranch.block);
  +      mergeLocals(branch, joinBranch, mayReuseFromLocals: true);
  +    }
  +    if (isExpression) {
         checkNotAborted();
  -      thenValue = builder.pop();
  -    }
  -    thenGraph = new SubGraph(thenBlock, builder.lastOpenedBlock);
  -    thenLocals = builder.localsHandler;
  -    return thenGraph;
  -  }
  -
  -  SubGraph buildElse(void visitElse(), LocalsHandler locals) {
  -    builder.localsHandler = locals;
  -    HBasicBlock elseBlock = builder.addNewBlock();
  -    conditionGraph.end.addSuccessor(elseBlock);
  -    builder.open(elseBlock);
  -    visitElse();
  -    if (branchesHaveValues) {
  -      checkNotAborted();
  -      elseValue = builder.pop();
  -    }
  -    elseGraph = new SubGraph(elseBlock, builder.lastOpenedBlock);
  -    elseLocals = builder.localsHandler;
  -    return elseGraph;
  -  }
  -
  -  HBasicBlock join() {
  -    HBasicBlock joinBlock = null;
  -    HBasicBlock thenBlock = thenGraph.end;
  -    HBasicBlock elseBlock = elseGraph.end;
  -    // If the last instruction is already a control-flow instruction then the
  -    // block has been aborted.
  -    if (thenBlock.last is HControlFlow) thenBlock = null;
  -    if (elseBlock.last is HControlFlow) elseBlock = null;
  -
  -    if (thenBlock !== null || elseBlock !== null) {
  -      joinBlock = builder.addNewBlock();
  -      if (thenBlock !== null) builder.goto(thenBlock, joinBlock);
  -      if (elseBlock !== null) builder.goto(elseBlock, joinBlock);
  -      // If the join block has two predecessors we have to merge the
  -      // locals. The current locals is what either the
  -      // condition or the else block left us with, so we merge that
  -      // with the set of locals we got after visiting the then
  -      // part of the if.
  -      builder.open(joinBlock);
  -      if (joinBlock.predecessors.length == 2) {
  -        builder.localsHandler.mergeWith(thenLocals, joinBlock);
  -        if (branchesHaveValues) {
  -          assert(thenValue !== null);
  -          assert(elseValue !== null);
  -          HPhi phi = new HPhi.manyInputs(null,
  -              <HInstruction>[thenValue, elseValue]);
  -          joinBlock.addPhi(phi);
  -          builder.stack.add(phi);
  -        }
  -      } else if (thenBlock !== null) {
  -        // The only predecessor is the then branch.
  -        builder.localsHandler = thenLocals;
  -      } else {
  -        assert(builder.localsHandler == elseLocals);
  -      }
  -    }
  -    return builder.current;
  +      return builder.pop();
  +    }
  +    return null;
     }
   
     handleIf(void visitCondition(), void visitThen(), void visitElse()) {
  -    _handleDiamondBranch(visitCondition, visitThen, visitElse, false);
  -  }
  -
  -  handleConditional(void visitCondition(), void visitThen(), void visitElse()) {
  -    _handleDiamondBranch(visitCondition, visitThen, visitElse, true);
  -  }
  -
  -  void _handleDiamondBranch(void visitCondition(),
  -                            void visitThen(),
  -                            void visitElse(),
  -                            bool isExpression) {
  -    branchesHaveValues = isExpression;
       if (visitElse == null) {
  -      if (isExpression) {
  -        compiler.internalError("Diamond branch with values but without else.",
  -                               node: diagnosticNode);
  -      }
         // Make sure to have an else part to avoid a critical edge. A
         // critical edge is an edge that connects a block with multiple
         // successors to a block with multiple predecessors. We avoid
  
positive.code:   /**
     * Merge [otherLocals] into this locals handler, creating phi-nodes when
     * there is a conflict.
     * If a phi node is necessary, it will use the otherLocals instruction as the
     * first input, and this handler's instruction as the second.
     * NOTICE: This means that the predecessor corresponding to [otherLocals]
     * should be the first predecessor of the current block, and the one
     * corresponding to this locals handler should be the second.
     */
    void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) {
      // If an element is in one map but not the other we can safely
  
negative.code:   }
  }
  
  class SsaBranch {
    final SsaBranchBuilder branchBuilder;
    final HBasicBlock block;
    LocalsHandler startLocals;
    LocalsHandler exitLocals;
    SubGraph graph;
  
    SsaBranch(this.branchBuilder) : block = new HBasicBlock();
  }
  
  class SsaBranchBuilder {
    final SsaBuilder builder;
    final Node diagnosticNode;
  
    SsaBranchBuilder(this.builder, [this.diagnosticNode]);
  
    Compiler get compiler() => builder.compiler;
  