# HG changeset patch # User Gilles Duboscq # Date 1383662761 -3600 # Node ID e53aa17b8fdf097c2bd509d281b391db00dfe270 # Parent 524afdbe0612ab7c09a22857b6bd4f4a4438e178 Fix some more problems in StampTool.add and simplify the overflow condition Add more tests to IntegerStampTest and split them into independent methods diff -r 524afdbe0612 -r e53aa17b8fdf 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 Tue Nov 05 15:44:30 2013 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Tue Nov 05 15:46:01 2013 +0100 @@ -167,23 +167,93 @@ @Test public void testNot() { - assertEquals(new IntegerStamp(Kind.Int, -11, -1, 0xfffffff0L, 0xffffffffL), StampTool.not(new IntegerStamp(Kind.Int, 0, 10, 0, 0xf))); + assertEquals(new IntegerStamp(Kind.Int, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(Kind.Int, 0, 10, 0, 0xf))); + } + + @Test + public void testAddIntSimple() { + assertEquals(StampFactory.forInteger(Kind.Int, 0, 30, 0, 31), StampTool.add(StampFactory.forInteger(Kind.Int, 0, 10), StampFactory.forInteger(Kind.Int, 0, 20))); + } + + @Test + public void testAddNegativeOverFlowInt1() { + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xffff_ffffL), + StampTool.add(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, 0), StampFactory.forInteger(Kind.Int, -1, 0))); + } + + @Test + public void testAddNegativeOverFlowInt2() { + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MAX_VALUE - 2, Integer.MAX_VALUE, 0x7fff_fffcL, 0x7fff_ffffL), + StampTool.add(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MIN_VALUE + 1), StampFactory.forInteger(Kind.Int, -3, -2))); + } + + @Test + public void testAddPositiveOverFlowInt1() { + assertEquals(StampFactory.forKind(Kind.Int), StampTool.add(StampFactory.forInteger(Kind.Int, 0, 1), StampFactory.forInteger(Kind.Int, 0, Integer.MAX_VALUE))); + } + + @Test + public void testAddPositiveOverFlowInt2() { + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MIN_VALUE + 2), + StampTool.add(StampFactory.forInteger(Kind.Int, Integer.MAX_VALUE - 1, Integer.MAX_VALUE), StampFactory.forInteger(Kind.Int, 2, 3))); + } + + @Test + public void testAddOverFlowsInt() { + assertEquals(StampFactory.forKind(Kind.Int), StampTool.add(StampFactory.forInteger(Kind.Int, -1, 1), StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE, Integer.MAX_VALUE))); + } + + @Test + public void testAddLongSimple() { + assertEquals(StampFactory.forInteger(Kind.Long, 0, 30, 0, 31), StampTool.add(StampFactory.forInteger(Kind.Long, 0, 10), StampFactory.forInteger(Kind.Long, 0, 20))); } @Test - public void testAdd() { - assertEquals(StampFactory.forInteger(Kind.Int, 0, 30), StampTool.add(StampFactory.forInteger(Kind.Int, 0, 10), StampFactory.forInteger(Kind.Int, 0, 20))); - assertEquals(StampFactory.forKind(Kind.Long), + public void testAddNegativOverFlowLong1() { + assertEquals(StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MAX_VALUE, 0, 0xffff_ffff_ffff_ffffL), 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))); + } + + @Test + public void testAddNegativeOverFlowLong2() { + assertEquals(StampFactory.forInteger(Kind.Long, Long.MAX_VALUE - 2, Long.MAX_VALUE), + StampTool.add(StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE + 1), StampFactory.forInteger(Kind.Long, -3, -2))); + } + + @Test + public void testAddPositiveOverFlowLong1() { + assertEquals(StampFactory.forKind(Kind.Long), StampTool.add(StampFactory.forInteger(Kind.Long, 0, 1), StampFactory.forInteger(Kind.Long, 0, Long.MAX_VALUE))); + } + + @Test + public void testAddPositiveOverFlowLong2() { + assertEquals(StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE + 2), + StampTool.add(StampFactory.forInteger(Kind.Long, Long.MAX_VALUE - 1, Long.MAX_VALUE), StampFactory.forInteger(Kind.Long, 2, 3))); + } - 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))); + @Test + public void testAddOverFlowsLong() { + assertEquals(StampFactory.forKind(Kind.Long), StampTool.add(StampFactory.forInteger(Kind.Long, -1, 1), StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MAX_VALUE))); + } + + @Test + public void testAdd1() { + assertEquals(StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE + 1, 31 + (Integer.MIN_VALUE + 1)), + StampTool.add(StampFactory.forInteger(Kind.Int, 0, 31), StampFactory.forInteger(Kind.Int, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 1))); + } - 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 + public void testAdd2() { + assertEquals(StampFactory.forInteger(Kind.Int, 0x8000_007e, 0x8000_007f, 0x8000_007eL, 0x8000_007fL), + StampTool.add(StampFactory.forInteger(Kind.Int, 0x7fff_fffe, 0x7fff_ffff, 0x7fff_fffeL, 0x7ffff_fffL), StampFactory.forInteger(Kind.Int, 128, 128))); + } + + @Test + public void testAdd3() { + assertEquals(StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MAX_VALUE - 1, 0, 0xffff_ffff_ffff_fffeL), + StampTool.add(StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MAX_VALUE - 1, 0, 0xffff_ffff_ffff_fffeL), + StampFactory.forInteger(Kind.Long, Long.MIN_VALUE, Long.MAX_VALUE - 1, 0, 0xffff_ffff_ffff_fffeL))); + } @Test diff -r 524afdbe0612 -r e53aa17b8fdf 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 Tue Nov 05 15:44:30 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Tue Nov 05 15:46:01 2013 +0100 @@ -135,42 +135,39 @@ } public static IntegerStamp add(IntegerStamp stamp1, IntegerStamp stamp2) { - try { - if (stamp1.isUnrestricted() || stamp2.isUnrestricted()) { - return (IntegerStamp) StampFactory.forKind(stamp1.kind()); - } - Kind kind = stamp1.kind(); - assert stamp1.kind() == stamp2.kind(); - long defaultMask = IntegerStamp.defaultMask(kind); - long variableBits = (stamp1.downMask() ^ stamp1.upMask()) | (stamp2.downMask() ^ stamp2.upMask()); - long variableBitsWithCarry = variableBits | (carryBits(stamp1.downMask(), stamp2.downMask()) ^ carryBits(stamp1.upMask(), stamp2.upMask())); - long newDownMask = (stamp1.downMask() + stamp2.downMask()) & ~variableBitsWithCarry; - long newUpMask = (stamp1.downMask() + stamp2.downMask()) | variableBitsWithCarry; + if (stamp1.isUnrestricted() || stamp2.isUnrestricted()) { + return (IntegerStamp) StampFactory.forKind(stamp1.kind()); + } + Kind kind = stamp1.kind(); + assert stamp1.kind() == stamp2.kind(); + long defaultMask = IntegerStamp.defaultMask(kind); + long variableBits = (stamp1.downMask() ^ stamp1.upMask()) | (stamp2.downMask() ^ stamp2.upMask()); + long variableBitsWithCarry = variableBits | (carryBits(stamp1.downMask(), stamp2.downMask()) ^ carryBits(stamp1.upMask(), stamp2.upMask())); + long newDownMask = (stamp1.downMask() + stamp2.downMask()) & ~variableBitsWithCarry; + long newUpMask = (stamp1.downMask() + stamp2.downMask()) | variableBitsWithCarry; - newDownMask &= defaultMask; - newUpMask &= defaultMask; + newDownMask &= defaultMask; + newUpMask &= defaultMask; - long lowerBound; - long upperBound; - 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 = signExtend(stamp1.lowerBound() + stamp2.lowerBound(), kind); - upperBound = signExtend(stamp1.upperBound() + stamp2.upperBound(), kind); - } - IntegerStamp limit = StampFactory.forInteger(kind, lowerBound, upperBound); - newUpMask &= limit.upMask(); - upperBound = signExtend(upperBound & newUpMask, kind); - lowerBound |= newDownMask; - return new IntegerStamp(kind, lowerBound, upperBound, newDownMask, newUpMask); - } catch (Throwable e) { - throw new RuntimeException(stamp1 + " + " + stamp2, e); + long lowerBound; + long upperBound; + 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) || (!lowerOverflowsPositively && upperOverflowsPositively)) { + lowerBound = kind.getMinValue(); + upperBound = kind.getMaxValue(); + } else { + lowerBound = signExtend((stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask, kind); + upperBound = signExtend((stamp1.upperBound() + stamp2.upperBound()) & defaultMask, kind); } + IntegerStamp limit = StampFactory.forInteger(kind, lowerBound, upperBound); + newUpMask &= limit.upMask(); + upperBound = signExtend(upperBound & newUpMask, kind); + newDownMask |= limit.downMask(); + lowerBound |= newDownMask; + return new IntegerStamp(kind, lowerBound, upperBound, newDownMask, newUpMask); } public static Stamp sub(IntegerStamp stamp1, IntegerStamp stamp2) {