tree-vrp.c (vrp_meet): Properly meet equivalent ranges.
authorRichard Guenther <rguenther@suse.de>
Wed, 13 Jun 2012 15:12:02 +0000 (15:12 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 13 Jun 2012 15:12:02 +0000 (15:12 +0000)
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.

From-SVN: r188517

gcc/ChangeLog
gcc/tree-vrp.c

index 4d3b63cb7cbbe1d9f91f53e103fc74230048c4ea..094c25b739ec30848f445074ab82a1b1cbc54351 100644 (file)
@@ -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
index c6f1d8e0a0ec83d82bb02bf4c6a00d0977e0b482..65ddb0fda577d0f24627a2333301f21c70bd7769 100644 (file)
@@ -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: