diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bdbbe42e418..d8fdb6dbd37 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-06-27 Diego Novillo + + 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 * tree-optimize.c (exercute_free_datastructures): diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31444a40c9a..1fab590a607 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-06-27 Diego Novillo + + PR 21959 + * gcc.dg/tree-ssa/pr21959.c: New test. + 2005-06-27 Jakub Jelinek * 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 00000000000..7b83b035271 --- /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 83c291d5913..c99aa386be3 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))