Hi!

As discussed in the PR and on IRC, when UNDEFINED meets some vr with
equivalences in it, we need to drop the equivalences, at least when
the equivalenced SSA_NAME definition doesn't dominate the PHI stmt.
The change in vrp_visit_phi_node is needed because otherwise vrp_meet
would drop the equivalences even when it should not.
The extract_range_from_cond_expr change is because when vrp_meet is
called first, we might remove some equivalences even from the original
SSA_NAME's vr.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.7?

2012-05-24  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/53465
        * tree-vrp.c (extract_range_from_cond_expr): First copy_value_range
        vr0 into *vr, then vrp_meet that.
        (vrp_meet): If one vr type is VR_UNDEFINED, ensure the result doesn't
        have any equivalences.
        (vrp_visit_phi_node): Call copy_value_range instead of vrp_meet the
        first time.

        * gcc.c-torture/execute/pr53465.c: New test.

--- gcc/tree-vrp.c.jj   2012-05-17 08:40:45.000000000 +0200
+++ gcc/tree-vrp.c      2012-05-24 10:36:50.433325234 +0200
@@ -3282,8 +3282,8 @@ extract_range_from_cond_expr (value_rang
     set_value_range_to_varying (&vr1);
 
   /* The resulting value range is the union of the operand ranges */
-  vrp_meet (&vr0, &vr1);
   copy_value_range (vr, &vr0);
+  vrp_meet (vr, &vr1);
 }
 
 
@@ -6888,13 +6888,17 @@ vrp_meet (value_range_t *vr0, value_rang
 {
   if (vr0->type == VR_UNDEFINED)
     {
-      copy_value_range (vr0, vr1);
+      /* Drop equivalences.  See PR53465.  */
+      set_value_range (vr0, vr1->type, vr1->min, vr1->max, NULL);
       return;
     }
 
   if (vr1->type == VR_UNDEFINED)
     {
-      /* Nothing to do.  VR0 already has the resulting range.  */
+      /* VR0 already has the resulting range, just drop equivalences.
+        See PR53465.  */
+      if (vr0->equiv)
+       bitmap_clear (vr0->equiv);
       return;
     }
 
@@ -7036,6 +7040,7 @@ vrp_visit_phi_node (gimple phi)
   tree lhs = PHI_RESULT (phi);
   value_range_t *lhs_vr = get_value_range (lhs);
   value_range_t vr_result = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
+  bool first = true;
   int edges, old_edges;
   struct loop *l;
 
@@ -7092,7 +7097,11 @@ vrp_visit_phi_node (gimple phi)
              fprintf (dump_file, "\n");
            }
 
-         vrp_meet (&vr_result, &vr_arg);
+         if (first)
+           copy_value_range (&vr_result, &vr_arg);
+         else
+           vrp_meet (&vr_result, &vr_arg);
+         first = false;
 
          if (vr_result.type == VR_VARYING)
            break;
--- gcc/testsuite/gcc.c-torture/execute/pr53465.c.jj    2012-05-24 
10:34:16.867240005 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr53465.c       2012-05-24 
10:33:28.000000000 +0200
@@ -0,0 +1,30 @@
+/* PR tree-optimization/53465 */
+
+extern void abort ();
+
+static const int a[] = { 1, 2 };
+
+void
+foo (const int *x, int y)
+{
+  int i;
+  int b = 0;
+  int c;
+  for (i = 0; i < y; i++)
+    {
+      int d = x[i];
+      if (d == 0)
+       break;
+      if (b && d <= c)
+       abort ();
+      c = d;
+      b = 1;
+    }
+}
+
+int
+main ()
+{
+  foo (a, 2);
+  return 0;
+}

        Jakub

Reply via email to