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/tree-ssa-loop-niter.c | |
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/tree-ssa-loop-niter.c')
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 35 |
1 files changed, 35 insertions, 0 deletions
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)) |