diff options
author | Xinliang David Li <davidxl@google.com> | 2010-11-09 02:01:06 +0000 |
---|---|---|
committer | Xinliang David Li <davidxl@gcc.gnu.org> | 2010-11-09 02:01:06 +0000 |
commit | b3a50850b16796a6bb2505cabf14571e1e13c656 (patch) | |
tree | 77b19f0611ab2226e65c86445c21d58557e5a8ab /gcc | |
parent | d5214afa121044b22e6c0b5c662f148f26c089d1 (diff) | |
download | gcc-b3a50850b16796a6bb2505cabf14571e1e13c656.zip gcc-b3a50850b16796a6bb2505cabf14571e1e13c656.tar.gz gcc-b3a50850b16796a6bb2505cabf14571e1e13c656.tar.bz2 |
Fix PR/46316
From-SVN: r166469
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/double-int.c | 13 | ||||
-rw-r--r-- | gcc/double-int.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr46316.c | 20 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 13 |
6 files changed, 56 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e4512dd..7e080ea 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2010-11-08 Xinliang David Li <davidxl@google.com> + + PR/46316 + * tree-vrp.c (adjust_range_with_scev): Check double_int + overflow. + * double-int.h (double_int_mul_with_sign): New function. + * double-int.c (double_int_mul_with_sign): New function. + 2010-11-08 Paul Koning <ni1d@arrl.net> * config/pdp11/pdp11.md (lshrsi3, lshrhi3): Fix wrong code. diff --git a/gcc/double-int.c b/gcc/double-int.c index cb63f85..f3501a5 100644 --- a/gcc/double-int.c +++ b/gcc/double-int.c @@ -718,6 +718,19 @@ double_int_mul (double_int a, double_int b) return ret; } +/* Returns A * B. If the operation overflows according to UNSIGNED_P, + *OVERFLOW is set to nonzero. */ + +double_int +double_int_mul_with_sign (double_int a, double_int b, + bool unsigned_p, int *overflow) +{ + double_int ret; + *overflow = mul_double_with_sign (a.low, a.high, b.low, b.high, + &ret.low, &ret.high, unsigned_p); + return ret; +} + /* Returns A + B. */ double_int diff --git a/gcc/double-int.h b/gcc/double-int.h index c2f74e9..6d15551 100644 --- a/gcc/double-int.h +++ b/gcc/double-int.h @@ -132,6 +132,7 @@ double_int_fits_in_uhwi_p (double_int cst) 2 * HOST_BITS_PER_WIDE_INT bits. */ double_int double_int_mul (double_int, double_int); +double_int double_int_mul_with_sign (double_int, double_int, bool, int *); double_int double_int_add (double_int, double_int); double_int double_int_sub (double_int, double_int); double_int double_int_neg (double_int); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4c348ba..e94dcef 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-11-08 Xinliang David Li <davidxl@google.com> + + PR/46316 + * gcc.dg/tree-ssa/pr46316.c: New test. + 2010-11-08 Janus Weil <janus@gcc.gnu.org> PR fortran/46344 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr46316.c b/gcc/testsuite/gcc.dg/tree-ssa/pr46316.c new file mode 100644 index 0000000..9b2e085 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr46316.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort (void); + +long long __attribute__((noinline,noclone)) +foo (long long t) +{ + while (t > -4) + t -= 2; + + return t; +} + +int main(void) +{ + if (foo (0) != -4) + abort (); + return 0; +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 2103e1b..d77cdef 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -3403,13 +3403,18 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, { value_range_t maxvr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }; double_int dtmp; - dtmp = double_int_mul (tree_to_double_int (step), - double_int_sub (loop->nb_iterations_upper_bound, - double_int_one)); + bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (step)); + int overflow = 0; + + dtmp = double_int_mul_with_sign (tree_to_double_int (step), + double_int_sub ( + loop->nb_iterations_upper_bound, + double_int_one), + unsigned_p, &overflow); tem = double_int_to_tree (TREE_TYPE (init), dtmp); /* If the multiplication overflowed we can't do a meaningful adjustment. */ - if (double_int_equal_p (dtmp, tree_to_double_int (tem))) + if (!overflow && double_int_equal_p (dtmp, tree_to_double_int (tem))) { extract_range_from_binary_expr (&maxvr, PLUS_EXPR, TREE_TYPE (init), init, tem); |