OSDN Git Service

* tree-vrp.c (extract_range_from_assert): Refine the result range
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Jan 2006 16:30:59 +0000 (16:30 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Jan 2006 16:30:59 +0000 (16:30 +0000)
if the variable referenced by the ASSERT_EXPR has a range and
either the tentative result range or the previous range is a
VR_ANTI_RANGE.

* gcc.dg/tree-ssa/vrp25.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109968 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/vrp25.c [new file with mode: 0644]
gcc/tree-vrp.c

index 71eb700..8da8006 100644 (file)
@@ -1,3 +1,10 @@
+2006-01-19  Jeff Law  <law@redhat.com>
+
+       * tree-vrp.c (extract_range_from_assert): Refine the result range
+       if the variable referenced by the ASSERT_EXPR has a range and
+       either the tentative result range or the previous range is a 
+       VR_ANTI_RANGE.
+
 2006-01-19  Richard Sandiford  <richard@codesourcery.com>
 
        * c-decl.c (add_flexible_array_elts_to_size): Simplify vector accesses.
index 4266cb0..ab86c53 100644 (file)
@@ -1,3 +1,7 @@
+2006-01-18  Jeff Law  <law@redhat.com>
+
+       * gcc.dg/tree-ssa/vrp25.c: New test.
+
 2006-01-19  Richard Sandiford  <richard@codesourcery.com>
 
        * gcc.dg/pr25805.c: Fix misapplied patch.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c
new file mode 100644 (file)
index 0000000..52f9ea2
--- /dev/null
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp-details" } */
+
+extern void abort ();
+int tree_code_length[100];
+
+blah (int code1)
+{
+  unsigned char D18670;
+
+  if (code1 != 53) goto L0; else goto L1;
+
+L0:
+  abort ();
+
+L1:
+  D18670 = tree_code_length[53];
+  if (D18670 <= 1) goto L2; else goto L3;
+
+L2:
+  abort ();
+
+L3:
+  if (D18670 == 2) goto L4; else goto L5;
+
+L4:
+  abort ();
+
+L5:
+  arf ();
+  if (code1 != 53) goto L6; else goto L7;
+
+L6:
+  abort ();
+
+L7:
+  if (D18670 <= 2) goto L8; else goto L9;
+
+L8:
+  abort ();
+
+L9:
+  return;
+
+}
+
+/* The second test of (code1 != 53) and the test (D18670 <= 2) are
+   both totally subsumed by earlier tests and thus should be folded
+   away using VRP.  */
+/* { dg-final { scan-tree-dump-times "Folding predicate" 2 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
+
index a5028b4..c4a921c 100644 (file)
@@ -1048,6 +1048,96 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
       if (compare_values (var_vr->min, vr_p->min) == 0
          && compare_values (var_vr->max, vr_p->max) == 0)
        set_value_range_to_varying (vr_p);
+      else
+       {
+         tree min, max, anti_min, anti_max, real_min, real_max;
+
+         /* We want to compute the logical AND of the two ranges;
+            there are three cases to consider.
+
+
+            1. The VR_ANTI_RANGE range is competely within the 
+               VR_RANGE and the endpoints of the ranges are
+               different.  In that case the resulting range
+               should be the VR_ANTI_RANGE.
+
+            2. The VR_ANTI_RANGE is completely disjoint from
+               the VR_RANGE.  In this case the resulting range
+               should be the VR_RANGE.
+
+            3. There is some overlap between the VR_ANTI_RANGE
+               and the VR_RANGE.
+
+               3a. If the high limit of the VR_ANTI_RANGE resides
+                   within the VR_RANGE, then the result is a new
+                   VR_RANGE starting at the high limit of the
+                   the VR_ANTI_RANGE + 1 and extending to the
+                   high limit of the original VR_RANGE.
+
+               3b. If the low limit of the VR_ANTI_RANGE resides
+                   within the VR_RANGE, then the result is a new
+                   VR_RANGE starting at the low limit of the original
+                   VR_RANGE and extending to the low limit of the
+                   VR_ANTI_RANGE - 1.  */
+         if (vr_p->type == VR_ANTI_RANGE)
+           {
+             anti_min = vr_p->min;
+             anti_max = vr_p->max;
+             real_min = var_vr->min;
+             real_max = var_vr->max;
+           }
+         else
+           {
+             anti_min = var_vr->min;
+             anti_max = var_vr->max;
+             real_min = vr_p->min;
+             real_max = vr_p->max;
+           }
+
+
+         /* Case 1, VR_ANTI_RANGE completely within VR_RANGE,
+            not including any endpoints.  */
+         if (compare_values (anti_max, real_max) == -1
+             && compare_values (anti_min, real_min) == 1)
+           {
+             set_value_range (vr_p, VR_ANTI_RANGE, anti_min,
+                              anti_max, vr_p->equiv);
+           }
+         /* Case 2, VR_ANTI_RANGE completely disjoint from
+            VR_RANGE.  */
+         else if (compare_values (anti_min, real_max) == 1
+                  || compare_values (anti_max, real_min) == -1)
+           {
+             set_value_range (vr_p, VR_RANGE, real_min,
+                              real_max, vr_p->equiv);
+           }
+         /* Case 3a, the anti-range extends into the low
+            part of the real range.  Thus creating a new
+            low for the real reange.  */
+         else if ((compare_values (anti_max, real_min) == 1
+                   || compare_values (anti_max, real_min) == 0)
+                  && compare_values (anti_max, real_max) == -1)
+           {
+             min = fold_build2 (PLUS_EXPR, TREE_TYPE (var_vr->min),
+                                anti_max,
+                                build_int_cst (TREE_TYPE (var_vr->min), 1));
+             max = real_max;
+             set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
+           }
+         /* Case 3b, the anti-range extends into the high
+            part of the real range.  Thus creating a new
+            higher for the real reange.  */
+         else if (compare_values (anti_min, real_min) == 1
+                  && (compare_values (anti_min, real_max) == -1
+                      || compare_values (anti_min, real_max) == 0))
+           {
+             max = fold_build2 (MINUS_EXPR, TREE_TYPE (var_vr->min),
+                                anti_min,
+                                build_int_cst (TREE_TYPE (var_vr->min), 1));
+             min = real_min;
+             set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
+           }
+       }
     }
 
   /* Remove names from the equivalence set that have ranges