changeset 13268:68b964b6dc8e

introduced BlockEndOp interface and require that every LIR block is terminated by such an operation LIR BranchOps now control whether or not additional unconditional jump is emitted (obviating the need for the ControlFlowOptimizer to eliminate such jumps)
author Doug Simon <doug.simon@oracle.com>
date Mon, 09 Dec 2013 15:24:27 +0100
parents 58d8de1f384b
children 8950e87ffcc9 ce017d1e4234
files graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java
diffstat 18 files changed, 374 insertions(+), 470 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Dec 09 15:24:27 2013 +0100
@@ -224,18 +224,18 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         switch (left.getKind().getStackKind()) {
             case Int:
             case Long:
             case Object:
-                append(new BranchOp(finalCondition, label));
+                append(new BranchOp(finalCondition, trueLabel, falseLabel));
                 break;
             case Float:
             case Double:
-                append(new FloatBranchOp(finalCondition, unorderedIsTrue, label));
+                append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -250,14 +250,22 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef destination, boolean negated) {
-        append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, destination));
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated) {
+        if (negated) {
+            append(new BranchOp(ConditionFlag.NoOverflow, noOverflow, overflow));
+        } else {
+            append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow));
+        }
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination) {
         emitIntegerTest(left, right);
-        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label));
+        if (negated) {
+            append(new BranchOp(Condition.NE, falseDestination, trueDestination));
+        } else {
+            append(new BranchOp(Condition.EQ, trueDestination, falseDestination));
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Dec 09 15:24:27 2013 +0100
@@ -44,7 +44,6 @@
 import com.oracle.graal.lir.hsail.HSAILArithmetic.ShiftOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.CompareBranchOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.FloatCompareBranchOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.FloatCondMoveOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ReturnOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.SwitchOp;
@@ -191,8 +190,8 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
-        // We don't have top worry about mirroring the condition on HSAIL.
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination) {
+        // We don't have to worry about mirroring the condition on HSAIL.
         Condition finalCondition = cond;
         Variable result = newVariable(left.getKind());
         Kind kind = left.getKind().getStackKind();
@@ -200,11 +199,11 @@
             case Int:
             case Long:
             case Object:
-                append(new CompareBranchOp(mapKindToCompareOp(kind), finalCondition, left, right, result, result, label));
+                append(new CompareBranchOp(mapKindToCompareOp(kind), finalCondition, left, right, result, result, trueDestination, falseDestination, false));
                 break;
             case Float:
             case Double:
-                append(new FloatCompareBranchOp(mapKindToCompareOp(kind), finalCondition, left, right, result, result, label, unorderedIsTrue));
+                append(new CompareBranchOp(mapKindToCompareOp(kind), finalCondition, left, right, result, result, trueDestination, falseDestination, unorderedIsTrue));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -212,12 +211,12 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated) {
         throw GraalInternalError.unimplemented();
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination) {
         throw GraalInternalError.unimplemented();
     }
 
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Dec 09 15:24:27 2013 +0100
@@ -294,27 +294,27 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination) {
         switch (left.getKind().getStackKind()) {
             case Int:
                 append(new CompareOp(ICMP, cond, left, right, nextPredRegNum));
-                append(new BranchOp(cond, label, nextPredRegNum++));
+                append(new BranchOp(cond, trueDestination, falseDestination, nextPredRegNum++));
                 break;
             case Long:
                 append(new CompareOp(LCMP, cond, left, right, nextPredRegNum));
-                append(new BranchOp(cond, label, nextPredRegNum++));
+                append(new BranchOp(cond, trueDestination, falseDestination, nextPredRegNum++));
                 break;
             case Float:
                 append(new CompareOp(FCMP, cond, left, right, nextPredRegNum));
-                append(new BranchOp(cond, label, nextPredRegNum++));
+                append(new BranchOp(cond, trueDestination, falseDestination, nextPredRegNum++));
                 break;
             case Double:
                 append(new CompareOp(DCMP, cond, left, right, nextPredRegNum));
-                append(new BranchOp(cond, label, nextPredRegNum++));
+                append(new BranchOp(cond, trueDestination, falseDestination, nextPredRegNum++));
                 break;
             case Object:
                 append(new CompareOp(ACMP, cond, left, right, nextPredRegNum));
-                append(new BranchOp(cond, label, nextPredRegNum++));
+                append(new BranchOp(cond, trueDestination, falseDestination, nextPredRegNum++));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -322,12 +322,12 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitOverflowCheckBranch()");
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination) {
         // / emitIntegerTest(left, right);
         // append(new BranchOp(negated ? Condition.NE : Condition.EQ, label));
         throw GraalInternalError.unimplemented("emitIntegerTestBranch()");
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Dec 09 15:24:27 2013 +0100
@@ -231,7 +231,7 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         Kind kind = left.getKind().getStackKind();
@@ -239,7 +239,7 @@
             case Int:
             case Long:
             case Object:
-                append(new BranchOp(finalCondition, label, kind));
+                append(new BranchOp(finalCondition, trueDestination, falseDestination, kind));
                 break;
             // case Float:
             // append(new CompareOp(FCMP, x, y));
@@ -255,15 +255,15 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated) {
         // append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, label));
         throw GraalInternalError.unimplemented();
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination) {
         emitIntegerTest(left, right);
-        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label, left.getKind().getStackKind()));
+        append(new BranchOp(negated ? Condition.NE : Condition.EQ, trueDestination, falseDestination, left.getKind().getStackKind()));
     }
 
     private void emitIntegerTest(Value a, Value b) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Dec 09 15:24:27 2013 +0100
@@ -25,6 +25,7 @@
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.api.meta.Value.*;
+import static com.oracle.graal.lir.LIR.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
 import static com.oracle.graal.nodes.ConstantNode.*;
 import static com.oracle.graal.phases.GraalOptions.*;
@@ -39,7 +40,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.nodes.*;
@@ -395,13 +396,14 @@
                 }
             }
         }
