# HG changeset patch # User Stefan Anzinger # Date 1407514493 25200 # Node ID 5c8a0b322d151a3128bf507a77de0ea10b3212b8 # Parent 2f4487a0b588a7c454acca8357ec479352b8bd7a [SPARC] Implement unsigned arithmethic, fix CAS, unary operations on stack and various other fixes diff -r 2f4487a0b588 -r 5c8a0b322d15 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 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); diff -r 2f4487a0b588 -r 5c8a0b322d15 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 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(); + } + } + } } diff -r 2f4487a0b588 -r 5c8a0b322d15 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java --- 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