changeset 17207:5a7b82c1514e

[SPARC] Add functionality to be able to do assembly in two passes (knowing offsets of forward branches)
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Wed, 24 Sep 2014 16:13:34 -0700
parents 2d401b9ca70d
children d8f4c1e6b538
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Assembler.java graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Label.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCDelayedControlTransfer.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java
diffstat 12 files changed, 434 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Wed Sep 24 16:13:34 2014 -0700
@@ -785,4 +785,14 @@
     public String getName() {
         return name;
     }
+
+    public void reset() {
+        infopoints.clear();
+        dataReferences.clear();
+        exceptionHandlers.clear();
+        marks.clear();
+        if (annotations != null) {
+            annotations.clear();
+        }
+    }
 }
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Wed Sep 24 16:13:34 2014 -0700
@@ -687,6 +687,9 @@
 
         public void setDisp10(int disp10) {
             this.disp10 = disp10 >> 2;
+            if (!isSimm10(this.disp10)) {
+                throw GraalInternalError.shouldNotReachHere("" + this.disp10);
+            }
             assert isSimm10(this.disp10) : this.disp10;
         }
 
@@ -2273,7 +2276,11 @@
     }
 
     public static boolean isSimm11(Constant constant) {
-        return isSimm11(constant.asLong());
+        return constant.isNull() || isSimm11(constant.asLong());
+    }
+
+    public static boolean isSimm5(Constant constant) {
+        return constant.isNull() || isSimm(constant.asLong(), 5);
     }
 
     public static boolean isSimm13(int imm) {
@@ -2426,6 +2433,12 @@
             /* VIS1 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Array8, src1, src2, dst);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS1);
+            super.emit(masm);
+        }
     }
 
     public static class Array16 extends Fmt3p {
@@ -2434,6 +2447,12 @@
             /* VIS1 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Array16, src1, src2, dst);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS1);
+            super.emit(masm);
+        }
     }
 
     public static class Array32 extends Fmt3p {
@@ -2442,6 +2461,12 @@
             /* VIS1 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Array32, src1, src2, dst);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS2);
+            super.emit(masm);
+        }
     }
 
     public static class Bmask extends Fmt3p {
@@ -2450,6 +2475,12 @@
             /* VIS2 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Bmask, src1, src2, dst);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS2);
+            super.emit(masm);
+        }
     }
 
     public static class Movwtos extends Fmt3p {
@@ -2458,6 +2489,12 @@
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movwtos, g0, src, dst);
             assert isSingleFloatRegister(dst);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS3);
+            super.emit(masm);
+        }
     }
 
     public static class Umulxhi extends Fmt3p {
@@ -2465,6 +2502,12 @@
             /* VIS3 only */
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.UMulxhi, src1, src2, dst);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS3);
+            super.emit(masm);
+        }
     }
 
     public static class Movxtod extends Fmt3p {
@@ -2473,6 +2516,12 @@
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movxtod, g0, src, dst);
             assert isDoubleFloatRegister(dst);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS3);
+            super.emit(masm);
+        }
     }
 
     public static class Movdtox extends Fmt3p {
@@ -2481,6 +2530,12 @@
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movdtox, g0, src, dst);
             assert isDoubleFloatRegister(src);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS3);
+            super.emit(masm);
+        }
     }
 
     public static class Movstosw extends Fmt3p {
@@ -2489,6 +2544,12 @@
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movstosw, g0, src, dst);
             assert isSingleFloatRegister(src);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS3);
+            super.emit(masm);
+        }
     }
 
     public static class Movstouw extends Fmt3p {
@@ -2497,11 +2558,16 @@
             super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movstouw, g0, src, dst);
             assert isSingleFloatRegister(src);
         }
