changeset 16926:5c8a0b322d15

[SPARC] Implement unsigned arithmethic, fix CAS, unary operations on stack and various other fixes
author Stefan Anzinger <stefan.anzinger@gmail.com>
date Fri, 08 Aug 2014 09:14:53 -0700
parents 2f4487a0b588
children 949347518b66
files graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java
diffstat 3 files changed, 145 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Jul 31 07:29:13 2014 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Aug 08 09:14:53 2014 -0700
@@ -35,6 +35,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
@@ -232,7 +233,7 @@
                 break;
             case Float:
             case Double:
-                append(new BranchOp(cond, trueDestination, falseDestination, kind));
+                append(new BranchOp(finalCondition, trueDestination, falseDestination, kind));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -241,8 +242,9 @@
 
     @Override
     public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
+        append(new BranchOp(ConditionFlag.CarrySet, overflow, noOverflow, Kind.Long));
         // append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, label));
-        throw GraalInternalError.unimplemented();
+// throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -457,16 +459,16 @@
         Variable result = newVariable(LIRKind.derive(input));
         switch (input.getKind().getStackKind()) {
             case Long:
-                append(new Op1Stack(LNEG, result, input));
+                append(new Unary2Op(LNEG, result, load(input)));
                 break;
             case Int:
-                append(new Op1Stack(INEG, result, input));
+                append(new Unary2Op(INEG, result, load(input)));
                 break;
             case Float:
-                append(new Op1Stack(FNEG, result, input));
+                append(new Unary2Op(FNEG, result, load(input)));
                 break;
             case Double:
-                append(new Op1Stack(DNEG, result, input));
+                append(new Unary2Op(DNEG, result, load(input)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -479,10 +481,10 @@
         Variable result = newVariable(LIRKind.derive(input));
         switch (input.getKind().getStackKind()) {
             case Int:
-                append(new Op1Stack(INOT, result, input));
+                append(new Unary2Op(INOT, result, load(input)));
                 break;
             case Long:
-                append(new Op1Stack(LNOT, result, input));
+                append(new Unary2Op(LNOT, result, load(input)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -597,12 +599,33 @@
 
     @Override
     public Value emitMulHigh(Value a, Value b) {
-        throw GraalInternalError.unimplemented();
+        switch (a.getKind().getStackKind()) {
+            case Int:
+                return emitMulHigh(IMUL, a, b);
+            case Long:
+                return emitMulHigh(LMUL, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
     }
 
     @Override
     public Value emitUMulHigh(Value a, Value b) {
-        throw GraalInternalError.unimplemented();
+        switch (a.getKind().getStackKind()) {
+            case Int:
+                return emitMulHigh(IUMUL, a, b);
+            case Long:
+                return emitMulHigh(LUMUL, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private Value emitMulHigh(SPARCArithmetic opcode, Value a, Value b) {
+        Variable result = newVariable(LIRKind.derive(a, b));
+        MulHighOp mulHigh = new MulHighOp(opcode, load(a), load(b), result, newVariable(LIRKind.derive(a, b)));
+        append(mulHigh);
+        return result;
     }
 
     @Override
@@ -665,10 +688,10 @@
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind().getStackKind()) {
             case Int:
-                append(new RemOp(IUREM, result, a, loadNonConst(b), state, this));
+                append(new RemOp(IUREM, result, load(a), load(b), state, this));
                 break;
             case Long:
-                append(new RemOp(LUREM, result, a, loadNonConst(b), state, this));
+                append(new RemOp(LUREM, result, load(a), loadNonConst(b), state, this));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -680,17 +703,20 @@
     @Override
     public Value emitUDiv(Value a, Value b, LIRFrameState state) {
         SPARCArithmetic op;
+        Value actualA = a;
+        Value actualB = b;
         switch (a.getKind().getStackKind()) {
             case Int:
                 op = IUDIV;
-                break;
+                actualA = emitZeroExtend(actualA, 32, 64);
+                actualB = emitZeroExtend(actualB, 32, 64);
             case Long:
                 op = LUDIV;
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        return emitBinary(op, false, a, b, state);
+        return emitBinary(op, false, actualA, actualB, state);
     }
 
     @Override
@@ -915,11 +941,11 @@
             assert inputVal.getKind() == Kind.Int || inputVal.getKind() == Kind.Short || inputVal.getKind() == Kind.Byte : inputVal.getKind();
             Variable result = newVariable(LIRKind.derive(inputVal).changeType(Kind.Int));
             long mask = IntegerStamp.defaultMask(fromBits);
-            Constant constant = Constant.forLong(mask);
-            if (canInlineConstant(constant)) {
+            Constant constant = Constant.forInt((int) mask);
+            if (fromBits == 32) {
+                append(new ShiftOp(IUSHR, result, inputVal, Constant.forInt(0)));
+            } else if (canInlineConstant(constant)) {
                 append(new BinaryRegConst(SPARCArithmetic.IAND, result, asAllocatable(inputVal), constant, null));
-            } else if (fromBits == 32) {
-                append(new ShiftOp(IUSHR, result, inputVal, Constant.forInt(0)));
             } else {
                 Variable maskVar = newVariable(LIRKind.derive(inputVal).changeType(Kind.Int));
                 emitMove(maskVar, constant);
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Thu Jul 31 07:29:13 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Fri Aug 08 09:14:53 2014 -0700
@@ -27,18 +27,20 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.sparc.*;
 
 public enum SPARCArithmetic {
     // @formatter:off
-    IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
-    LADD, LSUB, LMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
+    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,
     FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
     DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
     INEG, LNEG, FNEG, DNEG, INOT, LNOT,
@@ -161,6 +163,10 @@
         @State protected LIRFrameState state;
         protected Constant y;
 
+        public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y) {
+            this(opcode, result, x, y, null);
+        }
+
         public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y, LIRFrameState state) {
             this.opcode = opcode;
             this.result = result;
@@ -282,9 +288,16 @@
             switch (opcode) {
                 case ISUB:
                     assert isSimm13(crb.asIntConst(src1));
-                    new Sub(SPARC.g0, asIntReg(src2), asIntReg(src2)).emit(masm);
-                    new Add(asIntReg(src2), crb.asIntConst(src1), asIntReg(dst)).emit(masm);
+                    new Sub(SPARC.g0, asIntReg(src2), asIntReg(dst)).emit(masm);
+                    new Add(asIntReg(dst), crb.asIntConst(src1), asIntReg(dst)).emit(masm);
                     break;
+                case LSUB: {
+                    long c = crb.asLongConst(src1);
+                    assert isSimm13(c);
+                    new Sub(SPARC.g0, asLongReg(src2), asLongReg(dst)).emit(masm);
+                    new Add(asLongReg(dst), (int) c, asLongReg(dst)).emit(masm);
+                    break;
+                }
                 case IAND:
                     throw GraalInternalError.unimplemented();
                 case IDIV:
@@ -292,13 +305,14 @@
                     exceptionOffset = masm.position();
                     new Sdivx(asIntReg(dst), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
-                case LDIV:
+                case LDIV: {
                     int c = crb.asIntConst(src1);
                     assert isSimm13(c);
                     exceptionOffset = masm.position();
                     new Sdivx(asLongReg(src2), c, asLongReg(dst)).emit(masm);
                     new Mulx(asLongReg(src1), asLongReg(dst), asLongReg(dst)).emit(masm);
                     break;
+                }
                 case FSUB:
                 case FDIV:
                 case DSUB:
@@ -440,7 +454,6 @@
                     new Sdivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
                 case IUDIV:
-                    new Srl(asIntReg(src1), 0, asIntReg(src1)).emit(masm);
                     exceptionOffset = masm.position();
                     new Udivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
@@ -570,18 +583,13 @@
             switch (opcode) {
                 case IREM:
                     assert isSimm13(crb.asIntConst(src2));
-                    new Sra(asIntReg(src1), 0, asIntReg(src1)).emit(masm);
                     exceptionOffset = masm.position();
                     new Sdivx(asIntReg(src1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm);
                     new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch2)).emit(masm);
                     new Sub(asIntReg(src1), asIntReg(scratch2), asIntReg(dst)).emit(masm);
                     break;
                 case IUREM:
-                    new Sra(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm);
-                    exceptionOffset = masm.position();
-                    new Udivx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm);
-                    new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm);
-                    new Sub(asIntReg(src1), asIntReg(scratch1), asIntReg(dst)).emit(masm);
+                    GraalInternalError.unimplemented();
                     break;
                 case LREM:
                     assert isSimm13(crb.asIntConst(src2));
@@ -634,11 +642,12 @@
                     new Sub(asIntReg(srcLeft), asIntReg(scratch1), asIntReg(dst)).emit(masm);
                     break;
                 case IUREM:
-                    new Sra(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm);
+                    new Srl(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm);
+                    new Srl(asIntReg(src2), 0, asIntReg(dst)).emit(masm);
                     exceptionOffset = masm.position();
-                    new Udivx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
-                    new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
-                    new Sub(asIntReg(src1), asIntReg(scratch1), asIntReg(dst)).emit(masm);
+                    new Udivx(asIntReg(scratch1), asIntReg(dst), asIntReg(scratch2)).emit(masm);
+                    new Mulx(asIntReg(scratch2), asIntReg(dst), asIntReg(dst)).emit(masm);
+                    new Sub(asIntReg(scratch1), asIntReg(dst), asIntReg(dst)).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -653,6 +662,7 @@
 
     public static void emit(CompilationResultBuilder crb, SPARCAssembler masm, SPARCArithmetic opcode, Value dst, Value src, LIRFrameState info) {
         int exceptionOffset = -1;
+        Label notOrdered = new Label();
         if (isRegister(src)) {
             switch (opcode) {
                 case INEG:
@@ -716,18 +726,20 @@
                     new Fstod(asFloatReg(src), asDoubleReg(dst)).emit(masm);
                     break;
                 case F2L:
-                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm);
-                    new Fbe(false, 4 * 4).emit(masm);
+                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(src), asFloatReg(src)).emit(masm);
+                    new Fbo(false, notOrdered).emit(masm);
                     new Fstox(asFloatReg(src), asFloatReg(dst)).emit(masm);
                     new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    masm.bind(notOrdered);
                     break;
                 case F2I:
-                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm);
-                    new Fbo(false, 4 * 4).emit(masm);
+                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(src), asFloatReg(src)).emit(masm);
+                    new Fbo(false, notOrdered).emit(masm);
                     new Fstoi(asFloatReg(src), asFloatReg(dst)).emit(masm);
                     new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    masm.bind(notOrdered);
                     break;
                 case MOV_D2L:
                     new Movdtox(asDoubleReg(src), asLongReg(dst)).emit(masm);
@@ -742,18 +754,20 @@
                     new Movwtos(asIntReg(src), asFloatReg(dst)).emit(masm);
                     break;
                 case D2L:
-                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
-                    new Fbo(false, 4 * 4).emit(masm);
+                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(src), asDoubleReg(src)).emit(masm);
+                    new Fbo(false, notOrdered).emit(masm);
                     new Fdtox(asDoubleReg(src), asDoubleReg(dst)).emit(masm);
                     new Fxtod(asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
                     new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
+                    masm.bind(notOrdered);
                     break;
                 case D2I:
-                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
-                    new Fbo(false, 4 * 4).emit(masm);
+                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(src), asDoubleReg(src)).emit(masm);
+                    new Fbo(false, notOrdered).emit(masm);
                     new Fdtoi(asDoubleReg(src), asDoubleReg(dst)).emit(masm);
                     new Fitod(asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
                     new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
+                    masm.bind(notOrdered);
                     break;
                 case FNEG:
                     new Fnegs(asFloatReg(src), asFloatReg(dst)).emit(masm);
@@ -806,7 +820,11 @@
                 rk = result.getKind();
                 xsk = x.getKind().getStackKind();
                 ysk = y.getKind().getStackKind();
-                assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int;
+                boolean valid = false;
+                for (Kind k : new Kind[]{Kind.Int, Kind.Short, Kind.Byte, Kind.Char}) {
+                    valid |= rk == k && xsk == k && ysk == k;
+                }
+                assert valid : "rk: " + rk + " xsk: " + xsk + " ysk: " + ysk;
                 break;
             case LADD:
             case LSUB:
@@ -856,4 +874,54 @@
                 throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
         }
     }
+
+    public static class MulHighOp extends SPARCLIRInstruction {
+
+        @Opcode private final SPARCArithmetic opcode;
+        @Def({REG}) public AllocatableValue result;
+        @Alive({REG}) public AllocatableValue x;
+        @Alive({REG}) public AllocatableValue y;
+        @Temp({REG}) public AllocatableValue scratch;
+
+        public MulHighOp(SPARCArithmetic opcode, AllocatableValue x, AllocatableValue y, AllocatableValue result, AllocatableValue scratch) {
+            this.opcode = opcode;
+            this.x = x;
+            this.y = y;
+            this.scratch = scratch;
+            this.result = result;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            assert isRegister(x) && isRegister(y) && isRegister(result) && isRegister(scratch);
+            switch (opcode) {
+                case IMUL:
+                    new Mulx(asIntReg(x), asIntReg(y), asIntReg(result)).emit(masm);
+                    new Srax(asIntReg(result), 32, asIntReg(result)).emit(masm);
+                    break;
+                case IUMUL:
+                    new Srl(asIntReg(x), 0, asIntReg(scratch)).emit(masm);
+                    new Srl(asIntReg(y), 0, asIntReg(result)).emit(masm);
+                    new Mulx(asIntReg(result), asIntReg(scratch), asIntReg(result)).emit(masm);
+                    new Srlx(asIntReg(result), 32, asIntReg(result)).emit(masm);
+                    break;
+                case LMUL:
+                    new Umulxhi(asLongReg(x), asLongReg(y), asLongReg(result)).emit(masm);
+
+                    new Srlx(asLongReg(x), 63, asLongReg(scratch)).emit(masm);
+                    new Mulx(asLongReg(scratch), asLongReg(y), asLongReg(scratch)).emit(masm);
+                    new Sub(asLongReg(result), asLongReg(scratch), asLongReg(result)).emit(masm);
+
+                    new Srlx(asLongReg(y), 63, asLongReg(scratch)).emit(masm);
+                    new Mulx(asLongReg(scratch), asLongReg(x), asLongReg(scratch)).emit(masm);
+                    new Sub(asLongReg(result), asLongReg(scratch), asLongReg(result)).emit(masm);
+                    break;
+                case LUMUL:
+                    new Umulxhi(asLongReg(x), asLongReg(y), asLongReg(result)).emit(masm);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Thu Jul 31 07:29:13 2014 -0700
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Fri Aug 08 09:14:53 2014 -0700
@@ -72,7 +72,11 @@
     public void testMulHighUnsigned() {
         test("mulHighUnsigned", 7, 15);
         test("mulHighUnsigned", Integer.MAX_VALUE, 15);
+        test("mulHighUnsigned", 15, Integer.MAX_VALUE);
+        test("mulHighUnsigned", Integer.MAX_VALUE, Integer.MAX_VALUE);
+        test("mulHighUnsigned", 15, Integer.MIN_VALUE);
         test("mulHighUnsigned", Integer.MIN_VALUE, 15);
+        test("mulHighUnsigned", Integer.MIN_VALUE, Integer.MIN_VALUE);
     }
 
     @Test
@@ -98,7 +102,11 @@
     public void testLongMulHigh() {
         test("longMulHigh", 7L, 15L);
         test("longMulHigh", Long.MAX_VALUE, 15L);
+        test("longMulHigh", 15L, Long.MAX_VALUE);
+        test("longMulHigh", Long.MAX_VALUE, Long.MAX_VALUE);
         test("longMulHigh", Long.MIN_VALUE, 15L);
+        test("longMulHigh", 15L, Long.MIN_VALUE);
+        test("longMulHigh", Long.MIN_VALUE, Long.MIN_VALUE);
     }
 
     @Test