# HG changeset patch # User Roland Schatz # Date 1383560710 -3600 # Node ID 9334392ed2792dc6544fb06299046c5ebdfbe340 # Parent 2c4aa758ee1803e0c90a31e4bcc89b8627874178 Refactor ConvertNode. diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java --- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Mon Nov 04 11:25:10 2013 +0100 @@ -235,37 +235,11 @@ emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";" + comment); } - /** - * I2S requires special handling because Graal passes an int for the destination operand instead - * of a short. - */ - public void emitConvertIntToShort(Value dest, Value src) { - emitString("cvt_s16_s32 " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";"); - } - - /** - * I2C requires special handling because Graal passes an int for the destination operand instead - * of a char. - */ - public void emitConvertIntToChar(Value dest, Value src) { - emitString("cvt_u16_s32 " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";"); - } - - /** - * I2B requires special handling because Graal passes an int for the destination operand instead - * of a byte. - */ - public void emitConvertIntToByte(Value dest, Value src) { - emitString("cvt_s8_s32 " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";"); - } - - /** - * Generic handler for all other conversions. - * - */ - public void emitConvert(Value dest, Value src) { - String prefix = (getArgType(dest).equals("f32") && getArgType(src).equals("f64")) ? "cvt_near_" : "cvt_"; - emitString(prefix + getArgType(dest) + "_" + getArgType(src) + " " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";"); + public void emitConvert(Value dest, Value src, Kind destKind, Kind srcKind) { + String destType = getArgTypeFromKind(destKind); + String srcType = getArgTypeFromKind(srcKind); + String prefix = (destType.equals("f32") && srcType.equals("f64")) ? "cvt_near_" : "cvt_"; + emitString(prefix + destType + "_" + srcType + " " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";"); } public static String mapAddress(HSAILAddress addr) { diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java --- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Mon Nov 04 11:25:10 2013 +0100 @@ -344,13 +344,18 @@ public static class ConversionFormat extends SingleOperandFormat { - public ConversionFormat(Variable dst, Value src) { + private final Kind dstKind; + private final Kind srcKind; + + public ConversionFormat(Variable dst, Value src, Kind dstKind, Kind srcKind) { super(dst, src); + this.dstKind = dstKind; + this.srcKind = srcKind; } @Override public String emit() { - return (typeForKind(dest.getKind()) + "." + typeForKind(source.getKind()) + " " + emitVariable(dest) + ", " + emitValue(source) + ";"); + return (typeForKind(dstKind) + "." + typeForKind(srcKind) + " " + emitVariable(dest) + ", " + emitValue(source) + ";"); } } @@ -538,8 +543,8 @@ public static class Cvt extends ConversionFormat { - public Cvt(Variable dst, Variable src) { - super(dst, src); + public Cvt(Variable dst, Variable src, Kind dstKind, Kind srcKind) { + super(dst, src, dstKind, srcKind); } public void emit(PTXAssembler asm) { diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Nov 04 11:25:10 2013 +0100 @@ -685,95 +685,170 @@ } } + private AllocatableValue emitConvertMove(Kind kind, AllocatableValue input) { + Variable result = newVariable(kind); + emitMove(result, input); + return result; + } + + private AllocatableValue emitConvert1Op(Kind kind, AMD64Arithmetic op, AllocatableValue input) { + Variable result = newVariable(kind); + append(new Unary1Op(op, result, input)); + return result; + } + + private AllocatableValue emitConvert2Op(Kind kind, AMD64Arithmetic op, AllocatableValue input) { + Variable result = newVariable(kind); + append(new Unary2Op(op, result, input)); + return result; + } + @Override - public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { - Variable input = load(inputVal); - Variable result = newVariable(opcode.to); - switch (opcode) { - case B2L: - case S2L: - case C2L: - // x2L == x2I . I2L - // since byte, short and char are stored as int in registers, x2I is a nop - case I2L: - append(new Unary2Op(I2L, result, input)); - break; - case L2I: - append(new Unary1Op(L2I, result, input)); + public AllocatableValue emitConvert(Kind from, Kind to, Value inputVal) { + assert inputVal.getKind() == from.getStackKind(); + + AllocatableValue input = asAllocatable(inputVal); + if (from == to) { + return input; + } + switch (to) { + case Byte: + switch (from) { + case Short: + case Char: + case Int: + case Long: + return emitConvert2Op(to, I2B, input); + case Float: + case Double: + AllocatableValue intVal = emitConvert(from, Kind.Int, inputVal); + return emitConvert(Kind.Int, to, intVal); + } break; - case C2B: - case S2B: - case I2B: - case L2B: - append(new Unary2Op(I2B, result, input)); - break; - case B2C: - case S2C: - case I2C: - case L2C: - append(new Unary1Op(I2C, result, input)); + case Char: + switch (from) { + case Byte: + case Short: + case Int: + case Long: + return emitConvert1Op(to, I2C, input); + case Float: + case Double: + AllocatableValue intVal = emitConvert(from, Kind.Int, inputVal); + return emitConvert(Kind.Int, to, intVal); + } break; - case B2S: - case C2S: - case I2S: - case L2S: - append(new Unary2Op(I2S, result, input)); + case Short: + switch (from) { + case Byte: + case Char: + case Int: + case Long: + return emitConvert2Op(to, I2S, input); + case Float: + case Double: + AllocatableValue intVal = emitConvert(from, Kind.Int, inputVal); + return emitConvert(Kind.Int, to, intVal); + } break; - case F2D: - append(new Unary2Op(F2D, result, input)); - break; - case D2F: - append(new Unary2Op(D2F, result, input)); - break; - case I2F: - append(new Unary2Op(I2F, result, input)); + case Int: + switch (from) { + case Byte: + case Short: + case Char: + return emitConvertMove(to, input); + case Long: + return emitConvert1Op(to, L2I, input); + case Float: + return emitConvert2Op(to, F2I, input); + case Double: + return emitConvert2Op(to, D2I, input); + } break; - case I2D: - append(new Unary2Op(I2D, result, input)); - break; - case F2I: - append(new Unary2Op(F2I, result, input)); - break; - case D2I: - append(new Unary2Op(D2I, result, input)); + case Long: + switch (from) { + case Byte: + case Short: + case Char: + case Int: + return emitConvert2Op(to, I2L, input); + case Float: + return emitConvert2Op(to, F2L, input); + case Double: + return emitConvert2Op(to, D2L, input); + } break; - case L2F: - append(new Unary2Op(L2F, result, input)); - break; - case L2D: - append(new Unary2Op(L2D, result, input)); + case Float: + switch (from) { + case Byte: + case Short: + case Char: + case Int: + return emitConvert2Op(to, I2F, input); + case Long: + return emitConvert2Op(to, L2F, input); + case Double: + return emitConvert2Op(to, D2F, input); + } break; - case F2L: - append(new Unary2Op(F2L, result, input)); - break; - case D2L: - append(new Unary2Op(D2L, result, input)); + case Double: + switch (from) { + case Byte: + case Short: + case Char: + case Int: + return emitConvert2Op(to, I2D, input); + case Long: + return emitConvert2Op(to, L2D, input); + case Float: + return emitConvert2Op(to, F2D, input); + } break; - case MOV_I2F: - append(new Unary2Op(MOV_I2F, result, input)); - break; - case MOV_L2D: - append(new Unary2Op(MOV_L2D, result, input)); - break; - case MOV_F2I: - append(new Unary2Op(MOV_F2I, result, input)); - break; - case MOV_D2L: - append(new Unary2Op(MOV_D2L, result, input)); + } + throw GraalInternalError.shouldNotReachHere(); + } + + public AllocatableValue emitReinterpret(Kind to, Value inputVal) { + Kind from = inputVal.getKind(); + AllocatableValue input = asAllocatable(inputVal); + + // These cases require a move between CPU and FPU registers: + switch (to) { + case Int: + switch (from) { + case Float: + case Double: + return emitConvert2Op(to, MOV_F2I, input); + } break; - case UNSIGNED_I2L: - // Instructions that move or generate 32-bit register values also set the upper 32 - // bits of the register to zero. - // Consequently, there is no need for a special zero-extension move. - case B2I: - case C2I: - case S2I: - emitMove(result, input); + case Long: + switch (from) { + case Float: + case Double: + return emitConvert2Op(to, MOV_D2L, input); + } + break; + case Float: + switch (from) { + case Int: + case Long: + return emitConvert2Op(to, MOV_I2F, input); + } break; - default: - throw GraalInternalError.shouldNotReachHere(); + case Double: + switch (from) { + case Int: + case Long: + return emitConvert2Op(to, MOV_L2D, input); + } + break; } - return result; + + // Otherwise, just emit an ordinary move instruction. + // Instructions that move or generate 32-bit register values also set the upper 32 + // bits of the register to zero. + // Consequently, there is no need for a special zero-extension move. + return emitConvertMove(to, input); } @Override diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Mon Nov 04 11:25:10 2013 +0100 @@ -146,7 +146,7 @@ } else { Value indexRegister; Value convertedIndex; - convertedIndex = this.emitConvert(ConvertNode.Op.I2L, index); + convertedIndex = this.emitConvert(Kind.Int, Kind.Long, index); if (scale != 1) { indexRegister = emitUMul(convertedIndex, Constant.forInt(scale)); } else { @@ -593,55 +593,17 @@ } @Override - public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { + public Variable emitConvert(Kind from, Kind to, Value inputVal) { Variable input = load(inputVal); - Variable result = newVariable(opcode.to); - switch (opcode) { - case I2F: - append(new Op1Stack(I2F, result, input)); - break; - case I2L: - append(new Op1Stack(I2L, result, input)); - break; - case I2S: - append(new Op1Stack(I2S, result, input)); - break; - case I2C: - append(new Op1Stack(I2C, result, input)); - break; - case I2B: - append(new Op1Stack(I2B, result, input)); - break; - case I2D: - append(new Op1Stack(I2D, result, input)); - break; - case D2I: - append(new Op1Stack(D2I, result, input)); - break; - case D2F: - append(new Op1Stack(D2F, result, input)); - break; - case D2L: - append(new Op1Stack(D2L, result, input)); - break; - case L2I: - append(new Op1Stack(L2I, result, input)); - break; - case L2F: - append(new Op1Stack(L2F, result, input)); - break; - case L2D: - append(new Op1Stack(L2D, result, input)); - break; - case F2D: - append(new Op1Stack(F2D, result, input)); - break; - case F2L: - append(new Op1Stack(F2L, result, input)); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } + Variable result = newVariable(to); + append(new ConvertOp(result, input, to, from)); + return result; + } + + @Override + public Value emitReinterpret(Kind to, Value inputVal) { + Variable result = newVariable(to); + emitMove(result, inputVal); return result; } diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Mon Nov 04 11:25:10 2013 +0100 @@ -40,12 +40,11 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.ptx.*; +import com.oracle.graal.lir.ptx.PTXArithmetic.ConvertOp; import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp; -import com.oracle.graal.lir.ptx.PTXArithmetic.Unary1Op; -import com.oracle.graal.lir.ptx.PTXArithmetic.Unary2Op; import com.oracle.graal.lir.ptx.PTXCompare.CompareOp; import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp; import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp; @@ -63,7 +62,6 @@ import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.util.*; @@ -236,7 +234,7 @@ Value convertedIndex; Value indexRegister; - convertedIndex = emitConvert(Op.I2L, index); + convertedIndex = emitConvert(Kind.Int, Kind.Long, index); if (scale != 1) { if (CodeUtil.isPowerOf2(scale)) { indexRegister = emitShl(convertedIndex, Constant.forInt(CodeUtil.log2(scale))); @@ -678,76 +676,16 @@ } @Override - public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { + public Variable emitConvert(Kind from, Kind to, Value inputVal) { Variable input = load(inputVal); - Variable result = newVariable(opcode.to); - switch (opcode) { - case I2L: - append(new Unary2Op(I2L, result, input)); - break; - case L2I: - append(new Unary1Op(L2I, result, input)); - break; - case I2B: - append(new Unary2Op(I2B, result, input)); - break; - case I2C: - append(new Unary1Op(I2C, result, input)); - break; - case I2S: - append(new Unary2Op(I2S, result, input)); - break; - case F2D: - append(new Unary2Op(F2D, result, input)); - break; - case D2F: - append(new Unary2Op(D2F, result, input)); - break; - case I2F: - append(new Unary2Op(I2F, result, input)); - break; - case I2D: - append(new Unary2Op(I2D, result, input)); - break; - case F2I: - append(new Unary2Op(F2I, result, input)); - break; - case D2I: - append(new Unary2Op(D2I, result, input)); - break; - case L2F: - append(new Unary2Op(L2F, result, input)); - break; - case L2D: - append(new Unary2Op(L2D, result, input)); - break; - case F2L: - append(new Unary2Op(F2L, result, input)); - break; - case D2L: - append(new Unary2Op(D2L, result, input)); - break; - case MOV_I2F: - append(new Unary2Op(MOV_I2F, result, input)); - break; - case MOV_L2D: - append(new Unary2Op(MOV_L2D, result, input)); - break; - case MOV_F2I: - append(new Unary2Op(MOV_F2I, result, input)); - break; - case MOV_D2L: - append(new Unary2Op(MOV_D2L, result, input)); - break; - case UNSIGNED_I2L: - // Instructions that move or generate 32-bit register values also set the upper 32 - // bits of the register to zero. - // Consequently, there is no need for a special zero-extension move. - emitMove(result, input); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } + Variable result = newVariable(to); + append(new ConvertOp(result, input, to, from)); + return result; + } + + public Value emitReinterpret(Kind to, Value inputVal) { + Variable result = newVariable(to); + emitMove(result, inputVal); return result; } diff -r 2c4aa758ee18 -r 9334392ed279 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 Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Nov 04 11:25:10 2013 +0100 @@ -61,7 +61,6 @@ import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.util.*; @@ -156,7 +155,7 @@ } else { if (scale != 1) { // Variable longIndex = newVariable(Kind.Long); - Variable longIndex = emitConvert(Op.I2L, index); + AllocatableValue longIndex = emitConvert(Kind.Int, Kind.Long, index); if (CodeUtil.isPowerOf2(scale)) { indexRegister = emitShl(longIndex, Constant.forLong(CodeUtil.log2(scale))); } else { @@ -755,78 +754,164 @@ } } + private AllocatableValue emitConvertMove(Kind kind, AllocatableValue input) { + Variable result = newVariable(kind); + emitMove(result, input); + return result; + } + + private AllocatableValue emitConvert2Op(Kind kind, SPARCArithmetic op, AllocatableValue input) { + Variable result = newVariable(kind); + append(new Unary2Op(op, result, input)); + return result; + } + @Override - public Variable emitConvert(Op opcode, Value inputVal) { - Variable input = load(inputVal); - Variable result = newVariable(opcode.to); - switch (opcode) { - case I2L: - append(new Unary2Op(I2L, result, input)); - break; - case L2I: - append(new Unary2Op(L2I, result, input)); - break; - case I2B: - append(new Unary2Op(I2B, result, input)); - break; - case I2C: - append(new Unary2Op(I2C, result, input)); + public AllocatableValue emitConvert(Kind from, Kind to, Value inputVal) { + assert inputVal.getKind() == from.getStackKind(); + + AllocatableValue input = asAllocatable(inputVal); + if (from == to) { + return input; + } + switch (to) { + case Byte: + switch (from) { + case Short: + case Char: + case Int: + case Long: + return emitConvert2Op(to, I2B, input); + case Float: + case Double: + AllocatableValue intVal = emitConvert(from, Kind.Int, inputVal); + return emitConvert(Kind.Int, to, intVal); + } break; - case I2S: - append(new Unary2Op(I2S, result, input)); - break; - case F2D: - append(new Unary2Op(F2D, result, input)); - break; - case D2F: - append(new Unary2Op(D2F, result, input)); + case Char: + switch (from) { + case Byte: + case Short: + case Int: + case Long: + return emitConvert2Op(to, I2C, input); + case Float: + case Double: + AllocatableValue intVal = emitConvert(from, Kind.Int, inputVal); + return emitConvert(Kind.Int, to, intVal); + } break; - case I2F: - append(new Unary2Op(I2F, result, input)); + case Short: + switch (from) { + case Byte: + case Char: + case Int: + case Long: + return emitConvert2Op(to, I2S, input); + case Float: + case Double: + AllocatableValue intVal = emitConvert(from, Kind.Int, inputVal); + return emitConvert(Kind.Int, to, intVal); + } break; - case I2D: - append(new Unary2Op(I2D, result, input)); - break; - case F2I: - append(new Unary2Op(F2I, result, input)); + case Int: + switch (from) { + case Byte: + case Short: + case Char: + return emitConvertMove(to, input); + case Long: + return emitConvert2Op(to, L2I, input); + case Float: + return emitConvert2Op(to, F2I, input); + case Double: + return emitConvert2Op(to, D2I, input); + } break; - case D2I: - append(new Unary2Op(D2I, result, input)); - break; - case L2F: - append(new Unary2Op(L2F, result, input)); - break; - case L2D: - append(new Unary2Op(L2D, result, input)); + case Long: + switch (from) { + case Byte: + case Short: + case Char: + case Int: + return emitConvert2Op(to, I2L, input); + case Float: + return emitConvert2Op(to, F2L, input); + case Double: + return emitConvert2Op(to, D2L, input); + } break; - case F2L: - append(new Unary2Op(F2L, result, input)); + case Float: + switch (from) { + case Byte: + case Short: + case Char: + case Int: + return emitConvert2Op(to, I2F, input); + case Long: + return emitConvert2Op(to, L2F, input); + case Double: + return emitConvert2Op(to, D2F, input); + } break; - case D2L: - append(new Unary2Op(D2L, result, input)); - break; - case MOV_I2F: - append(new Unary2Op(MOV_I2F, result, input)); + case Double: + switch (from) { + case Byte: + case Short: + case Char: + case Int: + return emitConvert2Op(to, I2D, input); + case Long: + return emitConvert2Op(to, L2D, input); + case Float: + return emitConvert2Op(to, F2D, input); + } break; - case MOV_L2D: - append(new Unary2Op(MOV_L2D, result, input)); - break; - case MOV_F2I: - append(new Unary2Op(MOV_F2I, result, input)); - break; - case MOV_D2L: - append(new Unary2Op(MOV_D2L, result, input)); + } + throw GraalInternalError.shouldNotReachHere(); + } + + public AllocatableValue emitReinterpret(Kind to, Value inputVal) { + Kind from = inputVal.getKind(); + AllocatableValue input = asAllocatable(inputVal); + + // These cases require a move between CPU and FPU registers: + switch (to) { + case Int: + switch (from) { + case Float: + case Double: + return emitConvert2Op(to, MOV_F2I, input); + } break; - case UNSIGNED_I2L: - // Instructions that move or generate 32-bit register values also set the upper 32 - // bits of the register to zero. - // Consequently, there is no need for a special zero-extension move. - emitMove(result, input); + case Long: + switch (from) { + case Float: + case Double: + return emitConvert2Op(to, MOV_D2L, input); + } + break; + case Float: + switch (from) { + case Int: + case Long: + return emitConvert2Op(to, MOV_I2F, input); + } break; - default: - throw GraalInternalError.shouldNotReachHere(); + case Double: + switch (from) { + case Int: + case Long: + return emitConvert2Op(to, MOV_L2D, input); + } + break; } - return result; + + // Otherwise, just emit an ordinary move instruction. + // Instructions that move or generate 32-bit register values also set the upper 32 + // bits of the register to zero. + // Consequently, there is no need for a special zero-extension move. + return emitConvertMove(to, input); } @Override diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Nov 04 11:25:10 2013 +0100 @@ -688,9 +688,9 @@ frameState.ipush(append(new NormalizeCompareNode(x, y, isUnorderedLess))); } - private void genConvert(ConvertNode.Op opcode) { - ValueNode input = frameState.pop(opcode.from.getStackKind()); - frameState.push(opcode.to.getStackKind(), append(new ConvertNode(opcode, input))); + private void genConvert(Kind from, Kind to) { + ValueNode input = frameState.pop(from.getStackKind()); + frameState.push(to.getStackKind(), append(new ConvertNode(from, to, input))); } private void genIncrement() { @@ -1940,21 +1940,21 @@ case LOR : // fall through case LXOR : genLogicOp(Kind.Long, opcode); break; case IINC : genIncrement(); break; - case I2L : genConvert(ConvertNode.Op.I2L); break; - case I2F : genConvert(ConvertNode.Op.I2F); break; - case I2D : genConvert(ConvertNode.Op.I2D); break; - case L2I : genConvert(ConvertNode.Op.L2I); break; - case L2F : genConvert(ConvertNode.Op.L2F); break; - case L2D : genConvert(ConvertNode.Op.L2D); break; - case F2I : genConvert(ConvertNode.Op.F2I); break; - case F2L : genConvert(ConvertNode.Op.F2L); break; - case F2D : genConvert(ConvertNode.Op.F2D); break; - case D2I : genConvert(ConvertNode.Op.D2I); break; - case D2L : genConvert(ConvertNode.Op.D2L); break; - case D2F : genConvert(ConvertNode.Op.D2F); break; - case I2B : genConvert(ConvertNode.Op.I2B); break; - case I2C : genConvert(ConvertNode.Op.I2C); break; - case I2S : genConvert(ConvertNode.Op.I2S); break; + case I2L : genConvert(Kind.Int, Kind.Long); break; + case I2F : genConvert(Kind.Int, Kind.Float); break; + case I2D : genConvert(Kind.Int, Kind.Double); break; + case L2I : genConvert(Kind.Long, Kind.Int); break; + case L2F : genConvert(Kind.Long, Kind.Float); break; + case L2D : genConvert(Kind.Long, Kind.Double); break; + case F2I : genConvert(Kind.Float, Kind.Int); break; + case F2L : genConvert(Kind.Float, Kind.Long); break; + case F2D : genConvert(Kind.Float, Kind.Double); break; + case D2I : genConvert(Kind.Double, Kind.Int); break; + case D2L : genConvert(Kind.Double, Kind.Long); break; + case D2F : genConvert(Kind.Double, Kind.Float); break; + case I2B : genConvert(Kind.Int, Kind.Byte); break; + case I2C : genConvert(Kind.Int, Kind.Char); break; + case I2S : genConvert(Kind.Int, Kind.Short); break; case LCMP : genCompareOp(Kind.Long, false); break; case FCMPL : genCompareOp(Kind.Float, true); break; case FCMPG : genCompareOp(Kind.Float, false); break; diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java Mon Nov 04 11:25:10 2013 +0100 @@ -38,28 +38,16 @@ CALL, FDIV, FREM, - D2F, - D2I, - D2L, DADD, DDIV, DMUL, DNEG, DREM, DSUB, - F2D, - F2I, - F2L, FADD, FMUL, FNEG, FSUB, - I2B, - I2C, - I2D, - I2F, - I2L, - I2S, IADD, IAND, ICARRY, @@ -84,9 +72,6 @@ IUSHR, IUSUB, IXOR, - L2D, - L2F, - L2I, LADD, LAND, LCARRY, @@ -111,14 +96,29 @@ LUSHR, LUSUB, LXOR, - MOV_F2I, - MOV_D2L, - MOV_I2F, - MOV_L2D, OADD, SQRT, UNDEF; + public static class ConvertOp extends HSAILLIRInstruction { + private final Kind from; + private final Kind to; + @Def({REG}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + + public ConvertOp(AllocatableValue result, AllocatableValue x, Kind to, Kind from) { + this.from = from; + this.to = to; + this.result = result; + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { + masm.emitConvert(result, x, to, from); + } + } + public static class Op1Stack extends HSAILLIRInstruction { @Opcode private final HSAILArithmetic opcode; @Def({REG, HINT}) protected Value result; @@ -293,29 +293,6 @@ int exceptionOffset = -1; if (isRegister(src)) { switch (opcode) { - case I2F: - case I2D: - case I2L: - case F2I: - case F2D: - case F2L: - case D2I: - case D2L: - case D2F: - case L2I: - case L2F: - case L2D: - masm.emitConvert(dst, src); - break; - case I2S: - masm.emitConvertIntToShort(dst, src); - break; - case I2C: - masm.emitConvertIntToChar(dst, src); - break; - case I2B: - masm.emitConvertIntToByte(dst, src); - break; case SQRT: masm.emit("sqrt", dst, src); break; diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Mon Nov 04 11:25:10 2013 +0100 @@ -39,84 +39,33 @@ LADD, LSUB, LMUL, LDIV, LDIVREM, 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, - I2L, L2I, I2B, I2C, I2S, - F2D, D2F, - I2F, I2D, F2I, D2I, - L2F, L2D, F2L, D2L, - MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; + INEG, LNEG, FNEG, DNEG, INOT, LNOT; - /** - * Unary operation with separate source and destination operand. - */ - public static class Unary2Op extends PTXLIRInstruction { - @Opcode private final PTXArithmetic opcode; + public static class ConvertOp extends PTXLIRInstruction { + private final Kind from; + private final Kind to; @Def({REG}) protected AllocatableValue result; @Use({REG, STACK}) protected AllocatableValue x; - public Unary2Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) { - this.opcode = opcode; + public ConvertOp(AllocatableValue result, AllocatableValue x, Kind to, Kind from) { + this.from = from; + this.to = to; this.result = result; this.x = x; } @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - switch (opcode) { - case I2L: - case I2C: - case I2B: - case I2F: - case I2D: - case F2I: - case F2L: - case F2D: - case D2I: - case D2L: - case D2F: - break; // cvt handles the move - default: - PTXMove.move(tasm, masm, result, x); + Variable dst = (Variable) result; + Variable src = (Variable) x; + if (from == Kind.Long && to == Kind.Int) { + new And(dst, src, Constant.forLong(0xFFFFFFFF)).emit(masm); + } else if ((from == Kind.Int || from == Kind.Long) && to == Kind.Short) { + new And(dst, src, Constant.forInt((short) 0xFFFF)).emit(masm); + } else { + new Cvt((Variable) result, (Variable) x, to, from).emit(masm); } - emit(tasm, masm, opcode, result, x, null); - } - } - - /** - * Unary operation with single operand for source and destination. - */ - public static class Unary1Op extends PTXLIRInstruction { - @Opcode private final PTXArithmetic opcode; - @Def({REG, HINT}) protected AllocatableValue result; - @Use({REG, STACK}) protected AllocatableValue x; - - public Unary1Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) { - this.opcode = opcode; - this.result = result; - this.x = x; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - emit(tasm, masm, opcode, result); - } - } - - public static class Op1Reg extends PTXLIRInstruction { - @Opcode private final PTXArithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG}) protected Value x; - - public Op1Reg(PTXArithmetic opcode, Value result, Value x) { - this.opcode = opcode; - this.result = result; - this.x = x; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - emit(tasm, masm, opcode, result, x, null); } } @@ -270,22 +219,6 @@ } } - protected static void emit(@SuppressWarnings("unused") TargetMethodAssembler tasm, - PTXAssembler masm, PTXArithmetic opcode, Value result) { - - Variable var = (Variable) result; - switch (opcode) { - case L2I: - new And(var, var, Constant.forLong(0xFFFFFFFF)).emit(masm); - break; - case I2C: - new And(var, var, Constant.forInt((short) 0xFFFF)).emit(masm); - break; - default: - throw GraalInternalError.shouldNotReachHere("missing: " + opcode); - } - } - public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src, LIRFrameState info) { int exceptionOffset = -1; Variable dest = (Variable) dst; @@ -302,19 +235,6 @@ case LNOT: new Not(dest, source).emit(masm); break; - case I2L: - case I2C: - case I2B: - case I2F: - case I2D: - case F2I: - case F2L: - case F2D: - case D2I: - case D2L: - case D2F: - new Cvt(dest, source).emit(masm); - break; case LSHL: new Shl(dest, dest, src).emit(masm); break; diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Mon Nov 04 11:25:10 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.type.*; public class BasicInductionVariable extends InductionVariable { @@ -127,10 +126,9 @@ ValueNode maxTripCount = loop.counted().maxTripCountNode(assumePositiveTripCount); ValueNode initNode = this.initNode(); if (fromKind != kind) { - Op convertOp = Op.getOp(fromKind, kind); - stride = graph.unique(new ConvertNode(convertOp, stride)); - maxTripCount = graph.unique(new ConvertNode(convertOp, maxTripCount)); - initNode = graph.unique(new ConvertNode(convertOp, initNode)); + stride = graph.unique(new ConvertNode(fromKind, kind, stride)); + maxTripCount = graph.unique(new ConvertNode(fromKind, kind, maxTripCount)); + initNode = graph.unique(new ConvertNode(fromKind, kind, initNode)); } return IntegerArithmeticNode.add(graph, IntegerArithmeticNode.mul(graph, stride, IntegerArithmeticNode.sub(graph, maxTripCount, ConstantNode.forIntegerKind(kind, 1, graph))), initNode); } diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java --- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Mon Nov 04 11:25:10 2013 +0100 @@ -126,32 +126,35 @@ @Test public void testNarrowingConversions() { // byte cases - assertEquals(StampFactory.forInteger(Kind.Int, 0, 0), StampTool.intToByte(StampFactory.forInteger(Kind.Int, 0, 0))); - assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.intToByte(StampFactory.forInteger(Kind.Int, 0, 10))); - assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.intToByte(StampFactory.forInteger(Kind.Int, 10, 20))); - assertEquals(StampFactory.forInteger(Kind.Int, -10, 0), StampTool.intToByte(StampFactory.forInteger(Kind.Int, -10, 0))); - assertEquals(StampFactory.forInteger(Kind.Int, -20, -10), StampTool.intToByte(StampFactory.forInteger(Kind.Int, -20, -10))); - assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), StampTool.intToByte(StampFactory.forInteger(Kind.Int, 100, 200))); - assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), StampTool.intToByte(StampFactory.forInteger(Kind.Int, -100, 200))); - assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), StampTool.intToByte(StampFactory.forInteger(Kind.Int, -200, -100))); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 0), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 0), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 10), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 10, 20), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, -10, 0), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -10, 0), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, -20, -10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -20, -10), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 100, 200), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -100, 200), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -200, -100), Kind.Byte)); // char cases - assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.intToChar(StampFactory.forInteger(Kind.Int, 0, 10))); - assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.intToChar(StampFactory.forInteger(Kind.Int, 10, 20))); - assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), StampTool.intToChar(StampFactory.forInteger(Kind.Int, 20000, 80000))); - assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), StampTool.intToChar(StampFactory.forInteger(Kind.Int, -10000, 40000))); - assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), StampTool.intToChar(StampFactory.forInteger(Kind.Int, -40000, -10000))); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 10), Kind.Char)); + assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 10, 20), Kind.Char)); + assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 20000, 80000), Kind.Char)); + assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -10000, 40000), Kind.Char)); + assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -40000, -10000), Kind.Char)); // short cases - assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.intToShort(StampFactory.forInteger(Kind.Int, 0, 10))); - assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.intToShort(StampFactory.forInteger(Kind.Int, 10, 20))); - assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), StampTool.intToShort(StampFactory.forInteger(Kind.Int, 20000, 40000))); - assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), StampTool.intToShort(StampFactory.forInteger(Kind.Int, -10000, 40000))); - assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), StampTool.intToShort(StampFactory.forInteger(Kind.Int, -40000, -10000))); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 10), Kind.Short)); + assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 10, 20), Kind.Short)); + assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 20000, 40000), Kind.Short)); + assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -10000, 40000), Kind.Short)); + assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -40000, -10000), Kind.Short)); // int cases - assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.longToInt(StampFactory.forInteger(Kind.Long, 0, 10))); - assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.longToInt(StampFactory.forInteger(Kind.Long, 10, 20))); - assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), StampTool.longToInt(StampFactory.forInteger(Kind.Long, 20000000000L, 40000000000L))); - assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), StampTool.longToInt(StampFactory.forInteger(Kind.Long, -10000000000L, 40000000000L))); - assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), StampTool.longToInt(StampFactory.forInteger(Kind.Long, -40000000000L, -10000000000L))); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, 0, 10), Kind.Int)); + assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, 10, 20), Kind.Int)); + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), + StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, 20000000000L, 40000000000L), Kind.Int)); + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), + StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, -10000000000L, 40000000000L), Kind.Int)); + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), + StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, -40000000000L, -10000000000L), Kind.Int)); } @Test diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Mon Nov 04 11:25:10 2013 +0100 @@ -136,7 +136,7 @@ if (x() instanceof ConvertNode && y() instanceof ConvertNode) { ConvertNode convertX = (ConvertNode) x(); ConvertNode convertY = (ConvertNode) y(); - if (convertX.opcode.isLossless() && convertY.opcode.isLossless()) { + if (convertX.isLossless() && convertY.isLossless()) { setX(convertX.value()); setY(convertY.value()); } diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Mon Nov 04 11:25:10 2013 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.calc; -import static com.oracle.graal.api.meta.Kind.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; @@ -36,165 +34,10 @@ */ public class ConvertNode extends FloatingNode implements Canonicalizable, Lowerable, ArithmeticLIRLowerable { - public static enum Op { - // formatter:off - B2S(Byte, Short, true), - B2C(Byte, Char, true), - B2I(Byte, Int, true), - B2L(Byte, Long, true), - S2B(Short, Byte, false), - S2C(Short, Char, true), - S2I(Short, Int, true), - S2L(Short, Long, true), - C2B(Char, Byte, false), - C2S(Char, Short, true), - C2I(Char, Int, true), - C2L(Char, Long, true), - I2L(Int, Long, true), - L2I(Long, Int, false), - I2B(Int, Byte, false), - I2C(Int, Char, false), - I2S(Int, Short, false), - L2B(Long, Byte, false), - L2C(Long, Char, false), - L2S(Long, Short, false), - F2D(Float, Double, true), - D2F(Double, Float, false), - I2F(Int, Float, false), - I2D(Int, Double, true), - F2I(Float, Int, false), - D2I(Double, Int, false), - L2F(Long, Float, false), - L2D(Long, Double, false), - F2L(Float, Long, false), - D2L(Double, Long, false), - UNSIGNED_I2L(Int, Long, true), - MOV_I2F(Int, Float, false), - MOV_L2D(Long, Double, false), - MOV_F2I(Float, Int, false), - MOV_D2L(Double, Long, false); - // formatter:on - - public final Kind from; - public final Kind to; - public final boolean lossless; - - private Op(Kind from, Kind to, boolean lossless) { - this.from = from; - this.to = to; - this.lossless = lossless; - } - - public boolean isLossless() { - return lossless; - } - - public static Op getOp(Kind from, Kind to) { - switch (from) { - case Byte: - switch (to) { - case Char: - return B2C; - case Short: - return B2S; - case Int: - return B2I; - case Long: - return B2L; - default: - throw GraalInternalError.shouldNotReachHere(); - } - case Char: - switch (to) { - case Byte: - return C2B; - case Short: - return C2S; - case Int: - return C2I; - case Long: - return C2L; - default: - throw GraalInternalError.shouldNotReachHere(); - } - case Short: - switch (to) { - case Byte: - return S2B; - case Char: - return S2C; - case Int: - return S2I; - case Long: - return S2L; - default: - throw GraalInternalError.shouldNotReachHere(); - } - case Int: - switch (to) { - case Byte: - return I2B; - case Char: - return I2C; - case Short: - return I2S; - case Long: - return I2L; - case Float: - return I2F; - case Double: - return I2D; - default: - throw GraalInternalError.shouldNotReachHere(); - } - case Long: - switch (to) { - case Byte: - return L2B; - case Char: - return L2C; - case Short: - return L2S; - case Int: - return L2I; - case Float: - return L2F; - case Double: - return L2D; - default: - throw GraalInternalError.shouldNotReachHere(); - } - case Float: - switch (to) { - case Int: - return F2I; - case Long: - return F2L; - case Double: - return F2D; - default: - throw GraalInternalError.shouldNotReachHere(); - } - case Double: - switch (to) { - case Int: - return D2I; - case Long: - return D2L; - case Float: - return D2F; - default: - throw GraalInternalError.shouldNotReachHere(); - } - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - } - @Input private ValueNode value; - public final Op opcode; + private final Kind from; + private final Kind to; public ValueNode value() { return value; @@ -203,93 +46,186 @@ /** * Constructs a new Convert instance. * - * @param opcode the operation + * @param from the kind of the incoming value + * @param to the result kind * @param value the instruction producing the input value */ - public ConvertNode(Op opcode, ValueNode value) { - super(StampFactory.forKind(opcode.to.getStackKind())); - assert value.kind() == opcode.from.getStackKind() : opcode + " : " + value.kind() + " != " + opcode.from; - this.opcode = opcode; + public ConvertNode(Kind from, Kind to, ValueNode value) { + super(StampFactory.forKind(to.getStackKind())); + assert value.kind() == from.getStackKind() : "convert(" + from + ", " + to + ") : " + value.kind() + " != " + from; + this.from = from; + this.to = to; this.value = value; } + public Kind getFromKind() { + return from; + } + + public Kind getToKind() { + return to; + } + + public boolean isLossless() { + if (from == to) { + return true; + } + switch (from) { + case Byte: + return true; + case Short: + case Char: + return to != Kind.Byte; + case Int: + return to == Kind.Long || to == Kind.Double; + case Float: + return to == Kind.Double; + case Long: + case Double: + return false; + } + throw GraalInternalError.shouldNotReachHere(); + } + public Constant evalConst(Constant... inputs) { assert inputs.length == 1; Constant c = inputs[0]; - switch (opcode) { - case B2C: - return Constant.forChar((char) (byte) c.asInt()); - case B2S: - return Constant.forShort((byte) c.asInt()); - case B2I: - return Constant.forInt((byte) c.asInt()); - case B2L: - return Constant.forLong((byte) c.asInt()); - case C2B: - return Constant.forByte((byte) (char) c.asInt()); - case C2S: - return Constant.forShort((short) (char) c.asInt()); - case C2I: - return Constant.forInt((char) c.asInt()); - case C2L: - return Constant.forLong((char) c.asInt()); - case S2B: - return Constant.forByte((byte) (short) c.asInt()); - case S2C: - return Constant.forChar((char) (short) c.asInt()); - case S2I: - return Constant.forInt((short) c.asInt()); - case S2L: - return Constant.forLong((short) c.asInt()); - case I2L: - return Constant.forLong(c.asInt()); - case L2I: - return Constant.forInt((int) c.asLong()); - case I2B: - return Constant.forByte((byte) c.asInt()); - case I2C: - return Constant.forChar((char) c.asInt()); - case I2S: - return Constant.forShort((short) c.asInt()); - case L2B: - return Constant.forByte((byte) c.asLong()); - case L2C: - return Constant.forChar((char) c.asLong()); - case L2S: - return Constant.forShort((short) c.asLong()); - case F2D: - return Constant.forDouble(c.asFloat()); - case D2F: - return Constant.forFloat((float) c.asDouble()); - case I2F: - return Constant.forFloat(c.asInt()); - case I2D: - return Constant.forDouble(c.asInt()); - case F2I: - return Constant.forInt((int) c.asFloat()); - case D2I: - return Constant.forInt((int) c.asDouble()); - case L2F: - return Constant.forFloat(c.asLong()); - case L2D: - return Constant.forDouble(c.asLong()); - case F2L: - return Constant.forLong((long) c.asFloat()); - case D2L: - return Constant.forLong((long) c.asDouble()); - case UNSIGNED_I2L: - return Constant.forLong(c.asInt() & 0xffffffffL); - case MOV_I2F: - return Constant.forFloat(java.lang.Float.intBitsToFloat(c.asInt())); - case MOV_L2D: - return Constant.forDouble(java.lang.Double.longBitsToDouble(c.asLong())); - case MOV_F2I: - return Constant.forInt(java.lang.Float.floatToRawIntBits(c.asFloat())); - case MOV_D2L: - return Constant.forLong(java.lang.Double.doubleToRawLongBits(c.asDouble())); - default: - throw GraalInternalError.shouldNotReachHere(); + switch (from) { + case Byte: + byte byteVal = (byte) c.asInt(); + switch (to) { + case Byte: + return Constant.forByte(byteVal); + case Short: + return Constant.forShort(byteVal); + case Char: + return Constant.forChar((char) byteVal); + case Int: + return Constant.forInt(byteVal); + case Long: + return Constant.forLong(byteVal); + case Float: + return Constant.forFloat(byteVal); + case Double: + return Constant.forDouble(byteVal); + } + break; + case Char: + char charVal = (char) c.asInt(); + switch (to) { + case Byte: + return Constant.forByte((byte) charVal); + case Short: + return Constant.forShort((short) charVal); + case Char: + return Constant.forChar(charVal); + case Int: + return Constant.forInt(charVal); + case Long: + return Constant.forLong(charVal); + case Float: + return Constant.forFloat(charVal); + case Double: + return Constant.forDouble(charVal); + } + break; + case Short: + short shortVal = (short) c.asInt(); + switch (to) { + case Byte: + return Constant.forByte((byte) shortVal); + case Short: + return Constant.forShort(shortVal); + case Char: + return Constant.forChar((char) shortVal); + case Int: + return Constant.forInt(shortVal); + case Long: + return Constant.forLong(shortVal); + case Float: + return Constant.forFloat(shortVal); + case Double: + return Constant.forDouble(shortVal); + } + break; + case Int: + int intVal = c.asInt(); + switch (to) { + case Byte: + return Constant.forByte((byte) intVal); + case Short: + return Constant.forShort((short) intVal); + case Char: + return Constant.forChar((char) intVal); + case Int: + return Constant.forInt(intVal); + case Long: + return Constant.forLong(intVal); + case Float: + return Constant.forFloat(intVal); + case Double: + return Constant.forDouble(intVal); + } + break; + case Long: + long longVal = c.asLong(); + switch (to) { + case Byte: + return Constant.forByte((byte) longVal); + case Short: + return Constant.forShort((short) longVal); + case Char: + return Constant.forChar((char) longVal); + case Int: + return Constant.forInt((int) longVal); + case Long: + return Constant.forLong(longVal); + case Float: + return Constant.forFloat(longVal); + case Double: + return Constant.forDouble(longVal); + } + break; + case Float: + float floatVal = c.asFloat(); + switch (to) { + case Byte: + return Constant.forByte((byte) floatVal); + case Short: + return Constant.forShort((short) floatVal); + case Char: + return Constant.forChar((char) floatVal); + case Int: + return Constant.forInt((int) floatVal); + case Long: + return Constant.forLong((long) floatVal); + case Float: + return Constant.forFloat(floatVal); + case Double: + return Constant.forDouble(floatVal); + } + break; + case Double: + double doubleVal = c.asDouble(); + switch (to) { + case Byte: + return Constant.forByte((byte) doubleVal); + case Short: + return Constant.forShort((short) doubleVal); + case Char: + return Constant.forChar((char) doubleVal); + case Int: + return Constant.forInt((int) doubleVal); + case Long: + return Constant.forLong((long) doubleVal); + case Float: + return Constant.forFloat((float) doubleVal); + case Double: + return Constant.forDouble(doubleVal); + } + break; } + throw GraalInternalError.shouldNotReachHere(); } @Override @@ -312,21 +248,15 @@ } Stamp newStamp; IntegerStamp integerStamp = (IntegerStamp) stamp; - switch (opcode) { - case I2L: - newStamp = StampTool.intToLong(integerStamp); - break; - case L2I: - newStamp = StampTool.longToInt(integerStamp); + switch (to) { + case Byte: + case Short: + case Char: + case Int: + newStamp = StampTool.narrowingKindConversion(integerStamp, to); break; - case I2B: - newStamp = StampTool.intToByte(integerStamp); - break; - case I2C: - newStamp = StampTool.intToChar(integerStamp); - break; - case I2S: - newStamp = StampTool.intToShort(integerStamp); + case Long: + newStamp = StampTool.intToLong(integerStamp); break; default: return false; @@ -341,7 +271,7 @@ @Override public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitConvert(opcode, gen.operand(value()))); + gen.setResult(this, gen.emitConvert(from, to, gen.operand(value()))); } public static ValueNode convert(Kind toKind, ValueNode value) { @@ -349,19 +279,6 @@ if (fromKind == toKind) { return value; } - return value.graph().unique(new ConvertNode(Op.getOp(fromKind, toKind), value)); + return value.graph().unique(new ConvertNode(fromKind, toKind, value)); } - - @NodeIntrinsic - public static native float convert(@ConstantNodeParameter Op op, int value); - - @NodeIntrinsic - public static native int convert(@ConstantNodeParameter Op op, float value); - - @NodeIntrinsic - public static native double convert(@ConstantNodeParameter Op op, long value); - - @NodeIntrinsic - public static native long convert(@ConstantNodeParameter Op op, double value); - } diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Mon Nov 04 11:25:10 2013 +0100 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.calc; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * The {@code ReinterpretNode} class represents a reinterpreting conversion between primitive types. + */ +public class ReinterpretNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable { + + @Input private ValueNode value; + + public ValueNode value() { + return value; + } + + public ReinterpretNode(Kind to, ValueNode value) { + super(StampFactory.forKind(to.getStackKind())); + this.value = value; + } + + public Constant evalConst(Constant... inputs) { + assert inputs.length == 1; + Constant c = inputs[0]; + assert c.getKind() == value.kind(); + switch (c.getKind()) { + case Int: + switch (kind()) { + case Int: + return c; + case Long: + return Constant.forLong(c.asInt() & 0xFFFFFFFFL); + case Float: + return Constant.forFloat(Float.intBitsToFloat(c.asInt())); + case Double: + return Constant.forDouble(Double.longBitsToDouble(c.asInt() & 0xFFFFFFFFL)); + } + break; + case Long: + switch (kind()) { + case Int: + return Constant.forInt((int) c.asLong()); + case Long: + return c; + case Float: + return Constant.forFloat(Float.intBitsToFloat((int) c.asLong())); + case Double: + return Constant.forDouble(Double.longBitsToDouble(c.asLong())); + } + break; + case Float: + switch (kind()) { + case Int: + return Constant.forInt(Float.floatToRawIntBits(c.asFloat())); + case Long: + return Constant.forLong(Float.floatToRawIntBits(c.asFloat()) & 0xFFFFFFFFL); + case Float: + return c; + case Double: + return Constant.forDouble(Double.longBitsToDouble(Float.floatToRawIntBits(c.asFloat()) & 0xFFFFFFFFL)); + } + break; + case Double: + switch (kind()) { + case Int: + return Constant.forInt((int) Double.doubleToRawLongBits(c.asDouble())); + case Long: + return Constant.forLong(Double.doubleToRawLongBits(c.asDouble())); + case Float: + return Constant.forFloat(Float.intBitsToFloat((int) Double.doubleToRawLongBits(c.asDouble()))); + case Double: + return c; + } + break; + } + throw GraalInternalError.shouldNotReachHere(); + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (value.isConstant()) { + return ConstantNode.forPrimitive(evalConst(value.asConstant()), graph()); + } + return this; + } + + @Override + public void generate(ArithmeticLIRGenerator gen) { + gen.setResult(this, gen.emitReinterpret(kind(), gen.operand(value()))); + } + + public static ValueNode reinterpret(Kind toKind, ValueNode value) { + Kind fromKind = value.kind(); + if (fromKind == toKind) { + return value; + } + return value.graph().unique(new ReinterpretNode(toKind, value)); + } + + @NodeIntrinsic + public static native float reinterpret(@ConstantNodeParameter Kind kind, int value); + + @NodeIntrinsic + public static native int reinterpret(@ConstantNodeParameter Kind kind, float value); + + @NodeIntrinsic + public static native double reinterpret(@ConstantNodeParameter Kind kind, long value); + + @NodeIntrinsic + public static native long reinterpret(@ConstantNodeParameter Kind kind, double value); +} diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java Mon Nov 04 11:25:10 2013 +0100 @@ -24,7 +24,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; /** * This interface can be used to generate LIR for arithmetic operations (@see @@ -66,7 +65,9 @@ Value emitUShr(Value a, Value b); - Value emitConvert(ConvertNode.Op opcode, Value inputVal); + Value emitConvert(Kind from, Kind to, Value inputVal); + + Value emitReinterpret(Kind to, Value inputVal); Value emitMathAbs(Value input); diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Nov 04 11:25:10 2013 +0100 @@ -304,7 +304,7 @@ return StampFactory.forInteger(Kind.Long, intStamp.lowerBound(), intStamp.upperBound(), signExtend(intStamp.downMask(), Kind.Int), signExtend(intStamp.upMask(), Kind.Int)); } - private static IntegerStamp narrowingKindConvertion(IntegerStamp fromStamp, Kind toKind) { + public static IntegerStamp narrowingKindConversion(IntegerStamp fromStamp, Kind toKind) { assert toKind == Kind.Byte || toKind == Kind.Char || toKind == Kind.Short || toKind == Kind.Int; final long upperBound; if (fromStamp.lowerBound() < toKind.getMinValue()) { @@ -334,26 +334,6 @@ } } - public static IntegerStamp intToByte(IntegerStamp intStamp) { - assert intStamp.kind() == Kind.Int; - return narrowingKindConvertion(intStamp, Kind.Byte); - } - - public static IntegerStamp intToShort(IntegerStamp intStamp) { - assert intStamp.kind() == Kind.Int; - return narrowingKindConvertion(intStamp, Kind.Short); - } - - public static IntegerStamp intToChar(IntegerStamp intStamp) { - assert intStamp.kind() == Kind.Int; - return narrowingKindConvertion(intStamp, Kind.Char); - } - - public static IntegerStamp longToInt(IntegerStamp longStamp) { - assert longStamp.kind() == Kind.Long; - return narrowingKindConvertion(longStamp, Kind.Int); - } - public static long saturate(long v, Kind kind) { long max = kind.getMaxValue(); if (v > max) { diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertNode.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertNode.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertNode.java Mon Nov 04 11:25:10 2013 +0100 @@ -25,7 +25,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -37,12 +36,14 @@ public class AMD64ConvertNode extends FloatingNode implements ArithmeticLIRLowerable { @Input private ValueNode value; - public final Op opcode; + private final Kind from; + private final Kind to; - public AMD64ConvertNode(Op opcode, ValueNode value) { - super(StampFactory.forKind(opcode.to.getStackKind())); - this.opcode = opcode; + public AMD64ConvertNode(Kind from, Kind to, ValueNode value) { + super(StampFactory.forKind(to.getStackKind())); this.value = value; + this.from = from; + this.to = to; } public Constant evalConst(Constant... inputs) { @@ -52,6 +53,6 @@ } public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitConvert(opcode, gen.operand(value))); + gen.setResult(this, gen.emitConvert(from, to, gen.operand(value))); } } diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Mon Nov 04 11:25:10 2013 +0100 @@ -25,13 +25,10 @@ import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import java.util.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; @@ -147,20 +144,44 @@ public static class Templates extends AbstractTemplates { - private final EnumMap snippets; + private final SnippetInfo f2i; + private final SnippetInfo f2l; + private final SnippetInfo d2i; + private final SnippetInfo d2l; public Templates(Providers providers, TargetDescription target) { super(providers, target); - snippets = new EnumMap<>(Op.class); - snippets.put(Op.F2I, snippet(AMD64ConvertSnippets.class, "f2i")); - snippets.put(Op.F2L, snippet(AMD64ConvertSnippets.class, "f2l")); - snippets.put(Op.D2I, snippet(AMD64ConvertSnippets.class, "d2i")); - snippets.put(Op.D2L, snippet(AMD64ConvertSnippets.class, "d2l")); + f2i = snippet(AMD64ConvertSnippets.class, "f2i"); + f2l = snippet(AMD64ConvertSnippets.class, "f2l"); + d2i = snippet(AMD64ConvertSnippets.class, "d2i"); + d2l = snippet(AMD64ConvertSnippets.class, "d2l"); } public void lower(ConvertNode convert, LoweringTool tool) { - SnippetInfo key = snippets.get(convert.opcode); + SnippetInfo key = null; + switch (convert.getFromKind()) { + case Float: + switch (convert.getToKind()) { + case Int: + key = f2i; + break; + case Long: + key = f2l; + break; + } + break; + case Double: + switch (convert.getToKind()) { + case Int: + key = d2i; + break; + case Long: + key = d2l; + break; + } + break; + } if (key == null) { return; } @@ -169,10 +190,10 @@ Arguments args = new Arguments(key, graph.getGuardsStage()); args.add("input", convert.value()); - args.add("result", graph.unique(new AMD64ConvertNode(convert.opcode, convert.value()))); + args.add("result", graph.unique(new AMD64ConvertNode(convert.getFromKind(), convert.getToKind(), convert.value()))); SnippetTemplate template = template(args); - Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, args); + Debug.log("Lowering %c2%c in %s: node=%s, template=%s, arguments=%s", convert.getFromKind().getTypeChar(), convert.getToKind().getTypeChar(), graph, convert, template, args); template.instantiate(providers.getMetaAccess(), convert, DEFAULT_REPLACER, tool, args); graph.removeFloating(convert); } diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Mon Nov 04 11:25:10 2013 +0100 @@ -111,7 +111,8 @@ if (indexConvert) { ConvertNode convert = (ConvertNode) location.getIndex(); - Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(Kind.Int, convert.getFromKind()); + Assert.assertEquals(Kind.Long, convert.getToKind()); Assert.assertEquals(graph.getLocal(1), convert.value()); } else { Assert.assertEquals(graph.getLocal(1), location.getIndex()); @@ -135,7 +136,8 @@ if (indexConvert) { ConvertNode convert = (ConvertNode) location.getIndex(); - Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(Kind.Int, convert.getFromKind()); + Assert.assertEquals(Kind.Long, convert.getToKind()); Assert.assertEquals(graph.getLocal(1), convert.value()); } else { Assert.assertEquals(graph.getLocal(1), location.getIndex()); diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Mon Nov 04 11:25:10 2013 +0100 @@ -122,7 +122,8 @@ if (indexConvert) { ConvertNode convert = (ConvertNode) location.getIndex(); - Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(Kind.Int, convert.getFromKind()); + Assert.assertEquals(Kind.Long, convert.getToKind()); Assert.assertEquals(graph.getLocal(1), convert.value()); } else { Assert.assertEquals(graph.getLocal(1), location.getIndex()); @@ -151,7 +152,8 @@ if (indexConvert) { ConvertNode convert = (ConvertNode) location.getIndex(); - Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(Kind.Int, convert.getFromKind()); + Assert.assertEquals(Kind.Long, convert.getToKind()); Assert.assertEquals(graph.getLocal(1), convert.value()); } else { Assert.assertEquals(graph.getLocal(1), location.getIndex()); diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Mon Nov 04 11:25:10 2013 +0100 @@ -422,7 +422,7 @@ @Test public void testFloatSubstitutions() { - assertInGraph(test("floatToIntBits"), ConvertNode.class); // Java + assertInGraph(test("floatToIntBits"), ReinterpretNode.class); // Java test("intBitsToFloat"); } @@ -438,7 +438,7 @@ @Test public void testDoubleSubstitutions() { - assertInGraph(test("doubleToLongBits"), ConvertNode.class); // Java + assertInGraph(test("doubleToLongBits"), ReinterpretNode.class); // Java test("longBitsToDouble"); } diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DoubleSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DoubleSubstitutions.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DoubleSubstitutions.java Mon Nov 04 11:25:10 2013 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.replacements; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.calc.*; @@ -35,9 +36,7 @@ @MethodSubstitution public static long doubleToRawLongBits(double value) { - @JavacBug(id = 6995200) - Long result = ConvertNode.convert(ConvertNode.Op.MOV_D2L, value); - return result; + return ReinterpretNode.reinterpret(Kind.Long, value); } // TODO This method is not necessary, since the JDK method does exactly this @@ -52,8 +51,6 @@ @MethodSubstitution public static double longBitsToDouble(long bits) { - @JavacBug(id = 6995200) - Double result = ConvertNode.convert(ConvertNode.Op.MOV_L2D, bits); - return result; + return ReinterpretNode.reinterpret(Kind.Double, bits); } } diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FloatSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FloatSubstitutions.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FloatSubstitutions.java Mon Nov 04 11:25:10 2013 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.replacements; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.calc.*; @@ -35,9 +36,7 @@ @MethodSubstitution public static int floatToRawIntBits(float value) { - @JavacBug(id = 6995200) - Integer result = ConvertNode.convert(ConvertNode.Op.MOV_F2I, value); - return result; + return ReinterpretNode.reinterpret(Kind.Int, value); } // TODO This method is not necessary, since the JDK method does exactly this @@ -52,8 +51,6 @@ @MethodSubstitution public static float intBitsToFloat(int bits) { - @JavacBug(id = 6995200) - Float result = ConvertNode.convert(ConvertNode.Op.MOV_I2F, bits); - return result; + return ReinterpretNode.reinterpret(Kind.Float, bits); } } diff -r 2c4aa758ee18 -r 9334392ed279 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Sun Nov 03 15:27:52 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Nov 04 11:25:10 2013 +0100 @@ -312,31 +312,33 @@ } protected ValueNode fromUnsigned(StructuredGraph graph, ValueNode value) { - return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L); + return convert(graph, value, wordKind, true); } private ValueNode fromSigned(StructuredGraph graph, ValueNode value) { - return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.I2L); + return convert(graph, value, wordKind, false); } protected ValueNode toUnsigned(StructuredGraph graph, ValueNode value, Kind toKind) { - return convert(graph, value, toKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L); + return convert(graph, value, toKind, true); } - private static ValueNode convert(StructuredGraph graph, ValueNode value, Kind toKind, ConvertNode.Op longToIntOp, ConvertNode.Op intToLongOp) { - assert longToIntOp.from == Kind.Long && longToIntOp.to == Kind.Int; - assert intToLongOp.from == Kind.Int && intToLongOp.to == Kind.Long; + private static ValueNode convert(StructuredGraph graph, ValueNode value, Kind toKind, boolean unsigned) { if (value.kind() == toKind) { return value; } if (toKind == Kind.Int) { assert value.kind() == Kind.Long; - return graph.unique(new ConvertNode(longToIntOp, value)); + return graph.unique(new ConvertNode(Kind.Long, Kind.Int, value)); } else { assert toKind == Kind.Long; assert value.kind().getStackKind() == Kind.Int; - return graph.unique(new ConvertNode(intToLongOp, value)); + if (unsigned) { + return graph.unique(new ReinterpretNode(Kind.Long, value)); + } else { + return graph.unique(new ConvertNode(Kind.Int, Kind.Long, value)); + } } }