This fixes PR63800 which shows that PRE eliminate() avail handling
is too simplistic with the code to avoid vectorization regressions.
The following patch makes it properly restore old availability.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2014-11-10  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/63800
        * tree-ssa-pre.c (eliminate_push_avail): Push in a way so
        we can restore the previous availability in after_dom_children.
        (eliminate_dom_walker::after_dom_children): Restore
        previous availability.

        * gcc.dg/torture/pr63800.c: New testcase.

Index: gcc/tree-ssa-pre.c
===================================================================
--- gcc/tree-ssa-pre.c  (revision 216973)
+++ gcc/tree-ssa-pre.c  (working copy)
@@ -3904,8 +3926,11 @@ eliminate_push_avail (tree op)
     {
       if (el_avail.length () <= SSA_NAME_VERSION (valnum))
        el_avail.safe_grow_cleared (SSA_NAME_VERSION (valnum) + 1);
+      tree pushop = op;
+      if (el_avail[SSA_NAME_VERSION (valnum)])
+       pushop = el_avail[SSA_NAME_VERSION (valnum)];
+      el_avail_stack.safe_push (pushop);
       el_avail[SSA_NAME_VERSION (valnum)] = op;
-      el_avail_stack.safe_push (op);
     }
 }
 
@@ -4449,7 +4468,14 @@ eliminate_dom_walker::after_dom_children
 {
   tree entry;
   while ((entry = el_avail_stack.pop ()) != NULL_TREE)
-    el_avail[SSA_NAME_VERSION (VN_INFO (entry)->valnum)] = NULL_TREE;
+    {
+      tree valnum = VN_INFO (entry)->valnum;
+      tree old = el_avail[SSA_NAME_VERSION (valnum)];
+      if (old == entry)
+       el_avail[SSA_NAME_VERSION (valnum)] = NULL_TREE;
+      else
+       el_avail[SSA_NAME_VERSION (valnum)] = entry;
+    }
 }
 
 /* Eliminate fully redundant computations.  */
Index: gcc/testsuite/gcc.dg/torture/pr63800.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr63800.c      (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr63800.c      (working copy)
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+
+int a, b, c, d[2];
+
+int
+fn1 ()
+{
+  int f = 0;
+  d[1] = b = 1; 
+  for (; b; b--)
+    {
+      for (c = 0; c < 2; c++)
+       {
+         d[b] & 1 & b;
+         if (d[0])
+           f = d[b] * a;
+         if (f)
+           return 0;
+       }
+      d[b] && (d[0] = 0);
+    }
+  return 0;
+}

Reply via email to