diff options
author | Jeff Law <law@redhat.com> | 2005-06-21 12:46:33 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2005-06-21 12:46:33 -0600 |
commit | 2735e93e53bb4cf96a8f245b40bf29fefe946163 (patch) | |
tree | 51811cb1fc3462dd074a020bad55da4671ab8357 /gcc/tree-vrp.c | |
parent | a6b46ba2c84f81e70811e13581c99350cdc76400 (diff) | |
download | gcc-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.c | 29 |
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 |