diff options
author | Diego Novillo <dnovillo@redhat.com> | 2005-06-28 00:52:35 +0000 |
---|---|---|
committer | Diego Novillo <dnovillo@gcc.gnu.org> | 2005-06-27 20:52:35 -0400 |
commit | 3eca1bd776507834a9092ee8c871e91e78ef59b8 (patch) | |
tree | 6ac1b1fa0c3b8ade5a237d12fe531f37f0172b03 /gcc | |
parent | 5ab2b3e44e3a264663c716a85cd8d7566043ac7c (diff) | |
download | gcc-3eca1bd776507834a9092ee8c871e91e78ef59b8.zip gcc-3eca1bd776507834a9092ee8c871e91e78ef59b8.tar.gz gcc-3eca1bd776507834a9092ee8c871e91e78ef59b8.tar.bz2 |
re PR tree-optimization/21959 (vrp miscompiles Ada front-end, drops loop exit test in well-defined wrap-around circumstances)
PR 21959
* tree-ssa-loop-niter.c (scev_probably_wraps_p): Handle type
casts between unsigned and signed types with different size
or precision.
testsuite/ChangeLog
PR 21959
* gcc.dg/tree-ssa/pr21959.c: New test.
From-SVN: r101365
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr21959.c | 20 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 35 |
4 files changed, 67 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bdbbe42..d8fdb6d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-06-27 Diego Novillo <dnovillo@redhat.com> + + PR 21959 + * tree-ssa-loop-niter.c (scev_probably_wraps_p): Handle type + casts between unsigned and signed types with different size + or precision. + 2005-06-28 Jan Hubicka <jh@suse.cz> * tree-optimize.c (exercute_free_datastructures): diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31444a4..1fab590 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-06-27 Diego Novillo <dnovillo@redhat.com> + + PR 21959 + * gcc.dg/tree-ssa/pr21959.c: New test. + 2005-06-27 Jakub Jelinek <jakub@redhat.com> * gcc.c-torture/execute/builtins/lib/main.c (abort): Add prototype. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21959.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21959.c new file mode 100644 index 0000000..7b83b03 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21959.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp" } */ + +unsigned char c[0xFF]; +void f(void) +{ + unsigned char i; + c[128] = 128; + i = 0; + while (1) + { + /* This predicate should not be folded out. */ + if (((signed char) i) < 0) break; + c[i] = ' '; + i++; + } +} + +/* { dg-final { scan-tree-dump-times "Folding predicate " 0 "vrp" } } */ +/* { dg-final { cleanup-tree-dump "vrp" } } */ diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 83c291d..c99aa38 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -1649,6 +1649,41 @@ scev_probably_wraps_p (tree type, tree base, tree step, return true; } + /* If AT_STMT represents a cast operation, we may not be able to + take advantage of the undefinedness of signed type evolutions. + See PR 21959 for a test case. Essentially, given a cast + operation + unsigned char i; + signed char i.0; + ... + i.0_6 = (signed char) i_2; + if (i.0_6 < 0) + ... + + where i_2 and i.0_6 have the scev {0, +, 1}, we would consider + i_2 to wrap around, but not i.0_6, because it is of a signed + type. This causes VRP to erroneously fold the predicate above + because it thinks that i.0_6 cannot be negative. */ + if (TREE_CODE (at_stmt) == MODIFY_EXPR) + { + tree rhs = TREE_OPERAND (at_stmt, 1); + tree outer_t = TREE_TYPE (rhs); + + if (!TYPE_UNSIGNED (outer_t) + && (TREE_CODE (rhs) == NOP_EXPR || TREE_CODE (rhs) == CONVERT_EXPR)) + { + tree inner_t = TREE_TYPE (TREE_OPERAND (rhs, 0)); + + /* If the inner type is unsigned and its size and/or + precision are smaller to that of the outer type, then the + expression may wrap around. */ + if (TYPE_UNSIGNED (inner_t) + && (TYPE_SIZE (inner_t) <= TYPE_SIZE (outer_t) + || TYPE_PRECISION (inner_t) <= TYPE_PRECISION (outer_t))) + return true; + } + } + /* After having set INIT_IS_MAX, we can return false: when not using wrapping arithmetic, signed types don't wrap. */ if (!flag_wrapv && !TYPE_UNSIGNED (type)) |