changeset 18843:5e80dd2f1783

Extend emitMul, emitAdd and emitSub in ArithmeticLIRGenerator for explicitly requesting to set the flags register. (In AMD64 flags are set implicitly, but on SPARC it is not)
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Mon, 12 Jan 2015 19:34:31 +0100
parents 437894ecd7c5
children edbac8edc2e1 49e5c062e77a
files graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java 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/NodeLIRBuilder.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.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/gen/ArithmeticLIRGenerator.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java
diffstat 22 files changed, 218 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Jan 12 19:34:31 2015 +0100
@@ -53,6 +53,13 @@
         void emit(SPARCAssembler masm);
     }
 
+    public static final int CCR_ICC_SHIFT = 0;
+    public static final int CCR_XCC_SHIFT = 4;
+    public static final int CCR_C_SHIFT = 0;
+    public static final int CCR_V_SHIFT = 1;
+    public static final int CCR_Z_SHIFT = 2;
+    public static final int CCR_N_SHIFT = 3;
+
     // @formatter:off
     /**
      * Instruction format for Fmt00 instructions. This abstraction is needed as it
@@ -1468,19 +1475,6 @@
         }
     }
 
-    public static class Fmt4d {
-
-        public Fmt4d(SPARCAssembler masm, int op, int op3, int cond, int cc, int simm11, int rd) {
-            assert op == 2;
-            assert op3 >= 0 && op3 < 0x40;
-            assert cc >= 0 && cc < 0x8;
-            assert cond >= 0 && cond < 0x10;
-            assert rd >= 0 && rd < 0x20;
-
-            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | ImmedTrue | ((cc << 15) & 0x00040000) | cond << 14 | ((cc << 11) & 0x3) | simm11 & 0x00004000);
-        }
-    }
-
     public static class Fmt5a {
 
         public Fmt5a(SPARCAssembler masm, int op, int op3, int op5, int rs1, int rs2, int rs3, int rd) {
@@ -1588,10 +1582,11 @@
         Orncc(0x16, "orncc"),
         Xnorcc(0x17, "xnorcc"),
         Addccc(0x18, "addccc"),
-        Mulxcc(0x19, "mulxcc"),
+        // dos not exist
+        // Mulxcc(0x19, "mulxcc"),
         Umulcc(0x1A, "umulcc"),
         Smulcc(0x1B, "smulcc"),
-        Subccc(0x1C0, "subccc"),
+        Subccc(0x1C, "subccc"),
         Udivcc(0x1E, "udivcc"),
         Sdivcc(0x1F, "sdivcc"),
 
@@ -1655,8 +1650,10 @@
         Stf   (0b10_0100, "stf"),
         Stfsr (0b10_0101, "stfsr"),
         Staf  (0x10_0110, "staf"),
+        Rd    (0b10_1000, "rd"),
         Stdf  (0b10_0111, "stdf"),
 
+        Wr    (0b11_0000, "wr"),
         Fcmp  (0b11_0101, "fcmp"),
 
         Ldxa  (0b01_1011, "ldxa"),
@@ -1814,6 +1811,7 @@
         Movxtod(0x118, "movxtod"),
         Movwtos(0b1_0001_1001, "movwtos"),
         UMulxhi(0b0_0001_0110, "umulxhi"),
+        Lzcnt  (0b0_0001_0111, "lzcnt"),
         // end VIS3
 
         // start CAMMELLIA
@@ -2395,6 +2393,14 @@
         }
     }
 
+    public static class Lzcnt extends Fmt3p {
+
+        public Lzcnt(Register src1, Register dst) {
+            /* VIS3 only */
+            super(Ops.ArithOp, Op3s.Impdep1, Opfs.Lzcnt, g0, src1, dst);
+        }
+    }
+
     public static class And extends Fmt10 {
 
         public And(Register src1, int simm13, Register dst) {
@@ -3993,6 +3999,17 @@
         }
     }
 
