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" } } */
+
+