summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/tree-vrp.c211
2 files changed, 149 insertions, 69 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4d3b63cb7cb..094c25b739e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2012-06-13 Richard Guenther <rguenther@suse.de>
+
+ * tree-vrp.c (vrp_meet): Properly meet equivalent ranges.
+ Handle meeting two VR_RANGE to an VR_ANTI_RANGE. Implement
+ all possible meetings of VR_RANGE with VR_ANTI_RANGE and
+ VR_ANTI_RANGE with VR_ANTI_RANGE.
+
2012-06-13 Richard Earnshaw <rearnsha@arm.com>
* config.gcc (unsupported): Move obsoleted FPA-based configurations
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index c6f1d8e0a0e..65ddb0fda57 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -6914,87 +6914,153 @@ vrp_meet (value_range_t *vr0, value_range_t *vr1)
return;
}
- if (vr0->type == VR_RANGE && vr1->type == VR_RANGE)
+ if (vr0->type == vr1->type
+ && compare_values (vr0->min, vr1->min) == 0
+ && compare_values (vr0->max, vr1->max) == 0)
+ {
+ /* If the value-ranges are identical just insersect
+ their equivalencies. */
+ }
+ else if (vr0->type == VR_RANGE && vr1->type == VR_RANGE)
{
int cmp;
tree min, max;
- /* Compute the convex hull of the ranges. The lower limit of
- the new range is the minimum of the two ranges. If they
+ /* If the two ranges represent an anti-range produce a
+ VR_RANGE with swapped min/max and let the range canonicalization
+ fix things up. */
+ if (vrp_val_is_min (vr0->min) && !is_overflow_infinity (vr0->min)
+ && vrp_val_is_max (vr1->max) && !is_overflow_infinity (vr1->max)
+ && TREE_CODE (vr1->min) == INTEGER_CST
+ && TREE_CODE (vr0->max) == INTEGER_CST
+ && compare_values (vr0->max, vr1->min) == -1)
+ {
+ min = vr1->min;
+ max = vr0->max;
+ }
+ else if (vrp_val_is_min (vr1->min) && !is_overflow_infinity (vr1->min)
+ && vrp_val_is_max (vr0->max) && !is_overflow_infinity (vr0->max)
+ && TREE_CODE (vr1->max) == INTEGER_CST
+ && TREE_CODE (vr0->min) == INTEGER_CST
+ && compare_values (vr1->max, vr0->min) == -1)
+ {
+ max = vr1->max;
+ min = vr0->min;
+ }
+ /* Otherwise compute the convex hull of the ranges. The lower limit of
+ the new range is the minimum of the two ranges. If they
cannot be compared, then give up. */
- cmp = compare_values (vr0->min, vr1->min);
- if (cmp == 0 || cmp == 1)
- min = vr1->min;
- else if (cmp == -1)
- min = vr0->min;
- else
- goto give_up;
-
- /* Similarly, the upper limit of the new range is the maximum
- of the two ranges. If they cannot be compared, then
- give up. */
- cmp = compare_values (vr0->max, vr1->max);
- if (cmp == 0 || cmp == -1)
- max = vr1->max;
- else if (cmp == 1)
- max = vr0->max;
else
- goto give_up;
-
- /* Check for useless ranges. */
- if (INTEGRAL_TYPE_P (TREE_TYPE (min))
- && ((vrp_val_is_min (min) || is_overflow_infinity (min))
- && (vrp_val_is_max (max) || is_overflow_infinity (max))))
- goto give_up;
-
- /* The resulting set of equivalences is the intersection of
- the two sets. */
- if (vr0->equiv && vr1->equiv && vr0->equiv != vr1->equiv)
- bitmap_and_into (vr0->equiv, vr1->equiv);
- else if (vr0->equiv && !vr1->equiv)
- bitmap_clear (vr0->equiv);
-
- set_value_range (vr0, vr0->type, min, max, vr0->equiv);
- }
- else if (vr0->type == VR_ANTI_RANGE && vr1->type == VR_ANTI_RANGE)
- {
- /* Two anti-ranges meet only if their complements intersect.
- Only handle the case of identical ranges. */
- if (compare_values (vr0->min, vr1->min) == 0
- && compare_values (vr0->max, vr1->max) == 0
- && compare_values (vr0->min, vr0->max) == 0)
{
- /* The resulting set of equivalences is the intersection of
- the two sets. */
- if (vr0->equiv && vr1->equiv && vr0->equiv != vr1->equiv)
- bitmap_and_into (vr0->equiv, vr1->equiv);
- else if (vr0->equiv && !vr1->equiv)
- bitmap_clear (vr0->equiv);
+ cmp = compare_values (vr0->min, vr1->min);
+ if (cmp == 0 || cmp == 1)
+ min = vr1->min;
+ else if (cmp == -1)
+ min = vr0->min;
+ else
+ goto give_up;
+
+ /* Similarly, the upper limit of the new range is the maximum
+ of the two ranges. If they cannot be compared, then
+ give up. */
+ cmp = compare_values (vr0->max, vr1->max);
+ if (cmp == 0 || cmp == -1)
+ max = vr1->max;
+ else if (cmp == 1)
+ max = vr0->max;
+ else
+ goto give_up;
+
+ /* Check for useless ranges. */
+ if (INTEGRAL_TYPE_P (TREE_TYPE (min))
+ && ((vrp_val_is_min (min) || is_overflow_infinity (min))
+ && (vrp_val_is_max (max) || is_overflow_infinity (max))))
+ goto give_up;
}
- else
- goto give_up;
+
+ set_and_canonicalize_value_range (vr0, vr0->type, min, max, vr0->equiv);
}
else if (vr0->type == VR_ANTI_RANGE || vr1->type == VR_ANTI_RANGE)
{
- /* For a numeric range [VAL1, VAL2] and an anti-range ~[VAL3, VAL4],
- only handle the case where the ranges have an empty intersection.
- The result of the meet operation is the anti-range. */
- if (!symbolic_range_p (vr0)
- && !symbolic_range_p (vr1)
- && !value_ranges_intersect_p (vr0, vr1))
- {
- /* Copy most of VR1 into VR0. Don't copy VR1's equivalence
- set. We need to compute the intersection of the two
- equivalence sets. */
- if (vr1->type == VR_ANTI_RANGE)
- set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr0->equiv);
+ if (symbolic_range_p (vr0)
+ || symbolic_range_p (vr1))
+ goto give_up;
- /* The resulting set of equivalences is the intersection of
- the two sets. */
- if (vr0->equiv && vr1->equiv && vr0->equiv != vr1->equiv)
- bitmap_and_into (vr0->equiv, vr1->equiv);
- else if (vr0->equiv && !vr1->equiv)
- bitmap_clear (vr0->equiv);
+ /* [] is vr0, () is vr1 in the following classification comments. */
+ if (operand_less_p (vr0->max, vr1->min) == 1
+ || operand_less_p (vr1->max, vr0->min) == 1)
+ {
+ /* [ ] ( ) or ( ) [ ]
+ If the ranges have an empty intersection, result of the meet
+ operation is the anti-range or if both are anti-ranges
+ it covers all. */
+ if (vr0->type == VR_ANTI_RANGE
+ && vr1->type == VR_ANTI_RANGE)
+ goto give_up;
+ else if (vr1->type == VR_ANTI_RANGE)
+ set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr0->equiv);
+ }
+ else if (operand_less_p (vr1->max, vr0->max) == 1
+ && operand_less_p (vr0->min, vr1->min) == 1)
+ {
+ /* [ ( ) ]
+ Arbitrarily choose the left or inner gap. */
+ if (vr0->type == VR_ANTI_RANGE
+ && vr1->type == VR_ANTI_RANGE)
+ set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr0->equiv);
+ else if (vr0->type == VR_ANTI_RANGE)
+ set_and_canonicalize_value_range (vr0, vr0->type, vr0->min,
+ int_const_binop (MINUS_EXPR, vr1->min, integer_one_node),
+ vr0->equiv);
+ else
+ goto give_up;
+ }
+ else if (operand_less_p (vr0->max, vr1->max) == 1
+ && operand_less_p (vr1->min, vr0->min) == 1)
+ {
+ /* ( [ ] )
+ Arbitrarily choose the left or inner gap. */
+ if (vr0->type == VR_ANTI_RANGE
+ && vr1->type == VR_ANTI_RANGE)
+ /* Nothing to do. */;
+ else if (vr1->type == VR_ANTI_RANGE)
+ set_and_canonicalize_value_range (vr0, vr1->type, vr1->min,
+ int_const_binop (MINUS_EXPR, vr0->min, integer_one_node),
+ vr0->equiv);
+ else
+ goto give_up;
+ }
+ else if (operand_less_p (vr1->min, vr0->max) == 1
+ && operand_less_p (vr0->max, vr1->max) == 1)
+ {
+ /* [ ( ] ) */
+ if (vr0->type == VR_ANTI_RANGE
+ && vr1->type == VR_ANTI_RANGE)
+ set_value_range (vr0, vr0->type, vr1->min, vr0->max, vr0->equiv);
+ else if (vr0->type == VR_ANTI_RANGE)
+ set_and_canonicalize_value_range (vr0, vr0->type, vr0->min,
+ int_const_binop (MINUS_EXPR, vr1->min, integer_one_node),
+ vr0->equiv);
+ else
+ set_and_canonicalize_value_range (vr0, vr1->type,
+ int_const_binop (PLUS_EXPR, vr0->max, integer_one_node),
+ vr1->max, vr0->equiv);
+ }
+ else if (operand_less_p (vr0->min, vr1->max) == 1
+ && operand_less_p (vr1->max, vr0->max) == 1)
+ {
+ /* ( [ ) ] */
+ if (vr0->type == VR_ANTI_RANGE
+ && vr1->type == VR_ANTI_RANGE)
+ set_value_range (vr0, vr1->type, vr0->min, vr1->max, vr0->equiv);
+ else if (vr0->type == VR_ANTI_RANGE)
+ set_and_canonicalize_value_range (vr0, vr0->type,
+ int_const_binop (PLUS_EXPR, vr1->max, integer_one_node),
+ vr0->max, vr0->equiv);
+ else
+ set_and_canonicalize_value_range (vr0, vr1->type, vr1->min,
+ int_const_binop (MINUS_EXPR, vr0->min, integer_one_node),
+ vr0->equiv);
}
else
goto give_up;
@@ -7002,6 +7068,13 @@ vrp_meet (value_range_t *vr0, value_range_t *vr1)
else
gcc_unreachable ();
+ /* The resulting set of equivalences is always the intersection of
+ the two sets. Above we always left the equivalency set of vr0 as-is. */
+ if (vr0->equiv && vr1->equiv && vr0->equiv != vr1->equiv)
+ bitmap_and_into (vr0->equiv, vr1->equiv);
+ else if (vr0->equiv && !vr1->equiv)
+ bitmap_clear (vr0->equiv);
+
return;
give_up: