This removes one weakness in BIT_IOR_EXPR handling which gives up even if we can compute a fully negative range. The following thus extends zero_nonzero_bits_from_vr to extract sign-bit information (I believe that's the only bit we know sth about when both vr.min and vr.max are negative). It also adjusts BIT_IOR_EXPR handling to not give up for the min < max < 0 case.
Boostrapped on x86_64-unknown-linux-gnu, testing in progress. I guess BIT_AND_EXPR handling will show a similar weakness but a similar testcase (as added below) already passes. So I suppose we have to obfuscate it a bit more ;) Richard. 2011-08-05 Richard Guenther <rguent...@suse.de> * tree-vrp.c (zero_nonzero_bits_from_vr): Pass in a type. For ranges with negative values return information about the sign-bit. (extract_range_from_binary_expr_1): Adjust BIT_IOR_EXPR handling to handle sign-bit information for ranges with negative values. (simplify_bit_ops_using_ranges): Adjust. * gcc.dg/tree-ssa/vrp60.c: New testcase. Index: gcc/tree-vrp.c =================================================================== *** gcc/tree-vrp.c (revision 177425) --- gcc/tree-vrp.c (working copy) *************** vrp_int_const_binop (enum tree_code code *** 2138,2144 **** the bit is 1, otherwise it might be 0 or 1. */ static bool ! zero_nonzero_bits_from_vr (value_range_t *vr, double_int *may_be_nonzero, double_int *must_be_nonzero) { may_be_nonzero->low = ALL_ONES; --- 2138,2145 ---- the bit is 1, otherwise it might be 0 or 1. */ static bool ! zero_nonzero_bits_from_vr (value_range_t *vr, tree type, ! double_int *may_be_nonzero, double_int *must_be_nonzero) { may_be_nonzero->low = ALL_ONES; *************** zero_nonzero_bits_from_vr (value_range_t *** 2178,2183 **** --- 2179,2192 ---- must_be_nonzero->low &= ~mask; } } + else if (tree_int_cst_sgn (vr->max) < 0) + { + /* The only thing we know when the range covers only negative + values is that the sign bit must be set. */ + *may_be_nonzero = double_int_minus_one; + *must_be_nonzero + = double_int_setbit (double_int_zero, TYPE_PRECISION (type) - 1); + } return true; } return false; *************** extract_range_from_binary_expr_1 (value_ *** 2642,2650 **** double_int may_be_nonzero0, may_be_nonzero1; double_int must_be_nonzero0, must_be_nonzero1; ! int_cst_range0 = zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0, &must_be_nonzero0); ! int_cst_range1 = zero_nonzero_bits_from_vr (&vr1, &may_be_nonzero1, &must_be_nonzero1); type = VR_RANGE; --- 2651,2661 ---- double_int may_be_nonzero0, may_be_nonzero1; double_int must_be_nonzero0, must_be_nonzero1; ! int_cst_range0 = zero_nonzero_bits_from_vr (&vr0, expr_type, ! &may_be_nonzero0, &must_be_nonzero0); ! int_cst_range1 = zero_nonzero_bits_from_vr (&vr1, expr_type, ! &may_be_nonzero1, &must_be_nonzero1); type = VR_RANGE; *************** extract_range_from_binary_expr_1 (value_ *** 2683,2699 **** max = double_int_to_tree (expr_type, double_int_ior (may_be_nonzero0, may_be_nonzero1)); - if (tree_int_cst_sgn (max) < 0) - max = NULL_TREE; if (int_cst_range0) ! { ! if (tree_int_cst_sgn (min) < 0) ! min = vr0.min; ! else ! min = vrp_int_const_binop (MAX_EXPR, min, vr0.min); ! } if (int_cst_range1) min = vrp_int_const_binop (MAX_EXPR, min, vr1.min); } else if (code == BIT_XOR_EXPR) { --- 2694,2709 ---- max = double_int_to_tree (expr_type, double_int_ior (may_be_nonzero0, may_be_nonzero1)); if (int_cst_range0) ! min = vrp_int_const_binop (MAX_EXPR, min, vr0.min); if (int_cst_range1) min = vrp_int_const_binop (MAX_EXPR, min, vr1.min); + if (tree_int_cst_sgn (min) < 0) + ; + else if (tree_int_cst_sgn (max) >= 0) + ; + else + min = max = NULL_TREE; } else if (code == BIT_XOR_EXPR) { *************** simplify_bit_ops_using_ranges (gimple_st *** 6984,6992 **** else return false; ! if (!zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0, &must_be_nonzero0)) return false; ! if (!zero_nonzero_bits_from_vr (&vr1, &may_be_nonzero1, &must_be_nonzero1)) return false; switch (gimple_assign_rhs_code (stmt)) --- 6994,7004 ---- else return false; ! if (!zero_nonzero_bits_from_vr (&vr0, TREE_TYPE (op0), ! &may_be_nonzero0, &must_be_nonzero0)) return false; ! if (!zero_nonzero_bits_from_vr (&vr1, TREE_TYPE (op1), ! &may_be_nonzero1, &must_be_nonzero1)) return false; switch (gimple_assign_rhs_code (stmt)) Index: gcc/testsuite/gcc.dg/tree-ssa/vrp60.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/vrp60.c (revision 0) --- gcc/testsuite/gcc.dg/tree-ssa/vrp60.c (revision 0) *************** *** 0 **** --- 1,31 ---- + /* { dg-do compile } */ + /* { dg-options "-O2 -fno-tree-ccp -fno-tree-dominator-opts -fdump-tree-vrp1" } */ + + int foo (int x, int b) + { + int cst; + if (b) + cst = -__INT_MAX__ - 1; + else + cst = -__INT_MAX__; + x = x | cst; + if (x >= 0) + return 12345; + return x; + } + + int bar (int x, int b) + { + int cst; + if (b) + cst = __INT_MAX__; + else + cst = __INT_MAX__ - 1; + x = x & cst; + if (x < 0) + return 12345; + return x; + } + + /* { dg-final { scan-tree-dump-not "12345" "vrp1" } } */ + /* { dg-final { cleanup-tree-dump "vrp1" } } */