changeset 16321:fac4af29aeb8

[SPARC] Fixing lots of float and double issues.
author Stefan Anzinger <stefan.anzinger@gmail.com>
date Thu, 05 Jun 2014 11:28:16 +0200
parents fcac781d3592
children f96d9c455da5
files graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampProvider.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConstant.java graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMField.java graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMFlag.java graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMType.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/SPARCMove.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java test/whitelist_baseline.txt
diffstat 5 files changed, 277 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Jun 03 14:31:36 2014 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Thu Jun 05 11:28:16 2014 +0200
@@ -456,6 +456,43 @@
 
     // @formatter:off
     /**
+     * Instruction format for fcmp
+     *
+     * | 10  | --- |cc1|cc0|desc |   rs1   |   opf  | rs2 |
+     * |31 30|29 27|26 |25 |24 19|18     14|13     5|4   0|
+     */
+    // @formatter:on
+    public static class Fmt3c {
+        private int op;
+        private int cc;
+        private int desc;
+        private int opf;
+        private int rs1;
+        private int rs2;
+
+        public Fmt3c(Ops op, CC cc, int desc, Opfs opf, Register rs1, Register rs2) {
+            this.op = op.getValue();
+            this.opf = opf.getValue();
+            this.desc = desc;
+            this.rs1 = rs1.encoding();
+            this.rs2 = rs2.encoding();
+            this.cc = cc.getValue();
+        }
+
+        public void emit(SPARCAssembler masm) {
+            assert op == 2 || op == 3;
+            assert cc >= 0 && cc < 0x4;
+            assert opf >= 0 && opf < 0x200;
+            assert rs1 >= 0 && rs1 < 0x20;
+            assert rs2 >= 0 && rs2 < 0x20;
+            assert desc >= 0 && desc < 0x40;
+
+            masm.emitInt(op << 30 | cc << 25 | desc << 19 | rs1 << 14 | opf << 5 | rs2);
+        }
+    }
+
+    // @formatter:off
+    /**
      * Instruction format for Arithmetic, Logical, Moves, Tcc, Prefetch, and Misc.
      *
      * | 10  |   rd   |   op3   |   rs1   | i|     imm_asi   |   rs2   |
@@ -1043,7 +1080,9 @@
         Stf(0b100100, "stf"),
         Stfsr(0x25, "stfsr"),
         Staf(0x26, "staf"),
-        Stdf(0b100111, "stdf");
+        Stdf(0b100111, "stdf"),
+
+        Fcmp(0b110101, "fcmp");
 
         // @formatter:on
 
@@ -1181,6 +1220,9 @@
         Fnsmuld(0x79, "fnsmuld"),
         Fnhadds(0x71, "fnhadds"),
         Fnhaddd(0x72, "fnhaddd"),
+        Movdtox(0x110, "movdtox"),
+        Movstouw(0x111, "movstouw"),
+        Movstosw(0x113, "movstosw"),
         Movxtod(0x118, "movxtod"),
         Movwtos(0x119, "movwtos"),
         // end VIS3
@@ -1231,6 +1273,8 @@
 
         Fstoi(0xD1, "fstoi"),
         Fdtoi(0xD2, "fdtoi"),
+        Fstox(0x81, "fstox"),
+        Fdtox(0x82, "fdtox"),
         Fxtos(0x84, "fxtos"),
         Fxtod(0x88, "fxtod"),
         Fxtoq(0x8C, "fxtoq"),
@@ -1238,7 +1282,13 @@
         Fdtos(0xC6, "fdtos"),
         Fitod(0xC8, "fitod"),
         Fstod(0xC9, "fstod"),
-        Fitoq(0xCC, "fitoq")
+        Fitoq(0xCC, "fitoq"),
+
+
+        Fcmps(0x51, "fcmps"),
+        Fcmpd(0x52, "fcmpd"),
+        Fcmpq(0x53, "fcmpq"),
+
         ;
         // @formatter:on
 
@@ -1327,6 +1377,41 @@
         }
     }
 
+    public enum FCond {
+        Fba(0x8, "fba"),
+        Fbn(0x0, "fbn"),
+        Fbu(0x7, "fbu"),
+        Fbg(0x6, "fbg"),
+        Fbug(0x5, "fbug"),
+        Fbl(0x4, "fbl"),
+        Fbul(0x3, "fbul"),
+        Fblg(0x2, "fblg"),
+        Fbne(0x1, "fbne"),
+        Fbe(0x9, "fbe"),
+        Fbue(0xA, "fbue"),
+        Fbge(0xB, "fbge"),
+        Fbuge(0xC, "fbuge"),
+        Fble(0xD, "fble"),
+        Fbule(0xE, "fbule"),
+        Fbo(0xF, "fbo");
+        private final int value;
+        private final String operator;
+
+        private FCond(int value, String op) {
+            assert value >= 0 && value < 1 << 5 : value; // 4 bits
+            this.value = value;
+            this.operator = op;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        public String getOperator() {
+            return operator;
+        }
+    }
+
     public enum ConditionFlag {
         // @formatter:off
 
@@ -1692,6 +1777,27 @@
         }
     }
 
+    public static class Movdtox extends Fmt3p {
+        public Movdtox(Register src, Register dst) {
+            /* VIS3 only */
+            super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movdtox, g0, src, dst);
+        }
+    }
+
+    public static class Movstosw extends Fmt3p {
+        public Movstosw(Register src, Register dst) {
+            /* VIS3 only */
+            super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movstosw, g0, src, dst);
+        }
+    }
+
+    public static class Movstouw extends Fmt3p {
+        public Movstouw(Register src, Register dst) {
+            /* VIS3 only */
+            super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movstouw, g0, src, dst);
+        }
+    }
+
     public static class Fdtos extends Fmt3p {
         public Fdtos(Register src, Register dst) {
             /* VIS3 only */
@@ -2659,6 +2765,20 @@
         }
     }
 