+    public static class SMulcc extends Fmt10 {
+
+        public SMulcc(Register src1, int simm13, Register dst) {
+            super(Op3s.Smulcc, src1, simm13, dst);
+        }
+
+        public SMulcc(Register src1, Register src2, Register dst) {
+            super(Op3s.Smulcc, src1, src2, dst);
+        }
+    }
+
     public static class Or extends Fmt10 {
 
         public Or(Register src1, int simm13, Register dst) {
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Mon Jan 12 19:34:31 2015 +0100
@@ -266,7 +266,7 @@
 
     @Override
     protected Value genIntegerAdd(Kind kind, Value x, Value y) {
-        return gen.emitAdd(x, y);
+        return gen.emitAdd(x, y, false);
     }
 
     @Override
@@ -277,7 +277,7 @@
 
     @Override
     protected Value genIntegerMul(Kind kind, Value x, Value y) {
-        return gen.emitMul(x, y);
+        return gen.emitMul(x, y, false);
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Jan 12 19:34:31 2015 +0100
@@ -155,7 +155,7 @@
                 if (CodeUtil.isPowerOf2(scale)) {
                     indexRegister = emitShl(longIndex, JavaConstant.forLong(CodeUtil.log2(scale)));
                 } else {
-                    indexRegister = emitMul(longIndex, JavaConstant.forLong(scale));
+                    indexRegister = emitMul(longIndex, JavaConstant.forLong(scale), false);
                 }
                 scaleEnum = Scale.Times1;
 
@@ -179,7 +179,7 @@
                 indexRegister = displacementRegister;
                 scaleEnum = Scale.Times1;
             } else {
-                baseRegister = emitAdd(baseRegister, displacementRegister);
+                baseRegister = emitAdd(baseRegister, displacementRegister, false);
             }
         }
 
@@ -231,7 +231,7 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpLIRKind, double overflowProbability) {
         append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow, overflowProbability));
     }
 
@@ -498,7 +498,7 @@
     }
 
     @Override
-    public Variable emitAdd(Value a, Value b) {
+    public Variable emitAdd(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
                 return emitBinary(IADD, true, a, b);
@@ -514,7 +514,7 @@
     }
 
     @Override
-    public Variable emitSub(Value a, Value b) {
+    public Variable emitSub(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
                 return emitBinary(ISUB, false, a, b);
@@ -530,7 +530,7 @@
     }
 
     @Override
-    public Variable emitMul(Value a, Value b) {
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
                 return emitBinary(IMUL, true, a, b);
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Jan 12 19:34:31 2015 +0100
@@ -142,7 +142,7 @@
                 if (baseRegister.equals(Value.ILLEGAL)) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
-                    baseRegister = emitAdd(baseRegister, indexRegister);
+                    baseRegister = emitAdd(baseRegister, indexRegister, false);
                 }
             }
         }
@@ -201,7 +201,7 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpLIRKind, double overflowProbability) {
         throw GraalInternalError.unimplemented();
     }
 
@@ -321,7 +321,7 @@
     }
 
     @Override
-    public Variable emitAdd(Value a, Value b) {
+    public Variable emitAdd(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
@@ -346,7 +346,7 @@
     }
 
     @Override
-    public Variable emitSub(Value a, Value b) {
+    public Variable emitSub(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
@@ -368,7 +368,7 @@
     }
 
     @Override
-    public Variable emitMul(Value a, Value b) {
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Jan 12 19:34:31 2015 +0100
@@ -171,7 +171,7 @@
                     if (CodeUtil.isPowerOf2(scale)) {
                         indexRegister = emitShl(convertedIndex, JavaConstant.forInt(CodeUtil.log2(scale)));
                     } else {
-                        indexRegister = emitMul(convertedIndex, JavaConstant.forInt(scale));
+                        indexRegister = emitMul(convertedIndex, JavaConstant.forInt(scale), false);
                     }
                 } else {
                     indexRegister = convertedIndex;
@@ -181,7 +181,7 @@
                 } else {
                     Variable longBaseRegister = newVariable(LIRKind.derivedReference(Kind.Long));
                     emitMove(longBaseRegister, baseRegister);
-                    baseRegister = emitAdd(longBaseRegister, indexRegister);
+                    baseRegister = emitAdd(longBaseRegister, indexRegister, false);
                 }
             }
         }
@@ -255,7 +255,7 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpLIRKind, double overflowProbability) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitOverflowCheckBranch()");
     }
 
@@ -391,7 +391,7 @@
     }
 
     @Override
