diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/vrp-5.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/vrp-6.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/vrp21.c | 26 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 19 |
6 files changed, 109 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a9b189..db61463 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2005-08-05 James A. Morrison <phython@gcc.gnu.org> + + PR tree-optimization/23128 + * tree-vrp.c (vrp_int_const_binop): Check if unsigned addition or + subtraction wrap, and set TREE_OVERFLOW if they do. + 2005-08-05 Richard Henderson <rth@redhat.com> PR 21728 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d0fb7f3..8b37d46 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,11 @@ 2005-08-05 James A. Morrison <phython@gcc.gnu.org> + * gcc.c-torture/execute/vrp-5.c: New test. + * gcc.c-torture/execute/vrp-6.c: New test. + * gcc.dg/tree-ssa/vrp21.c: New test. + +2005-08-05 James A. Morrison <phython@gcc.gnu.org> + * g++.dg/parse/pr22514.C: New test. 2005-08-05 J"orn Rennecke <joern.rennecke@st.com> diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-5.c b/gcc/testsuite/gcc.c-torture/execute/vrp-5.c new file mode 100644 index 0000000..8f3c725 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/vrp-5.c @@ -0,0 +1,22 @@ +extern void exit (int); +extern void abort (); + +void test(unsigned int a, unsigned int b) +{ + if (a < 5) + abort(); + if (b < 5) + abort(); + if (a + b != 0U) + abort(); +} + +int main(int argc, char *argv[]) +{ + unsigned int x = 0x80000000; + test(x, x); + exit (0); +} + + + diff --git a/gcc/testsuite/gcc.c-torture/execute/vrp-6.c b/gcc/testsuite/gcc.c-torture/execute/vrp-6.c new file mode 100644 index 0000000..7c6a175 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/vrp-6.c @@ -0,0 +1,33 @@ +#include <limits.h> + +extern void exit (int); +extern void abort (); + +void test01(unsigned int a, unsigned int b) +{ + if (a < 5) + abort(); + if (b < 5) + abort(); + if (a - b != 5) + abort(); +} + +void test02(unsigned int a, unsigned int b) +{ + if (a >= 12) + if (b > 15) + if (a - b < UINT_MAX - 15U) + abort (); +} + +int main(int argc, char *argv[]) +{ + unsigned x = 0x80000000; + test01(x + 5, x); + test02(14, 16); + exit (0); +} + + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp21.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp21.c new file mode 100644 index 0000000..3cd817d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp21.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp" } */ + +extern void link_error (); + +void test01(unsigned int a, unsigned int b) +{ + unsigned int x = 0x80000000; + if (a < x) + if (b < x) + if (a > 5) + if (a + b == 0U) + link_error (); +} + +void test02(unsigned int a, unsigned int b) +{ + unsigned int x = 0x80000000; + if (a > x) + if (b < x) + if (a - b == 1U) + link_error (); +} + +/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp" } } */ +/* { dg-final { cleanup-tree-dump "vrp" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 68bcb1e..a77be84 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -915,12 +915,25 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2) on -INF and +INF. */ res = int_const_binop (code, val1, val2, 0); + if (TYPE_UNSIGNED (TREE_TYPE (val1))) + { + int checkz = compare_values (res, val1); + + /* Ensure that res = val1 + val2 >= val1 + or that res = val1 - val2 <= val1. */ + if ((code == PLUS_EXPR && !(checkz == 1 || checkz == 0)) + || (code == MINUS_EXPR && !(checkz == 0 || checkz == -1))) + { + res = copy_node (res); + TREE_OVERFLOW (res) = 1; + } + } /* If the operation overflowed but neither VAL1 nor VAL2 are overflown, return -INF or +INF depending on the operation and the combination of signs of the operands. */ - if (TREE_OVERFLOW (res) - && !TREE_OVERFLOW (val1) - && !TREE_OVERFLOW (val2)) + else if (TREE_OVERFLOW (res) + && !TREE_OVERFLOW (val1) + && !TREE_OVERFLOW (val2)) { int sgn1 = tree_int_cst_sgn (val1); int sgn2 = tree_int_cst_sgn (val2); |