On Tue, 2006-03-21 at 10:14 +0100, Duncan Sands wrote: > Hi Jeff, on the subject of seeing through typecasts, I was playing around > with VRP and noticed that the following "if" statement is not eliminated: > > int u (unsigned char c) { > int i = c; > > if (i < 0 || i > 255) > return -1; /* never taken */ > else > return 0; > } > > Is it supposed to be? Fixed thusly. Bootstrapped and regression tested on i686-pc-linux-gnu.
* tree-vrp.c (extract_range_from_unary_expr): Derive ranges for type conversions of a VR_VARYING source to a wider type. * gcc.dg/tree-ssa/vrp28.c: New test. Index: tree-vrp.c =================================================================== *** tree-vrp.c (revision 112250) --- tree-vrp.c (working copy) *************** extract_range_from_unary_expr (value_ran *** 1641,1654 **** return; } ! /* Refuse to operate on varying and symbolic ranges. Also, if the ! operand is neither a pointer nor an integral type, set the ! resulting range to VARYING. TODO, in some cases we may be able ! to derive anti-ranges (like nonzero values). */ ! if (vr0.type == VR_VARYING ! || (!INTEGRAL_TYPE_P (TREE_TYPE (op0)) ! && !POINTER_TYPE_P (TREE_TYPE (op0))) ! || symbolic_range_p (&vr0)) { set_value_range_to_varying (vr); return; --- 1641,1652 ---- return; } ! /* Refuse to operate on symbolic ranges, or if neither operand is ! a pointer or integral type. */ ! if ((!INTEGRAL_TYPE_P (TREE_TYPE (op0)) ! && !POINTER_TYPE_P (TREE_TYPE (op0))) ! || (vr0.type != VR_VARYING ! && symbolic_range_p (&vr0))) { set_value_range_to_varying (vr); return; *************** extract_range_from_unary_expr (value_ran *** 1681,1700 **** or equal to the new max, then we can safely use the newly computed range for EXPR. This allows us to compute accurate ranges through many casts. */ ! if (vr0.type == VR_RANGE) ! { ! tree new_min, new_max; ! /* Convert VR0's min/max to OUTER_TYPE. */ ! new_min = fold_convert (outer_type, vr0.min); ! new_max = fold_convert (outer_type, vr0.max); /* Verify the new min/max values are gimple values and ! that they compare equal to VR0's min/max values. */ if (is_gimple_val (new_min) && is_gimple_val (new_max) ! && tree_int_cst_equal (new_min, vr0.min) ! && tree_int_cst_equal (new_max, vr0.max) && compare_values (new_min, new_max) <= 0 && compare_values (new_min, new_max) >= -1) { --- 1679,1714 ---- or equal to the new max, then we can safely use the newly computed range for EXPR. This allows us to compute accurate ranges through many casts. */ ! if (vr0.type == VR_RANGE ! || (vr0.type == VR_VARYING ! && TYPE_PRECISION (outer_type) > TYPE_PRECISION (inner_type))) ! { ! tree new_min, new_max, orig_min, orig_max; ! ! /* Convert the input operand min/max to OUTER_TYPE. If ! the input has no range information, then use the min/max ! for the input's type. */ ! if (vr0.type == VR_RANGE) ! { ! orig_min = vr0.min; ! orig_max = vr0.max; ! } ! else ! { ! orig_min = TYPE_MIN_VALUE (inner_type); ! orig_max = TYPE_MAX_VALUE (inner_type); ! } ! new_min = fold_convert (outer_type, orig_min); ! new_max = fold_convert (outer_type, orig_max); /* Verify the new min/max values are gimple values and ! that they compare equal to the orignal input's ! min/max values. */ if (is_gimple_val (new_min) && is_gimple_val (new_max) ! && tree_int_cst_equal (new_min, orig_min) ! && tree_int_cst_equal (new_max, orig_max) && compare_values (new_min, new_max) <= 0 && compare_values (new_min, new_max) >= -1) { *************** extract_range_from_unary_expr (value_ran *** 1717,1722 **** --- 1731,1746 ---- } } + /* Conversion of a VR_VARYING value to a wider type can result + in a usable range. So wait until after we've handled conversions + before dropping the result to VR_VARYING if we had a source + operand that is VR_VARYING. */ + if (vr0.type == VR_VARYING) + { + set_value_range_to_varying (vr); + return; + } + /* Apply the operation to each end of the range and see what we end up with. */ if (code == NEGATE_EXPR Index: testsuite/gcc.dg/tree-ssa/vrp28.c =================================================================== *** testsuite/gcc.dg/tree-ssa/vrp28.c (revision 0) --- testsuite/gcc.dg/tree-ssa/vrp28.c (revision 0) *************** *** 0 **** --- 1,32 ---- + /* { dg-do compile } */ + /* { dg-options "-O2 -fdump-tree-vrp1" } */ + + int f(_Bool a) + { + int t = a; + if (t != 2) + return 0; + return 1; + } + + int f1(unsigned char a) + { + int t = a; + if (t != 256) + return 0; + return 1; + } + + int f3 (unsigned char c) + { + int i = c; + if (i < 0 || i > 255) + return -1; + else + return 0; + } + + /* { dg-final { scan-tree-dump-times "if " 0 "vrp1" } } * / + /* { dg-final { cleanup-tree-dump "vrp1" } } */ + +