-    public Variable emitAdd(Value a, Value b) {
+    public Variable emitAdd(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
@@ -413,7 +413,7 @@
     }
 
     @Override
-    public Variable emitSub(Value a, Value b) {
+    public Variable emitSub(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
@@ -435,7 +435,7 @@
     }
 
     @Override
-    public Variable emitMul(Value a, Value b) {
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jan 12 19:34:31 2015 +0100
@@ -145,7 +145,7 @@
                     if (CodeUtil.isPowerOf2(scale)) {
                         indexRegister = emitShl(longIndex, JavaConstant.forLong(CodeUtil.log2(scale)));
                     } else {
-                        indexRegister = emitMul(longIndex, JavaConstant.forLong(scale));
+                        indexRegister = emitMul(longIndex, JavaConstant.forLong(scale), false);
                     }
                 } else {
                     indexRegister = asAllocatable(index);
@@ -171,7 +171,7 @@
                 } else {
                     Variable longBaseRegister = newVariable(LIRKind.derivedReference(Kind.Long));
                     emitMove(longBaseRegister, baseRegister);
-                    baseRegister = emitAdd(longBaseRegister, JavaConstant.forLong(finalDisp));
+                    baseRegister = emitAdd(longBaseRegister, JavaConstant.forLong(finalDisp), false);
                 }
             }
         }
@@ -253,8 +253,9 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
-        append(new BranchOp(ConditionFlag.OverflowSet, overflow, noOverflow, Kind.Long));
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpLIRKind, double overflowProbability) {
+        Kind cmpKind = (Kind) cmpLIRKind.getPlatformKind();
+        append(new BranchOp(ConditionFlag.OverflowSet, overflow, noOverflow, cmpKind));
     }
 
     @Override
@@ -584,12 +585,12 @@
     }
 
     @Override
-    public Variable emitAdd(Value a, Value b) {
+    public Variable emitAdd(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
-                return emitBinary(IADD, true, a, b);
+                return emitBinary(setFlags ? IADDCC : IADD, true, a, b);
             case Long:
-                return emitBinary(LADD, true, a, b);
+                return emitBinary(setFlags ? LADDCC : LADD, true, a, b);
             case Float:
                 return emitBinary(FADD, true, a, b);
             case Double:
@@ -600,12 +601,12 @@
     }
 
     @Override
-    public Variable emitSub(Value a, Value b) {
+    public Variable emitSub(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
-                return emitBinary(ISUB, false, a, b);
+                return emitBinary(setFlags ? ISUBCC : ISUB, false, a, b);
             case Long:
-                return emitBinary(LSUB, false, a, b);
+                return emitBinary(setFlags ? LSUBCC : LSUB, false, a, b);
             case Float:
                 return emitBinary(FSUB, false, a, b);
             case Double:
@@ -616,12 +617,18 @@
     }
 
     @Override
-    public Variable emitMul(Value a, Value b) {
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
-                return emitBinary(IMUL, true, a, b);
+                return emitBinary(setFlags ? IMULCC : IMUL, true, a, b);
             case Long:
-                return emitBinary(LMUL, true, a, b);
+                if (setFlags) {
+                    Variable result = newVariable(LIRKind.derive(a, b));
+                    append(new SPARCLMulccOp(result, a, b, this));
+                    return result;
+                } else {
+                    return emitBinary(LMUL, true, a, b);
+                }
             case Float:
                 return emitBinary(FMUL, true, a, b);
             case Double:
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Mon Jan 12 19:34:31 2015 +0100
@@ -598,8 +598,10 @@
         return getDebugInfoBuilder().build(state, exceptionEdge);
     }
 
-    public void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability) {
-        gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), probability);
+    @Override
+    public void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, Stamp stamp, double probability) {
+        LIRKind cmpKind = getLIRGeneratorTool().getLIRKind(stamp);
+        gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), cmpKind, probability);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Mon Jan 12 19:34:31 2015 +0100
@@ -85,10 +85,10 @@
             assert !gen.getCodeCache().needsDataPatch(asConstant(offset));
             Variable longAddress = gen.newVariable(LIRKind.value(Kind.Long));
             gen.emitMove(longAddress, address);
-            address = getGen().emitAdd(longAddress, asConstant(offset));
+            address = getGen().emitAdd(longAddress, asConstant(offset), false);
         } else {
             if (isLegal(offset)) {
-                address = getGen().emitAdd(address, offset);
+                address = getGen().emitAdd(address, offset, false);
             }
         }
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Jan 12 19:34:31 2015 +0100
@@ -26,6 +26,7 @@
 import static com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
@@ -34,11 +35,15 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.sparc.SPARC.CPUFeature;
+import com.oracle.graal.sparc.*;
 
 public enum SPARCArithmetic {
     // @formatter:off
     IADD, ISUB, IMUL, IUMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
     LADD, LSUB, LMUL, LUMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
+    IADDCC, ISUBCC, IMULCC,
+    LADDCC, LSUBCC, LMULCC,
     FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
     DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
     INEG, LNEG, FNEG, DNEG, INOT, LNOT,
@@ -175,6 +180,49 @@
         }
     }
 