+
+        @Override
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.VIS3);
+            super.emit(masm);
+        }
     }
 
     public static class Fdtos extends Fmt3p {
         public Fdtos(Register src, Register dst) {
-            /* VIS3 only */
             super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fdtos, g0, src, dst);
             assert isSingleFloatRegister(dst);
             assert isDoubleFloatRegister(src);
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Assembler.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Assembler.java	Wed Sep 24 16:13:34 2014 -0700
@@ -33,6 +33,7 @@
 public abstract class Assembler {
 
     public final TargetDescription target;
+    private Set<LabelHint> jumpDisplacementHints;
 
     /**
      * Backing code buffer.
@@ -50,7 +51,7 @@
 
     /**
      * Returns the current position of the underlying code buffer.
-     * 
+     *
      * @return current position in code buffer
      */
     public int position() {
@@ -123,7 +124,7 @@
 
     /**
      * Closes this assembler. No extra data can be written to this assembler after this call.
-     * 
+     *
      * @param trimmedCopy if {@code true}, then a copy of the underlying byte array up to (but not
      *            including) {@code position()} is returned
      * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true}
@@ -148,7 +149,7 @@
 
     /**
      * Creates a name for a label.
-     * 
+     *
      * @param l the label for which a name is being created
      * @param id a label identifier that is unique with the scope of this assembler
      * @return a label name in the form of "L123"
@@ -188,4 +189,59 @@
      * Emits a NOP instruction to advance the current PC.
      */
     public abstract void ensureUniquePC();
+
+    public void reset() {
+        codeBuffer.reset();
+        captureLabelPositions();
+    }
+
+    private void captureLabelPositions() {
+        if (jumpDisplacementHints == null) {
+            return;
+        }
+        for (LabelHint request : this.jumpDisplacementHints) {
+            request.capture();
+        }
+    }
+
+    public LabelHint requestLabelHint(Label label) {
+        if (jumpDisplacementHints == null) {
+            jumpDisplacementHints = new HashSet<>();
+        }
+        LabelHint hint = new LabelHint(label, position());
+        this.jumpDisplacementHints.add(hint);
+        return hint;
+    }
+
+    public static class LabelHint {
+        private Label label;
+        private int forPosition;
+        private int capturedTarget;
+        private boolean captured = false;
+
+        protected LabelHint(Label label, int lastPosition) {
+            super();
+            this.label = label;
+            this.forPosition = lastPosition;
+        }
+
+        protected void capture() {
+            this.capturedTarget = label.position();
+            this.captured = true;
+        }
+
+        public int getTarget() {
+            assert isValid();
+            return capturedTarget;
+        }
+
+        public int getPosition() {
+            assert isValid();
+            return forPosition;
+        }
+
+        public boolean isValid() {
+            return captured;
+        }
+    }
 }
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java	Wed Sep 24 16:13:34 2014 -0700
@@ -232,4 +232,8 @@
             return (data[pos + 3] & 0xff) << 24 | (data[pos + 2] & 0xff) << 16 | (data[pos + 1] & 0xff) << 8 | (data[pos + 0] & 0xff) << 0;
         }
     }
+
+    public void reset() {
+        position = 0;
+    }
 }
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Label.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Label.java	Wed Sep 24 16:13:34 2014 -0700
@@ -40,7 +40,7 @@
 
     /**
      * Returns the position of this label in the code buffer.
-     * 
+     *
      * @return the position
      */
     public int position() {
@@ -61,7 +61,7 @@
 
     /**
      * Binds the label to the specified position.
-     * 
+     *
      * @param pos the position
      */
     protected void bind(int pos) {
@@ -92,6 +92,13 @@
         }
     }
 