-        if (block.getSuccessorCount() >= 1 && !endsWithJump(block)) {
+        if (block.getSuccessorCount() >= 1 && !hasBlockEnd(block)) {
             NodeClassIterable successors = block.getEndNode().successors();
             assert successors.isNotEmpty() : "should have at least one successor : " + block.getEndNode();
-
             emitJump(getLIRBlock((FixedNode) successors.first()));
         }
 
+        assert verifyBlock(lir, block);
+
         if (traceLevel >= 1) {
             TTY.println("END Generating LIR for block B" + block.getId());
         }
@@ -421,18 +423,12 @@
 
     protected abstract boolean peephole(ValueNode valueNode);
 
-    private boolean endsWithJump(Block block) {
-        List<LIRInstruction> instructions = lir.lir(block);
-        if (instructions.size() == 0) {
+    private boolean hasBlockEnd(Block block) {
+        List<LIRInstruction> ops = lir.lir(block);
+        if (ops.size() == 0) {
             return false;
         }
-        LIRInstruction lirInstruction = instructions.get(instructions.size() - 1);
-        if (lirInstruction instanceof StandardOp.JumpOp) {
-            return true;
-        } else if (lirInstruction instanceof FallThroughOp) {
-            return ((FallThroughOp) lirInstruction).fallThroughTarget() != null;
-        }
-        return false;
+        return ops.get(ops.size() - 1) instanceof BlockEndOp;
     }
 
     private void doRoot(ValueNode instr) {
@@ -569,23 +565,19 @@
     }
 
     private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor) {
-        emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor);
-        emitJump(trueSuccessor);
+        emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, falseSuccessor);
     }
 
-    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
-        emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock);
-        emitJump(trueSuccessorBlock);
+    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+        emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor);
     }
 
     public void emitOverflowCheckBranch(LabelRef noOverflowBlock, LabelRef overflowBlock) {
-        emitOverflowCheckBranch(overflowBlock, false);
-        emitJump(noOverflowBlock);
+        emitOverflowCheckBranch(overflowBlock, noOverflowBlock, false);
     }
 
-    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
-        emitIntegerTestBranch(operand(test.x()), operand(test.y()), true, falseSuccessorBlock);
-        emitJump(trueSuccessorBlock);
+    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+        emitIntegerTestBranch(operand(test.x()), operand(test.y()), false, trueSuccessor, falseSuccessor);
     }
 
     public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
@@ -619,11 +611,11 @@
 
     public abstract void emitJump(LabelRef label);
 
-    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label);
+    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination);
 
-    public abstract void emitOverflowCheckBranch(LabelRef label, boolean negated);
+    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, boolean negated);
 
-    public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label);
+    public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef trueDestination, LabelRef falseDestination);
 
     public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Mon Dec 09 15:24:27 2013 +0100
@@ -26,11 +26,12 @@
 
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
 @Opcode("DEOPT")
