# HG changeset patch # User Roland Schatz # Date 1392980028 -3600 # Node ID 958c99d0790cfa397a056256dea3ad274e004b22 # Parent f2b300c6e621fbd85699359d65bdeba7fb8af589 Split convert node into separate nodes for different conversions. diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Fri Feb 21 11:53:48 2014 +0100 @@ -424,6 +424,18 @@ } /** + * Creates a {@link Constant} from a primitive integer of a certain width. + */ + public static Constant forPrimitiveInt(int bits, long i) { + assert bits <= 64; + if (bits > 32) { + return new Constant(Kind.Long, null, i); + } else { + return new Constant(Kind.Int, null, (int) i); + } + } + + /** * Creates a boxed constant for the given kind from an Object. The object needs to be of the * Java boxed type corresponding to the kind. * diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Fri Feb 21 11:53:48 2014 +0100 @@ -312,9 +312,7 @@ emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";" + comment); } - public void emitConvert(Value dest, Value src, Kind destKind, Kind srcKind) { - String destType = getArgTypeFromKind(destKind); - String srcType = getArgTypeFromKind(srcKind); + public void emitConvert(Value dest, Value src, String destType, String srcType) { String prefix = (destType.equals("f32") && srcType.equals("f64")) ? "cvt_near_" : "cvt_"; emitString(prefix + destType + "_" + srcType + " " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";"); } diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Feb 21 11:53:48 2014 +0100 @@ -64,6 +64,7 @@ import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.calc.FloatConvertNode.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; @@ -173,7 +174,7 @@ } else if (scaleEnum == null) { /* Scale value that architecture cannot handle, so scale manually. */ - Value longIndex = index.getKind().getStackKind() == Kind.Int ? emitConvert(Kind.Int, Kind.Long, index) : index; + Value longIndex = index.getKind() == Kind.Long ? index : emitSignExtend(index, 32, 64); if (CodeUtil.isPowerOf2(scale)) { indexRegister = emitShl(longIndex, Constant.forLong(CodeUtil.log2(scale))); } else { @@ -707,12 +708,6 @@ } } - 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)); @@ -725,111 +720,6 @@ return result; } - @Override - 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 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 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 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 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 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 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; - } - throw GraalInternalError.shouldNotReachHere(); - } - public AllocatableValue emitReinterpret(Kind to, Value inputVal) { Kind from = inputVal.getKind(); AllocatableValue input = asAllocatable(inputVal); @@ -842,40 +732,23 @@ case Int: switch (from) { case Float: - case Double: return emitConvert2Op(to, MOV_F2I, input); } break; case Long: switch (from) { - case Float: case Double: return emitConvert2Op(to, MOV_D2L, input); - case Int: - /* - * Unsigned int-to-long conversion: In theory, instructions that move or - * generate 32-bit register values also set the upper 32 bits of the - * register to zero. However, we cannot rely that the value was really - * generated by an instruction, it could come from an untrusted source such - * as native code. Therefore, make sure the high bits are really cleared. - */ - Variable temp = newVariable(Kind.Int); - Variable result = newVariable(Kind.Long); - append(new BinaryRegConst(AMD64Arithmetic.IAND, temp, input, Constant.forInt(0xFFFFFFFF))); - emitMove(result, temp); - return result; } break; case Float: switch (from) { case Int: - case Long: return emitConvert2Op(to, MOV_I2F, input); } break; case Double: switch (from) { - case Int: case Long: return emitConvert2Op(to, MOV_L2D, input); } @@ -884,6 +757,101 @@ throw GraalInternalError.shouldNotReachHere(); } + public Value emitFloatConvert(FloatConvert op, Value inputVal) { + AllocatableValue input = asAllocatable(inputVal); + switch (op) { + case D2F: + return emitConvert2Op(Kind.Float, D2F, input); + case D2I: + return emitConvert2Op(Kind.Int, D2I, input); + case D2L: + return emitConvert2Op(Kind.Long, D2L, input); + case F2D: + return emitConvert2Op(Kind.Double, F2D, input); + case F2I: + return emitConvert2Op(Kind.Int, F2I, input); + case F2L: + return emitConvert2Op(Kind.Long, F2L, input); + case I2D: + return emitConvert2Op(Kind.Double, I2D, input); + case I2F: + return emitConvert2Op(Kind.Float, I2F, input); + case L2D: + return emitConvert2Op(Kind.Double, L2D, input); + case L2F: + return emitConvert2Op(Kind.Float, L2F, input); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Value emitNarrow(Value inputVal, int bits) { + if (inputVal.getKind() == Kind.Long && bits <= 32) { + // TODO make it possible to reinterpret Long as Int in LIR without move + return emitConvert1Op(Kind.Int, L2I, asAllocatable(inputVal)); + } else { + return inputVal; + } + } + + @Override + public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { + assert fromBits <= toBits && toBits <= 64; + if (fromBits == toBits) { + return inputVal; + } else if (toBits > 32) { + // sign extend to 64 bits + if (fromBits == 32) { + return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal)); + } else if (fromBits < 32) { + // TODO implement direct x2L sign extension conversions + Value intVal = emitSignExtend(inputVal, fromBits, 32); + return emitSignExtend(intVal, 32, toBits); + } else { + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } + } else { + // sign extend to 32 bits (smaller values are internally represented as 32 bit values) + switch (fromBits) { + case 8: + return emitConvert2Op(Kind.Int, I2B, asAllocatable(inputVal)); + case 16: + return emitConvert2Op(Kind.Int, I2S, asAllocatable(inputVal)); + case 32: + return inputVal; + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } + } + } + + @Override + public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { + assert fromBits <= toBits && toBits <= 64; + if (fromBits == toBits) { + return inputVal; + } else if (fromBits > 32) { + assert inputVal.getKind() == Kind.Long; + Variable result = newVariable(Kind.Long); + long mask = IntegerStamp.defaultMask(fromBits); + append(new BinaryRegConst(AMD64Arithmetic.LAND, result, asAllocatable(inputVal), Constant.forLong(mask))); + return result; + } else { + assert inputVal.getKind() == Kind.Int; + Variable result = newVariable(Kind.Int); + int mask = (int) IntegerStamp.defaultMask(fromBits); + append(new BinaryRegConst(AMD64Arithmetic.IAND, result, asAllocatable(inputVal), Constant.forInt(mask))); + if (toBits > 32) { + Variable longResult = newVariable(Kind.Long); + emitMove(longResult, result); + return longResult; + } else { + return result; + } + } + } + @Override public void emitMembar(int barriers) { int necessaryBarriers = target().arch.requiredBarriers(barriers); diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Fri Feb 21 11:53:48 2014 +0100 @@ -53,6 +53,8 @@ import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; /** @@ -145,7 +147,7 @@ } else { Value indexRegister; Value convertedIndex; - convertedIndex = this.emitConvert(Kind.Int, Kind.Long, index); + convertedIndex = this.emitSignExtend(index, 32, 64); if (scale != 1) { indexRegister = emitUMul(convertedIndex, Constant.forInt(scale)); } else { @@ -592,14 +594,91 @@ } @Override - public Variable emitConvert(Kind from, Kind to, Value inputVal) { + public Value emitFloatConvert(FloatConvert op, Value inputVal) { Variable input = load(inputVal); - Variable result = newVariable(to); + + String from; + switch (op) { + case D2F: + case D2I: + case D2L: + from = "f64"; + break; + case F2D: + case F2I: + case F2L: + from = "f32"; + break; + case I2D: + case I2F: + from = "s32"; + break; + case L2D: + case L2F: + from = "s64"; + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + + Variable result; + String to; + switch (op) { + case D2I: + case F2I: + to = "s32"; + result = newVariable(Kind.Int); + break; + case D2L: + case F2L: + to = "s64"; + result = newVariable(Kind.Long); + break; + case F2D: + case I2D: + case L2D: + to = "f64"; + result = newVariable(Kind.Double); + break; + case D2F: + case I2F: + case L2F: + to = "f32"; + result = newVariable(Kind.Float); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + append(new ConvertOp(result, input, to, from)); return result; } @Override + public Value emitNarrow(Value inputVal, int bits) { + Variable input = load(inputVal); + Variable result = newVariable(bits > 32 ? Kind.Long : Kind.Int); + append(new ConvertOp(result, input, "s" + bits, input.getKind() == Kind.Long ? "s64" : "s32")); + return result; + } + + @Override + public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { + Variable input = load(inputVal); + Variable result = newVariable(toBits > 32 ? Kind.Long : Kind.Int); + append(new ConvertOp(result, input, "s" + toBits, "s" + fromBits)); + return result; + } + + @Override + public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { + Variable input = load(inputVal); + Variable result = newVariable(toBits > 32 ? Kind.Long : Kind.Int); + append(new ConvertOp(result, input, "u" + toBits, "u" + fromBits)); + return result; + } + + @Override public Value emitReinterpret(Kind to, Value inputVal) { Variable result = newVariable(to); emitMove(result, inputVal); @@ -816,7 +895,7 @@ @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { - assert v.kind() == Kind.Object; + assert v.stamp() instanceof ObjectStamp; Variable obj = newVariable(Kind.Object); emitMove(obj, operand(v)); append(new HSAILMove.NullCheckOp(obj, state(deopting))); diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Fri Feb 21 11:53:48 2014 +0100 @@ -62,8 +62,10 @@ 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.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; /** @@ -232,7 +234,7 @@ Value convertedIndex; Value indexRegister; - convertedIndex = emitConvert(Kind.Int, Kind.Long, index); + convertedIndex = emitSignExtend(index, 32, 64); if (scale != 1) { if (CodeUtil.isPowerOf2(scale)) { indexRegister = emitShl(convertedIndex, Constant.forInt(CodeUtil.log2(scale))); @@ -681,14 +683,110 @@ return result; } - @Override - public Variable emitConvert(Kind from, Kind to, Value inputVal) { + public Variable emitConvertOp(Kind from, Kind to, Value inputVal) { Variable input = load(inputVal); Variable result = newVariable(to); append(new ConvertOp(result, input, to, from)); return result; } + @Override + public Value emitFloatConvert(FloatConvert op, Value inputVal) { + switch (op) { + case D2F: + return emitConvertOp(Kind.Double, Kind.Float, inputVal); + case D2I: + return emitConvertOp(Kind.Double, Kind.Int, inputVal); + case D2L: + return emitConvertOp(Kind.Double, Kind.Long, inputVal); + case F2D: + return emitConvertOp(Kind.Float, Kind.Double, inputVal); + case F2I: + return emitConvertOp(Kind.Float, Kind.Int, inputVal); + case F2L: + return emitConvertOp(Kind.Float, Kind.Long, inputVal); + case I2D: + return emitConvertOp(Kind.Int, Kind.Double, inputVal); + case I2F: + return emitConvertOp(Kind.Int, Kind.Float, inputVal); + case L2D: + return emitConvertOp(Kind.Long, Kind.Double, inputVal); + case L2F: + return emitConvertOp(Kind.Long, Kind.Float, inputVal); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Value emitNarrow(Value inputVal, int bits) { + if (inputVal.getKind() == Kind.Long && bits <= 32) { + return emitConvertOp(Kind.Long, Kind.Int, inputVal); + } else { + return inputVal; + } + } + + @Override + public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { + assert fromBits <= toBits && toBits <= 64; + if (fromBits == toBits) { + return inputVal; + } else if (toBits > 32) { + // sign extend to 64 bits + switch (fromBits) { + case 8: + return emitConvertOp(Kind.Byte, Kind.Long, inputVal); + case 16: + return emitConvertOp(Kind.Short, Kind.Long, inputVal); + case 32: + return emitConvertOp(Kind.Int, Kind.Long, inputVal); + case 64: + return inputVal; + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } + } else { + // sign extend to 32 bits (smaller values are internally represented as 32 bit values) + switch (fromBits) { + case 8: + return emitConvertOp(Kind.Byte, Kind.Int, inputVal); + case 16: + return emitConvertOp(Kind.Short, Kind.Int, inputVal); + case 32: + return inputVal; + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } + } + } + + @Override + public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { + assert fromBits <= toBits && toBits <= 64; + if (fromBits == toBits) { + return inputVal; + } else if (fromBits > 32) { + assert inputVal.getKind() == Kind.Long; + Variable result = newVariable(Kind.Long); + long mask = IntegerStamp.defaultMask(fromBits); + append(new Op2Stack(LAND, result, inputVal, Constant.forLong(mask))); + return result; + } else { + assert inputVal.getKind() == Kind.Int; + Variable result = newVariable(Kind.Int); + int mask = (int) IntegerStamp.defaultMask(fromBits); + append(new Op2Stack(IAND, result, inputVal, Constant.forInt(mask))); + if (toBits > 32) { + Variable longResult = newVariable(Kind.Long); + emitMove(longResult, result); + return longResult; + } else { + return result; + } + } + } + public Value emitReinterpret(Kind to, Value inputVal) { Variable result = newVariable(to); emitMove(result, inputVal); diff -r f2b300c6e621 -r 958c99d0790c 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 Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Fri Feb 21 11:53:48 2014 +0100 @@ -60,7 +60,9 @@ 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.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; /** @@ -153,8 +155,7 @@ indexRegister = Value.ILLEGAL; } else { if (scale != 1) { - // Variable longIndex = newVariable(Kind.Long); - AllocatableValue longIndex = emitConvert(Kind.Int, Kind.Long, index); + Value longIndex = emitSignExtend(index, 32, 64); if (CodeUtil.isPowerOf2(scale)) { indexRegister = emitShl(longIndex, Constant.forLong(CodeUtil.log2(scale))); } else { @@ -766,108 +767,98 @@ } @Override - public AllocatableValue emitConvert(Kind from, Kind to, Value inputVal) { - assert inputVal.getKind() == from.getStackKind(); + public Value emitFloatConvert(FloatConvert op, Value inputVal) { + AllocatableValue input = asAllocatable(inputVal); + switch (op) { + case D2F: + return emitConvert2Op(Kind.Float, D2F, input); + case D2I: + return emitConvert2Op(Kind.Int, D2I, input); + case D2L: + return emitConvert2Op(Kind.Long, D2L, input); + case F2D: + return emitConvert2Op(Kind.Double, F2D, input); + case F2I: + return emitConvert2Op(Kind.Int, F2I, input); + case F2L: + return emitConvert2Op(Kind.Long, F2L, input); + case I2D: + return emitConvert2Op(Kind.Double, I2D, input); + case I2F: + return emitConvert2Op(Kind.Float, I2F, input); + case L2D: + return emitConvert2Op(Kind.Double, L2D, input); + case L2F: + return emitConvert2Op(Kind.Float, L2F, input); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } - AllocatableValue input = asAllocatable(inputVal); - if (from == to) { - return input; + @Override + public Value emitNarrow(Value inputVal, int bits) { + if (inputVal.getKind() == Kind.Long && bits <= 32) { + return emitConvert2Op(Kind.Int, L2I, asAllocatable(inputVal)); + } else { + return inputVal; } - 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 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 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 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 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 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 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; + } + + @Override + public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { + assert fromBits <= toBits && toBits <= 64; + if (fromBits == toBits) { + return inputVal; + } else if (toBits > 32) { + // sign extend to 64 bits + if (fromBits == 32) { + return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal)); + } else if (fromBits < 32) { + // TODO implement direct x2L sign extension conversions + Value intVal = emitSignExtend(inputVal, fromBits, 32); + return emitSignExtend(intVal, 32, toBits); + } else { + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } + } else { + // sign extend to 32 bits (smaller values are internally represented as 32 bit values) + switch (fromBits) { + case 8: + return emitConvert2Op(Kind.Int, I2B, asAllocatable(inputVal)); + case 16: + return emitConvert2Op(Kind.Int, I2S, asAllocatable(inputVal)); + case 32: + return inputVal; + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } } - throw GraalInternalError.shouldNotReachHere(); + } + + @Override + public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { + assert fromBits <= toBits && toBits <= 64; + if (fromBits == toBits) { + return inputVal; + } else if (fromBits > 32) { + assert inputVal.getKind() == Kind.Long; + Variable result = newVariable(Kind.Long); + long mask = IntegerStamp.defaultMask(fromBits); + append(new BinaryRegConst(SPARCArithmetic.LAND, result, asAllocatable(inputVal), Constant.forLong(mask))); + return result; + } else { + assert inputVal.getKind() == Kind.Int; + Variable result = newVariable(Kind.Int); + int mask = (int) IntegerStamp.defaultMask(fromBits); + append(new BinaryRegConst(SPARCArithmetic.IAND, result, asAllocatable(inputVal), Constant.forInt(mask))); + if (toBits > 32) { + Variable longResult = newVariable(Kind.Long); + emitMove(longResult, result); + return longResult; + } else { + return result; + } + } } public AllocatableValue emitReinterpret(Kind to, Value inputVal) { diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java Fri Feb 21 11:53:48 2014 +0100 @@ -47,8 +47,8 @@ @Override public void lower(Node n, LoweringTool tool) { - if (n instanceof ConvertNode) { - convertSnippets.lower((ConvertNode) n, tool); + if (n instanceof FloatConvertNode) { + convertSnippets.lower((FloatConvertNode) n, tool); } else { super.lower(n, tool); } diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Fri Feb 21 11:53:48 2014 +0100 @@ -264,18 +264,18 @@ case Short: case Char: case Int: - returnValue = unique(new ConvertNode(Kind.Long, Kind.Int, result)); + returnValue = unique(new NarrowNode(result, 32)); break; case Long: returnValue = result; break; case Float: { - ValueNode asInt = unique(new ConvertNode(Kind.Long, Kind.Int, result)); - returnValue = unique(new ReinterpretNode(Kind.Float, asInt)); + ValueNode asInt = unique(new NarrowNode(result, 32)); + returnValue = ReinterpretNode.reinterpret(Kind.Float, asInt); break; } case Double: - returnValue = unique(new ReinterpretNode(returnKind, result)); + returnValue = ReinterpretNode.reinterpret(Kind.Double, result); break; case Object: getObjectResult = createInvoke(getClass(), "getObjectResult", args.get(Thread)); diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -140,8 +140,8 @@ ValueNode srcAddr = computeBase(getSource(), getSourcePosition()); ValueNode destAddr = computeBase(getDestination(), getDestinationPosition()); ValueNode len = getLength(); - if (len.kind() != Kind.Long) { - len = graph().unique(new ConvertNode(len.kind(), Kind.Long, len)); + if (len.stamp().getStackKind() != Kind.Long) { + len = IntegerConvertNode.convert(len, StampFactory.forKind(Kind.Long)); } ForeignCallNode call = graph.add(new ForeignCallNode(Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getForeignCalls(), desc, srcAddr, destAddr, len)); call.setStateAfter(stateAfter()); diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Feb 21 11:53:48 2014 +0100 @@ -44,6 +44,7 @@ import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; @@ -708,9 +709,30 @@ frameState.ipush(append(new NormalizeCompareNode(x, y, isUnorderedLess))); } - private void genConvert(Kind from, Kind to) { + private void genFloatConvert(FloatConvert op, Kind from, Kind to) { + ValueNode input = frameState.pop(from.getStackKind()); + frameState.push(to.getStackKind(), append(new FloatConvertNode(op, input))); + } + + private void genSignExtend(Kind from, Kind to) { ValueNode input = frameState.pop(from.getStackKind()); - frameState.push(to.getStackKind(), append(new ConvertNode(from, to, input))); + if (from != from.getStackKind()) { + input = append(new NarrowNode(input, from.getBitCount())); + } + frameState.push(to.getStackKind(), append(new SignExtendNode(input, to.getBitCount()))); + } + + private void genZeroExtend(Kind from, Kind to) { + ValueNode input = frameState.pop(from.getStackKind()); + if (from != from.getStackKind()) { + input = append(new NarrowNode(input, from.getBitCount())); + } + frameState.push(to.getStackKind(), append(new ZeroExtendNode(input, to.getBitCount()))); + } + + private void genNarrow(Kind from, Kind to) { + ValueNode input = frameState.pop(from.getStackKind()); + frameState.push(to.getStackKind(), append(new NarrowNode(input, to.getBitCount()))); } private void genIncrement() { @@ -1991,21 +2013,21 @@ case LOR : // fall through case LXOR : genLogicOp(Kind.Long, opcode); break; case IINC : genIncrement(); 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 I2F : genFloatConvert(FloatConvert.I2F, Kind.Int, Kind.Float); break; + case I2D : genFloatConvert(FloatConvert.I2D, Kind.Int, Kind.Double); break; + case L2F : genFloatConvert(FloatConvert.L2F, Kind.Long, Kind.Float); break; + case L2D : genFloatConvert(FloatConvert.L2D, Kind.Long, Kind.Double); break; + case F2I : genFloatConvert(FloatConvert.F2I, Kind.Float, Kind.Int); break; + case F2L : genFloatConvert(FloatConvert.F2L, Kind.Float, Kind.Long); break; + case F2D : genFloatConvert(FloatConvert.F2D, Kind.Float, Kind.Double); break; + case D2I : genFloatConvert(FloatConvert.D2I, Kind.Double, Kind.Int); break; + case D2L : genFloatConvert(FloatConvert.D2L, Kind.Double, Kind.Long); break; + case D2F : genFloatConvert(FloatConvert.D2F, Kind.Double, Kind.Float); break; + case L2I : genNarrow(Kind.Long, Kind.Int); break; + case I2L : genSignExtend(Kind.Int, Kind.Long); break; + case I2B : genSignExtend(Kind.Byte, Kind.Int); break; + case I2S : genSignExtend(Kind.Short, Kind.Int); break; + case I2C : genZeroExtend(Kind.Char, Kind.Int); break; case LCMP : genCompareOp(Kind.Long, false); break; case FCMPL : genCompareOp(Kind.Float, true); break; case FCMPG : genCompareOp(Kind.Float, false); break; diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java Fri Feb 21 11:53:48 2014 +0100 @@ -105,12 +105,12 @@ UNDEF; public static class ConvertOp extends HSAILLIRInstruction { - private final Kind from; - private final Kind to; + private final String from; + private final String to; @Def({REG}) protected AllocatableValue result; @Use({REG, STACK}) protected AllocatableValue x; - public ConvertOp(AllocatableValue result, AllocatableValue x, Kind to, Kind from) { + public ConvertOp(AllocatableValue result, AllocatableValue x, String to, String from) { this.from = from; this.to = to; this.result = result; diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Fri Feb 21 11:53:48 2014 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.loop; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -119,28 +118,28 @@ } @Override - public ValueNode extremumNode(boolean assumePositiveTripCount, Kind kind) { - Kind fromKind = phi.kind(); + public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) { + Stamp fromStamp = phi.stamp(); StructuredGraph graph = graph(); ValueNode stride = strideNode(); ValueNode initNode = this.initNode(); - if (fromKind != kind) { - stride = graph.unique(new ConvertNode(fromKind, kind, stride)); - initNode = graph.unique(new ConvertNode(fromKind, kind, initNode)); + if (!fromStamp.isCompatible(stamp)) { + stride = IntegerConvertNode.convert(stride, stamp); + initNode = IntegerConvertNode.convert(initNode, stamp); } ValueNode maxTripCount = loop.counted().maxTripCountNode(assumePositiveTripCount); - if (maxTripCount.kind() != kind) { - maxTripCount = graph.unique(new ConvertNode(maxTripCount.kind(), kind, maxTripCount)); + if (!maxTripCount.stamp().isCompatible(stamp)) { + maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp); } - return IntegerArithmeticNode.add(graph, IntegerArithmeticNode.mul(graph, stride, IntegerArithmeticNode.sub(graph, maxTripCount, ConstantNode.forIntegerKind(kind, 1, graph))), initNode); + return IntegerArithmeticNode.add(graph, IntegerArithmeticNode.mul(graph, stride, IntegerArithmeticNode.sub(graph, maxTripCount, ConstantNode.forIntegerStamp(stamp, 1, graph))), initNode); } @Override public ValueNode exitValueNode() { - Kind kind = phi.kind(); + Stamp stamp = phi.stamp(); ValueNode maxTripCount = loop.counted().maxTripCountNode(false); - if (maxTripCount.kind() != kind) { - maxTripCount = graph().unique(new ConvertNode(maxTripCount.kind(), kind, maxTripCount)); + if (!maxTripCount.stamp().isCompatible(stamp)) { + maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp); } return IntegerArithmeticNode.add(graph(), IntegerArithmeticNode.mul(graph(), strideNode(), maxTripCount), initNode()); } diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Fri Feb 21 11:53:48 2014 +0100 @@ -22,10 +22,10 @@ */ package com.oracle.graal.loop; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.type.*; public class DerivedOffsetInductionVariable extends InductionVariable { @@ -92,8 +92,8 @@ } @Override - public ValueNode extremumNode(boolean assumePositiveTripCount, Kind kind) { - return op(base.extremumNode(assumePositiveTripCount, kind), ConvertNode.convert(graph(), kind, offset)); + public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) { + return op(base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(offset, stamp)); } @Override diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Fri Feb 21 11:53:48 2014 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.loop; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.type.*; @@ -102,8 +101,8 @@ } @Override - public ValueNode extremumNode(boolean assumePositiveTripCount, Kind kind) { - return IntegerArithmeticNode.mul(graph(), base.extremumNode(assumePositiveTripCount, kind), ConvertNode.convert(graph(), kind, scale)); + public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) { + return IntegerArithmeticNode.mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp)); } @Override diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java Fri Feb 21 11:53:48 2014 +0100 @@ -22,9 +22,9 @@ */ package com.oracle.graal.loop; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; /** * This class describes a value node that is an induction variable in a counted loop. @@ -89,10 +89,10 @@ * induction variable in the loop body of the last iteration. */ public ValueNode extremumNode() { - return extremumNode(false, valueNode().kind()); + return extremumNode(false, valueNode().stamp()); } - public abstract ValueNode extremumNode(boolean assumePositiveTripCount, Kind kind); + public abstract ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp); public abstract boolean isConstantExtremum(); diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -152,7 +152,7 @@ } /** - * Returns a node for a primitive constant. + * Returns a node for a Java primitive. */ public static ConstantNode forPrimitive(Constant constant, StructuredGraph graph) { assert constant.getKind() != Kind.Object; @@ -255,6 +255,33 @@ return graph.unique(node); } + /** + * Returns a node for a constant integer that's not directly representable as Java primitive + * (e.g. short). + */ + public static ConstantNode forIntegerBits(int bits, boolean unsigned, long value, StructuredGraph graph) { + Constant constant = Constant.forPrimitiveInt(bits, value); + long bounds; + if (unsigned) { + bounds = ZeroExtendNode.zeroExtend(value, bits); + } else { + bounds = SignExtendNode.signExtend(value, bits); + } + return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, unsigned, bounds, bounds))); + } + + /** + * Returns a node for a constant integer that's compatible to a given stamp. + */ + public static ConstantNode forIntegerStamp(Stamp stamp, long value, StructuredGraph graph) { + if (stamp instanceof IntegerStamp) { + IntegerStamp intStamp = (IntegerStamp) stamp; + return forIntegerBits(intStamp.getBits(), intStamp.isUnsigned(), value, graph); + } else { + return forIntegerKind(stamp.getStackKind(), value, graph); + } + } + public static ConstantNode forIntegerKind(Kind kind, long value, StructuredGraph graph) { switch (kind) { case Byte: diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -136,15 +136,15 @@ if (x() instanceof ConvertNode && y() instanceof ConvertNode) { ConvertNode convertX = (ConvertNode) x(); ConvertNode convertY = (ConvertNode) y(); - if (convertX.isLossless() && convertY.isLossless() && convertX.getFromKind() == convertY.getFromKind()) { - setX(convertX.value()); - setY(convertY.value()); + if (convertX.isLossless() && convertY.isLossless() && convertX.getInput().stamp().isCompatible(convertY.getInput().stamp())) { + setX(convertX.getInput()); + setY(convertY.getInput()); } } else if (x() instanceof ConvertNode && y().isConstant()) { ConvertNode convertX = (ConvertNode) x(); ConstantNode newY = canonicalConvertConstant(convertX, y().asConstant()); if (newY != null) { - setX(convertX.value()); + setX(convertX.getInput()); setY(newY); } } else if (y() instanceof ConvertNode && x().isConstant()) { @@ -152,7 +152,7 @@ ConstantNode newX = canonicalConvertConstant(convertY, x().asConstant()); if (newX != null) { setX(newX); - setY(convertY.value()); + setY(convertY.getInput()); } } return this; @@ -160,9 +160,8 @@ private static ConstantNode canonicalConvertConstant(ConvertNode convert, Constant constant) { if (convert.isLossless()) { - assert constant.getKind() == convert.getToKind(); - Constant reverseConverted = ConvertNode.convert(convert.getToKind(), convert.getFromKind(), constant); - if (convert.evalConst(reverseConverted).equals(constant)) { + Constant reverseConverted = convert.reverse(constant); + if (convert.convert(reverseConverted).equals(constant)) { return ConstantNode.forPrimitive(reverseConverted, convert.graph()); } } diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -22,277 +22,36 @@ */ package com.oracle.graal.nodes.calc; +import com.oracle.graal.api.code.*; 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 ConvertNode} class represents a conversion between primitive types. + * Represents a conversion between primitive types. */ -public class ConvertNode extends FloatingNode implements Canonicalizable, Lowerable, ArithmeticLIRLowerable { - - @Input private ValueNode value; - - private final Kind from; - private final Kind to; - - public ValueNode value() { - return value; - } - - /** - * Constructs a new Convert instance. - * - * @param from the kind of the incoming value - * @param to the result kind - * @param value the instruction producing the input value - */ - 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 abstract class ConvertNode extends FloatingNode implements ArithmeticOperation { - public Kind getFromKind() { - return from; - } - - public Kind getToKind() { - return to; - } + @Input private ValueNode input; - 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(); + protected ConvertNode(Stamp stamp, ValueNode input) { + super(stamp); + this.input = input; } - public static Constant convert(Kind from, Kind to, Constant c) { - 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(); + public ValueNode getInput() { + return input; } - public Constant evalConst(Constant... inputs) { - assert inputs.length == 1; - return convert(from, to, inputs[0]); - } + public abstract Constant convert(Constant c); - @Override - public Node canonical(CanonicalizerTool tool) { - if (from == to) { - return value; - } else if (value.isConstant()) { - return ConstantNode.forPrimitive(evalConst(value.asConstant()), graph()); - } else if (value instanceof ConvertNode) { - ConvertNode other = (ConvertNode) value; - if (other.isLossless() && other.to != Kind.Char) { - if (other.from == this.to) { - return other.value(); - } else { - return graph().unique(new ConvertNode(other.from, this.to, other.value())); - } - } - } - return this; - } + public abstract Constant reverse(Constant c); + + public abstract boolean isLossless(); @Override - public boolean inferStamp() { - Stamp stamp = value.stamp(); - if (!(stamp instanceof IntegerStamp)) { - if (stamp instanceof FloatStamp) { - return false; - } - assert stamp instanceof IllegalStamp; - return updateStamp(stamp); - } - Stamp newStamp; - IntegerStamp integerStamp = (IntegerStamp) stamp; - switch (to) { - case Byte: - case Short: - case Char: - case Int: - newStamp = StampTool.narrowingKindConversion(integerStamp, to); - break; - case Long: - newStamp = StampTool.intToLong(integerStamp); - break; - default: - return false; - } - return updateStamp(newStamp); - } - - @Override - public void lower(LoweringTool tool) { - tool.getLowerer().lower(this, tool); - } - - @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitConvert(from, to, gen.operand(value()))); - } - - public static ValueNode convert(StructuredGraph graph, Kind toKind, ValueNode value) { - Kind fromKind = value.kind(); - if (fromKind == toKind) { - return value; - } - return graph.unique(new ConvertNode(fromKind, toKind, value)); + public Constant evalConst(Constant... inputs) { + assert inputs.length == 1; + return convert(inputs[0]); } } diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2014, 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.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * A {@code FloatConvert} converts between integers and floating point numbers according to Java + * semantics. + */ +public class FloatConvertNode extends ConvertNode implements Lowerable, ArithmeticLIRLowerable { + + public enum FloatConvert { + F2I, D2I, F2L, D2L, I2F, L2F, D2F, I2D, L2D, F2D; + + public FloatConvert reverse() { + switch (this) { + case D2F: + return F2D; + case D2I: + return I2D; + case D2L: + return L2D; + case F2D: + return D2F; + case F2I: + return I2F; + case F2L: + return L2F; + case I2D: + return D2I; + case I2F: + return F2I; + case L2D: + return D2L; + case L2F: + return F2L; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + private final FloatConvert op; + + public FloatConvertNode(FloatConvert op, ValueNode input) { + super(createStamp(op, input), input); + this.op = op; + } + + private static Stamp createStamp(FloatConvert op, ValueNode input) { + switch (op) { + case I2F: + case I2D: + assert input.stamp() instanceof IntegerStamp && ((IntegerStamp) input.stamp()).getBits() == 32; + break; + case L2F: + case L2D: + assert input.stamp() instanceof IntegerStamp && ((IntegerStamp) input.stamp()).getBits() == 64; + break; + case F2I: + case F2L: + case F2D: + assert input.stamp() instanceof FloatStamp && ((FloatStamp) input.stamp()).getBits() == 32; + break; + case D2I: + case D2L: + case D2F: + assert input.stamp() instanceof FloatStamp && ((FloatStamp) input.stamp()).getBits() == 64; + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + + switch (op) { + case F2I: + case D2I: + return StampFactory.forKind(Kind.Int); + case F2L: + case D2L: + return StampFactory.forKind(Kind.Long); + case I2F: + case L2F: + case D2F: + return StampFactory.forKind(Kind.Float); + case I2D: + case L2D: + case F2D: + return StampFactory.forKind(Kind.Double); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + public FloatConvert getOp() { + return op; + } + + @Override + public boolean inferStamp() { + return updateStamp(createStamp(op, getInput())); + } + + private static Constant convert(FloatConvert op, Constant value) { + switch (op) { + case F2I: + return Constant.forInt((int) value.asFloat()); + case D2I: + return Constant.forInt((int) value.asDouble()); + case F2L: + return Constant.forLong((long) value.asFloat()); + case D2L: + return Constant.forLong((long) value.asDouble()); + case I2F: + return Constant.forFloat(value.asInt()); + case L2F: + return Constant.forFloat(value.asLong()); + case D2F: + return Constant.forFloat((float) value.asDouble()); + case I2D: + return Constant.forDouble(value.asInt()); + case L2D: + return Constant.forDouble(value.asLong()); + case F2D: + return Constant.forDouble(value.asFloat()); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Constant convert(Constant c) { + return convert(op, c); + } + + @Override + public Constant reverse(Constant c) { + return convert(op.reverse(), c); + } + + @Override + public boolean isLossless() { + switch (op) { + case F2D: + case I2D: + return true; + default: + return false; + } + } + + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } + + public void generate(ArithmeticLIRGenerator gen) { + gen.setResult(this, gen.emitFloatConvert(op, gen.operand(getInput()))); + } +} diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, 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.*; + +/** + * An {@code IntegerConvert} converts an integer to an integer of different width. + */ +public abstract class IntegerConvertNode extends ConvertNode implements Canonicalizable, ArithmeticLIRLowerable { + + private final int resultBits; + + protected IntegerConvertNode(Stamp stamp, ValueNode input, int resultBits) { + super(stamp, input); + this.resultBits = resultBits; + } + + public int getResultBits() { + return resultBits; + } + + public int getInputBits() { + if (getInput().stamp() instanceof IntegerStamp) { + return ((IntegerStamp) getInput().stamp()).getBits(); + } else { + return 0; + } + } + + public static long convert(long value, int bits, boolean unsigned) { + if (unsigned) { + return ZeroExtendNode.zeroExtend(value, bits); + } else { + return SignExtendNode.signExtend(value, bits); + } + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (getInput().stamp() instanceof IntegerStamp) { + int inputBits = ((IntegerStamp) getInput().stamp()).getBits(); + if (inputBits == resultBits) { + return getInput(); + } else if (getInput().isConstant()) { + Constant ret = evalConst(getInput().asConstant()); + return ConstantNode.forIntegerBits(resultBits, false, ret.asLong(), graph()); + } + } + + return this; + } + + public static ValueNode convert(ValueNode input, Stamp stamp) { + StructuredGraph graph = input.graph(); + IntegerStamp fromStamp = (IntegerStamp) input.stamp(); + IntegerStamp toStamp = (IntegerStamp) stamp; + + ValueNode result; + if (toStamp.getBits() == fromStamp.getBits()) { + result = input; + } else if (toStamp.getBits() < fromStamp.getBits()) { + result = graph.unique(new NarrowNode(input, toStamp.getBits())); + } else { + // toStamp.getBits() > fromStamp.getBits() + if (fromStamp.isUnsigned()) { + result = graph.unique(new ZeroExtendNode(input, toStamp.getBits())); + } else { + result = graph.unique(new SignExtendNode(input, toStamp.getBits())); + } + } + + IntegerStamp resultStamp = (IntegerStamp) result.stamp(); + assert toStamp.getBits() == resultStamp.getBits(); + if (toStamp.isUnsigned() == resultStamp.isUnsigned()) { + return result; + } else { + return graph.unique(new ReinterpretNode(toStamp, result)); + } + } +} diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014, 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 NarrowNode} converts an integer to a narrower integer. + */ +public class NarrowNode extends IntegerConvertNode { + + public NarrowNode(ValueNode input, int resultBits) { + super(StampTool.narrowingConversion(input.stamp(), resultBits), input, resultBits); + } + + public static long narrow(long value, int resultBits) { + return value & IntegerStamp.defaultMask(resultBits); + } + + @Override + public Constant convert(Constant c) { + return Constant.forPrimitiveInt(getResultBits(), narrow(c.asLong(), getResultBits())); + } + + @Override + public Constant reverse(Constant input) { + IntegerStamp stamp = (IntegerStamp) stamp(); + long result; + if (stamp.isUnsigned()) { + result = ZeroExtendNode.zeroExtend(input.asLong(), getResultBits()); + } else { + result = SignExtendNode.signExtend(input.asLong(), getResultBits()); + } + return Constant.forPrimitiveInt(getInputBits(), result); + } + + @Override + public boolean isLossless() { + return false; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (getInput() instanceof NarrowNode) { + NarrowNode other = (NarrowNode) getInput(); + return graph().unique(new NarrowNode(other.getInput(), getResultBits())); + } else if (getInput() instanceof IntegerConvertNode) { + // SignExtendNode or ZeroExtendNode + IntegerConvertNode other = (IntegerConvertNode) getInput(); + if (getResultBits() == other.getInputBits()) { + return other.getInput(); + } else if (getResultBits() < other.getInputBits()) { + return graph().unique(new NarrowNode(other.getInput(), getResultBits())); + } else { + if (other instanceof SignExtendNode) { + return graph().unique(new SignExtendNode(other.getInput(), getResultBits())); + } else if (other instanceof ZeroExtendNode) { + return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); + } + } + } + + return super.canonical(tool); + } + + @Override + public boolean inferStamp() { + return updateStamp(StampTool.narrowingConversion(getInput().stamp(), getResultBits())); + } + + @Override + public void generate(ArithmeticLIRGenerator gen) { + gen.setResult(this, gen.emitNarrow(gen.operand(getInput()), getResultBits())); + } +} diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -30,7 +30,9 @@ import com.oracle.graal.nodes.type.*; /** - * The {@code ReinterpretNode} class represents a reinterpreting conversion between primitive types. + * The {@code ReinterpretNode} class represents a reinterpreting conversion that changes the stamp + * of a primitive value to some other incompatible stamp. The new stamp must have the same width as + * the old stamp. */ public class ReinterpretNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable { @@ -40,64 +42,45 @@ return value; } - public ReinterpretNode(Kind to, ValueNode value) { - super(StampFactory.forKind(to.getStackKind())); + private ReinterpretNode(Kind to, ValueNode value) { + this(StampFactory.forKind(to), value); + } + + public ReinterpretNode(Stamp to, ValueNode value) { + super(to); + assert to instanceof PrimitiveStamp; this.value = value; } public Constant evalConst(Constant... inputs) { assert inputs.length == 1; Constant c = inputs[0]; - assert c.getKind() == value.kind(); + assert c.getKind().getBitCount() == ((PrimitiveStamp) stamp()).getBits(); 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)); + if (stamp() instanceof FloatStamp) { + return Constant.forFloat(Float.intBitsToFloat(c.asInt())); + } else { + return c; } - 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())); + if (stamp() instanceof FloatStamp) { + return Constant.forDouble(Double.longBitsToDouble(c.asLong())); + } else { + return c; } - 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)); + if (stamp() instanceof IntegerStamp) { + return Constant.forInt(Float.floatToRawIntBits(c.asFloat())); + } else { + return c; } - 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; + if (stamp() instanceof IntegerStamp) { + return Constant.forLong(Double.doubleToRawLongBits(c.asDouble())); + } else { + return c; } - break; } throw GraalInternalError.shouldNotReachHere(); } @@ -107,6 +90,9 @@ if (value.isConstant()) { return ConstantNode.forPrimitive(evalConst(value.asConstant()), graph()); } + if (stamp().isCompatible(value.stamp())) { + return value; + } return this; } @@ -116,10 +102,6 @@ } 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)); } diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014, 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 SignExtendNode} converts an integer to a wider integer using sign extension. + */ +public class SignExtendNode extends IntegerConvertNode { + + public SignExtendNode(ValueNode input, int resultBits) { + super(StampTool.signExtend(input.stamp(), resultBits), input, resultBits); + } + + public static long signExtend(long value, int inputBits) { + if (inputBits < 64) { + if ((value >>> (inputBits - 1) & 1) == 1) { + return value | (-1L << inputBits); + } else { + return value & ~(-1L << inputBits); + } + } else { + return value; + } + } + + @Override + public Constant convert(Constant c) { + return Constant.forPrimitiveInt(getResultBits(), signExtend(c.asLong(), getInputBits())); + } + + @Override + public Constant reverse(Constant c) { + return Constant.forPrimitiveInt(getInputBits(), NarrowNode.narrow(c.asLong(), getInputBits())); + } + + @Override + public boolean isLossless() { + return true; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (getInput() instanceof SignExtendNode) { + SignExtendNode other = (SignExtendNode) getInput(); + return graph().unique(new SignExtendNode(other.getInput(), getResultBits())); + } else if (getInput() instanceof ZeroExtendNode) { + ZeroExtendNode other = (ZeroExtendNode) getInput(); + if (other.getResultBits() > other.getInputBits()) { + return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); + } + } + + if (getInput().stamp() instanceof IntegerStamp) { + IntegerStamp inputStamp = (IntegerStamp) getInput().stamp(); + if ((inputStamp.upMask() & (1L << (getInputBits() - 1))) == 0L) { + return graph().unique(new ZeroExtendNode(getInput(), getResultBits())); + } + } + + return super.canonical(tool); + } + + @Override + public boolean inferStamp() { + return updateStamp(StampTool.signExtend(getInput().stamp(), getResultBits())); + } + + @Override + public void generate(ArithmeticLIRGenerator gen) { + gen.setResult(this, gen.emitSignExtend(gen.operand(getInput()), getInputBits(), getResultBits())); + } +} diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, 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 ZeroExtendNode} converts an integer to a wider integer using zero extension. + */ +public class ZeroExtendNode extends IntegerConvertNode { + + public ZeroExtendNode(ValueNode input, int resultBits) { + super(StampTool.zeroExtend(input.stamp(), resultBits), input, resultBits); + } + + public static long zeroExtend(long value, int inputBits) { + if (inputBits < 64) { + return value & ~(-1L << inputBits); + } else { + return value; + } + } + + @Override + public Constant convert(Constant c) { + return Constant.forPrimitiveInt(getResultBits(), zeroExtend(c.asLong(), getInputBits())); + } + + @Override + public Constant reverse(Constant c) { + return Constant.forPrimitiveInt(getInputBits(), NarrowNode.narrow(c.asLong(), getInputBits())); + } + + @Override + public boolean isLossless() { + return true; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (getInput() instanceof ZeroExtendNode) { + ZeroExtendNode other = (ZeroExtendNode) getInput(); + return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); + } + + return super.canonical(tool); + } + + @Override + public boolean inferStamp() { + return updateStamp(StampTool.zeroExtend(getInput().stamp(), getResultBits())); + } + + @Override + public void generate(ArithmeticLIRGenerator gen) { + gen.setResult(this, gen.emitZeroExtend(gen.operand(getInput()), getInputBits(), getResultBits())); + } +} diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java Fri Feb 21 11:53:48 2014 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; /** * This interface can be used to generate LIR for arithmetic operations (@see @@ -65,10 +66,16 @@ Value emitUShr(Value a, Value b); - Value emitConvert(Kind from, Kind to, Value inputVal); + Value emitFloatConvert(FloatConvert op, Value inputVal); Value emitReinterpret(Kind to, Value inputVal); + Value emitNarrow(Value inputVal, int bits); + + Value emitSignExtend(Value inputVal, int fromBits, int toBits); + + Value emitZeroExtend(Value inputVal, int fromBits, int toBits); + Value emitMathAbs(Value input); Value emitMathSqrt(Value input); diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java Fri Feb 21 11:53:48 2014 +0100 @@ -42,6 +42,14 @@ return bits; } + public static int getBits(Stamp stamp) { + if (stamp instanceof PrimitiveStamp) { + return ((PrimitiveStamp) stamp).getBits(); + } else { + return 0; + } + } + @Override public int hashCode() { final int prime = 31; diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Fri Feb 21 11:53:48 2014 +0100 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.calc.*; /** * Helper class that is used to keep all stamp-related operations in one place. @@ -178,15 +179,15 @@ lowerBound = (stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask; upperBound = (stamp1.upperBound() + stamp2.upperBound()) & defaultMask; if (!unsigned) { - lowerBound = signExtend(lowerBound, bits); - upperBound = signExtend(upperBound, bits); + lowerBound = SignExtendNode.signExtend(lowerBound, bits); + upperBound = SignExtendNode.signExtend(upperBound, bits); } } IntegerStamp limit = StampFactory.forInteger(bits, unsigned, lowerBound, upperBound); newUpMask &= limit.upMask(); upperBound &= newUpMask; if (!unsigned) { - upperBound = signExtend(upperBound, bits); + upperBound = SignExtendNode.signExtend(upperBound, bits); } newDownMask |= limit.downMask(); lowerBound |= newDownMask; @@ -213,6 +214,8 @@ lowerBound = downMask | (-1L << (bits - 1)); upperBound = IntegerStamp.defaultMaxValue(bits, false) & upMask; } + lowerBound = IntegerConvertNode.convert(lowerBound, bits, false); + upperBound = IntegerConvertNode.convert(upperBound, bits, false); return new IntegerStamp(bits, false, lowerBound, upperBound, downMask, upMask); } @@ -316,16 +319,85 @@ return value.unrestricted(); } + public static Stamp signExtend(Stamp input, int resultBits) { + if (input instanceof IntegerStamp) { + IntegerStamp inputStamp = (IntegerStamp) input; + int inputBits = inputStamp.getBits(); + assert inputBits <= resultBits; + + long defaultMask = IntegerStamp.defaultMask(resultBits); + long downMask = SignExtendNode.signExtend(inputStamp.downMask(), inputBits) & defaultMask; + long upMask = SignExtendNode.signExtend(inputStamp.upMask(), inputBits) & defaultMask; + + return new IntegerStamp(resultBits, inputStamp.isUnsigned(), inputStamp.lowerBound(), inputStamp.upperBound(), downMask, upMask); + } else { + return input.illegal(); + } + } + + public static Stamp zeroExtend(Stamp input, int resultBits) { + if (input instanceof IntegerStamp) { + IntegerStamp inputStamp = (IntegerStamp) input; + int inputBits = inputStamp.getBits(); + assert inputBits <= resultBits; + + long downMask = ZeroExtendNode.zeroExtend(inputStamp.downMask(), inputBits); + long upMask = ZeroExtendNode.zeroExtend(inputStamp.upMask(), inputBits); + + return new IntegerStamp(resultBits, inputStamp.isUnsigned(), inputStamp.lowerBound(), inputStamp.upperBound(), downMask, upMask); + } else { + return input.illegal(); + } + } + public static Stamp intToLong(IntegerStamp intStamp) { long downMask = intStamp.downMask(); long upMask = intStamp.upMask(); if (!intStamp.isUnsigned()) { - downMask = signExtend(downMask, intStamp.getBits()); - upMask = signExtend(upMask, intStamp.getBits()); + downMask = SignExtendNode.signExtend(downMask, intStamp.getBits()); + upMask = SignExtendNode.signExtend(upMask, intStamp.getBits()); } return new IntegerStamp(64, intStamp.isUnsigned(), intStamp.lowerBound(), intStamp.upperBound(), downMask, upMask); } + public static Stamp narrowingConversion(Stamp input, int resultBits) { + if (input instanceof IntegerStamp) { + IntegerStamp inputStamp = (IntegerStamp) input; + boolean unsigned = inputStamp.isUnsigned(); + int inputBits = inputStamp.getBits(); + assert resultBits <= inputBits; + if (resultBits == inputBits) { + return inputStamp; + } + + final long upperBound; + if (inputStamp.lowerBound() < IntegerStamp.defaultMinValue(resultBits, unsigned)) { + upperBound = IntegerStamp.defaultMaxValue(resultBits, unsigned); + } else { + upperBound = saturate(inputStamp.upperBound(), resultBits, unsigned); + } + final long lowerBound; + if (inputStamp.upperBound() > IntegerStamp.defaultMaxValue(resultBits, unsigned)) { + lowerBound = IntegerStamp.defaultMinValue(resultBits, unsigned); + } else { + lowerBound = saturate(inputStamp.lowerBound(), resultBits, unsigned); + } + + long defaultMask = IntegerStamp.defaultMask(resultBits); + long newDownMask = inputStamp.downMask() & defaultMask; + long newUpMask = inputStamp.upMask() & defaultMask; + long newLowerBound = (lowerBound | newDownMask) & newUpMask; + long newUpperBound = (upperBound | newDownMask) & newUpMask; + if (!unsigned) { + newLowerBound = SignExtendNode.signExtend(newLowerBound, resultBits); + newUpperBound = SignExtendNode.signExtend(newUpperBound, resultBits); + } + return new IntegerStamp(resultBits, unsigned, newLowerBound, newUpperBound, newDownMask, newUpMask); + } else { + return input.illegal(); + } + } + public static IntegerStamp narrowingKindConversion(IntegerStamp fromStamp, Kind toKind) { assert toKind == Kind.Byte || toKind == Kind.Char || toKind == Kind.Short || toKind == Kind.Int; final long upperBound; @@ -348,14 +420,6 @@ return new IntegerStamp(toKind.getStackKind().getBitCount(), false, (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask); } - private static long signExtend(long value, int bits) { - if (bits < 64 && (value >>> (bits - 1) & 1) == 1) { - return value | (-1L << bits); - } else { - return value; - } - } - private static long signExtend(long value, Kind valueKind) { if (valueKind != Kind.Char && valueKind != Kind.Long && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) { return value | (-1L << valueKind.getBitCount()); @@ -364,7 +428,21 @@ } } - public static long saturate(long v, Kind kind) { + private static long saturate(long v, int bits, boolean unsigned) { + if (bits < 64) { + long max = IntegerStamp.defaultMaxValue(bits, unsigned); + if (v > max) { + return max; + } + long min = IntegerStamp.defaultMinValue(bits, unsigned); + if (v < min) { + return min; + } + } + return v; + } + + private static long saturate(long v, Kind kind) { long max = kind.getMaxValue(); if (v > max) { return max; diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2012, 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.replacements.amd64; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * This node has the semantics of the AMD64 conversions. It is used in the lowering of the - * {@link ConvertNode} which, on AMD64 needs a {@link AMD64ConvertNode} plus some fixup code that - * handles the corner cases that differ between AMD64 and Java. - */ -public class AMD64ConvertNode extends FloatingNode implements ArithmeticLIRLowerable { - - @Input private ValueNode value; - private final Kind from; - private final Kind to; - - 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) { - // this node should never have been created if its input is constant - assert false; - return null; - } - - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitConvert(from, to, gen.operand(value))); - } -} diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Fri Feb 21 11:53:48 2014 +0100 @@ -158,42 +158,33 @@ d2l = snippet(AMD64ConvertSnippets.class, "d2l"); } - public void lower(ConvertNode convert, LoweringTool tool) { - SnippetInfo key = null; - switch (convert.getFromKind()) { - case Float: - switch (convert.getToKind()) { - case Int: - key = f2i; - break; - case Long: - key = f2l; - break; - } + public void lower(FloatConvertNode convert, LoweringTool tool) { + SnippetInfo key; + switch (convert.getOp()) { + case F2I: + key = f2i; + break; + case F2L: + key = f2l; break; - case Double: - switch (convert.getToKind()) { - case Int: - key = d2i; - break; - case Long: - key = d2l; - break; - } + case D2I: + key = d2i; break; - } - if (key == null) { - return; + case D2L: + key = d2l; + break; + default: + return; } StructuredGraph graph = convert.graph(); Arguments args = new Arguments(key, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("input", convert.value()); - args.add("result", graph.unique(new AMD64ConvertNode(convert.getFromKind(), convert.getToKind(), convert.value()))); + args.add("input", convert.getInput()); + args.add("result", graph.unique(new AMD64FloatConvertNode(convert.stamp(), convert.getOp(), convert.getInput()))); SnippetTemplate template = 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); + Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getOp(), graph, convert, template, args); template.instantiate(providers.getMetaAccess(), convert, DEFAULT_REPLACER, tool, args); graph.removeFloating(convert); } diff -r f2b300c6e621 -r 958c99d0790c graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Fri Feb 21 11:53:48 2014 +0100 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012, 2014, 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.replacements.amd64; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * This node has the semantics of the AMD64 floating point conversions. It is used in the lowering + * of the {@link FloatConvertNode} which, on AMD64 needs a {@link AMD64FloatConvertNode} plus some + * fixup code that handles the corner cases that differ between AMD64 and Java. + */ +public class AMD64FloatConvertNode extends FloatingNode implements ArithmeticLIRLowerable { + + private final FloatConvert op; + @Input private ValueNode value; + + public AMD64FloatConvertNode(Stamp stamp, FloatConvert op, ValueNode value) { + super(stamp); + this.op = op; + this.value = value; + } + + public Constant evalConst(Constant... inputs) { + // this node should never have been created if its input is constant + throw GraalInternalError.shouldNotReachHere(); + } + + public void generate(ArithmeticLIRGenerator gen) { + gen.setResult(this, gen.emitFloatConvert(op, gen.operand(value))); + } +} diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Fri Feb 21 11:53:48 2014 +0100 @@ -102,7 +102,7 @@ private static void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { ReadNode read = (ReadNode) graph.start().next(); - Assert.assertEquals(kind.getStackKind(), read.kind()); + Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind()); Assert.assertEquals(graph.getParameter(0), read.object()); IndexedLocationNode location = (IndexedLocationNode) read.location(); @@ -111,10 +111,10 @@ Assert.assertEquals(1, location.getIndexScaling()); if (indexConvert) { - ConvertNode convert = (ConvertNode) location.getIndex(); - Assert.assertEquals(Kind.Int, convert.getFromKind()); - Assert.assertEquals(Kind.Long, convert.getToKind()); - Assert.assertEquals(graph.getParameter(1), convert.value()); + SignExtendNode convert = (SignExtendNode) location.getIndex(); + Assert.assertEquals(convert.getInputBits(), 32); + Assert.assertEquals(convert.getResultBits(), 64); + Assert.assertEquals(graph.getParameter(1), convert.getInput()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } @@ -127,7 +127,6 @@ WriteNode write = (WriteNode) graph.start().next(); Assert.assertEquals(graph.getParameter(2), write.value()); Assert.assertEquals(graph.getParameter(0), write.object()); - Assert.assertEquals(Kind.Void, write.kind()); Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); IndexedLocationNode location = (IndexedLocationNode) write.location(); @@ -136,10 +135,10 @@ Assert.assertEquals(1, location.getIndexScaling()); if (indexConvert) { - ConvertNode convert = (ConvertNode) location.getIndex(); - Assert.assertEquals(Kind.Int, convert.getFromKind()); - Assert.assertEquals(Kind.Long, convert.getToKind()); - Assert.assertEquals(graph.getParameter(1), convert.value()); + SignExtendNode convert = (SignExtendNode) location.getIndex(); + Assert.assertEquals(convert.getInputBits(), 32); + Assert.assertEquals(convert.getResultBits(), 64); + Assert.assertEquals(graph.getParameter(1), convert.getInput()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Fri Feb 21 11:53:48 2014 +0100 @@ -110,11 +110,11 @@ WordCastNode cast = (WordCastNode) graph.start().next(); ReadNode read = (ReadNode) cast.next(); - Assert.assertEquals(kind.getStackKind(), read.kind()); + Assert.assertEquals(kind.getStackKind(), read.stamp().getStackKind()); Assert.assertEquals(cast, read.object()); Assert.assertEquals(graph.getParameter(0), cast.getInput()); - Assert.assertEquals(target.wordKind, cast.kind()); + Assert.assertEquals(target.wordKind, cast.stamp().getStackKind()); IndexedLocationNode location = (IndexedLocationNode) read.location(); Assert.assertEquals(kind, location.getValueKind()); @@ -122,10 +122,10 @@ Assert.assertEquals(1, location.getIndexScaling()); if (indexConvert) { - ConvertNode convert = (ConvertNode) location.getIndex(); - Assert.assertEquals(Kind.Int, convert.getFromKind()); - Assert.assertEquals(Kind.Long, convert.getToKind()); - Assert.assertEquals(graph.getParameter(1), convert.value()); + SignExtendNode convert = (SignExtendNode) location.getIndex(); + Assert.assertEquals(convert.getInputBits(), 32); + Assert.assertEquals(convert.getResultBits(), 64); + Assert.assertEquals(graph.getParameter(1), convert.getInput()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } @@ -139,12 +139,11 @@ WriteNode write = (WriteNode) cast.next(); Assert.assertEquals(graph.getParameter(2), write.value()); - Assert.assertEquals(Kind.Void, write.kind()); Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); Assert.assertEquals(cast, write.object()); Assert.assertEquals(graph.getParameter(0), cast.getInput()); - Assert.assertEquals(target.wordKind, cast.kind()); + Assert.assertEquals(target.wordKind, cast.stamp().getStackKind()); IndexedLocationNode location = (IndexedLocationNode) write.location(); Assert.assertEquals(kind, location.getValueKind()); @@ -152,10 +151,10 @@ Assert.assertEquals(1, location.getIndexScaling()); if (indexConvert) { - ConvertNode convert = (ConvertNode) location.getIndex(); - Assert.assertEquals(Kind.Int, convert.getFromKind()); - Assert.assertEquals(Kind.Long, convert.getToKind()); - Assert.assertEquals(graph.getParameter(1), convert.value()); + SignExtendNode convert = (SignExtendNode) location.getIndex(); + Assert.assertEquals(convert.getInputBits(), 32); + Assert.assertEquals(convert.getResultBits(), 64); + Assert.assertEquals(graph.getParameter(1), convert.getInput()); } else { Assert.assertEquals(graph.getParameter(1), location.getIndex()); } diff -r f2b300c6e621 -r 958c99d0790c 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 Thu Feb 20 14:42:01 2014 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Fri Feb 21 11:53:48 2014 +0100 @@ -301,14 +301,14 @@ if (toKind == Kind.Int) { assert value.kind() == Kind.Long; - return graph.unique(new ConvertNode(Kind.Long, Kind.Int, value)); + return graph.unique(new NarrowNode(value, 32)); } else { assert toKind == Kind.Long; assert value.kind().getStackKind() == Kind.Int; if (unsigned) { - return graph.unique(new ReinterpretNode(Kind.Long, value)); + return graph.unique(new ZeroExtendNode(value, 64)); } else { - return graph.unique(new ConvertNode(Kind.Int, Kind.Long, value)); + return graph.unique(new SignExtendNode(value, 64)); } } }