# HG changeset patch # User Stefan Anzinger # Date 1401960496 -7200 # Node ID fac4af29aeb888baa0b68eaab47ab68fe579b775 # Parent fcac781d35927950b56022f9c18d55ec66696d75 [SPARC] Fixing lots of float and double issues. diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- 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) { diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampProvider.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- 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 diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java --- 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 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); diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConstant.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMField.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMFlag.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMType.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java --- 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; diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java --- 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(); diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java diff -r fcac781d3592 -r fac4af29aeb8 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java diff -r fcac781d3592 -r fac4af29aeb8 test/whitelist_baseline.txt