# HG changeset patch # User Roland Schatz # Date 1412589092 -7200 # Node ID 98e60bdf6d0573063d69e34710ddb37b7d3ae7b4 # Parent da1f5b9ccac6fea84ff747b156e7cc074215fe26 Use ArithmeticOpTable for primitive convert operations. diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Mon Oct 06 11:51:32 2014 +0200 @@ -191,7 +191,7 @@ } private Value emitFloatConvertMemory(FloatConvertNode op, Access access) { - switch (op.getOp()) { + switch (op.getFloatConvert()) { case D2F: return emitConvert2MemoryOp(Kind.Float, D2F, access); case D2I: diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Mon Oct 06 11:51:32 2014 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; /** * Information about arithmetic operations. @@ -43,6 +44,12 @@ private final BinaryOp or; private final BinaryOp xor; + private final IntegerConvertOp zeroExtend; + private final IntegerConvertOp signExtend; + private final IntegerConvertOp narrow; + + private final FloatConvertOp[] floatConvert; + public static ArithmeticOpTable forStamp(Stamp s) { if (s instanceof ArithmeticStamp) { return ((ArithmeticStamp) s).getOps(); @@ -67,26 +74,18 @@ BinaryOp or = null; BinaryOp xor = null; + IntegerConvertOp zeroExtend = null; + IntegerConvertOp signExtend = null; + IntegerConvertOp narrow = null; + + FloatConvertOp[] floatConvert = new FloatConvertOp[FloatConvert.values().length]; + for (Op op : ops) { if (op == null) { continue; } - if (op instanceof UnaryOp) { - UnaryOp unary = (UnaryOp) op; - switch (unary.getOperator()) { - case '-': - assert neg == null; - neg = unary; - break; - case '~': - assert not == null; - not = unary; - break; - default: - throw GraalInternalError.shouldNotReachHere("unknown unary operator " + unary.getOperator()); - } - } else { + if (op instanceof BinaryOp) { BinaryOp binary = (BinaryOp) op; switch (binary.getOperator()) { case '+': @@ -124,13 +123,53 @@ default: throw GraalInternalError.shouldNotReachHere("unknown binary operator " + binary.getOperator()); } + } else if (op instanceof IntegerConvertOp) { + IntegerConvertOp convert = (IntegerConvertOp) op; + switch (convert.getOperator()) { + case IntegerConvertOp.ZERO_EXTEND: + assert zeroExtend == null; + zeroExtend = convert; + break; + case IntegerConvertOp.SIGN_EXTEND: + assert signExtend == null; + signExtend = convert; + break; + case IntegerConvertOp.NARROW: + assert narrow == null; + narrow = convert; + break; + default: + throw GraalInternalError.shouldNotReachHere("unknown integer conversion operator " + convert.getOperator()); + } + } else if (op instanceof FloatConvertOp) { + FloatConvertOp convert = (FloatConvertOp) op; + int idx = convert.getFloatConvert().ordinal(); + assert floatConvert[idx] == null; + floatConvert[idx] = convert; + } else if (op instanceof UnaryOp) { + UnaryOp unary = (UnaryOp) op; + switch (unary.getOperator()) { + case '-': + assert neg == null; + neg = unary; + break; + case '~': + assert not == null; + not = unary; + break; + default: + throw GraalInternalError.shouldNotReachHere("unknown unary operator " + unary.getOperator()); + } + } else { + throw GraalInternalError.shouldNotReachHere("unknown Op subclass " + op); } } - return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor); + return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor, zeroExtend, signExtend, narrow, floatConvert); } - private ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, BinaryOp xor) { + private ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, BinaryOp xor, IntegerConvertOp zeroExtend, + IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp[] floatConvert) { this.neg = neg; this.add = add; this.sub = sub; @@ -141,6 +180,10 @@ this.and = and; this.or = or; this.xor = xor; + this.zeroExtend = zeroExtend; + this.signExtend = signExtend; + this.narrow = narrow; + this.floatConvert = floatConvert; } /** @@ -213,6 +256,22 @@ return xor; } + public IntegerConvertOp getZeroExtend() { + return zeroExtend; + } + + public IntegerConvertOp getSignExtend() { + return signExtend; + } + + public IntegerConvertOp getNarrow() { + return narrow; + } + + public FloatConvertOp getFloatConvert(FloatConvert op) { + return floatConvert[op.ordinal()]; + } + public abstract static class Op { private final char operator; @@ -318,4 +377,52 @@ return null; } } -} \ No newline at end of file + + public abstract static class FloatConvertOp extends UnaryOp { + + private final FloatConvert op; + + protected FloatConvertOp(FloatConvert op) { + super('\0'); + this.op = op; + } + + public FloatConvert getFloatConvert() { + return op; + } + + @Override + public String toString() { + return op.name(); + } + } + + public abstract static class IntegerConvertOp extends Op { + + public static final char ZERO_EXTEND = 'z'; + public static final char SIGN_EXTEND = 's'; + public static final char NARROW = 'n'; + + protected IntegerConvertOp(char op) { + super(op); + } + + public abstract Constant foldConstant(int inputBits, int resultBits, Constant value); + + public abstract Stamp foldStamp(int resultBits, Stamp stamp); + + @Override + public String toString() { + switch (getOperator()) { + case ZERO_EXTEND: + return "ZeroExtend"; + case SIGN_EXTEND: + return "SignExtend"; + case NARROW: + return "Narrow"; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } +} diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Mon Oct 06 11:51:32 2014 +0200 @@ -22,12 +22,15 @@ */ package com.oracle.graal.compiler.common.type; +import static com.oracle.graal.compiler.common.calc.FloatConvert.*; + import java.util.function.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.spi.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp; public class FloatStamp extends PrimitiveStamp { @@ -431,5 +434,89 @@ // TODO return stamp1.unrestricted(); } + }, + + new FloatConvertOp(F2I) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forInt((int) value.asFloat()); + } + + @Override + public Stamp foldStamp(Stamp stamp) { + assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 32; + return StampFactory.forKind(Kind.Int); + } + }, + + new FloatConvertOp(F2L) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forLong((long) value.asFloat()); + } + + @Override + public Stamp foldStamp(Stamp stamp) { + assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 32; + return StampFactory.forKind(Kind.Long); + } + }, + + new FloatConvertOp(D2I) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forInt((int) value.asDouble()); + } + + @Override + public Stamp foldStamp(Stamp stamp) { + assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 64; + return StampFactory.forKind(Kind.Int); + } + }, + + new FloatConvertOp(D2L) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forLong((long) value.asDouble()); + } + + @Override + public Stamp foldStamp(Stamp stamp) { + assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 64; + return StampFactory.forKind(Kind.Long); + } + }, + + new FloatConvertOp(F2D) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forDouble(value.asFloat()); + } + + @Override + public Stamp foldStamp(Stamp stamp) { + assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 32; + return StampFactory.forKind(Kind.Double); + } + }, + + new FloatConvertOp(D2F) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forFloat((float) value.asDouble()); + } + + @Override + public Stamp foldStamp(Stamp stamp) { + assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 64; + return StampFactory.forKind(Kind.Float); + } }); } diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Mon Oct 06 11:51:32 2014 +0200 @@ -22,6 +22,9 @@ */ package com.oracle.graal.compiler.common.type; +import static com.oracle.graal.compiler.common.calc.FloatConvert.*; +import static com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.*; + import java.util.*; import com.oracle.graal.api.code.*; @@ -29,6 +32,8 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.spi.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp; /** @@ -350,6 +355,20 @@ return (x + y) ^ x ^ y; } + private static long saturate(long v, int bits) { + if (bits < 64) { + long max = CodeUtil.maxValue(bits); + if (v > max) { + return max; + } + long min = CodeUtil.minValue(bits); + if (v < min) { + return min; + } + } + return v; + } + public static final ArithmeticOpTable OPS = ArithmeticOpTable.create( new UnaryOp('-') { @@ -633,5 +652,153 @@ IntegerStamp stamp = (IntegerStamp) s; return Constant.forPrimitiveInt(stamp.getBits(), 0); } + }, + + new IntegerConvertOp(ZERO_EXTEND) { + + @Override + public Constant foldConstant(int inputBits, int resultBits, Constant value) { + return Constant.forPrimitiveInt(resultBits, CodeUtil.zeroExtend(value.asLong(), inputBits)); + } + + @Override + public Stamp foldStamp(int resultBits, Stamp input) { + IntegerStamp stamp = (IntegerStamp) input; + int inputBits = stamp.getBits(); + assert inputBits <= resultBits; + + long downMask = CodeUtil.zeroExtend(stamp.downMask(), inputBits); + long upMask = CodeUtil.zeroExtend(stamp.upMask(), inputBits); + + if (stamp.lowerBound() < 0 && stamp.upperBound() >= 0) { + // signed range including 0 and -1 + // after sign extension, the whole range from 0 to MAX_INT is possible + return IntegerStamp.stampForMask(resultBits, downMask, upMask); + } + + long lowerBound = CodeUtil.zeroExtend(stamp.lowerBound(), inputBits); + long upperBound = CodeUtil.zeroExtend(stamp.upperBound(), inputBits); + + return new IntegerStamp(resultBits, lowerBound, upperBound, downMask, upMask); + } + }, + + new IntegerConvertOp(SIGN_EXTEND) { + + @Override + public Constant foldConstant(int inputBits, int resultBits, Constant value) { + return Constant.forPrimitiveInt(resultBits, CodeUtil.signExtend(value.asLong(), inputBits)); + } + + @Override + public Stamp foldStamp(int resultBits, Stamp input) { + IntegerStamp stamp = (IntegerStamp) input; + int inputBits = stamp.getBits(); + assert inputBits <= resultBits; + + long defaultMask = CodeUtil.mask(resultBits); + long downMask = CodeUtil.signExtend(stamp.downMask(), inputBits) & defaultMask; + long upMask = CodeUtil.signExtend(stamp.upMask(), inputBits) & defaultMask; + + return new IntegerStamp(resultBits, stamp.lowerBound(), stamp.upperBound(), downMask, upMask); + } + }, + + new IntegerConvertOp(NARROW) { + + @Override + public Constant foldConstant(int inputBits, int resultBits, Constant value) { + return Constant.forPrimitiveInt(resultBits, CodeUtil.narrow(value.asLong(), resultBits)); + } + + @Override + public Stamp foldStamp(int resultBits, Stamp input) { + IntegerStamp stamp = (IntegerStamp) input; + int inputBits = stamp.getBits(); + assert resultBits <= inputBits; + if (resultBits == inputBits) { + return stamp; + } + + final long upperBound; + if (stamp.lowerBound() < CodeUtil.minValue(resultBits)) { + upperBound = CodeUtil.maxValue(resultBits); + } else { + upperBound = saturate(stamp.upperBound(), resultBits); + } + final long lowerBound; + if (stamp.upperBound() > CodeUtil.maxValue(resultBits)) { + lowerBound = CodeUtil.minValue(resultBits); + } else { + lowerBound = saturate(stamp.lowerBound(), resultBits); + } + + long defaultMask = CodeUtil.mask(resultBits); + long newDownMask = stamp.downMask() & defaultMask; + long newUpMask = stamp.upMask() & defaultMask; + long newLowerBound = CodeUtil.signExtend((lowerBound | newDownMask) & newUpMask, resultBits); + long newUpperBound = CodeUtil.signExtend((upperBound | newDownMask) & newUpMask, resultBits); + return new IntegerStamp(resultBits, newLowerBound, newUpperBound, newDownMask, newUpMask); + } + }, + + new FloatConvertOp(I2F) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forFloat(value.asInt()); + } + + @Override + public Stamp foldStamp(Stamp input) { + IntegerStamp stamp = (IntegerStamp) input; + assert stamp.getBits() == 32; + return StampFactory.forFloat(Kind.Float, stamp.lowerBound(), stamp.upperBound(), true); + } + }, + + new FloatConvertOp(L2F) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forFloat(value.asLong()); + } + + @Override + public Stamp foldStamp(Stamp input) { + IntegerStamp stamp = (IntegerStamp) input; + assert stamp.getBits() == 64; + return StampFactory.forFloat(Kind.Float, stamp.lowerBound(), stamp.upperBound(), true); + } + }, + + new FloatConvertOp(I2D) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forDouble(value.asInt()); + } + + @Override + public Stamp foldStamp(Stamp input) { + IntegerStamp stamp = (IntegerStamp) input; + assert stamp.getBits() == 32; + return StampFactory.forFloat(Kind.Double, stamp.lowerBound(), stamp.upperBound(), true); + } + }, + + new FloatConvertOp(L2D) { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forDouble(value.asLong()); + } + + @Override + public Stamp foldStamp(Stamp input) { + IntegerStamp stamp = (IntegerStamp) input; + assert stamp.getBits() == 64; + return StampFactory.forFloat(Kind.Double, stamp.lowerBound(), stamp.upperBound(), true); + } }); } diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Mon Oct 06 11:51:32 2014 +0200 @@ -106,7 +106,7 @@ private HashMap strategyMap = new HashMap<>(); void initStrategyMap() { - strategyMap.put(NodeClass.get(ConvertNode.class), PassThruStrategy); + strategyMap.put(NodeClass.get(IntegerConvertNode.class), PassThruStrategy); strategyMap.put(NodeClass.get(FloatConvertNode.class), PassThruStrategy); strategyMap.put(NodeClass.get(NewInstanceNode.class), NewObjectStrategy); strategyMap.put(NodeClass.get(NewArrayNode.class), NewObjectStrategy); diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Mon Oct 06 11:51:32 2014 +0200 @@ -40,7 +40,7 @@ * Compress or uncompress an oop or metaspace pointer. */ @NodeInfo(nameTemplate = "{p#op/s}") -public class CompressionNode extends ConvertNode implements LIRLowerable { +public class CompressionNode extends UnaryNode implements ConvertNode, LIRLowerable { enum CompressionOp { Compress, diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java --- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Mon Oct 06 11:51:32 2014 +0200 @@ -27,6 +27,7 @@ import org.junit.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -128,38 +129,41 @@ assertEquals(new IntegerStamp(64, -10000, 1000, 0, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -10000, 1000)); } + private static Stamp narrowingKindConversion(Stamp stamp, Kind kind) { + Stamp narrow = IntegerStamp.OPS.getNarrow().foldStamp(kind.getBitCount(), stamp); + IntegerConvertOp implicitExtend = kind.isUnsigned() ? IntegerStamp.OPS.getZeroExtend() : IntegerStamp.OPS.getSignExtend(); + return implicitExtend.foldStamp(32, narrow); + } + @Test public void testNarrowingConversions() { // byte cases - assertEquals(StampFactory.forInteger(Kind.Int, 0, 0), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 0), Kind.Byte)); - assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 10), Kind.Byte)); - assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 10, 20), Kind.Byte)); - assertEquals(StampFactory.forInteger(Kind.Int, -10, 0), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -10, 0), Kind.Byte)); - assertEquals(StampFactory.forInteger(Kind.Int, -20, -10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -20, -10), Kind.Byte)); - assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 100, 200), Kind.Byte)); - assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -100, 200), Kind.Byte)); - assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -200, -100), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 0), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 0), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 10), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 10, 20), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, -10, 0), narrowingKindConversion(StampFactory.forInteger(Kind.Int, -10, 0), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, -20, -10), narrowingKindConversion(StampFactory.forInteger(Kind.Int, -20, -10), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 100, 200), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Int, -100, 200), Kind.Byte)); + assertEquals(StampFactory.forInteger(Kind.Int, Byte.MIN_VALUE, Byte.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Int, -200, -100), Kind.Byte)); // char cases - assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 10), Kind.Char)); - assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 10, 20), Kind.Char)); - assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 20000, 80000), Kind.Char)); - assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -10000, 40000), Kind.Char)); - assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -40000, -10000), Kind.Char)); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 10), Kind.Char)); + assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 10, 20), Kind.Char)); + assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 20000, 80000), Kind.Char)); + assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Int, -10000, 40000), Kind.Char)); + assertEquals(StampFactory.forInteger(Kind.Int, Character.MIN_VALUE, Character.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Int, -40000, -10000), Kind.Char)); // short cases - assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 10), Kind.Short)); - assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 10, 20), Kind.Short)); - assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, 20000, 40000), Kind.Short)); - assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -10000, 40000), Kind.Short)); - assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Int, -40000, -10000), Kind.Short)); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 0, 10), Kind.Short)); + assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 10, 20), Kind.Short)); + assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Int, 20000, 40000), Kind.Short)); + assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Int, -10000, 40000), Kind.Short)); + assertEquals(StampFactory.forInteger(Kind.Int, Short.MIN_VALUE, Short.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Int, -40000, -10000), Kind.Short)); // int cases - assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, 0, 10), Kind.Int)); - assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, 10, 20), Kind.Int)); - assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), - StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, 20000000000L, 40000000000L), Kind.Int)); - assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), - StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, -10000000000L, 40000000000L), Kind.Int)); - assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), - StampTool.narrowingKindConversion(StampFactory.forInteger(Kind.Long, -40000000000L, -10000000000L), Kind.Int)); + assertEquals(StampFactory.forInteger(Kind.Int, 0, 10), narrowingKindConversion(StampFactory.forInteger(Kind.Long, 0, 10), Kind.Int)); + assertEquals(StampFactory.forInteger(Kind.Int, 10, 20), narrowingKindConversion(StampFactory.forInteger(Kind.Long, 10, 20), Kind.Int)); + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Long, 20000000000L, 40000000000L), Kind.Int)); + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Long, -10000000000L, 40000000000L), Kind.Int)); + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE), narrowingKindConversion(StampFactory.forInteger(Kind.Long, -40000000000L, -10000000000L), Kind.Int)); } @Test @@ -269,7 +273,7 @@ private static void testSignExtendShort(long lower, long upper) { Stamp shortStamp = StampFactory.forInteger(16, lower, upper); - Stamp intStamp = StampTool.signExtend(shortStamp, 32); + Stamp intStamp = IntegerStamp.OPS.getSignExtend().foldStamp(32, shortStamp); assertEquals(StampFactory.forInteger(32, lower, upper), intStamp); } @@ -285,7 +289,7 @@ private static void testZeroExtendShort(long lower, long upper, long newLower, long newUpper) { Stamp shortStamp = StampFactory.forInteger(16, lower, upper); - Stamp intStamp = StampTool.zeroExtend(shortStamp, 32); + Stamp intStamp = IntegerStamp.OPS.getZeroExtend().foldStamp(32, shortStamp); assertEquals(StampFactory.forInteger(32, newLower, newUpper), intStamp); } diff -r da1f5b9ccac6 -r 98e60bdf6d05 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 Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Mon Oct 06 11:51:32 2014 +0200 @@ -25,30 +25,26 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; /** * Represents a conversion between primitive types. */ -@NodeInfo -public abstract class ConvertNode extends UnaryNode implements ArithmeticOperation { +public interface ConvertNode extends ArithmeticOperation, NodeInterface { + + ValueNode getValue(); - protected ConvertNode(Stamp stamp, ValueNode value) { - super(stamp, value); - } + Constant convert(Constant c); - public abstract Constant convert(Constant c); - - public abstract Constant reverse(Constant c); + Constant reverse(Constant c); /** * Check whether a conversion is lossless. * * @return true iff reverse(convert(c)) == c for all c */ - public abstract boolean isLossless(); + boolean isLossless(); /** * Check whether a conversion preserves comparison order. @@ -56,13 +52,14 @@ * @param op a comparison operator * @return true iff (c1 op c2) == (convert(c1) op convert(c2)) for all c1, c2 */ - public boolean preservesOrder(Condition op) { + default boolean preservesOrder(Condition op) { return isLossless(); } - @Override - public Constant evalConst(Constant... inputs) { + default Constant evalConst(Constant... inputs) { assert inputs.length == 1; return convert(inputs[0]); } + + ValueNode asNode(); } diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Mon Oct 06 11:51:32 2014 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -37,114 +37,41 @@ * semantics. */ @NodeInfo -public class FloatConvertNode extends ConvertNode implements Lowerable, ArithmeticLIRLowerable { +public class FloatConvertNode extends UnaryArithmeticNode implements ConvertNode, Lowerable, ArithmeticLIRLowerable { - protected final FloatConvert op; + protected final FloatConvertOp reverseOp; public static FloatConvertNode create(FloatConvert op, ValueNode input) { return USE_GENERATED_NODES ? new FloatConvertNodeGen(op, input) : new FloatConvertNode(op, input); } - protected FloatConvertNode(FloatConvert op, ValueNode input) { - super(createStamp(op, input), input); - this.op = op; + private FloatConvertNode(ArithmeticOpTable table, FloatConvert op, ValueNode input) { + super(table.getFloatConvert(op), input); + ArithmeticOpTable revTable = ArithmeticOpTable.forStamp(stamp()); + reverseOp = revTable.getFloatConvert(op.reverse()); } - 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: - return StampFactory.forFloat(Kind.Float, ((IntegerStamp) input.stamp()).lowerBound(), ((IntegerStamp) input.stamp()).upperBound(), true); - case D2F: - return StampFactory.forKind(Kind.Float); - case I2D: - case L2D: - return StampFactory.forFloat(Kind.Double, ((IntegerStamp) input.stamp()).lowerBound(), ((IntegerStamp) input.stamp()).upperBound(), true); - case F2D: - return StampFactory.forKind(Kind.Double); - default: - throw GraalInternalError.shouldNotReachHere(); - } + protected FloatConvertNode(FloatConvert op, ValueNode input) { + this(ArithmeticOpTable.forStamp(input.stamp()), op, input); } - public FloatConvert getOp() { - return op; - } - - @Override - public boolean inferStamp() { - return updateStamp(createStamp(op, getValue())); - } - - 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(); - } + public FloatConvert getFloatConvert() { + return ((FloatConvertOp) getOp()).getFloatConvert(); } @Override public Constant convert(Constant c) { - return convert(op, c); + return op.foldConstant(c); } @Override public Constant reverse(Constant c) { - return convert(op.reverse(), c); + return reverseOp.foldConstant(c); } @Override public boolean isLossless() { - switch (op) { + switch (getFloatConvert()) { case F2D: case I2D: return true; @@ -155,11 +82,14 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - if (forValue.isConstant()) { - return ConstantNode.forConstant(evalConst(forValue.asConstant()), null); - } else if (forValue instanceof FloatConvertNode) { + ValueNode ret = super.canonical(tool, forValue); + if (ret != this) { + return ret; + } + + if (forValue instanceof FloatConvertNode) { FloatConvertNode other = (FloatConvertNode) forValue; - if (other.isLossless() && other.op == this.op.reverse()) { + if (other.isLossless() && other.op == this.reverseOp) { return other.getValue(); } } @@ -171,6 +101,6 @@ } public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getValue()))); + builder.setResult(this, gen.emitFloatConvert(getFloatConvert(), builder.operand(getValue()))); } } diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Mon Oct 06 11:51:32 2014 +0200 @@ -22,7 +22,10 @@ */ package com.oracle.graal.nodes.calc; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp; import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -31,12 +34,17 @@ * An {@code IntegerConvert} converts an integer to an integer of different width. */ @NodeInfo -public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable { +public abstract class IntegerConvertNode extends UnaryNode implements ConvertNode, ArithmeticLIRLowerable { + + protected final IntegerConvertOp op; + protected final IntegerConvertOp reverseOp; protected final int resultBits; - protected IntegerConvertNode(Stamp stamp, ValueNode input, int resultBits) { - super(stamp, input); + protected IntegerConvertNode(IntegerConvertOp op, IntegerConvertOp reverseOp, int resultBits, ValueNode input) { + super(op.foldStamp(resultBits, input.stamp()), input); + this.op = op; + this.reverseOp = reverseOp; this.resultBits = resultBits; } @@ -52,13 +60,29 @@ } } - protected ValueNode canonicalConvert(@SuppressWarnings("hiding") ValueNode value) { + @Override + public Constant convert(Constant c) { + return op.foldConstant(getInputBits(), getResultBits(), c); + } + + @Override + public Constant reverse(Constant c) { + return reverseOp.foldConstant(getResultBits(), getInputBits(), c); + } + + @Override + public boolean inferStamp() { + return updateStamp(op.foldStamp(resultBits, getValue().stamp())); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { if (value.stamp() instanceof IntegerStamp) { int inputBits = ((IntegerStamp) value.stamp()).getBits(); if (inputBits == resultBits) { return value; } else if (value.isConstant()) { - return ConstantNode.forIntegerBits(resultBits, evalConst(value.asConstant()).asLong()); + return ConstantNode.forPrimitive(stamp(), convert(forValue.asConstant())); } } return this; diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Mon Oct 06 11:51:32 2014 +0200 @@ -22,14 +22,12 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; 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. @@ -41,19 +39,12 @@ return USE_GENERATED_NODES ? new NarrowNodeGen(input, resultBits) : new NarrowNode(input, resultBits); } - protected NarrowNode(ValueNode input, int resultBits) { - super(StampTool.narrowingConversion(input.stamp(), resultBits), input, resultBits); + private NarrowNode(ArithmeticOpTable ops, ValueNode input, int resultBits) { + super(ops.getNarrow(), ops.getSignExtend(), resultBits, input); } - @Override - public Constant convert(Constant c) { - return Constant.forPrimitiveInt(getResultBits(), CodeUtil.narrow(c.asLong(), getResultBits())); - } - - @Override - public Constant reverse(Constant input) { - long result = CodeUtil.signExtend(input.asLong(), getResultBits()); - return Constant.forPrimitiveInt(getInputBits(), result); + protected NarrowNode(ValueNode input, int resultBits) { + this(ArithmeticOpTable.forStamp(input.stamp()), input, resultBits); } @Override @@ -63,7 +54,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - ValueNode ret = canonicalConvert(forValue); + ValueNode ret = super.canonical(tool, forValue); if (ret != this) { return ret; } @@ -100,11 +91,6 @@ } @Override - public boolean inferStamp() { - return updateStamp(StampTool.narrowingConversion(getValue().stamp(), getResultBits())); - } - - @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { builder.setResult(this, gen.emitNarrow(builder.operand(getValue()), getResultBits())); } diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Mon Oct 06 11:51:32 2014 +0200 @@ -22,15 +22,12 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; 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. @@ -42,18 +39,12 @@ return USE_GENERATED_NODES ? new SignExtendNodeGen(input, resultBits) : new SignExtendNode(input, resultBits); } - protected SignExtendNode(ValueNode input, int resultBits) { - super(StampTool.signExtend(input.stamp(), resultBits), input, resultBits); + private SignExtendNode(ArithmeticOpTable ops, ValueNode input, int resultBits) { + super(ops.getSignExtend(), ops.getNarrow(), resultBits, input); } - @Override - public Constant convert(Constant c) { - return Constant.forPrimitiveInt(getResultBits(), CodeUtil.signExtend(c.asLong(), getInputBits())); - } - - @Override - public Constant reverse(Constant c) { - return Constant.forPrimitiveInt(getInputBits(), CodeUtil.narrow(c.asLong(), getInputBits())); + protected SignExtendNode(ValueNode input, int resultBits) { + this(ArithmeticOpTable.forStamp(input.stamp()), input, resultBits); } @Override @@ -63,7 +54,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - ValueNode ret = canonicalConvert(forValue); + ValueNode ret = super.canonical(tool, forValue); if (ret != this) { return ret; } @@ -95,11 +86,6 @@ } @Override - public boolean inferStamp() { - return updateStamp(StampTool.signExtend(getValue().stamp(), getResultBits())); - } - - @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { builder.setResult(this, gen.emitSignExtend(builder.operand(getValue()), getInputBits(), getResultBits())); } diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Mon Oct 06 11:51:32 2014 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; @@ -31,7 +30,6 @@ import com.oracle.graal.nodeinfo.*; 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. @@ -43,18 +41,12 @@ return USE_GENERATED_NODES ? new ZeroExtendNodeGen(input, resultBits) : new ZeroExtendNode(input, resultBits); } - protected ZeroExtendNode(ValueNode input, int resultBits) { - super(StampTool.zeroExtend(input.stamp(), resultBits), input, resultBits); + private ZeroExtendNode(ArithmeticOpTable ops, ValueNode input, int resultBits) { + super(ops.getZeroExtend(), ops.getNarrow(), resultBits, input); } - @Override - public Constant convert(Constant c) { - return Constant.forPrimitiveInt(getResultBits(), CodeUtil.zeroExtend(c.asLong(), getInputBits())); - } - - @Override - public Constant reverse(Constant c) { - return Constant.forPrimitiveInt(getInputBits(), CodeUtil.narrow(c.asLong(), getInputBits())); + protected ZeroExtendNode(ValueNode input, int resultBits) { + this(ArithmeticOpTable.forStamp(input.stamp()), input, resultBits); } @Override @@ -63,8 +55,8 @@ } @Override - public boolean preservesOrder(Condition op) { - switch (op) { + public boolean preservesOrder(Condition cond) { + switch (cond) { case GE: case GT: case LE: @@ -77,7 +69,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - ValueNode ret = canonicalConvert(forValue); + ValueNode ret = super.canonical(tool, forValue); if (ret != this) { return ret; } @@ -106,11 +98,6 @@ } @Override - public boolean inferStamp() { - return updateStamp(StampTool.zeroExtend(getValue().stamp(), getResultBits())); - } - - @Override public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { builder.setResult(this, gen.emitZeroExtend(builder.operand(getValue()), getInputBits(), getResultBits())); } diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Oct 06 11:51:32 2014 +0200 @@ -108,7 +108,7 @@ assert indexScaling > 0 && CodeUtil.isPowerOf2(indexScaling); int scale = CodeUtil.log2(indexScaling); return (IntegerStamp) IntegerStamp.OPS.getAdd().foldStamp(StampFactory.forInteger(64, displacement, displacement), - StampTool.signExtend(StampTool.leftShift(index.stamp(), StampFactory.forInteger(64, scale, scale)), 64)); + IntegerStamp.OPS.getSignExtend().foldStamp(64, StampTool.leftShift(index.stamp(), StampFactory.forInteger(64, scale, scale)))); } @Override diff -r da1f5b9ccac6 -r 98e60bdf6d05 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 Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Oct 06 11:51:32 2014 +0200 @@ -136,135 +136,6 @@ 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 = CodeUtil.mask(resultBits); - long downMask = CodeUtil.signExtend(inputStamp.downMask(), inputBits) & defaultMask; - long upMask = CodeUtil.signExtend(inputStamp.upMask(), inputBits) & defaultMask; - - return new IntegerStamp(resultBits, 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 = CodeUtil.zeroExtend(inputStamp.downMask(), inputBits); - long upMask = CodeUtil.zeroExtend(inputStamp.upMask(), inputBits); - - if (inputStamp.lowerBound() < 0 && inputStamp.upperBound() >= 0) { - // signed range including 0 and -1 - // after sign extension, the whole range from 0 to MAX_INT is possible - return IntegerStamp.stampForMask(resultBits, downMask, upMask); - } - - long lowerBound = CodeUtil.zeroExtend(inputStamp.lowerBound(), inputBits); - long upperBound = CodeUtil.zeroExtend(inputStamp.upperBound(), inputBits); - - return new IntegerStamp(resultBits, lowerBound, upperBound, downMask, upMask); - } else { - return input.illegal(); - } - } - - public static Stamp narrowingConversion(Stamp input, int resultBits) { - if (input instanceof IntegerStamp) { - IntegerStamp inputStamp = (IntegerStamp) input; - int inputBits = inputStamp.getBits(); - assert resultBits <= inputBits; - if (resultBits == inputBits) { - return inputStamp; - } - - final long upperBound; - if (inputStamp.lowerBound() < CodeUtil.minValue(resultBits)) { - upperBound = CodeUtil.maxValue(resultBits); - } else { - upperBound = saturate(inputStamp.upperBound(), resultBits); - } - final long lowerBound; - if (inputStamp.upperBound() > CodeUtil.maxValue(resultBits)) { - lowerBound = CodeUtil.minValue(resultBits); - } else { - lowerBound = saturate(inputStamp.lowerBound(), resultBits); - } - - long defaultMask = CodeUtil.mask(resultBits); - long newDownMask = inputStamp.downMask() & defaultMask; - long newUpMask = inputStamp.upMask() & defaultMask; - long newLowerBound = CodeUtil.signExtend((lowerBound | newDownMask) & newUpMask, resultBits); - long newUpperBound = CodeUtil.signExtend((upperBound | newDownMask) & newUpMask, resultBits); - return new IntegerStamp(resultBits, 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; - if (fromStamp.lowerBound() < toKind.getMinValue()) { - upperBound = toKind.getMaxValue(); - } else { - upperBound = saturate(fromStamp.upperBound(), toKind); - } - final long lowerBound; - if (fromStamp.upperBound() > toKind.getMaxValue()) { - lowerBound = toKind.getMinValue(); - } else { - lowerBound = saturate(fromStamp.lowerBound(), toKind); - } - - long defaultMask = CodeUtil.mask(toKind.getBitCount()); - long intMask = CodeUtil.mask(32); - long newUpMask = signExtend(fromStamp.upMask() & defaultMask, toKind) & intMask; - long newDownMask = signExtend(fromStamp.downMask() & defaultMask, toKind) & intMask; - return new IntegerStamp(toKind.getStackKind().getBitCount(), (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask); - } - - 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()); - } else { - return value; - } - } - - private static long saturate(long v, int bits) { - if (bits < 64) { - long max = CodeUtil.maxValue(bits); - if (v > max) { - return max; - } - long min = CodeUtil.minValue(bits); - if (v < min) { - return min; - } - } - return v; - } - - private static long saturate(long v, Kind kind) { - long max = kind.getMaxValue(); - if (v > max) { - return max; - } - long min = kind.getMinValue(); - if (v < min) { - return min; - } - return v; - } - /** * Compute the stamp resulting from the unsigned comparison being true. * diff -r da1f5b9ccac6 -r 98e60bdf6d05 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 Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Mon Oct 06 11:51:32 2014 +0200 @@ -161,7 +161,7 @@ public void lower(FloatConvertNode convert, LoweringTool tool) { SnippetInfo key; - switch (convert.getOp()) { + switch (convert.getFloatConvert()) { case F2I: key = f2i; break; @@ -182,7 +182,7 @@ Arguments args = new Arguments(key, graph.getGuardsStage(), tool.getLoweringStage()); args.add("input", convert.getValue()); - args.add("result", graph.unique(AMD64FloatConvertNode.create(convert.stamp(), convert.getOp(), convert.getValue()))); + args.add("result", graph.unique(AMD64FloatConvertNode.create(convert.getOp(), convert.getValue()))); SnippetTemplate template = template(args); Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getOp(), graph, convert, template, args); diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Mon Oct 06 11:51:32 2014 +0200 @@ -24,8 +24,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -39,19 +39,17 @@ * fixup code that handles the corner cases that differ between AMD64 and Java. */ @NodeInfo -public class AMD64FloatConvertNode extends UnaryNode implements ArithmeticLIRLowerable { +public class AMD64FloatConvertNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable { - protected final FloatConvert op; - - public static AMD64FloatConvertNode create(Stamp stamp, FloatConvert op, ValueNode value) { - return USE_GENERATED_NODES ? new AMD64FloatConvertNodeGen(stamp, op, value) : new AMD64FloatConvertNode(stamp, op, value); + public static AMD64FloatConvertNode create(UnaryOp op, ValueNode value) { + return USE_GENERATED_NODES ? new AMD64FloatConvertNodeGen(op, value) : new AMD64FloatConvertNode(op, value); } - protected AMD64FloatConvertNode(Stamp stamp, FloatConvert op, ValueNode value) { - super(stamp, value); - this.op = op; + protected AMD64FloatConvertNode(UnaryOp op, ValueNode value) { + super(op, value); } + @Override public Constant evalConst(Constant... inputs) { // this node should never have been created if its input is constant throw GraalInternalError.shouldNotReachHere(); @@ -64,6 +62,6 @@ } public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getValue()))); + builder.setResult(this, gen.emitFloatConvert(((FloatConvertOp) getOp()).getFloatConvert(), builder.operand(getValue()))); } } diff -r da1f5b9ccac6 -r 98e60bdf6d05 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Mon Oct 06 10:40:55 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Mon Oct 06 11:51:32 2014 +0200 @@ -534,10 +534,10 @@ switch (kind) { case Boolean: case Byte: - return StampTool.narrowingConversion(stamp, 8); + return IntegerStamp.OPS.getNarrow().foldStamp(8, stamp); case Char: case Short: - return StampTool.narrowingConversion(stamp, 16); + return IntegerStamp.OPS.getNarrow().foldStamp(16, stamp); } return stamp; }