diff options
author | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-03-21 21:01:42 +0000 |
---|---|---|
committer | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-03-21 21:01:42 +0000 |
commit | bb22ee7f0477afac4b81a03a285cd5c79d7d9690 (patch) | |
tree | 8da33b4204779d57062fb867c60614ce5f2ad2a4 /gcc/tree-vrp.c | |
parent | 517cabaa23db050f16284d3718f49f25cc881940 (diff) | |
download | ppe42-gcc-bb22ee7f0477afac4b81a03a285cd5c79d7d9690.tar.gz ppe42-gcc-bb22ee7f0477afac4b81a03a285cd5c79d7d9690.zip |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@112256 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 278347d4d9f..d3d57edb55f 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -1641,14 +1641,12 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr) 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)) + /* 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; @@ -1681,20 +1679,36 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr) 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) + if (vr0.type == VR_RANGE + || (vr0.type == VR_VARYING + && TYPE_PRECISION (outer_type) > TYPE_PRECISION (inner_type))) { - tree new_min, new_max; + tree new_min, new_max, orig_min, orig_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); + /* 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 VR0's min/max values. */ + 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, vr0.min) - && tree_int_cst_equal (new_max, vr0.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) { @@ -1717,6 +1731,16 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr) } } + /* 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 |