+    public void reset() {
+        if (this.patchPositions != null) {
+            this.patchPositions.clear();
+        }
+        this.position = -1;
+    }
+
     @Override
     public String toString() {
         return isBound() ? String.valueOf(position()) : "?";
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Sep 24 16:13:34 2014 -0700
@@ -215,32 +215,40 @@
         HotSpotVMConfig config = getRuntime().getConfig();
         Label unverifiedStub = installedCodeOwner == null || installedCodeOwner.isStatic() ? null : new Label();
 
-        // Emit the prefix
+        int i = 0;
+        do {
+            if (i > 0) {
+                crb.reset();
+                lir.resetLabels();
+                resetDelayedControlTransfers(lir);
+            }
 
-        if (unverifiedStub != null) {
-            MarkId.recordMark(crb, MarkId.UNVERIFIED_ENTRY);
-            // We need to use JavaCall here because we haven't entered the frame yet.
-            CallingConvention cc = regConfig.getCallingConvention(JavaCall, null, new JavaType[]{getProviders().getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false);
-            Register inlineCacheKlass = g5; // see MacroAssembler::ic_call
-
-            try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
-                Register scratch = sc.getRegister();
-                Register receiver = asRegister(cc.getArgument(0));
-                SPARCAddress src = new SPARCAddress(receiver, config.hubOffset);
+            // Emit the prefix
+            if (unverifiedStub != null) {
+                MarkId.recordMark(crb, MarkId.UNVERIFIED_ENTRY);
+                // We need to use JavaCall here because we haven't entered the frame yet.
+                CallingConvention cc = regConfig.getCallingConvention(JavaCall, null, new JavaType[]{getProviders().getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false);
+                Register inlineCacheKlass = g5; // see MacroAssembler::ic_call
 
-                new Ldx(src, scratch).emit(masm);
-                new Cmp(scratch, inlineCacheKlass).emit(masm);
-            }
-            new Bpne(CC.Xcc, unverifiedStub).emit(masm);
-            new Nop().emit(masm);  // delay slot
-        }
+                try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+                    Register scratch = sc.getRegister();
+                    Register receiver = asRegister(cc.getArgument(0));
+                    SPARCAddress src = new SPARCAddress(receiver, config.hubOffset);
 
-        masm.align(config.codeEntryAlignment);
-        MarkId.recordMark(crb, MarkId.OSR_ENTRY);
-        MarkId.recordMark(crb, MarkId.VERIFIED_ENTRY);
+                    new Ldx(src, scratch).emit(masm);
+                    new Cmp(scratch, inlineCacheKlass).emit(masm);
+                }
+                new Bpne(CC.Xcc, unverifiedStub).emit(masm);
+                new Nop().emit(masm);  // delay slot
+            }
 
-        // Emit code for the LIR
-        crb.emit(lir);
+            masm.align(config.codeEntryAlignment);
+            MarkId.recordMark(crb, MarkId.OSR_ENTRY);
+            MarkId.recordMark(crb, MarkId.VERIFIED_ENTRY);
+
+            // Emit code for the LIR
+            crb.emit(lir);
+        } while (i++ < 1);
 
         HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext;
         HotSpotForeignCallsProvider foreignCalls = getProviders().getForeignCalls();
@@ -263,6 +271,16 @@
         }
     }
 
+    private static void resetDelayedControlTransfers(LIR lir) {
+        for (AbstractBlock<?> block : lir.codeEmittingOrder()) {
+            for (LIRInstruction inst : lir.getLIRforBlock(block)) {
+                if (inst instanceof SPARCDelayedControlTransfer) {
+                    ((SPARCDelayedControlTransfer) inst).resetState();
+                }
+            }
+        }
+    }
+
     /**
      * Fix-up over whole LIR.
      *
@@ -299,7 +317,7 @@
                     delayTransferPosition = i;
                 } else if (delayedTransfer != null) {
                     boolean overlap = acc.add(inst);
-                    if (inst instanceof SPARCTailDelayedLIRInstruction && !overlap) {
+                    if (!overlap && inst instanceof SPARCTailDelayedLIRInstruction) {
                         // We have found a non overlapping LIR instruction which can be delayed
                         ((SPARCTailDelayedLIRInstruction) inst).setDelayedControlTransfer(delayedTransfer);
                         delayedTransfer = null;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Wed Sep 24 16:13:34 2014 -0700
@@ -73,7 +73,7 @@
     }
 
     @Opcode("CALL_DIRECT")
-    public static class DirectCallOp extends MethodCallOp implements SPARCDelayedControlTransfer {
+    public static class DirectCallOp extends MethodCallOp /* implements SPARCDelayedControlTransfer */{
         private boolean emitted = false;
         private int before = -1;
 
@@ -114,6 +114,11 @@
             new Call(0).emit(masm);
             emitted = true;
         }
+
+        public void resetState() {
+            emitted = false;
+            before = -1;
+        }
     }
 
     @Opcode("CALL_INDIRECT")
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Wed Sep 24 16:13:34 2014 -0700
@@ -69,12 +69,17 @@
         @Use({REG, CONST}) protected Value y;
         protected final Condition condition;
         protected final LabelRef trueDestination;
