The following fixes a missed CFG cleanup opportunity (requiring its
iteration) that ultimatively causes us to create a dead if-converted
loop variant (discovered as dead by CFG cleanup run by ifcvt).

The issue is that when removing unreachable code CFG cleanup does not
schedule predecessors of path exits for revisiting but only the path
exit itself - this leads to a missed BB merging opportunity.  Fixed
by slightly re-organizing the BB merging code.

Bootstrapped / tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2016-08-09  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/71802
        * tree-cfgcleanup.c (cleanup_tree_cfg_bb): Make sure to catch
        all merge opportunities with the predecessor.

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

Index: gcc/tree-cfgcleanup.c
===================================================================
*** gcc/tree-cfgcleanup.c       (revision 239164)
--- gcc/tree-cfgcleanup.c       (working copy)
*************** cleanup_tree_cfg_bb (basic_block bb)
*** 641,664 ****
        && remove_forwarder_block (bb))
      return true;
  
    /* Merging the blocks may create new opportunities for folding
       conditional branches (due to the elimination of single-valued PHI
       nodes).  */
!   if (single_succ_p (bb)
!       && can_merge_blocks_p (bb, single_succ (bb)))
      {
!       /* If there is a merge opportunity with the predecessor
!          do nothing now but wait until we process the predecessor.
!        This happens when we visit BBs in a non-optimal order and
!        avoids quadratic behavior with adjusting stmts BB pointer.  */
!       if (single_pred_p (bb)
!         && can_merge_blocks_p (single_pred (bb), bb))
!       ;
!       else
!       {
!         merge_blocks (bb, single_succ (bb));
!         return true;
!       }
      }
  
    return false;
--- 641,665 ----
        && remove_forwarder_block (bb))
      return true;
  
+   /* If there is a merge opportunity with the predecessor
+      do nothing now but wait until we process the predecessor.
+      This happens when we visit BBs in a non-optimal order and
+      avoids quadratic behavior with adjusting stmts BB pointer.  */
+   if (single_pred_p (bb)
+       && can_merge_blocks_p (single_pred (bb), bb))
+     /* But make sure we _do_ visit it.  When we remove unreachable paths
+        ending in a backedge we fail to mark the destinations predecessors
+        as changed.  */
+     bitmap_set_bit (cfgcleanup_altered_bbs, single_pred (bb)->index);
+ 
    /* Merging the blocks may create new opportunities for folding
       conditional branches (due to the elimination of single-valued PHI
       nodes).  */
!   else if (single_succ_p (bb)
!          && can_merge_blocks_p (bb, single_succ (bb)))
      {
!       merge_blocks (bb, single_succ (bb));
!       return true;
      }
  
    return false;
Index: gcc/testsuite/gcc.dg/torture/pr71802.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr71802.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr71802.c      (working copy)
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do compile } */
+ 
+ int b, c;
+ long d, f;
+ void fn1()
+ {
+   char g;
+   long long h = 0;
+   int *i;
+   if (0) {
+ L2:
+       b && (b = f);
+       d = 3;
+       for (; d;) {
+         char *j = &g;
+         c = *j = 0;
+ L3:
+         *j %= b;
+         for (; g <= 4;)
+           ;
+       }
+       goto L2;
+   }
+   for (; *i; *i = 1) {
+       if ((h -= 4) == (h != (b ?: d))) {
+         g = 3;
+         goto L3;
+       }
+       i = (int *)&h;
+       *i = f;
+       i = (int *)&f;
+       if ((h && 6) - (h = 0))
+       goto L2;
+   }
+   for (; d;)
+     goto L3;
+ }

Reply via email to