We can't directly drop to VARYING from UNDEFINED in likely_value as an UNDEFINED value can later become CONSTANT which would make us go up the lattice.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2012-01-05 Richard Guenther <rguent...@suse.de> PR tree-optimization/51760 * tree-ssa-ccp.c (likely_value): Drop UNDEFINED to CONSTANT, not VARYING. (bit_value_unop): Handle UNDEFINED operands. (bit_value_binop): Likewise. * gcc.dg/torture/pr51760.c: New testcase. Index: gcc/tree-ssa-ccp.c =================================================================== --- gcc/tree-ssa-ccp.c (revision 182901) +++ gcc/tree-ssa-ccp.c (working copy) @@ -657,9 +657,10 @@ likely_value (gimple stmt) } } /* If there was an UNDEFINED operand but the result may be not UNDEFINED - fall back to VARYING even if there were CONSTANT operands. */ + fall back to CONSTANT. During iteration UNDEFINED may still drop + to CONSTANT. */ if (has_undefined_operand) - return VARYING; + return CONSTANT; /* We do not consider virtual operands here -- load from read-only memory may have only VARYING virtual operands, but still be @@ -1368,6 +1369,10 @@ bit_value_unop (enum tree_code code, tre prop_value_t rval = get_value_for_expr (rhs, true); double_int value, mask; prop_value_t val; + + if (rval.lattice_val == UNDEFINED) + return rval; + gcc_assert ((rval.lattice_val == CONSTANT && TREE_CODE (rval.value) == INTEGER_CST) || double_int_minus_one_p (rval.mask)); @@ -1399,6 +1404,16 @@ bit_value_binop (enum tree_code code, tr prop_value_t r2val = get_value_for_expr (rhs2, true); double_int value, mask; prop_value_t val; + + if (r1val.lattice_val == UNDEFINED + || r2val.lattice_val == UNDEFINED) + { + val.lattice_val = VARYING; + val.value = NULL_TREE; + val.mask = double_int_minus_one; + return val; + } + gcc_assert ((r1val.lattice_val == CONSTANT && TREE_CODE (r1val.value) == INTEGER_CST) || double_int_minus_one_p (r1val.mask)); Index: gcc/testsuite/gcc.dg/torture/pr51760.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr51760.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr51760.c (revision 0) @@ -0,0 +1,19 @@ +/* { dg-do compile } */ + +extern inline __attribute__ ((always_inline)) void * +memmove (void *dest, const void *src, __SIZE_TYPE__ len) +{ + return __builtin___memmove_chk (dest, src, len, + __builtin_object_size (dest, 0)); +} + +void +foo (void) +{ + char a[64], *b; + for (;;) + { + memmove (a, b, 0); + b = a; + } +}