diff options
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 211 |
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: |