summaryrefslogtreecommitdiffstats
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2006-03-21 21:01:42 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2006-03-21 21:01:42 +0000
commitbb22ee7f0477afac4b81a03a285cd5c79d7d9690 (patch)
tree8da33b4204779d57062fb867c60614ce5f2ad2a4 /gcc/tree-vrp.c
parent517cabaa23db050f16284d3718f49f25cc881940 (diff)
downloadppe42-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.c56
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
OpenPOWER on IntegriCloud