# HG changeset patch # User Gilles Duboscq # Date 1382638549 -7200 # Node ID 035474349265ac9b4015468c8407f2e297e307d1 # Parent d1f8d0538b7986aa340b468e65e05448afc3e330 Serveral fixes to StampTool.add and some tests diff -r d1f8d0538b79 -r 035474349265 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 Thu Oct 24 11:44:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Thu Oct 24 20:15:49 2013 +0200 @@ -174,6 +174,13 @@ StampTool.add(StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE + 1), StampFactory.forInteger(Kind.Long, Integer.MIN_VALUE, Integer.MAX_VALUE))); assertEquals(StampFactory.forInteger(Kind.Int, -2147483647, 31 - 2147483647), StampTool.add(StampFactory.forInteger(Kind.Int, 0, 31), StampFactory.forInteger(Kind.Int, -2147483647, -2147483647))); + + assertEquals(StampFactory.forInteger(Kind.Int, 0x8000007e, 0x8000007f, 0x8000007eL, 0x8000007fL), + StampTool.add(StampFactory.forInteger(Kind.Int, 0x7ffffffe, 0x7fffffff, 0x7ffffffeL, 0x7fffffffL), StampFactory.forInteger(Kind.Int, 128, 128))); + + assertEquals(StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL), + StampTool.add(StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL), + StampFactory.forInteger(Kind.Long, -9223372036854775808L, 9223372036854775806L, 0, 0xfffffffffffffffeL))); } @Test diff -r d1f8d0538b79 -r 035474349265 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 Oct 24 11:44:55 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Thu Oct 24 20:15:49 2013 +0200 @@ -114,13 +114,23 @@ return StampFactory.forKind(kind); } - private static boolean addOverflows(long x, long y, Kind kind) { + private static boolean addOverflowsPositively(long x, long y, Kind kind) { long result = x + y; if (kind == Kind.Long) { - return ((x ^ result) & (y ^ result)) < 0; + return (~x & ~y & result) < 0; } else { assert kind == Kind.Int; - return result > Integer.MAX_VALUE || result < Integer.MIN_VALUE; + return result > Integer.MAX_VALUE; + } + } + + private static boolean addOverflowsNegatively(long x, long y, Kind kind) { + long result = x + y; + if (kind == Kind.Long) { + return (x & y & ~result) < 0; + } else { + assert kind == Kind.Int; + return result < Integer.MIN_VALUE; } } @@ -142,16 +152,22 @@ long lowerBound; long upperBound; - if (addOverflows(stamp1.lowerBound(), stamp2.lowerBound(), kind) || addOverflows(stamp1.upperBound(), stamp2.upperBound(), kind)) { + boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), kind); + boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), kind); + boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), kind); + boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), kind); + if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsNegatively && !lowerOverflowsPositively && upperOverflowsPositively)) { lowerBound = kind.getMinValue(); upperBound = kind.getMaxValue(); } else { - lowerBound = stamp1.lowerBound() + stamp2.lowerBound(); - upperBound = stamp1.upperBound() + stamp2.upperBound(); + lowerBound = signExtend(stamp1.lowerBound() + stamp2.lowerBound(), kind); + upperBound = signExtend(stamp1.upperBound() + stamp2.upperBound(), kind); } IntegerStamp limit = StampFactory.forInteger(kind, lowerBound, upperBound); newUpMask &= limit.upMask(); - return new IntegerStamp(kind, lowerBound | newDownMask, signExtend(upperBound & newUpMask, kind), newDownMask, newUpMask); + upperBound = signExtend(upperBound & newUpMask, kind); + lowerBound |= newDownMask; + return new IntegerStamp(kind, lowerBound, upperBound, newDownMask, newUpMask); } catch (Throwable e) { throw new RuntimeException(stamp1 + " + " + stamp2, e); } @@ -239,14 +255,15 @@ long lowerBound; long upperBound; long downMask = value.downMask() >>> shiftCount; + long upMask = value.upMask() >>> shiftCount; if (value.lowerBound() < 0) { lowerBound = downMask; - upperBound = IntegerStamp.defaultMask(kind) >>> shiftCount; + upperBound = upMask; } else { lowerBound = value.lowerBound() >>> shiftCount; upperBound = value.upperBound() >>> shiftCount; } - return new IntegerStamp(kind, lowerBound, upperBound, downMask, value.upMask() >>> shiftCount); + return new IntegerStamp(kind, lowerBound, upperBound, downMask, upMask); } } long mask = IntegerStamp.upMaskFor(kind, value.lowerBound(), value.upperBound()); @@ -310,7 +327,7 @@ } private static long signExtend(long value, Kind valueKind) { - if (valueKind != Kind.Char && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) { + if (valueKind != Kind.Char && valueKind != Kind.Long && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) { return value | (-1L << valueKind.getBitCount()); } else { return value;