+    public static class Fstox extends Fmt3n {
+
+        public Fstox(SPARCAssembler masm, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fstox.getValue(), src2.encoding(), dst.encoding());
+        }
+    }
+
+    public static class Fdtox extends Fmt3n {
+
+        public Fdtox(SPARCAssembler masm, Register src2, Register dst) {
+            super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fdtox.getValue(), src2.encoding(), dst.encoding());
+        }
+    }
+
     public static class Fstod extends Fmt3n {
 
         public Fstod(SPARCAssembler masm, Register src2, Register dst) {
@@ -2898,6 +3018,20 @@
         }
     }
 
+    public static class Fcmp extends Fmt3c {
+
+        public Fcmp(CC cc, Opfs opf, Register r1, Register r2) {
+            super(Ops.ArithOp, cc, 0b110101, opf, r1, r2);
+        }
+    }
+
+    public static class Fbfcc extends Fmt00b {
+
+        public Fbfcc(SPARCAssembler asm, FCond cond, boolean annul, int disp) {
+            super(asm, Ops.BranchOp.getValue(), annul ? 1 : 0, cond.getValue(), 0b110, disp);
+        }
+    }
+
     public static class Illtrap extends Fmt00a {
 
         public Illtrap(int const22) {
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Jun 03 14:31:36 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Jun 05 11:28:16 2014 +0200
@@ -617,6 +617,7 @@
     @Override
     public Value emitRem(Value a, Value b, LIRFrameState state) {
         Variable result = newVariable(a.getKind());
+        Variable q = null;
         switch (a.getKind().getStackKind()) {
             case Int:
                 append(new RemOp(IREM, result, a, loadNonConst(b), state, this));
@@ -624,6 +625,22 @@
             case Long:
                 append(new RemOp(LREM, result, a, loadNonConst(b), state, this));
                 break;
+            case Float:
+                q = newVariable(Kind.Float);
+                append(new Op2Stack(FDIV, q, a, b));
+                append(new Unary2Op(F2I, q, q));
+                append(new Unary2Op(I2F, q, q));
+                append(new Op2Stack(FMUL, q, q, b));
+                append(new Op2Stack(FSUB, result, a, q));
+                break;
+            case Double:
+                q = newVariable(Kind.Double);
+                append(new Op2Stack(DDIV, q, a, b));
+                append(new Unary2Op(D2L, q, q));
+                append(new Unary2Op(L2D, q, q));
+                append(new Op2Stack(DMUL, q, q, b));
+                append(new Op2Stack(DSUB, result, a, q));
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
         }
@@ -771,19 +788,33 @@
     @Override
     public Value emitFloatConvert(FloatConvert op, Value inputVal) {
         AllocatableValue input = asAllocatable(inputVal);
+        Kind fromRegisterKind = null;
+        Kind toRegisterKind = null;
+        SPARCArithmetic conversionInstruction = null;
         switch (op) {
             case D2F:
                 return emitConvert2Op(Kind.Float, D2F, input);
             case D2I:
-                return emitConvert2Op(Kind.Int, D2I, input);
+                fromRegisterKind = Kind.Double;
+                toRegisterKind = Kind.Int;
+                conversionInstruction = D2I;
+                break;
+            case F2L:
+                Variable v = newVariable(Kind.Double);
+                emitMove(v, input);
+                input = v;
             case D2L:
-                return emitConvert2Op(Kind.Long, D2L, input);
+                fromRegisterKind = Kind.Double;
+                toRegisterKind = Kind.Long;
+                conversionInstruction = D2L;
+                break;
             case F2D:
                 return emitConvert2Op(Kind.Double, F2D, input);
             case F2I:
-                return emitConvert2Op(Kind.Int, F2I, input);
-            case F2L:
-                return emitConvert2Op(Kind.Long, F2L, input);
+                fromRegisterKind = Kind.Float;
+                toRegisterKind = Kind.Int;
+                conversionInstruction = F2I;
+                break;
             case I2D:
                 return emitConvert2Op(Kind.Double, L2D, emitConvert2Op(Kind.Long, I2L, input));
             case I2F:
@@ -795,6 +826,13 @@
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
+        if (fromRegisterKind != null) {
+            AllocatableValue var = newVariable(toRegisterKind);
+            emitMove(var, emitConvert2Op(fromRegisterKind, conversionInstruction, input));
+            return var;
+        } else {
+            throw GraalInternalError.shouldNotReachHere();
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Tue Jun 03 14:31:36 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Thu Jun 05 11:28:16 2014 +0200
@@ -58,7 +58,15 @@
         ArrayList<Register> list = new ArrayList<>();
         for (Register reg : getAllocatableRegisters()) {
             if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
-                list.add(reg);
+                // Special treatment for double precision
+                if (kind == Kind.Double) {
+                    // Only even register numbers are valid double precision regs
+                    if (reg.number % 2 == 0) {
+                        list.add(reg);
+                    }
+                } else {
+                    list.add(reg);
+                }
             }
         }
 
@@ -201,8 +209,18 @@
                         locations[i] = register.asValue(kind);
                     }
                     break;
+                case Double:
+                    if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
+                        if (currentFloating % 2 != 0) {
+                            // Make register number even to be a double reg
+                            currentFloating++;
+                        }
+                        Register register = fpuParameterRegisters[currentFloating];
+                        currentFloating += 2; // Only every second is a double register
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
                 case Float:
-                case Double:
                     if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
                         Register register = fpuParameterRegisters[currentFloating++];
                         locations[i] = register.asValue(kind);
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Tue Jun 03 14:31:36 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Thu Jun 05 11:28:16 2014 +0200
@@ -556,16 +556,15 @@
                 case D2F:
                     new Fdtos(asDoubleReg(src), asFloatReg(dst)).emit(masm);
                     break;
-                /*
-                 * case L2F:
-                 * 
-                 * new Movxtod(asLongReg(src), asDoubleReg(dst)).emit(masm); new Fxtod(masm,
-                 * asDoubleReg(dst), asDoubleReg(dst)); new Fdtos(asDoubleReg(dst),
-                 * asFloatReg(dst)).emit(masm); break;
-                 */
                 case L2D:
-                    new Movxtod(asLongReg(src), asDoubleReg(dst)).emit(masm);
-                    new Fxtod(masm, asDoubleReg(dst), asDoubleReg(dst));
+                    if (src.getPlatformKind() == Kind.Long) {
+                        new Movxtod(asLongReg(src), asDoubleReg(dst)).emit(masm);
+                        new Fxtod(masm, asDoubleReg(dst), asDoubleReg(dst));
+                    } else if (src.getPlatformKind() == Kind.Double) {
+                        new Fxtod(masm, asDoubleReg(src), asDoubleReg(dst));
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("cannot handle source register " + src.getPlatformKind());
+                    }
                     break;
                 case I2L:
                     new Signx(asIntReg(src), asLongReg(dst)).emit(masm);
@@ -590,12 +589,46 @@
                     new Sra(asIntReg(dst), 16, asIntReg(dst)).emit(masm);
                     break;
                 case I2F:
-                    new Movwtos(asIntReg(src), asFloatReg(dst)).emit(masm);
-                    new Fitos(masm, asFloatReg(dst), asFloatReg(dst));
+                    if (src.getPlatformKind() == Kind.Int) {
+                        new Movwtos(asIntReg(src), asFloatReg(dst)).emit(masm);
+                        new Fitos(masm, asFloatReg(dst), asFloatReg(dst));
+                    } else if (src.getPlatformKind() == Kind.Float) {
+                        new Fitos(masm, asFloatReg(src), asFloatReg(dst));
+                    } else {
+                        throw GraalInternalError.shouldNotReachHere("cannot handle source register " + src.getPlatformKind());
+                    }
                     break;
                 case F2D:
                     new Fstod(masm, asDoubleReg(dst), asDoubleReg(dst));
                     break;
+                case F2L:
+                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    new Fbfcc(masm, FCond.Fbo, false, 4);
+                    new Fstox(masm, asFloatReg(dst), asFloatReg(dst));
+                    new Fitos(masm, asFloatReg(dst), asFloatReg(dst));
+                    new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    break;
+                case F2I:
+                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    new Fbfcc(masm, FCond.Fbo, false, 4);
+                    new Fstoi(masm, asFloatReg(dst), asFloatReg(dst));
+                    new Fitos(masm, asFloatReg(dst), asFloatReg(dst));
+                    new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    break;
+                case D2L:
+                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
+                    new Fbfcc(masm, FCond.Fbo, false, 4);
+                    new Fdtox(masm, asDoubleReg(dst), asDoubleReg(dst));
+                    new Fxtod(masm, asDoubleReg(dst), asDoubleReg(dst));
+                    new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
+                    break;
+                case D2I:
+                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
+                    new Fbfcc(masm, FCond.Fbo, false, 4);
+                    new Fdtoi(masm, asDoubleReg(dst), asDoubleReg(dst));
+                    new Fitod(masm, asDoubleReg(dst), asDoubleReg(dst));
+                    new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
+                    break;
                 case FNEG:
                     new Fnegs(masm, asFloatReg(src), asFloatReg(dst));
                     break;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Jun 03 14:31:36 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Thu Jun 05 11:28:16 2014 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
+import com.sun.org.apache.bcel.internal.generic.*;
 
 public class SPARCMove {
 
@@ -319,9 +320,13 @@
                     new Stx(asRegister(input), addr).emit(masm);
                     break;
                 case Float:
+                    new Stf(asRegister(input), addr).emit(masm);
+                    break;
                 case Double:
+                    new Stdf(asRegister(input), addr).emit(masm);
+                    break;
                 default:
-                    throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
+                    throw GraalInternalError.shouldNotReachHere("missing: " + kind);
             }
         }
     }
@@ -391,10 +396,14 @@
         }
     }
 
