When LIM ends up using predicated store motion it can wreck the
IL too much for PHI hoisting to still apply when it should.  The
following avoids messing with existing PHIs (apart from virtuals)
by splitting the edge in the problematical case to have a joiner
before the existing PHI.

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

Richard.

2015-09-15  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/67470
        * tree-ssa-loop-im.c (execute_sm_if_changed): Preserve PHI
        structure for PHI hoisting by inserting a forwarder block
        if appropriate.

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

Index: gcc/tree-ssa-loop-im.c
===================================================================
*** gcc/tree-ssa-loop-im.c      (revision 227779)
--- gcc/tree-ssa-loop-im.c      (working copy)
*************** execute_sm_if_changed (edge ex, tree mem
*** 1839,1844 ****
--- 1900,1922 ----
  
    if (loop_has_only_one_exit)
      ex = split_block_after_labels (ex->dest);
+   else
+     {
+       for (gphi_iterator gpi = gsi_start_phis (ex->dest);
+          !gsi_end_p (gpi); gsi_next (&gpi))
+       {
+         gphi *phi = gpi.phi ();
+         if (virtual_operand_p (gimple_phi_result (phi)))
+           continue;
+ 
+         /* When the destination has a non-virtual PHI node with multiple
+            predecessors make sure we preserve the PHI structure by
+            forcing a forwarder block so that hoisting of that PHI will
+            still work.  */
+         split_edge (ex);
+         break;
+       }
+     }
  
    old_dest = ex->dest;
    new_bb = split_edge (ex);
Index: gcc/testsuite/gcc.dg/torture/pr67470.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr67470.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr67470.c      (working copy)
***************
*** 0 ****
--- 1,30 ----
+ /* { dg-do run } */
+ 
+ int a, b, *c, d, e;
+ 
+ void abort (void);
+ 
+ int
+ main ()
+ {
+   int f, *g, **h = &g;
+   for (; b;)
+     {
+       c = &a;
+       for (e = 0; e < 1; e++)
+       *h = 0;
+       for (; d; d++)
+       if (f)
+         *c = 0;
+       else
+         {
+           *c = e = 0;
+           *h = &a;
+         }
+ 
+       if (a && !g)
+       abort ();
+ 
+     }
+   return 0;
+ }

Reply via email to