The following fixes a long-standing bug in tree if-conversion.
The transform phase relies on being able to extract edge predicates
by simply using the predicate under which its source block is
executed.  That obviously isn't the correct one if the source
block ends in a condition itself.  Thus the following patch
verifies that each predecessor edge of blocks we will if-convert
is non-critical.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2013-06-24  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/57521
        * tree-if-conv.c (if_convertible_bb_p): Verify that all edges
        are non-critical.
        (pass_if_conversion): Add TODO_verify_ssa.

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

Index: gcc/tree-if-conv.c
===================================================================
*** gcc/tree-if-conv.c  (revision 200367)
--- gcc/tree-if-conv.c  (working copy)
*************** if_convertible_bb_p (struct loop *loop,
*** 873,878 ****
--- 873,886 ----
        && !bb_postdominates_preds (bb))
      return false;
  
+   /* All incoming edges have to be non-critical as otherwise edge
+      predicates are not equal to basic-block predicates of the edge
+      source.  */
+   if (EDGE_COUNT (bb->preds) > 1)
+     FOR_EACH_EDGE (e, ei, bb->preds)
+       if (EDGE_COUNT (e->src->succs) > 1)
+       return false;
+ 
    return true;
  }
  
*************** struct gimple_opt_pass pass_if_conversio
*** 1870,1875 ****
    0,                                  /* properties_destroyed */
    0,                                  /* todo_flags_start */
    TODO_verify_stmts | TODO_verify_flow
!                                         /* todo_flags_finish */
   }
  };
--- 1878,1883 ----
    0,                                  /* properties_destroyed */
    0,                                  /* todo_flags_start */
    TODO_verify_stmts | TODO_verify_flow
!     | TODO_verify_ssa                 /* todo_flags_finish */
   }
  };
Index: gcc/testsuite/gcc.dg/torture/pr57521.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr57521.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr57521.c      (working copy)
***************
*** 0 ****
--- 1,51 ----
+ /* { dg-do run } */
+ /* { dg-options "-ftree-loop-if-convert" } */
+ 
+ void abort (void);
+ 
+ int a, b, c, d, o = 1, p;
+ short e;
+ 
+ int
+ fn1 (int * p1)
+ {
+   int f, g, h, j = 0, k = 0, l = 0;
+   unsigned int i;
+   int *m[1] = { &l };
+   for (; b >= 0; b--)
+     {
+       if (*p1)
+       if (j >= 0)
+         {
+           int n = 1;
+           e = 1;
+           h = a ? a : 1 % n;
+           g = h > 0 ? 0 : h + 1;
+           k = c + g;
+         }
+       else
+         continue;
+       else
+       {
+ 
+         f = d > 0 ? 0 : d + 1;
+         i = f;
+         j = 1 + i;
+       }
+       l++;
+     }
+   return k;
+ }
+ 
+ int
+ main ()
+ {
+   for (;; p++)
+     {
+       fn1 (&o);
+       break;
+     }
+   if (e != 1)
+     abort ();
+   return 0;
+ }

Reply via email to