# HG changeset patch # User Stefan Anzinger # Date 1410967434 25200 # Node ID 4a1ee9bebd33111bf727af3f58a31791bde8bec0 # Parent 832c8c93c949b6986192d507c9b36c477d6b62cb# Parent 8ca5e41dde86eb7107c9820e1abc32f5c0995cbd Merge diff -r 8ca5e41dde86 -r 4a1ee9bebd33 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 Sep 16 22:00:52 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Wed Sep 17 08:23:54 2014 -0700 @@ -1515,6 +1515,8 @@ Fones(0x7F, "fones"), Fandd(0b0_0111_0000, "fandd"), Fands(0b0_0111_0001, "fands"), + Fxord(0b0_0110_1100, "fxord"), + Fxors(0b0_0110_1101, "fxord"), // end VIS1 // start VIS2 @@ -2197,7 +2199,7 @@ super(0, ConditionFlag.Equal, Op2s.Bp, cc, predictTaken ? 1 : 0, label); } - public Bpe(boolean annul, CC cc, Label label, boolean predictTaken) { + public Bpe(CC cc, boolean annul, boolean predictTaken, Label label) { super(annul ? 1 : 0, ConditionFlag.Equal, Op2s.Bp, cc, predictTaken ? 1 : 0, label); } @@ -3428,6 +3430,18 @@ } } + public static class Fabss extends Fmt3p { + public Fabss(Register src2, Register dst) { + super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fabss, SPARC.r0, src2, dst); + } + } + + public static class Fabsd extends Fmt3p { + public Fabsd(Register src2, Register dst) { + super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fabsd, SPARC.r0, src2, dst); + } + } + public static class Fsrc1d extends Fmt3p { public Fsrc1d(Register src1, Register dst) { @@ -4135,6 +4149,18 @@ } } + public static class Fxord extends Fmt3p { + public Fxord(Register src1, Register src2, Register dst) { + super(Ops.ArithOp, Op3s.Impdep1, Opfs.Fxord, src1, src2, dst); + } + } + + public static class Fxors extends Fmt3p { + public Fxors(Register src1, Register src2, Register dst) { + super(Ops.ArithOp, Op3s.Impdep1, Opfs.Fxors, src1, src2, dst); + } + } + public static class Fands extends Fmt3p { public Fands(Register src1, Register src2, Register dst) { super(Ops.ArithOp, Op3s.Impdep1, Opfs.Fands, src1, src2, dst); diff -r 8ca5e41dde86 -r 4a1ee9bebd33 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Tue Sep 16 22:00:52 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Wed Sep 17 08:23:54 2014 -0700 @@ -44,11 +44,8 @@ @Override public void align(int modulus) { - if (position() % modulus != 0) { - final int count = modulus - (position() % modulus); - for (int i = 0; i < count; i++) { - new Nop().emit(this); - } + while (position() % modulus != 0) { + new Nop().emit(this); } } diff -r 8ca5e41dde86 -r 4a1ee9bebd33 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 Sep 16 22:00:52 2014 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Sep 17 08:23:54 2014 -0700 @@ -56,11 +56,13 @@ import com.oracle.graal.lir.sparc.SPARCMove.LoadDataAddressOp; import com.oracle.graal.lir.sparc.SPARCMove.MembarOp; import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGp; +import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGpVIS3; import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp; import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp; import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp; import com.oracle.graal.phases.util.*; import com.oracle.graal.sparc.*; +import com.oracle.graal.sparc.SPARC.*; /** * This class implements the SPARC specific portion of the LIR generator. @@ -409,9 +411,7 @@ @Override public Value emitMathAbs(Value input) { Variable result = newVariable(LIRKind.derive(input)); - AllocatableValue mask = newVariable(LIRKind.value(Kind.Double)); - emitMove(mask, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL))); - append(new BinaryRegReg(DAND, result, asAllocatable(input), mask)); + append(new SPARCMathIntrinsicOp(ABS, result, asAllocatable(input))); return result; } @@ -869,8 +869,12 @@ } private void moveBetweenFpGp(AllocatableValue dst, AllocatableValue src) { - StackSlot tempSlot = getTempSlot(LIRKind.value(Kind.Long)); - append(new MoveFpGp(dst, src, tempSlot)); + if (!getArchitecture().getFeatures().contains(CPUFeature.VIS3)) { + StackSlot tempSlot = getTempSlot(LIRKind.value(Kind.Long)); + append(new MoveFpGp(dst, src, tempSlot)); + } else { + append(new MoveFpGpVIS3(dst, src)); + } } private StackSlot getTempSlot(LIRKind kind) { diff -r 8ca5e41dde86 -r 4a1ee9bebd33 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Tue Sep 16 22:00:52 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Wed Sep 17 08:23:54 2014 -0700 @@ -76,13 +76,13 @@ protected Set computeFeatures(HotSpotVMConfig config) { Set features = EnumSet.noneOf(CPUFeature.class); - if (config.vis1Instructions != 0) { + if ((config.sparcFeatures & config.vis1Instructions) != 0) { features.add(CPUFeature.VIS1); } - if (config.vis2Instructions != 0) { + if ((config.sparcFeatures & config.vis2Instructions) != 0) { features.add(CPUFeature.VIS2); } - if (config.vis3Instructions != 0) { + if ((config.sparcFeatures & config.vis3Instructions) != 0) { features.add(CPUFeature.VIS3); } return features; diff -r 8ca5e41dde86 -r 4a1ee9bebd33 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java Tue Sep 16 22:00:52 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java Wed Sep 17 08:23:54 2014 -0700 @@ -129,7 +129,7 @@ private void emit8ByteCompare(SPARCMacroAssembler masm, Register result, Register array1, Register array2, Register length, Label trueLabel, Label falseLabel) { Label loop = new Label(); Label compareTail = new Label(); - + // new Ldx(new SPARCAddress(o6, 3), g0).emit(masm); Register tempReg1 = asRegister(temp4); Register tempReg2 = asRegister(temp5); new And(result, VECTOR_SIZE - 1, result).emit(masm); // tail count (in bytes) @@ -137,27 +137,41 @@ new Bpe(CC.Xcc, compareTail).emit(masm); new Nop().emit(masm); + Label compareTailCorrectVectorEnd = new Label(); + new Sub(length, VECTOR_SIZE, length).emit(masm); new Add(array1, length, array1).emit(masm); new Add(array2, length, array2).emit(masm); new Sub(g0, length, length).emit(masm); + // Compare the last element first + new Ldx(new SPARCAddress(array1, 0), tempReg1).emit(masm); + new Ldx(new SPARCAddress(array2, 0), tempReg2).emit(masm); + new Cmp(tempReg1, tempReg2).emit(masm); + new Bpne(Xcc, true, false, falseLabel).emit(masm); + new Nop().emit(masm); + new Bpr(RCondition.Rc_z, false, false, length, compareTailCorrectVectorEnd).emit(masm); + new Nop().emit(masm); + // Load the first value from array 1 (Later done in back branch delay-slot) new Ldx(new SPARCAddress(array1, length), tempReg1).emit(masm); masm.bind(loop); new Ldx(new SPARCAddress(array2, length), tempReg2).emit(masm); - new Cmp(tempReg1, tempReg2).emit(masm); new Bpne(Xcc, false, false, falseLabel).emit(masm); // Delay slot, not annul, add for next iteration - new Add(length, VECTOR_SIZE, length).emit(masm); - - new Bpr(RCondition.Rc_nz, true, true, length, loop).emit(masm); + new Addcc(length, VECTOR_SIZE, length).emit(masm); + new Bpne(Xcc, true, true, loop).emit(masm); // Annul, to prevent access past the array new Ldx(new SPARCAddress(array1, length), tempReg1).emit(masm); // Load in delay slot // Tail count zero, therefore we can go to the end new Bpr(RCondition.Rc_z, true, true, result, trueLabel).emit(masm); new Nop().emit(masm); + masm.bind(compareTailCorrectVectorEnd); + // Correct the array pointers + new Add(array1, VECTOR_SIZE, array1).emit(masm); + new Add(array2, VECTOR_SIZE, array2).emit(masm); + masm.bind(compareTail); } diff -r 8ca5e41dde86 -r 4a1ee9bebd33 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java diff -r 8ca5e41dde86 -r 4a1ee9bebd33 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java Tue Sep 16 22:00:52 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java Wed Sep 17 08:23:54 2014 -0700 @@ -25,7 +25,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fsqrtd; +import com.oracle.graal.asm.sparc.SPARCAssembler.*; import com.oracle.graal.asm.sparc.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; @@ -39,7 +39,8 @@ COS, TAN, LOG, - LOG10 + LOG10, + ABS } @Opcode private final IntrinsicOpcode opcode; @@ -54,9 +55,31 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + Kind inputKind = (Kind) input.getLIRKind().getPlatformKind(); switch (opcode) { case SQRT: - new Fsqrtd(asDoubleReg(input), asDoubleReg(result)).emit(masm); + switch (inputKind) { + case Float: + new Fsqrts(asFloatReg(input), asFloatReg(result)).emit(masm); + break; + case Double: + new Fsqrtd(asDoubleReg(input), asDoubleReg(result)).emit(masm); + break; + default: + GraalInternalError.shouldNotReachHere(); + } + break; + case ABS: + switch (inputKind) { + case Float: + new Fabss(asFloatReg(input), asFloatReg(result)).emit(masm); + break; + case Double: + new Fabsd(asDoubleReg(input), asDoubleReg(result)).emit(masm); + break; + default: + GraalInternalError.shouldNotReachHere(); + } break; case LOG: case LOG10: diff -r 8ca5e41dde86 -r 4a1ee9bebd33 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 Sep 16 22:00:52 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Wed Sep 17 08:23:54 2014 -0700 @@ -23,15 +23,46 @@ package com.oracle.graal.lir.sparc; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.api.meta.Kind.*; +import static com.oracle.graal.asm.sparc.SPARCAssembler.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import static com.oracle.graal.sparc.SPARC.*; -import static com.oracle.graal.asm.sparc.SPARCAssembler.*; import com.oracle.graal.api.code.CompilationResult.RawData; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import com.oracle.graal.asm.sparc.SPARCAssembler.Add; +import com.oracle.graal.asm.sparc.SPARCAssembler.Fmovd; +import com.oracle.graal.asm.sparc.SPARCAssembler.Fmovs; +import com.oracle.graal.asm.sparc.SPARCAssembler.Fxord; +import com.oracle.graal.asm.sparc.SPARCAssembler.Fxors; +import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf; +import com.oracle.graal.asm.sparc.SPARCAssembler.Ldf; +import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsb; +import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsh; +import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw; +import com.oracle.graal.asm.sparc.SPARCAssembler.Lduh; +import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx; +import com.oracle.graal.asm.sparc.SPARCAssembler.Membar; +import com.oracle.graal.asm.sparc.SPARCAssembler.Movdtox; +import com.oracle.graal.asm.sparc.SPARCAssembler.Movstosw; +import com.oracle.graal.asm.sparc.SPARCAssembler.Movstouw; +import com.oracle.graal.asm.sparc.SPARCAssembler.Movwtos; +import com.oracle.graal.asm.sparc.SPARCAssembler.Movxtod; +import com.oracle.graal.asm.sparc.SPARCAssembler.Or; +import com.oracle.graal.asm.sparc.SPARCAssembler.Rdpc; +import com.oracle.graal.asm.sparc.SPARCAssembler.Stb; +import com.oracle.graal.asm.sparc.SPARCAssembler.Stdf; +import com.oracle.graal.asm.sparc.SPARCAssembler.Stf; +import com.oracle.graal.asm.sparc.SPARCAssembler.Sth; +import com.oracle.graal.asm.sparc.SPARCAssembler.Stw; +import com.oracle.graal.asm.sparc.SPARCAssembler.Stx; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cas; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Casx; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Clr; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.ImplicitNullCheck; @@ -39,6 +70,7 @@ import com.oracle.graal.lir.StandardOp.NullCheck; import com.oracle.graal.lir.asm.*; import com.oracle.graal.sparc.*; +import com.oracle.graal.sparc.SPARC.CPUFeature; public class SPARCMove { @@ -189,6 +221,61 @@ } } + /** + * Move between floating-point and general purpose register domain (WITH VIS3) + */ + @Opcode("MOVE") + public static class MoveFpGpVIS3 extends SPARCLIRInstruction implements MoveOp { + + @Def({REG}) protected AllocatableValue result; + @Use({REG}) protected AllocatableValue input; + + public MoveFpGpVIS3(AllocatableValue result, AllocatableValue input) { + super(); + this.result = result; + this.input = input; + } + + public Value getInput() { + return input; + } + + public AllocatableValue getResult() { + return result; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + Kind inputKind = (Kind) input.getPlatformKind(); + Kind resultKind = (Kind) result.getPlatformKind(); + if (resultKind == Float) { + if (inputKind == Int || inputKind == Short || inputKind == Char || inputKind == Byte) { + new Movwtos(asIntReg(input), asFloatReg(result)).emit(masm); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else if (resultKind == Double) { + if (inputKind == Int || inputKind == Short || inputKind == Char || inputKind == Byte) { + new Movxtod(asIntReg(input), asDoubleReg(result)).emit(masm); + } else { + new Movxtod(asLongReg(input), asDoubleReg(result)).emit(masm); + } + } else if (inputKind == Float) { + if (resultKind == Int || resultKind == Short || resultKind == Byte) { + new Movstosw(asFloatReg(input), asIntReg(result)).emit(masm); + } else { + new Movstouw(asFloatReg(input), asIntReg(result)).emit(masm); + } + } else if (inputKind == Double) { + if (resultKind == Long) { + new Movdtox(asDoubleReg(input), asLongReg(result)).emit(masm); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + } + } + public abstract static class MemOp extends SPARCLIRInstruction implements ImplicitNullCheck { protected final Kind kind; @@ -655,6 +742,7 @@ private static void const2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Constant input) { try (SPARCScratchRegister sc = SPARCScratchRegister.get()) { Register scratch = sc.getRegister(); + boolean hasVIS3 = ((SPARC) masm.target.arch).getFeatures().contains(CPUFeature.VIS3); switch (input.getKind().getStackKind()) { case Int: if (input.isDefaultForKind()) { @@ -674,28 +762,54 @@ new Setx(input.asLong(), asLongReg(result)).emit(masm); } break; - case Float: - // TODO: Handle it the same way, as in the double case with Movwtos - crb.asFloatConstRef(input); - // First load the address into the scratch register - new Setx(0, scratch, true).emit(masm); - // Now load the float value - new Ldf(scratch, asFloatReg(result)).emit(masm); + case Float: { + float constant = input.asFloat(); + int constantBits = java.lang.Float.floatToIntBits(constant); + if (constantBits == 0) { + new Fxors(asFloatReg(result), asFloatReg(result), asFloatReg(result)).emit(masm); + } else { + if (hasVIS3) { + if (isSimm13(constantBits)) { + new Or(g0, constantBits, scratch).emit(masm); + } else { + new Setx(constantBits, scratch, false).emit(masm); + } + // Now load the float value + new Movwtos(scratch, asFloatReg(result)).emit(masm); + } else { + crb.asFloatConstRef(input); + // First load the address into the scratch register + new Setx(0, scratch, true).emit(masm); + // Now load the float value + new Ldf(scratch, asFloatReg(result)).emit(masm); + } + } break; - case Double: - // instead loading this from memory and do the complicated lookup, - // just load it directly into a scratch register - // First load the address into the scratch register - // new Setx(Double.doubleToLongBits(input.asDouble()), scratch, - // true).emit(masm); - // Now load the float value - // new Movxtod(scratch, asDoubleReg(result)).emit(masm); - crb.asDoubleConstRef(input); - // First load the address into the scratch register - new Setx(0, scratch, true).emit(masm); - // Now load the float value - new Lddf(scratch, asDoubleReg(result)).emit(masm); + } + case Double: { + double constant = input.asDouble(); + long constantBits = java.lang.Double.doubleToLongBits(constant); + if (constantBits == 0) { + new Fxord(asDoubleReg(result), asDoubleReg(result), asDoubleReg(result)).emit(masm); + } else { + if (hasVIS3) { + if (isSimm13(constantBits)) { + new Or(g0, (int) constantBits, scratch).emit(masm); + } else { + new Setx(constantBits, scratch, false).emit(masm); + } + // Now load the float value + new Movxtod(scratch, asDoubleReg(result)).emit(masm); + } else { + crb.asDoubleConstRef(input); + // First load the address into the scratch register + new Setx(0, scratch, true).emit(masm); + // Now load the float value + new Lddf(scratch, asDoubleReg(result)).emit(masm); + } + } break; + } case Object: if (input.isNull()) { new Clr(asRegister(result)).emit(masm); diff -r 8ca5e41dde86 -r 4a1ee9bebd33 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Tue Sep 16 22:00:52 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Wed Sep 17 08:23:54 2014 -0700 @@ -33,7 +33,7 @@ /** * Substitutions for {@link java.lang.Math} methods. */ -@ClassSubstitution(value = java.lang.Math.class, defaultGuard = UnsafeSubstitutions.GetAndSetGuard.class) +@ClassSubstitution(value = java.lang.Math.class) public class MathSubstitutionsX86 { private static final double PI_4 = Math.PI / 4; @@ -48,12 +48,12 @@ return MathIntrinsicNode.compute(x, Operation.SQRT); } - @MethodSubstitution + @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) public static double log(double x) { return MathIntrinsicNode.compute(x, Operation.LOG); } - @MethodSubstitution + @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) public static double log10(double x) { return MathIntrinsicNode.compute(x, Operation.LOG10); } @@ -61,7 +61,7 @@ /** * Special cases from {@link Math#pow} and __ieee754_pow (in sharedRuntimeTrans.cpp). */ - @MethodSubstitution + @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) public static double pow(double x, double y) { // If the second argument is positive or negative zero, then the result is 1.0. if (y == 0) { @@ -107,7 +107,7 @@ // accurate within [-pi/4, pi/4]. Examine the passed value and provide // a slow path for inputs outside of that interval. - @MethodSubstitution + @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) public static double sin(double x) { if (abs(x) < PI_4) { return MathIntrinsicNode.compute(x, Operation.SIN); @@ -116,7 +116,7 @@ } } - @MethodSubstitution + @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) public static double cos(double x) { if (abs(x) < PI_4) { return MathIntrinsicNode.compute(x, Operation.COS); @@ -125,7 +125,7 @@ } } - @MethodSubstitution + @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) public static double tan(double x) { if (abs(x) < PI_4) { return MathIntrinsicNode.compute(x, Operation.TAN);