+        protected LabelHint trueDestinationHint;
         protected final LabelRef falseDestination;
+        protected LabelHint falseDestinationHint;
         protected final Kind kind;
         protected final boolean unorderedIsTrue;
         private boolean emitted = false;
         private int delaySlotPosition = -1;
         private double trueDestinationProbability;
+        // This describes the maximum offset between the first emitted (load constant in to scratch,
+        // if does not fit into simm5 of cbcond) instruction and the final branch instruction
+        private static int maximumSelfOffsetInstructions = 4;
 
         public CompareBranchOp(SPARCCompare opcode, Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind, boolean unorderedIsTrue,
                         double trueDestinationProbability) {
@@ -95,16 +100,159 @@
                 assert masm.position() - delaySlotPosition == 4 : "Only one instruction can be stuffed into the delay slot";
             }
             if (!emitted) {
-                SPARCCompare.emit(crb, masm, opcode, x, y);
-                emitted = emitBranch(crb, masm, true);
+                requestHints(masm);
+                if (canUseShortBranch(crb, masm, masm.position() + maximumSelfOffsetInstructions * masm.target.wordSize)) {
+                    emitted = emitShortCompareBranch(crb, masm);
+                }
+                if (!emitted) {
+                    SPARCCompare.emit(crb, masm, opcode, x, y);
+                    emitted = emitBranch(crb, masm, true);
+                }
             }
 
             assert emitted;
         }
 
         public void emitControlTransfer(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            SPARCCompare.emit(crb, masm, opcode, x, y);
-            emitted = emitBranch(crb, masm, false);
+            requestHints(masm);
+            // When we use short branches, no delay slot is available
+            if (!canUseShortBranch(crb, masm, masm.position() + maximumSelfOffsetInstructions * masm.target.wordSize)) {
+                SPARCCompare.emit(crb, masm, opcode, x, y);
+                emitted = emitBranch(crb, masm, false);
+            }
+        }
+
+        private void requestHints(SPARCMacroAssembler masm) {
+            if (trueDestinationHint == null) {
+                this.trueDestinationHint = masm.requestLabelHint(trueDestination.label());
+            }
+            if (falseDestinationHint == null) {
+                this.falseDestinationHint = masm.requestLabelHint(falseDestination.label());
+            }
+
+        }
+
+        /**
+         * Tries to use the emit the compare/branch instruction.
+         * <p>
+         * CBcond has follwing limitations
+         * <ul>
+         * <li>Immediate field is only 5 bit and is on the right
+         * <li>Jump offset is maximum of -+512 instruction
+         *
+         * <p>
+         * We get from outside
+         * <ul>
+         * <li>at least one of trueDestination falseDestination is within reach of +-512
+         * instructions
+         * <li>two registers OR one register and a constant which fits simm13
+         *
+         * <p>
+         * We do:
+         * <ul>
+         * <li>find out which target needs to be branched conditionally
+         * <li>find out if fall-through is possible, if not, a unconditional branch is needed after
+         * cbcond (needJump=true)
+         * <li>if no fall through: we need to put the closer jump into the cbcond branch and the
+         * farther into the jmp (unconditional branch)
+         * <li>if constant on the left side, mirror to be on the right
+         * <li>if constant on right does not fit into simm5, put it into a scratch register
+         *
+         * @param crb
+         * @param masm
+         * @return true if the branch could be emitted
+         */
+        private boolean emitShortCompareBranch(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            Value tmpValue;
+            Value actualX = x;
+            Value actualY = y;
+            Condition actualCondition = condition;
+            Label actualTrueTarget = trueDestination.label();
+            Label actualFalseTarget = falseDestination.label();
+            Label tmpTarget;
+            boolean needJump;
+            if (crb.isSuccessorEdge(trueDestination)) {
+                actualCondition = actualCondition.negate();
+                tmpTarget = actualTrueTarget;
+                actualTrueTarget = actualFalseTarget;
+                actualFalseTarget = tmpTarget;
+                needJump = false;
+            } else {
+                needJump = !crb.isSuccessorEdge(falseDestination);
+                if (needJump && !isShortBranch(masm, masm.position() + maximumSelfOffsetInstructions * masm.target.wordSize, trueDestinationHint, actualTrueTarget)) {
+                    // we have to jump in either way, so we must put the shorter
+                    // branch into the actualTarget as only one of the two jump targets
+                    // is guaranteed to be simm10
+                    actualCondition = actualCondition.negate();
+                    tmpTarget = actualTrueTarget;
+                    actualTrueTarget = actualFalseTarget;
+                    actualFalseTarget = tmpTarget;
+                }
+            }
+            // Keep the constant on the right
+            if (isConstant(actualX)) {
+                tmpValue = actualX;
+                actualX = actualY;
+                actualY = tmpValue;
+                actualCondition = actualCondition.mirror();
+            }
+            ConditionFlag conditionFlag = ConditionFlag.fromCondtition(CC.Icc, actualCondition, false);
+            boolean isValidConstant = isConstant(actualY) && isSimm5(asConstant(actualY));
+            SPARCScratchRegister scratch = null;
+            try {
+                if (isConstant(actualY) && !isValidConstant) { // Make sure, the y value is loaded
+                    scratch = SPARCScratchRegister.get();
+                    Value scratchValue = scratch.getRegister().asValue(actualY.getLIRKind());
+                    SPARCMove.move(crb, masm, scratchValue, actualY, SPARCDelayedControlTransfer.DUMMY);
+                    actualY = scratchValue;
+                }
+                emitCBCond(masm, actualX, actualY, actualTrueTarget, conditionFlag);
+                new Nop().emit(masm);
+            } finally {
+                if (scratch != null) {// release the scratch if used
+                    scratch.close();
+                }
+            }
+            if (needJump) {
+                masm.jmp(actualFalseTarget);
+                new Nop().emit(masm);
+            }
+            return true;
+        }
+
+        private static void emitCBCond(SPARCMacroAssembler masm, Value actualX, Value actualY, Label actualTrueTarget, ConditionFlag conditionFlag) {
+            switch ((Kind) actualX.getLIRKind().getPlatformKind()) {
+                case Byte:
+                case Char:
+                case Short:
+                case Int:
+                    if (isConstant(actualY)) {
+                        int constantY = asConstant(actualY).asInt();
+                        new CBcondw(conditionFlag, asIntReg(actualX), constantY, actualTrueTarget).emit(masm);
+                    } else {
+                        new CBcondw(conditionFlag, asIntReg(actualX), asIntReg(actualY), actualTrueTarget).emit(masm);
+                    }
+                    break;
+                case Long:
+                    if (isConstant(actualY)) {
+                        int constantY = (int) asConstant(actualY).asLong();
+                        new CBcondx(conditionFlag, asLongReg(actualX), constantY, actualTrueTarget).emit(masm);
+                    } else {
+                        new CBcondx(conditionFlag, asLongReg(actualX), asLongReg(actualY), actualTrueTarget).emit(masm);
+                    }
+                    break;
+                case Object:
+                    if (isConstant(actualY)) {
+                        // Object constant valid can only be null
+                        assert asConstant(actualY).isNull();
+                        new CBcondx(conditionFlag, asObjectReg(actualX), 0, actualTrueTarget).emit(masm);
+                    } else { // this is already loaded
+                        new CBcondx(conditionFlag, asObjectReg(actualX), asObjectReg(actualY), actualTrueTarget).emit(masm);
+                    }
+                    break;
+                default:
+                    GraalInternalError.shouldNotReachHere();
+            }
         }
 
         public boolean emitBranch(CompilationResultBuilder crb, SPARCMacroAssembler masm, boolean withDelayedNop) {
@@ -146,10 +294,61 @@
             }
             return true; // emitted
         }