-final class AMD64DeoptimizeOp extends AMD64LIRInstruction {
+final class AMD64DeoptimizeOp extends AMD64LIRInstruction implements BlockEndOp {
 
     @State private LIRFrameState info;
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Mon Dec 09 15:24:27 2013 +0100
@@ -30,13 +30,14 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
  * Superclass for operations that use the value of RBP saved in a method's prologue.
  */
-abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction {
+abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction implements BlockEndOp {
 
     /**
      * The type of location (i.e., stack or register) in which RBP is saved is not known until
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Dec 09 15:24:27 2013 +0100
@@ -24,7 +24,6 @@
 
 import static com.oracle.graal.api.code.UnsignedMath.*;
 import static com.oracle.graal.api.meta.MetaUtil.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.Options.*;
 import static com.oracle.graal.nodes.PiArrayNode.*;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Mon Dec 09 15:24:27 2013 +0100
@@ -35,11 +35,10 @@
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.calc.*;
 
-// @formatter:off
 public class AMD64ControlFlow {
 
     public static class ReturnOp extends AMD64LIRInstruction {
@@ -56,60 +55,54 @@
         }
     }
 
+    public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp {
+        protected final ConditionFlag condition;
+        protected final LabelRef trueDestination;
+        protected final LabelRef falseDestination;
 
-    public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp {
-        protected ConditionFlag condition;
-        protected LabelRef destination;
-
-        public BranchOp(Condition condition, LabelRef destination) {
-            this(intCond(condition), destination);
+        public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination) {
+            this(intCond(condition), trueDestination, falseDestination);
         }
 
-        public BranchOp(ConditionFlag condition, LabelRef destination) {
+        public BranchOp(ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination) {
             this.condition = condition;
-            this.destination = destination;
+            this.trueDestination = trueDestination;
+            this.falseDestination = falseDestination;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            masm.jcc(condition, destination.label());
-        }
-
-        @Override
-        public LabelRef destination() {
-            return destination;
+            int sourceIndex = crb.getCurrentBlockIndex();
+            if (trueDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                jcc(masm, true, falseDestination);
+            } else {
+                jcc(masm, false, trueDestination);
+                if (!falseDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                    masm.jmp(falseDestination.label());
+                }
+            }
         }
 
-        @Override
-        public void negate(LabelRef newDestination) {
-            destination = newDestination;
-            condition = condition.negate();
+        protected void jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target) {
+            masm.jcc(negate ? condition.negate() : condition, target.label());
         }
     }
 
-
     public static class FloatBranchOp extends BranchOp {
         protected boolean unorderedIsTrue;
 
-        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination) {
-            super(floatCond(condition), destination);
+        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination) {
+            super(floatCond(condition), trueDestination, falseDestination);
             this.unorderedIsTrue = unorderedIsTrue;
         }
 
         @Override
-        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            floatJcc(masm, condition, unorderedIsTrue, destination.label());
-        }
-
-        @Override
-        public void negate(LabelRef newDestination) {
-            super.negate(newDestination);
-            unorderedIsTrue = !unorderedIsTrue;
+        protected void jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target) {
+            floatJcc(masm, negate ? condition.negate() : condition, negate ? !unorderedIsTrue : unorderedIsTrue, target.label());
         }
     }
 
-
-    public static class TableSwitchOp extends AMD64LIRInstruction {
+    public static class TableSwitchOp extends AMD64LIRInstruction implements BlockEndOp {
         private final int lowKey;
         private final LabelRef defaultTarget;
         private final LabelRef[] targets;
@@ -130,7 +123,7 @@
         }
     }
 
-    public static class SequentialSwitchOp extends AMD64LIRInstruction implements FallThroughOp {
+    public static class SequentialSwitchOp extends AMD64LIRInstruction implements BlockEndOp {
         @Use({CONST}) protected Constant[] keyConstants;
         private final LabelRef[] keyTargets;
         private LabelRef defaultTarget;
@@ -176,25 +169,13 @@
             } else {
                 throw new GraalInternalError("sequential switch only supported for int, long and object");
             }
-            if (defaultTarget != null) {
+            if (!defaultTarget.isCodeEmittingOrderSuccessorEdge(crb.getCurrentBlockIndex())) {
                 masm.jmp(defaultTarget.label());
-            } else {
-                masm.hlt();
             }
         }
-
-        @Override
-        public LabelRef fallThroughTarget() {
-            return defaultTarget;
-        }
-
-        @Override
-        public void setFallThroughTarget(LabelRef target) {
-            defaultTarget = target;
-        }
     }
 
-    public static class SwitchRangesOp extends AMD64LIRInstruction implements FallThroughOp {
+    public static class SwitchRangesOp extends AMD64LIRInstruction implements BlockEndOp {
         private final LabelRef[] keyTargets;
         private LabelRef defaultTarget;
         private final int[] lowKeys;
@@ -234,8 +215,11 @@
                 }
                 prevHighKey = highKey;
             }
+
             if (defaultTarget != null) {
-                masm.jmp(defaultTarget.label());
+                if (!defaultTarget.isCodeEmittingOrderSuccessorEdge(crb.getCurrentBlockIndex())) {
+                    masm.jmp(defaultTarget.label());
+                }
             } else {
                 masm.bind(actualDefaultTarget);
                 masm.hlt();
@@ -250,16 +234,6 @@
             assert key.getKind() == Kind.Int;
         }
 
-        @Override
-        public LabelRef fallThroughTarget() {
-            return defaultTarget;
-        }
-
-        @Override
-        public void setFallThroughTarget(LabelRef target) {
-            defaultTarget = target;
-        }
-
         private static boolean isSorted(int[] values) {
             for (int i = 1; i < values.length; i++) {
                 if (values[i - 1] >= values[i]) {
@@ -270,7 +244,6 @@
         }
     }
 
-
     @Opcode("CMOVE")
     public static class CondMoveOp extends AMD64LIRInstruction {
         @Def({REG, HINT}) protected Value result;
@@ -291,7 +264,6 @@
         }
     }
 
-
     @Opcode("CMOVE")
     public static class FloatCondMoveOp extends AMD64LIRInstruction {
         @Def({REG}) protected Value result;
@@ -403,50 +375,78 @@
         if (isRegister(other)) {
             assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move";
             switch (other.getKind()) {
-                case Int:  masm.cmovl(cond, asRegister(result), asRegister(other)); break;
-                case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break;
-                default:   throw GraalInternalError.shouldNotReachHere();
+                case Int:
+                    masm.cmovl(cond, asRegister(result), asRegister(other));
+                    break;
+                case Long:
+                    masm.cmovq(cond, asRegister(result), asRegister(other));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
         } else {
             AMD64Address addr = (AMD64Address) crb.asAddress(other);
             switch (other.getKind()) {
-                case Int:  masm.cmovl(cond, asRegister(result), addr); break;
-                case Long: masm.cmovq(cond, asRegister(result), addr); break;
-                default:   throw GraalInternalError.shouldNotReachHere();
+                case Int:
+                    masm.cmovl(cond, asRegister(result), addr);
+                    break;
+                case Long:
+                    masm.cmovq(cond, asRegister(result), addr);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
         }
     }
 
     private static ConditionFlag intCond(Condition cond) {
         switch (cond) {
-            case EQ: return ConditionFlag.Equal;
-            case NE: return ConditionFlag.NotEqual;
-            case LT: return ConditionFlag.Less;
-            case LE: return ConditionFlag.LessEqual;
-            case GE: return ConditionFlag.GreaterEqual;
-            case GT: return ConditionFlag.Greater;
-            case BE: return ConditionFlag.BelowEqual;
-            case AE: return ConditionFlag.AboveEqual;
-            case AT: return ConditionFlag.Above;
-            case BT: return ConditionFlag.Below;
-            default: throw GraalInternalError.shouldNotReachHere();
+            case EQ:
+                return ConditionFlag.Equal;
+            case NE:
+                return ConditionFlag.NotEqual;
+            case LT:
+                return ConditionFlag.Less;
+            case LE:
+                return ConditionFlag.LessEqual;
+            case GE:
+                return ConditionFlag.GreaterEqual;
+            case GT:
+                return ConditionFlag.Greater;
+            case BE:
+                return ConditionFlag.BelowEqual;
+            case AE:
+                return ConditionFlag.AboveEqual;
+            case AT:
+                return ConditionFlag.Above;
+            case BT:
+                return ConditionFlag.Below;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     private static ConditionFlag floatCond(Condition cond) {
         switch (cond) {
-            case EQ: return ConditionFlag.Equal;
-            case NE: return ConditionFlag.NotEqual;
-            case LT: return ConditionFlag.Below;
-            case LE: return ConditionFlag.BelowEqual;
-            case GE: return ConditionFlag.AboveEqual;
-            case GT: return ConditionFlag.Above;
-            default: throw GraalInternalError.shouldNotReachHere();
+            case EQ:
+                return ConditionFlag.Equal;
+            case NE:
+                return ConditionFlag.NotEqual;
+            case LT:
+                return ConditionFlag.Below;
+            case LE:
+                return ConditionFlag.BelowEqual;
+            case GE:
+                return ConditionFlag.AboveEqual;
+            case GT:
+                return ConditionFlag.Above;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     private static boolean trueOnUnordered(ConditionFlag condition) {
-        switch(condition) {
+        switch (condition) {
             case AboveEqual:
             case NotEqual:
             case Above:
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Mon Dec 09 15:24:27 2013 +0100
@@ -28,7 +28,7 @@
 import com.oracle.graal.asm.hsail.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.calc.*;
 
@@ -46,7 +46,7 @@
      * performing HSAIL code. Thus the execution path for both the TABLESWITCH and LOOKUPSWITCH
      * bytecodes go through this op.
      */
-    public static class SwitchOp extends HSAILLIRInstruction implements FallThroughOp {
+    public static class SwitchOp extends HSAILLIRInstruction implements BlockEndOp {
         /**
          * The array of key constants used for the cases of this switch statement.
          */
@@ -78,25 +78,6 @@
         }
 
         /**
-         * Get the default target for this switch op.
-         */
-        @Override
-        public LabelRef fallThroughTarget() {
-            return defaultTarget;
-        }
-
-        /**
-         * Set the default target.
-         * 
-         * @param target the default target
-         */
-        @Override
-        public void setFallThroughTarget(LabelRef target) {
-            defaultTarget = target;
-
-        }
-
-        /**
          * Generates the code for this switch op.
          * 
          * The keys for switch statements in Java bytecode for of type int. However, Graal also
@@ -116,7 +97,7 @@
                     masm.cbr(masm.nameOf(keyTargets[i].label()));
                 }
                 // Generate a jump for the default target if there is one.
-                if (defaultTarget != null) {
+                if (defaultTarget != null && !defaultTarget.isCodeEmittingOrderSuccessorEdge(crb.getCurrentBlockIndex())) {
                     masm.jmp(defaultTarget.label());
                 }
 
@@ -127,7 +108,7 @@
         }
     }
 
-    public static class ReturnOp extends HSAILLIRInstruction {
+    public static class ReturnOp extends HSAILLIRInstruction implements BlockEndOp {
 
         @Use({REG, ILLEGAL}) protected Value x;
 
@@ -184,119 +165,37 @@
         @Use({REG, CONST}) protected Value x;
         @Use({REG, CONST}) protected Value y;
         @Def({REG}) protected Value z;
-        protected Condition condition;
-        protected LabelRef destination;
-        protected boolean unordered = false;
+        protected final Condition condition;
+        protected final LabelRef trueDestination;
+        protected final LabelRef falseDestination;
         @Def({REG}) protected Value result;
+        protected final boolean unordered;
 
-        public CompareBranchOp(HSAILCompare opcode, Condition condition, Value x, Value y, Value z, Value result, LabelRef destination) {
+        public CompareBranchOp(HSAILCompare opcode, Condition condition, Value x, Value y, Value z, Value result, LabelRef trueDestination, LabelRef falseDestination, boolean unordered) {
             this.condition = condition;
             this.opcode = opcode;
             this.x = x;
             this.y = y;
             this.z = z;
             this.result = result;
-            this.destination = destination;
-        }
-
-        @Override
-        public LabelRef destination() {
-            return destination;
-        }
-
-        @Override
-        public void negate(LabelRef newDestination) {
-            destination = newDestination;
-            condition = condition.negate();
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            HSAILCompare.emit(crb, masm, condition, x, y, z, unordered);
-            masm.cbr(masm.nameOf(destination.label()));
-        }
-    }
-
-    public static class FloatCompareBranchOp extends CompareBranchOp {
-
-        public FloatCompareBranchOp(HSAILCompare opcode, Condition condition, Value x, Value y, Value z, Value result, LabelRef destination, boolean unordered) {
-            super(opcode, condition, x, y, z, result, destination);
-            this.unordered = unordered;
-        }
-
-        @Override
-        public void negate(LabelRef newDestination) {
-            destination = newDestination;
-            condition = condition.negate();
-            unordered = !unordered;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            HSAILCompare.emit(crb, masm, condition, x, y, z, unordered);
-            masm.cbr(masm.nameOf(destination.label()));
-        }
-    }
-
-    public static class DoubleCompareBranchOp extends CompareBranchOp {
-
-        public DoubleCompareBranchOp(HSAILCompare opcode, Condition condition, Value x, Value y, Value z, Value result, LabelRef destination, boolean unordered) {
-            super(opcode, condition, x, y, z, result, destination);
+            this.trueDestination = trueDestination;
+            this.falseDestination = falseDestination;
             this.unordered = unordered;
         }
 
         @Override
-        public void negate(LabelRef newDestination) {
-            destination = newDestination;
-            condition = condition.negate();
-            unordered = !unordered;
-        }
-
-        @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            HSAILCompare.emit(crb, masm, condition, x, y, z, unordered);
-            masm.cbr(masm.nameOf(destination.label()));
-        }
-    }
-
-    public static class BranchOp extends HSAILLIRInstruction implements StandardOp.BranchOp {
-
-        protected Condition condition;
-        protected LabelRef destination;
-        @Def({REG}) protected Value result;
-
-        public BranchOp(Condition condition, Value result, LabelRef destination) {
-            this.condition = condition;
-            this.destination = destination;
-            this.result = result;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            masm.cbr(masm.nameOf(destination.label()));
-        }
-
-        @Override
-        public LabelRef destination() {
-            return destination;
-        }
-
-        @Override
-        public void negate(LabelRef newDestination) {
-            destination = newDestination;
-            condition = condition.negate();
-        }
-    }
-
-    public static class FloatBranchOp extends BranchOp {
-
-        public FloatBranchOp(Condition condition, Value result, LabelRef destination) {
-            super(condition, result, destination);
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            masm.cbr(masm.nameOf(destination.label()));
+            int sourceIndex = crb.getCurrentBlockIndex();
+            if (trueDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                HSAILCompare.emit(crb, masm, condition.negate(), x, y, z, !unordered);
+                masm.cbr(masm.nameOf(falseDestination.label()));
+            } else {
+                HSAILCompare.emit(crb, masm, condition, x, y, z, unordered);
+                masm.cbr(masm.nameOf(trueDestination.label()));
+                if (!falseDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                    masm.jmp(falseDestination.label());
+                }
+            }
         }
     }
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Dec 09 15:24:27 2013 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.lir.ptx;
 
-import static com.oracle.graal.asm.ptx.PTXAssembler.*;
-import static com.oracle.graal.asm.ptx.PTXMacroAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
 import static com.oracle.graal.nodes.calc.Condition.*;
@@ -32,9 +30,12 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.ptx.*;
+import com.oracle.graal.asm.ptx.PTXAssembler.Global;
+import com.oracle.graal.asm.ptx.PTXAssembler.Setp;
+import com.oracle.graal.asm.ptx.PTXMacroAssembler.Mov;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.calc.*;
 
@@ -69,30 +70,29 @@
 
     public static class BranchOp extends PTXLIRInstruction implements StandardOp.BranchOp {
 
-        protected Condition condition;
-        protected LabelRef destination;
+        protected final Condition condition;
+        protected final LabelRef trueDestination;
+        protected final LabelRef falseDestination;
         protected int predRegNum;
 
-        public BranchOp(Condition condition, LabelRef destination, int predReg) {
+        public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, int predReg) {
             this.condition = condition;
-            this.destination = destination;
+            this.trueDestination = trueDestination;
+            this.falseDestination = falseDestination;
             this.predRegNum = predReg;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) {
-            masm.bra(masm.nameOf(destination.label()), predRegNum);
-        }
-
-        @Override
-        public LabelRef destination() {
-            return destination;
-        }
-
-        @Override
-        public void negate(LabelRef newDestination) {
-            destination = newDestination;
-            condition = condition.negate();
+            int sourceIndex = crb.getCurrentBlockIndex();
+            if (trueDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                masm.bra(masm.nameOf(falseDestination.label()), predRegNum);
+            } else {
+                masm.bra(masm.nameOf(trueDestination.label()));
+                if (!falseDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                    masm.jmp(falseDestination.label());
+                }
+            }
         }
     }
 
@@ -193,7 +193,7 @@
         }
     }
 
-    public static class SequentialSwitchOp extends PTXLIRInstruction implements FallThroughOp {
+    public static class SequentialSwitchOp extends PTXLIRInstruction implements BlockEndOp {
 
         @Use({CONST}) protected Constant[] keyConstants;
         private final LabelRef[] keyTargets;
@@ -235,24 +235,16 @@
                 throw new GraalInternalError("sequential switch only supported for int, long and object");
             }
             if (defaultTarget != null) {
-                masm.jmp(defaultTarget.label());
+                if (!defaultTarget.isCodeEmittingOrderSuccessorEdge(crb.getCurrentBlockIndex())) {
+                    masm.jmp(defaultTarget.label());
+                }
             } else {
                 // masm.hlt();
             }
         }
-
-        @Override
-        public LabelRef fallThroughTarget() {
-            return defaultTarget;
-        }
-
-        @Override
-        public void setFallThroughTarget(LabelRef target) {
-            defaultTarget = target;
-        }
     }
 
-    public static class TableSwitchOp extends PTXLIRInstruction {
+    public static class TableSwitchOp extends PTXLIRInstruction implements BlockEndOp {
 
         private final int lowKey;
         private final LabelRef defaultTarget;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Dec 09 15:24:27 2013 +0100
@@ -33,7 +33,7 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.calc.*;
 
@@ -43,66 +43,73 @@
 
     public static class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp {
 
-        protected Condition condition;
-        protected LabelRef destination;
+        protected final Condition condition;
+        protected final LabelRef trueDestination;
+        protected final LabelRef falseDestination;
         protected final Kind kind;
 
-        public BranchOp(Condition condition, LabelRef destination, Kind kind) {
+        public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind) {
             this.condition = condition;
-            this.destination = destination;
+            this.trueDestination = trueDestination;
+            this.falseDestination = falseDestination;
             this.kind = kind;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            int sourceIndex = crb.getCurrentBlockIndex();
+            Label actualTarget;
+            Condition actualCondition;
+            boolean needJump;
+            if (trueDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                actualCondition = condition.negate();
+                actualTarget = falseDestination.label();
+                needJump = false;
+            } else {
+                actualCondition = condition;
+                actualTarget = trueDestination.label();
+                needJump = !falseDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex);
+            }
             assert kind == Kind.Int || kind == Kind.Long || kind == Kind.Object;
             CC cc = kind == Kind.Int ? CC.Icc : CC.Xcc;
-            switch (condition) {
+            switch (actualCondition) {
                 case EQ:
-                    new Bpe(cc, destination.label()).emit(masm);
+                    new Bpe(cc, actualTarget).emit(masm);
                     break;
                 case NE:
-                    new Bpne(cc, destination.label()).emit(masm);
+                    new Bpne(cc, actualTarget).emit(masm);
                     break;
                 case BT:
-                    new Bplu(cc, destination.label()).emit(masm);
+                    new Bplu(cc, actualTarget).emit(masm);
                     break;
                 case LT:
-                    new Bpl(cc, destination.label()).emit(masm);
+                    new Bpl(cc, actualTarget).emit(masm);
                     break;
                 case BE:
-                    new Bpleu(cc, destination.label()).emit(masm);
+                    new Bpleu(cc, actualTarget).emit(masm);
                     break;
                 case LE:
-                    new Bple(cc, destination.label()).emit(masm);
+                    new Bple(cc, actualTarget).emit(masm);
                     break;
                 case GE:
-                    new Bpge(cc, destination.label()).emit(masm);
+                    new Bpge(cc, actualTarget).emit(masm);
                     break;
                 case AE:
-                    new Bpgeu(cc, destination.label()).emit(masm);
+                    new Bpgeu(cc, actualTarget).emit(masm);
                     break;
                 case GT:
-                    new Bpg(cc, destination.label()).emit(masm);
+                    new Bpg(cc, actualTarget).emit(masm);
                     break;
                 case AT:
-                    new Bpgu(cc, destination.label()).emit(masm);
+                    new Bpgu(cc, actualTarget).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
             new Nop().emit(masm);  // delay slot
-        }
-
-        @Override
-        public LabelRef destination() {
-            return destination;
-        }
-
-        @Override
-        public void negate(LabelRef newDestination) {
-            destination = newDestination;
-            condition = condition.negate();
+            if (needJump) {
+                masm.jmp(falseDestination.label());
+            }
         }
     }
 
@@ -257,7 +264,7 @@
         }
     }
 
-    public static class SequentialSwitchOp extends SPARCLIRInstruction implements FallThroughOp {
+    public static class SequentialSwitchOp extends SPARCLIRInstruction implements BlockEndOp {
 
         @Use({CONST}) protected Constant[] keyConstants;
         private final LabelRef[] keyTargets;
@@ -310,24 +317,16 @@
                 throw new GraalInternalError("sequential switch only supported for int, long and object");
             }
             if (defaultTarget != null) {
-                masm.jmp(defaultTarget.label());
+                if (!defaultTarget.isCodeEmittingOrderSuccessorEdge(crb.getCurrentBlockIndex())) {
+                    masm.jmp(defaultTarget.label());
+                }
             } else {
                 new Illtrap(0).emit(masm);
             }
         }
-
-        @Override
-        public LabelRef fallThroughTarget() {
-            return defaultTarget;
-        }
-
-        @Override
-        public void setFallThroughTarget(LabelRef target) {
-            defaultTarget = target;
-        }
     }
 
-    public static class SwitchRangesOp extends SPARCLIRInstruction implements FallThroughOp {
+    public static class SwitchRangesOp extends SPARCLIRInstruction implements BlockEndOp {
 
         private final LabelRef[] keyTargets;
         private LabelRef defaultTarget;
@@ -368,11 +367,14 @@
                 }
                 prevHighKey = highKey;
             }
+
             if (defaultTarget != null) {
-                new Bpa(defaultTarget.label()).emit(masm);
+                if (!defaultTarget.isCodeEmittingOrderSuccessorEdge(crb.getCurrentBlockIndex())) {
+                    new Bpa(defaultTarget.label()).emit(masm);
+                }
             } else {
                 masm.bind(actualDefaultTarget);
-                // masm.hlt();
+                new Illtrap(0).emit(masm);
             }
             throw GraalInternalError.unimplemented();
         }
@@ -385,16 +387,6 @@
             assert key.getKind() == Kind.Int;
         }
 
-        @Override
-        public LabelRef fallThroughTarget() {
-            return defaultTarget;
-        }
-
-        @Override
-        public void setFallThroughTarget(LabelRef target) {
-            defaultTarget = target;
-        }
-
         private static boolean isSorted(int[] values) {
             for (int i = 1; i < values.length; i++) {
                 if (values[i - 1] >= values[i]) {
@@ -405,7 +397,7 @@
         }
     }
 
-    public static class TableSwitchOp extends SPARCLIRInstruction {
+    public static class TableSwitchOp extends SPARCLIRInstruction implements BlockEndOp {
 
         private final int lowKey;
         private final LabelRef defaultTarget;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Mon Dec 09 15:24:27 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.lir;
 
+import static com.oracle.graal.lir.LIR.*;
+
 import java.util.*;
 
 import com.oracle.graal.debug.*;
@@ -35,10 +37,9 @@
     /**
      * Performs control flow optimizations on the given LIR graph.
      */
-    public static void optimize(LIR ir) {
-        List<Block> blocks = ir.codeEmittingOrder();
-        ControlFlowOptimizer.deleteEmptyBlocks(ir, blocks);
-        ControlFlowOptimizer.deleteUnnecessaryJumps(ir, blocks);
+    public static void optimize(LIR lir) {
+        List<Block> blocks = lir.codeEmittingOrder();
+        ControlFlowOptimizer.deleteEmptyBlocks(lir, blocks);
     }
 
     private ControlFlowOptimizer() {
@@ -51,28 +52,28 @@
      * @param block the block checked for deletion
      * @return whether the block can be deleted
      */
-    private static boolean canDeleteBlock(LIR ir, Block block) {
+    private static boolean canDeleteBlock(LIR lir, Block block) {
         if (block.getSuccessorCount() != 1 || block.getPredecessorCount() == 0 || block.getFirstSuccessor() == block) {
             return false;
         }
 
-        List<LIRInstruction> instructions = ir.lir(block);
+        List<LIRInstruction> instructions = lir.lir(block);
 
         assert instructions.size() >= 2 : "block must have label and branch";
         assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label";
         assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "last instruction must always be a branch";
-        assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) ir.lir(block.getFirstSuccessor()).get(0)).getLabel() : "branch target must be the successor";
+        assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.lir(block.getFirstSuccessor()).get(0)).getLabel() : "branch target must be the successor";
 
         // Block must have exactly one successor.
         return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState();
     }
 
-    private static void deleteEmptyBlocks(LIR ir, List<Block> blocks) {
-        assert verify(blocks);
+    private static void deleteEmptyBlocks(LIR lir, List<Block> blocks) {
+        assert verifyBlocks(lir, blocks);
         Iterator<Block> iterator = blocks.iterator();
         while (iterator.hasNext()) {
             Block block = iterator.next();
-            if (canDeleteBlock(ir, block)) {
+            if (canDeleteBlock(lir, block)) {
                 // adjust successor and predecessor lists
                 Block other = block.getFirstSuccessor();
                 for (Block pred : block.getPredecessors()) {
@@ -90,51 +91,6 @@
                 iterator.remove();
             }
         }
-        assert verify(blocks);
-    }
-
-    private static void deleteUnnecessaryJumps(LIR ir, List<Block> blocks) {
-        // skip the last block because there a branch is always necessary
-        for (int i = blocks.size() - 2; i >= 0; i--) {
-            Block block = blocks.get(i);
-            List<LIRInstruction> instructions = ir.lir(block);
-
-            LIRInstruction lastOp = instructions.get(instructions.size() - 1);
-            if (lastOp instanceof StandardOp.JumpOp) {
-                StandardOp.JumpOp lastJump = (StandardOp.JumpOp) lastOp;
-
-                if (!lastOp.hasState()) {
-                    if (lastJump.destination().label() == ((StandardOp.LabelOp) ir.lir(blocks.get(i + 1)).get(0)).getLabel()) {
-                        // delete last branch instruction
-                        instructions.remove(instructions.size() - 1);
-                    } else {
-                        LIRInstruction prevOp = instructions.get(instructions.size() - 2);
-                        if (prevOp instanceof StandardOp.BranchOp) {
-                            StandardOp.BranchOp prevBranch = (StandardOp.BranchOp) prevOp;
-
-                            if (prevBranch.destination().label() == ((StandardOp.LabelOp) ir.lir(blocks.get(i + 1)).get(0)).getLabel() && !prevOp.hasState()) {
-                                // eliminate a conditional branch to the immediate successor
-                                prevBranch.negate(lastJump.destination());
-                                instructions.remove(instructions.size() - 1);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        assert verify(blocks);
-    }
-
-    private static boolean verify(List<Block> code) {
-        for (Block block : code) {
-            for (Block sux : block.getSuccessors()) {
-                assert code.contains(sux) : "missing successor from: " + block + "to: " + sux;
-            }
-            for (Block pred : block.getPredecessors()) {
-                assert code.contains(pred) : "missing predecessor from: " + block + "to: " + pred;
-            }
-        }
-
-        return true;
+        assert verifyBlocks(lir, blocks);
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Mon Dec 09 15:24:27 2013 +0100
@@ -183,23 +183,14 @@
         assert numSux == 2 : "method should not be called otherwise";
 
         LIRInstruction lastInstruction = instructions.get(instructions.size() - 1);
-        if (lastInstruction instanceof StandardOp.FallThroughOp) {
-            assert ((StandardOp.FallThroughOp) lastInstruction).fallThroughTarget() != null : "block must end with unconditional jump";
-            // fall through ops like switches cannot be optimized anyway - they have input operands
-            return;
-        } else {
-            assert lastInstruction instanceof StandardOp.JumpOp : "block must end with unconditional jump";
-        }
-
         if (lastInstruction.hasState()) {
             // cannot optimize instructions when debug info is needed
             return;
         }
 
-        LIRInstruction branch = instructions.get(instructions.size() - 2);
+        LIRInstruction branch = lastInstruction;
         if (!(branch instanceof StandardOp.BranchOp) || branch.hasOperands()) {
-            // Only blocks that end with two branches (conditional branch followed
-            // by unconditional branch) are optimized.
+            // Only blocks that end with a conditional branch are optimized.
             // In addition, a conditional branch with operands (including state) cannot
             // be optimized. Moving a successor instruction before such a branch may
             // interfere with the operands of the branch. For example, a successive move
@@ -207,9 +198,9 @@
             return;
         }
 
-        // now it is guaranteed that the block ends with two branch instructions.
-        // the instructions are inserted at the end of the block before these two branches
-        int insertIdx = instructions.size() - 2;
+        // Now it is guaranteed that the block ends with a conditional branch.
+        // The instructions are inserted at the end of the block before the branch.
+        int insertIdx = instructions.size() - 1;
 
         // setup a list with the lir-instructions of all successors
         for (Block sux : block.getSuccessors()) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Dec 09 15:24:27 2013 +0100
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -139,7 +140,11 @@
     public void emitCode(CompilationResultBuilder crb) {
         crb.frameContext.enter(crb);
 
-        for (Block b : codeEmittingOrder()) {
+        // notifyBlocksOfSuccessors();
+
+        int index = 0;
+        for (Block b : codeEmittingOrder) {
+            crb.setCurrentBlockIndex(index++);
             emitBlock(crb, b);
         }
     }
@@ -154,21 +159,21 @@
                 crb.blockComment(String.format("%d %s", op.id(), op));
             }
 
-            emitOp(crb, op);
+            try {
+                emitOp(crb, op);
+            } catch (GraalInternalError e) {
+                throw e.addContext("lir instruction", block + "@" + op.id() + " " + op + "\n" + codeEmittingOrder);
+            }
         }
     }
 
     private static void emitOp(CompilationResultBuilder crb, LIRInstruction op) {
         try {
-            try {
-                op.emitCode(crb);
-            } catch (AssertionError t) {
-                throw new GraalInternalError(t);
-            } catch (RuntimeException t) {
-                throw new GraalInternalError(t);
-            }
-        } catch (GraalInternalError e) {
-            throw e.addContext("lir instruction", op);
+            op.emitCode(crb);
+        } catch (AssertionError t) {
+            throw new GraalInternalError(t);
+        } catch (RuntimeException t) {
+            throw new GraalInternalError(t);
         }
     }
 
@@ -183,4 +188,30 @@
     public boolean hasArgInCallerFrame() {
         return hasArgInCallerFrame;
     }
+
+    public static boolean verifyBlock(LIR lir, Block block) {
+        List<LIRInstruction> ops = lir.lir(block);
+        if (ops.size() == 0) {
+            return true;
+        }
+        for (LIRInstruction op : ops.subList(0, ops.size() - 1)) {
+            assert !(op instanceof BlockEndOp) : op.getClass();
+        }
+        LIRInstruction end = ops.get(ops.size() - 1);
+        assert end instanceof BlockEndOp : end.getClass();
+        return true;
+    }
+
+    public static boolean verifyBlocks(LIR lir, List<Block> blocks) {
+        for (Block block : blocks) {
+            for (Block sux : block.getSuccessors()) {
+                assert blocks.contains(sux) : "missing successor from: " + block + "to: " + sux;
+            }
+            for (Block pred : block.getPredecessors()) {
+                assert blocks.contains(pred) : "missing predecessor from: " + block + "to: " + pred;
+            }
+            verifyBlock(lir, block);
+        }
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Mon Dec 09 15:24:27 2013 +0100
@@ -22,20 +22,26 @@
  */
 package com.oracle.graal.lir;
 
+import java.util.*;
+
 import com.oracle.graal.asm.*;
+import com.oracle.graal.lir.StandardOp.BranchOp;
+import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.nodes.cfg.*;
 
 /**
- * LIR instructions such as JUMP and BRANCH need to reference their target {@link Block}. However,
- * direct references are not possible since the control flow graph (and therefore successors lists)
- * can be changed by optimizations - and fixing the instructions is error prone. Therefore, we only
- * reference of block B from block A only via the tuple (A, successor-index-of-B), i.e., indirectly
- * by storing the index into the successor list of A. Note that therefore it is not allowed to
- * reorder the successor list!
+ * LIR instructions such as {@link JumpOp} and {@link BranchOp} need to reference their target
+ * {@link Block}. However, direct references are not possible since the control flow graph (and
+ * therefore successors lists) can be changed by optimizations - and fixing the instructions is
+ * error prone. Therefore, we represent an edge to block B from block A via the tuple {@code (A,
+ * successor-index-of-B)}. That is, indirectly by storing the index into the successor list of A.
+ * Note therefore that the successor list cannot be re-ordered.
  */
-public abstract class LabelRef {
+public final class LabelRef {
 
-    public abstract Label label();
+    private final LIR lir;
+    private final Block block;
+    private final int suxIndex;
 
     /**
      * Returns a new reference to a successor of the given block.
@@ -45,17 +51,48 @@
      * @return The newly created label reference.
      */
     public static LabelRef forSuccessor(final LIR lir, final Block block, final int suxIndex) {
-        return new LabelRef() {
+        return new LabelRef(lir, block, suxIndex);
+    }
+
+    /**
+     * Returns a new reference to a successor of the given block.
+     * 
+     * @param block The base block that contains the successor list.
+     * @param suxIndex The index of the successor.
+     */
+    private LabelRef(final LIR lir, final Block block, final int suxIndex) {
+        this.lir = lir;
+        this.block = block;
+        this.suxIndex = suxIndex;
+    }
+
+    public Block getSourceBlock() {
+        return block;
+    }
 
-            @Override
-            public Label label() {
-                return ((StandardOp.LabelOp) lir.lir(block.getSuccessors().get(suxIndex)).get(0)).getLabel();
-            }
+    public Block getTargetBlock() {
+        return block.getSuccessors().get(suxIndex);
+    }
+
+    public Label label() {
+        return ((StandardOp.LabelOp) lir.lir(getTargetBlock()).get(0)).getLabel();
+    }
 
-            @Override
-            public String toString() {
-                return suxIndex < block.getSuccessorCount() ? block.getSuccessors().get(suxIndex).toString() : "?" + block + ":" + suxIndex + "?";
-            }
-        };
+    /**
+     * Determines if the edge represented by this object is from a block to its lexical successor in
+     * the code emitting order of blocks.
+     * 
+     * @param sourceIndex the index of this edge's {@linkplain #getSourceBlock() source} in the code
+     *            emitting order
+     */
+    public boolean isCodeEmittingOrderSuccessorEdge(int sourceIndex) {
+        List<Block> order = lir.codeEmittingOrder();
+        assert order.get(sourceIndex) == block;
+        return sourceIndex < order.size() - 1 && order.get(sourceIndex + 1) == getTargetBlock();
+    }
+
+    @Override
+    public String toString() {
+        return suxIndex < block.getSuccessorCount() ? getTargetBlock().toString() : "?" + block + ":" + suxIndex + "?";
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Mon Dec 09 15:24:27 2013 +0100
@@ -40,15 +40,10 @@
 public class StandardOp {
 
     /**
-     * Marker interface for LIR ops that can fall through to the next operation, like a switch
-     * statement. setFallThroughTarget(null) can be used to make the operation fall through to the
-     * next one.
+     * A block delimiter. Every well formed block must contain exactly one such operation and it
+     * must be the last operation in the block.
      */
-    public interface FallThroughOp {
-
-        LabelRef fallThroughTarget();
-
-        void setFallThroughTarget(LabelRef target);
+    public interface BlockEndOp {
     }
 
     public interface NullCheck {
@@ -62,8 +57,7 @@
     }
 
     /**
-     * LIR operation that defines the position of a label. The first operation of every block must
-     * implement this interface.
+     * LIR operation that defines the position of a label.
      */
     public static class LabelOp extends LIRInstruction {
 
@@ -107,11 +101,9 @@
     }
 
     /**
-     * LIR operation that is an unconditional jump to {@link #destination()}. When the LIR is
-     * constructed, the last operation of every block must implement this interface. After register
-     * allocation, unnecessary jumps can be deleted.
+     * LIR operation that is an unconditional jump to a {@link #destination()}.
      */
-    public static class JumpOp extends LIRInstruction {
+    public static class JumpOp extends LIRInstruction implements BlockEndOp {
 
         private final LabelRef destination;
 
@@ -130,14 +122,9 @@
     }
 
     /**
-     * Marker interface for a LIR operation that is a conditional jump to {@link #destination()}.
-     * Conditional jumps may be negated or optimized away after register allocation.
+     * Marker interface for a LIR operation that is a conditional jump.
      */
-    public interface BranchOp {
-
-        LabelRef destination();
-
-        void negate(LabelRef newDestination);
+    public interface BranchOp extends BlockEndOp {
     }
 
     /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Mon Dec 09 15:21:45 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Mon Dec 09 15:24:27 2013 +0100
@@ -59,6 +59,11 @@
     public final FrameMap frameMap;
 
     /**
+     * The index of the block currently being processed in the code emitting block order.
+     */
+    private int currentBlockIndex;
+
+    /**
      * The object that emits code for managing a method's frame.
      */
     public final FrameContext frameContext;
@@ -278,4 +283,18 @@
         StackSlot slot = asStackSlot(value);
         return asm.makeAddress(frameMap.registerConfig.getFrameRegister(), frameMap.offsetForStackSlot(slot));
     }
+
+    /**
+     * Gets the index of the block currently being processed in the code emitting block order.
+     */
+    public int getCurrentBlockIndex() {
+        return currentBlockIndex;
+    }
+
+    /**
+     * Sets the index of the block currently being processed in the code emitting block order.
+     */
+    public void setCurrentBlockIndex(int index) {
+        this.currentBlockIndex = index;
+    }
 }