+    /**
+     * Calculates the product and condition code for long multiplication of long values.
+     */
+    public static class SPARCLMulccOp extends SPARCLIRInstruction {
+        @Def({REG}) protected Value result;
+        @Alive({REG}) protected Value x;
+        @Alive({REG}) protected Value y;
+        @Temp({REG}) protected Value scratch1;
+        @Temp({REG}) protected Value scratch2;
+
+        public SPARCLMulccOp(Value result, Value x, Value y, LIRGeneratorTool gen) {
+            this.result = result;
+            this.x = x;
+            this.y = y;
+            this.scratch1 = gen.newVariable(LIRKind.derive(x, y));
+            this.scratch2 = gen.newVariable(LIRKind.derive(x, y));
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            Label noOverflow = new Label();
+            new Mulx(asLongReg(x), asLongReg(y), asLongReg(result)).emit(masm);
+
+            // Calculate the upper 64 bit signed := (umulxhi product - (x{63}&y + y{63}&x))
+            new Umulxhi(asLongReg(x), asLongReg(y), asLongReg(scratch1)).emit(masm);
+            new Srax(asLongReg(x), 63, asLongReg(scratch2)).emit(masm);
+            new And(asLongReg(scratch2), asLongReg(y), asLongReg(scratch2)).emit(masm);
+            new Sub(asLongReg(scratch1), asLongReg(scratch2), asLongReg(scratch1)).emit(masm);
+
+            new Srax(asLongReg(y), 63, asLongReg(scratch2)).emit(masm);
+            new And(asLongReg(scratch2), asLongReg(x), asLongReg(scratch2)).emit(masm);
+            new Sub(asLongReg(scratch1), asLongReg(scratch2), asLongReg(scratch1)).emit(masm);
+
+            // Now construct the lower half and compare
+            new Srax(asLongReg(result), 63, asLongReg(scratch2)).emit(masm);
+            new Cmp(asLongReg(scratch1), asLongReg(scratch2)).emit(masm);
+            new Bpe(CC.Xcc, false, true, noOverflow).emit(masm);
+            new Nop().emit(masm);
+            new Wrccr(SPARC.g0, 1 << (CCR_XCC_SHIFT + CCR_V_SHIFT)).emit(masm);
+            masm.bind(noOverflow);
+        }
+    }
+
     private static void emitRegConstant(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, JavaConstant src2, LIRFrameState info,
                     SPARCDelayedControlTransfer delaySlotLir) {
         assert isSimm13(crb.asIntConst(src2)) : src2;
@@ -185,12 +233,20 @@
             case IADD:
                 new Add(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
                 break;
+            case IADDCC:
+                new Addcc(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
+                break;
             case ISUB:
                 new Sub(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
                 break;
+            case ISUBCC:
+                new Subcc(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
+                break;
             case IMUL:
                 new Mulx(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
                 break;
+            case IMULCC:
+                throw GraalInternalError.unimplemented();
             case IDIV:
                 new Sdivx(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
                 break;
@@ -218,9 +274,15 @@
             case LADD:
                 new Add(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
                 break;
+            case LADDCC:
+                new Addcc(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
+                break;
             case LSUB:
                 new Sub(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
                 break;
+            case LSUBCC:
+                new Subcc(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
+                break;
             case LMUL:
                 new Mulx(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
                 break;
@@ -276,14 +338,42 @@
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Add(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                 break;
+            case IADDCC:
+                delaySlotLir.emitControlTransfer(crb, masm);
+                new Addcc(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
+                break;
             case ISUB:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Sub(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                 break;
+            case ISUBCC:
+                delaySlotLir.emitControlTransfer(crb, masm);
+                new Subcc(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
+                break;
             case IMUL:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Mulx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                 break;
+            case IMULCC:
+                try (SPARCScratchRegister tmpScratch = SPARCScratchRegister.get()) {
+                    Register tmp = tmpScratch.getRegister();
+                    new Mulx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
+                    Label noOverflow = new Label();
+                    new Sra(asIntReg(dst), 0, tmp).emit(masm);
+                    new Xorcc(SPARC.g0, SPARC.g0, SPARC.g0).emit(masm);
+                    if (masm.hasFeature(CPUFeature.CBCOND)) {
+                        new CBcondx(ConditionFlag.Equal, tmp, asIntReg(dst), noOverflow).emit(masm);
+                        // Is necessary, otherwise we will have a penalty of 5 cycles in S3
+                        new Nop().emit(masm);
+                    } else {
+                        new Cmp(tmp, asIntReg(dst)).emit(masm);
+                        new Bpe(CC.Xcc, noOverflow).emit(masm);
+                        new Nop().emit(masm);
+                    }
+                    new Wrccr(SPARC.g0, 1 << (SPARCAssembler.CCR_ICC_SHIFT + SPARCAssembler.CCR_V_SHIFT)).emit(masm);
+                    masm.bind(noOverflow);
+                }
+                break;
             case IDIV:
                 new Signx(asIntReg(src1), asIntReg(src1)).emit(masm);
                 new Signx(asIntReg(src2), asIntReg(src2)).emit(masm);
@@ -328,14 +418,24 @@
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Add(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                 break;
+            case LADDCC:
+                delaySlotLir.emitControlTransfer(crb, masm);
+                new Addcc(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
+                break;
             case LSUB:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Sub(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                 break;
+            case LSUBCC:
+                delaySlotLir.emitControlTransfer(crb, masm);
+                new Subcc(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
+                break;
             case LMUL:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Mulx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                 break;
+            case LMULCC:
+                throw GraalInternalError.unimplemented();
             case LDIV:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 exceptionOffset = masm.position();
@@ -659,8 +759,11 @@
 
         switch (opcode) {
             case IADD:
+            case IADDCC:
             case ISUB:
+            case ISUBCC:
             case IMUL:
+            case IMULCC:
             case IDIV:
             case IREM:
             case IAND:
@@ -681,8 +784,11 @@
                 assert valid : "rk: " + rk + " xsk: " + xsk + " ysk: " + ysk;
                 break;
             case LADD:
+            case LADDCC:
             case LSUB:
+            case LSUBCC:
             case LMUL:
+            case LMULCC:
             case LDIV:
             case LREM:
             case LAND:
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Jan 12 19:34:31 2015 +0100
@@ -413,7 +413,7 @@
                 if (actualCondition != null) {
                     emitBranch(masm, actualTarget, actualCondition, cc, false);
                 } else if (actualConditionFlag != null) {
-                    emitBranch(masm, actualTarget, actualConditionFlag);
+                    emitBranch(masm, actualTarget, actualConditionFlag, cc);
                 } else {
                     GraalInternalError.shouldNotReachHere();
                 }
@@ -475,8 +475,8 @@
         }
     }
 
-    private static void emitBranch(SPARCMacroAssembler masm, Label target, ConditionFlag actualCondition) {
-        new Fmt00b(false, actualCondition, Op2s.Br, target).emit(masm);
+    private static void emitBranch(SPARCMacroAssembler masm, Label target, ConditionFlag actualCondition, CC cc) {
+        new Fmt00c(0, actualCondition, Op2s.Bp, cc, 0, target).emit(masm);
     }
 
     private static void emitBranch(SPARCMacroAssembler masm, Label target, Condition actualCondition, CC cc, boolean predictTaken) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Mon Jan 12 19:34:31 2015 +0100
@@ -29,6 +29,12 @@
 
 /**
  * This interface can be used to generate LIR for arithmetic operations.
+ *
+ * The setFlags flag in emitAdd, emitSub and emitMul indicates, that the instruction must set the
+ * flags register to be used for a later branch. (On AMD64, the condition codes are set in every
+ * arithmetic instruction, but other architectures optionally set the flags register) If setFlags is
+ * set, the instruction must set the flags register; if false, the instruction may or may not set
+ * the flags register.
  */
 public interface ArithmeticLIRGenerator {
 
@@ -36,11 +42,11 @@
 
     Value emitNegate(Value input);
 
-    Value emitAdd(Value a, Value b);
+    Value emitAdd(Value a, Value b, boolean setFlags);
 
-    Value emitSub(Value a, Value b);
+    Value emitSub(Value a, Value b, boolean setFlags);
 
-    Value emitMul(Value a, Value b);
+    Value emitMul(Value a, Value b, boolean setFlags);
 
     Value emitMulHigh(Value a, Value b);
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Mon Jan 12 19:34:31 2015 +0100
@@ -241,7 +241,7 @@
     public abstract void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
                     double trueDestinationProbability);
 
-    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
+    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpKind, double overflowProbability);
 
     public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Mon Jan 12 19:34:31 2015 +0100
@@ -165,7 +165,7 @@
     void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
                     double trueDestinationProbability);
 
-    void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
+    void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpKind, double overflowProbability);
 
     void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Mon Jan 12 19:34:31 2015 +0100
@@ -102,6 +102,6 @@
             op1 = op2;
             op2 = tmp;
         }
-        builder.setResult(this, gen.emitAdd(op1, op2));
+        builder.setResult(this, gen.emitAdd(op1, op2, false));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Mon Jan 12 19:34:31 2015 +0100
@@ -110,6 +110,6 @@
             op1 = op2;
             op2 = tmp;
         }
-        builder.setResult(this, gen.emitMul(op1, op2));
+        builder.setResult(this, gen.emitMul(op1, op2, false));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Mon Jan 12 19:34:31 2015 +0100
@@ -137,6 +137,6 @@
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY())));
+        builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY()), false));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Mon Jan 12 19:34:31 2015 +0100
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -66,7 +67,7 @@
 
     LIRGeneratorTool getLIRGeneratorTool();
 
-    void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability);
+    void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, Stamp compareStamp, double probability);
 
     Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments);
 
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Mon Jan 12 19:34:31 2015 +0100
@@ -47,12 +47,20 @@
     public void testAdd() {
         test("add", 1, 2);
         test("add", Integer.MAX_VALUE, 2);
+        test("add", Integer.MIN_VALUE, -1);
+        test("add", -1, 2);
     }
 
     @Test
     public void testMul() {
         test("mul", 1, 2);
+        test("mul", -1, 2);
+        test("mul", Integer.MIN_VALUE, 1);
+        test("mul", Integer.MIN_VALUE, 2);
+        test("mul", Integer.MIN_VALUE, Integer.MIN_VALUE);
+        test("mul", Integer.MAX_VALUE, 1);
         test("mul", Integer.MAX_VALUE, 2);
+        test("mul", Integer.MAX_VALUE, Integer.MAX_VALUE);
     }
 
     @Test
@@ -90,6 +98,10 @@
         test("longMul", (long) Integer.MAX_VALUE, 2L);
         test("longMul", (long) Integer.MIN_VALUE, 2L);
         test("longMul", Long.MAX_VALUE, 2L);
+        test("longMul", Long.MAX_VALUE, 1L);
+        test("longMul", Long.MAX_VALUE, Long.MAX_VALUE);
+        test("longMul", Long.MIN_VALUE, Long.MIN_VALUE);
+        test("longMul", Long.MIN_VALUE, Long.MAX_VALUE);
     }
 
     @Test
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Mon Jan 12 19:34:31 2015 +0100
@@ -41,6 +41,6 @@
 
     @Override
     protected Value generateArithmetic(NodeLIRBuilderTool gen) {
-        return gen.getLIRGeneratorTool().emitAdd(gen.operand(getX()), gen.operand(getY()));
+        return gen.getLIRGeneratorTool().emitAdd(gen.operand(getX()), gen.operand(getY()), true);
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Mon Jan 12 19:34:31 2015 +0100
@@ -69,7 +69,7 @@
     @Override
     public void generate(NodeLIRBuilderTool generator) {
         generator.setResult(this, generateArithmetic(generator));
-        generator.emitOverflowCheckBranch(getOverflowSuccessor(), getNext(), probability(getOverflowSuccessor()));
+        generator.emitOverflowCheckBranch(getOverflowSuccessor(), getNext(), stamp, probability(getOverflowSuccessor()));
     }
 
     protected abstract Value generateArithmetic(NodeLIRBuilderTool generator);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Mon Jan 12 19:34:31 2015 +0100
@@ -41,6 +41,6 @@
 
     @Override
     protected Value generateArithmetic(NodeLIRBuilderTool gen) {
-        return gen.getLIRGeneratorTool().emitMul(gen.operand(getX()), gen.operand(getY()));
+        return gen.getLIRGeneratorTool().emitMul(gen.operand(getX()), gen.operand(getY()), true);
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Mon Jan 12 18:02:01 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Mon Jan 12 19:34:31 2015 +0100
@@ -41,6 +41,6 @@
 
     @Override
     protected Value generateArithmetic(NodeLIRBuilderTool gen) {
-        return gen.getLIRGeneratorTool().emitSub(gen.operand(getX()), gen.operand(getY()));
+        return gen.getLIRGeneratorTool().emitSub(gen.operand(getX()), gen.operand(getY()), true);
     }
 }