anchor.diff:        boolifiedRight = popBoolified();
       }
   
  -    handleIf(visitCondition, visitThen, null);
  +    handleIf(diagnosticNode, visitCondition, visitThen, null);
       HPhi result = new HPhi.manyInputs(null,
           <HInstruction>[boolifiedRight, graph.addConstantBool(!isAnd)]);
       current.addPhi(result);
  
positive.code:   }
  
    visitIf(If node) {
      handleIf(() => visit(node.condition),
               () => visit(node.thenPart),
               node.elsePart != null ? () => visit(node.elsePart) : null);
    }
  
    void handleIf(void visitCondition(), void visitThen(), void visitElse()) {
      HBasicBlock conditionStartBlock = openNewBlock();
      visitCondition();
      SubExpression conditionGraph =
          new SubExpression(conditionStartBlock, lastOpenedBlock);
      HInstruction condition = popBoolified();
      HIf branch = new HIf(condition);
      HBasicBlock conditionBlock = close(branch);
  
      LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
  
      // The then part.
      HBasicBlock thenBlock = addNewBlock();
      conditionBlock.addSuccessor(thenBlock);
      open(thenBlock);
      visitThen();
      SubGraph thenGraph = new SubGraph(thenBlock, lastOpenedBlock);
      thenBlock = current;
  
      // Reset the locals state to the state after the condition and keep the
      // current state in [thenLocals].
      LocalsHandler thenLocals = localsHandler;
  
      // Now the else part.
      localsHandler = savedLocals;
      if (visitElse == null) {
        // 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
        // such edges because they prevent inserting copies during code
        // generation of phi instructions.
        visitElse = () {};
      }
  
      HBasicBlock elseBlock = addNewBlock();
      conditionBlock.addSuccessor(elseBlock);
      open(elseBlock);
      visitElse();
      SubGraph elseGraph = new SubGraph(elseBlock, lastOpenedBlock);
      elseBlock = current;
  
      HBasicBlock joinBlock = null;
      if (thenBlock !== null || elseBlock !== null) {
        joinBlock = addNewBlock();
        if (thenBlock !== null) goto(thenBlock, joinBlock);
        if (elseBlock !== null) 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.
        open(joinBlock);
        if (joinBlock.predecessors.length == 2) {
          localsHandler.mergeWith(thenLocals, joinBlock);
        } else if (thenBlock !== null) {
          // The only predecessor is the then branch.
          localsHandler = thenLocals;
        }
      }
      HIfBlockInformation info =
          new HIfBlockInformation(
              new HSubExpressionBlockInformation(conditionGraph),
              new HSubGraphBlockInformation(thenGraph),
              wrapStatementGraph(elseGraph));
      conditionStartBlock.setBlockFlow(info, joinBlock);
      branch.blockInformation = conditionStartBlock.blockFlow;
    }
  
    void visitLogicalAndOr(Send node, Operator op) {
      handleLogicalAndOr(() { visit(node.receiver); },
                         () { visit(node.argumentsNode); },
                         isAnd: (const SourceString("&&") == op.source));
    }
  
  
    void handleLogicalAndOr(void left(), void right(), [bool isAnd = true]) {
      // x && y is transformed into:
      //   t0 = boolify(x);
      //   if (t0) {
  
negative.code:     return instruction;
    }
  }
  
  class SsaBranchBuilder {
    final SsaBuilder builder;
    final Node diagnosticNode;
  
    bool branchesHaveValues;
    HInstruction thenValue;
    HInstruction elseValue;
    // The locals-handler at the end of the condition block.
    LocalsHandler conditionLocals;
    LocalsHandler thenLocals;
    LocalsHandler elseLocals;
    SubGraph conditionGraph;
    SubGraph thenGraph;
    SubGraph elseGraph;
  
    SsaBranchBuilder(this.builder, [this.diagnosticNode]);
  
    Compiler get compiler() => builder.compiler;
  
    void checkNotAborted() {
      if (builder.isAborted()) {
        compiler.unimplemented("aborted control flow", node: diagnosticNode);
      }
    }
  
    SubGraph buildCondition(void doCondition()) {
      HBasicBlock conditionStartBlock = builder.openNewBlock();
      doCondition();
      checkNotAborted();
      assert(builder.current === builder.lastOpenedBlock);
      HInstruction condition = builder.popBoolified();
      HIf branch = new HIf(condition);
      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) {
        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;
    }
  
    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
        // such edges because they prevent inserting copies during code
        // generation of phi instructions.
        visitElse = () {};
      }
  
      buildCondition(visitCondition);
      buildThen(visitThen, new LocalsHandler.from(conditionLocals));
      // Use the locals state after the condition. We are the last ones to use the
      // conditionLocals. So we don't need to make a copy of it.
      buildElse(visitElse, conditionLocals);
      HBasicBlock joinBlock = join();
  
      HIfBlockInformation info =
          new HIfBlockInformation(
              new HSubExpressionBlockInformation(conditionGraph),
              new HSubGraphBlockInformation(thenGraph),
              new HSubGraphBlockInformation(elseGraph));
  
      HBasicBlock conditionStartBlock = conditionGraph.start;
      conditionGraph.start.setBlockFlow(info, joinBlock);
      HIf branch = conditionGraph.end.last;
      assert(branch is HIf);
      branch.blockInformation = conditionStartBlock.blockFlow;
    }
  }
  