+
+        private boolean canUseShortBranch(CompilationResultBuilder crb, SPARCAssembler asm, int position) {
+            if (!asm.hasFeature(CPUFeature.CBCOND)) {
+                return false;
+            }
+            switch ((Kind) x.getPlatformKind()) {
+                case Byte:
+                case Char:
+                case Short:
+                case Int:
+                case Long:
+                case Object:
+                    break;
+                default:
+                    return false;
+            }
+            boolean hasShortJumpTarget = false;
+            if (!crb.isSuccessorEdge(trueDestination)) {
+                hasShortJumpTarget |= isShortBranch(asm, position, trueDestinationHint, trueDestination.label());
+            }
+            if (!crb.isSuccessorEdge(falseDestination)) {
+                hasShortJumpTarget |= isShortBranch(asm, position, falseDestinationHint, falseDestination.label());
+            }
+            return hasShortJumpTarget;
+        }
+
+        private static boolean isShortBranch(SPARCAssembler asm, int position, LabelHint hint, Label label) {
+            int disp = 0;
+            if (label.isBound()) {
+                disp = label.position() - position;
+
+            } else if (hint != null && hint.isValid()) {
+                disp = hint.getTarget() - hint.getPosition();
+            }
+            if (disp != 0) {
+                if (disp < 0) {
+                    disp -= maximumSelfOffsetInstructions * asm.target.wordSize;
+                } else {
+                    disp += maximumSelfOffsetInstructions * asm.target.wordSize;
+                }
+                return isSimm10(disp >> 2);
+            } else if (hint == null) {
+                asm.requestLabelHint(label);
+            }
+            return false;
+        }
+
+        public void resetState() {
+            emitted = false;
+            delaySlotPosition = -1;
+        }
     }
 
     public static class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp {
-        // TODO: Conditioncode/flag handling needs to be improved;
+        // TODO: Condition code/flag handling needs to be improved;
         protected final Condition condition;
         protected final ConditionFlag conditionFlag;
         protected final LabelRef trueDestination;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCDelayedControlTransfer.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCDelayedControlTransfer.java	Wed Sep 24 16:13:34 2014 -0700
@@ -43,6 +43,9 @@
         public String toString() {
             return "null";
         }
+
+        public void resetState() {
+        }
     };
 
     /**
@@ -53,4 +56,6 @@
      * @param masm
      */
     public void emitControlTransfer(CompilationResultBuilder crb, SPARCMacroAssembler masm);