+    @SuppressWarnings("unused")
     private static void reg2reg(SPARCAssembler masm, Value result, Value input) {
         final Register src = asRegister(input);
         final Register dst = asRegister(result);
-        if (src.equals(dst)) {
+        // implicit conversions between double and float registers can happen in the "same Register"
+// f0->d0
+        boolean isFloatToDoubleConversion = result.getKind() == Kind.Double && input.getKind() == Kind.Float;
+        if (src.equals(dst) && !isFloatToDoubleConversion) {
             return;
         }
         switch (input.getKind()) {
@@ -404,10 +413,31 @@
                 new Mov(src, dst).emit(masm);
                 break;
             case Float:
-                new Fmovs(src, dst).emit(masm);
+                switch (result.getKind()) {
+                    case Long:
+                        new Movstosw(src, dst).emit(masm);
+                        break;
+                    case Int:
+                        new Movstouw(src, dst).emit(masm);
+                        break;
+                    case Float:
+                        new Fmovs(src, dst).emit(masm);
+                        break;
+                    case Double:
+                        new Fstod(masm, src, dst);
+                        break;
+                    default:
+                        throw GraalInternalError.shouldNotReachHere();
+                }
                 break;
             case Double:
-                new Fmovd(src, dst).emit(masm);
+                if (result.getPlatformKind() == Kind.Long) {
+                    new Movdtox(src, dst).emit(masm);
+                } else if (result.getPlatformKind() == Kind.Int) {
+                    new Movstouw(src, dst).emit(masm);
+                } else {
+                    new Fmovd(src, dst).emit(masm);
+                }
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();