From b17775aba4c709c1fc3f19af33d50b025e3891f4 Mon Sep 17 00:00:00 2001 From: "James A. Morrison" Date: Sat, 6 Aug 2005 05:35:31 +0000 Subject: [PATCH] re PR tree-optimization/23128 (VRP fails for unsigned values) 2005-08-05 James A. Morrison 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. From-SVN: r102800 --- gcc/ChangeLog | 6 ++++ gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/gcc.c-torture/execute/vrp-5.c | 22 ++++++++++++++ gcc/testsuite/gcc.c-torture/execute/vrp-6.c | 33 +++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/vrp21.c | 26 ++++++++++++++++ gcc/tree-vrp.c | 19 ++++++++++-- 6 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/vrp-5.c create mode 100644 gcc/testsuite/gcc.c-torture/execute/vrp-6.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp21.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a9b189c9de..db61463c1d2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2005-08-05 James A. Morrison + + 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 PR 21728 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d0fb7f368bb..8b37d466490 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2005-08-05 James A. Morrison + + * 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 * g++.dg/parse/pr22514.C: New test. 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 00000000000..8f3c7255a02 --- /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 00000000000..7c6a1750f7d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/vrp-6.c @@ -0,0 +1,33 @@ +#include + +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 00000000000..3cd817d71e2 --- /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 68bcb1e6a8f..a77be8479cd 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); -- 2.30.2