+
+    public void resetState();
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java	Wed Sep 24 16:13:34 2014 -0700
@@ -41,21 +41,26 @@
         assert !emitDone;
         if (!crb.isSuccessorEdge(destination())) {
             new Bpa(destination().label()).emit(masm);
+            delaySlotPosition = masm.position();
         }
-        delaySlotPosition = masm.position();
         emitDone = true;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb) {
-        if (!emitDone) {
-            SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
-            if (!crb.isSuccessorEdge(destination())) {
+        if (!crb.isSuccessorEdge(destination())) {
+            if (!emitDone) {
+                SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
                 new Bpa(destination().label()).emit(masm);
                 new Nop().emit(masm);
+            } else {
+                assert crb.asm.position() - delaySlotPosition == 4;
             }
-        } else {
-            assert crb.asm.position() - delaySlotPosition == 4;
         }
     }
+
+    public void resetState() {
+        delaySlotPosition = -1;
+        emitDone = false;
+    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Wed Sep 24 16:13:34 2014 -0700
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.cfg.*;
-import com.oracle.graal.lir.StandardOp.BlockEndOp;
+import com.oracle.graal.lir.StandardOp.*;
 
 /**
  * This class implements the overall container for the LIR graph and directs its construction,
@@ -210,4 +210,15 @@
     public void setSpillMoveFactory(SpillMoveFactory spillMoveFactory) {
         this.spillMoveFactory = spillMoveFactory;
     }
+
+    public void resetLabels() {
+
+        for (AbstractBlock<?> block : codeEmittingOrder()) {
+            for (LIRInstruction inst : lirInstructions.get(block)) {
+                if (inst instanceof LabelOp) {
+                    ((LabelOp) inst).getLabel().reset();
+                }
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Tue Sep 23 12:12:26 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Wed Sep 24 16:13:34 2014 -0700
@@ -358,4 +358,9 @@
             throw new GraalInternalError(t);
         }
     }
+
+    public void reset() {
+        asm.reset();
+        compilationResult.reset();
+    }
 }