aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2005-06-21 12:46:33 -0600
committerJeff Law <law@gcc.gnu.org>2005-06-21 12:46:33 -0600
commit2735e93e53bb4cf96a8f245b40bf29fefe946163 (patch)
tree51811cb1fc3462dd074a020bad55da4671ab8357 /gcc/tree-vrp.c
parenta6b46ba2c84f81e70811e13581c99350cdc76400 (diff)
downloadgcc-2735e93e53bb4cf96a8f245b40bf29fefe946163.zip
gcc-2735e93e53bb4cf96a8f245b40bf29fefe946163.tar.gz
gcc-2735e93e53bb4cf96a8f245b40bf29fefe946163.tar.bz2
tree-vrp.c (extract_range_from_unary_expr): Handle type conversions better.
* tree-vrp.c (extract_range_from_unary_expr): Handle type conversions better. * gcc.dg/tree-ssa/vrp15.c: New test. From-SVN: r101232
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 217ecc3..81b0c0a 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -1286,6 +1286,35 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
tree inner_type = TREE_TYPE (op0);
tree outer_type = TREE_TYPE (expr);
+ /* If VR0 represents a simple range, then try to convert
+ the min and max values for the range to the same type
+ as OUTER_TYPE. If the results compare equal to VR0's
+ min and max values and the new min is still less than
+ 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) >= -2)
+ {
+ set_value_range (vr, VR_RANGE, new_min, new_max, vr->equiv);
+ return;
+ }
+ }
+
/* When converting types of different sizes, set the result to
VARYING. Things like sign extensions and precision loss may
change the range. For instance, if x_3 is of type 'long long