re PR tree-optimization/80549 (wrong code at -O2 and -O3 in both 32-bit and 64-bit...
authorRichard Biener <rguenther@suse.de>
Tue, 2 May 2017 11:24:52 +0000 (11:24 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 2 May 2017 11:24:52 +0000 (11:24 +0000)
2017-05-02  Richard Biener  <rguenther@suse.de>

PR tree-optimization/80549
* tree-cfgcleanup.c (mfb_keep_latches): New helper.
(cleanup_tree_cfg_noloop): Create forwarders to known loop
headers if they do not have a preheader.

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

From-SVN: r247486

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr80549.c [new file with mode: 0644]
gcc/tree-cfgcleanup.c

index 4f7c9f7b1dd7b0f0eb51a57c3ecba2ff756f6941..5cbb7e77679ed7c2269f5f63e2cdeeed14920794 100644 (file)
@@ -1,3 +1,10 @@
+2017-05-02  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/80549
+       * tree-cfgcleanup.c (mfb_keep_latches): New helper.
+       (cleanup_tree_cfg_noloop): Create forwarders to known loop
+       headers if they do not have a preheader.
+
 2017-05-02  Martin Liska  <mliska@suse.cz>
 
        PR other/80589
index 3c5269745346786f9e88fd6c007c2d6134cd256a..5c4b7dfdeaf39e318d1130be2a4393eedf222857 100644 (file)
@@ -1,3 +1,8 @@
+2017-05-02  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/80549
+       * gcc.dg/torture/pr80549.c: New testcase.
+
 2017-05-02  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
 
        * gcc.dg/pr78138.c: Use __SIZE_TYPE__ instead of
diff --git a/gcc/testsuite/gcc.dg/torture/pr80549.c b/gcc/testsuite/gcc.dg/torture/pr80549.c
new file mode 100644 (file)
index 0000000..64ace59
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+
+signed char a, b;
+int c;
+short d;
+void fn1(int p1)
+{
+  short e = 4;
+  int f;
+  d = 0;
+  for (; d <= 0; d++)
+    e = 0;
+  if (e)
+    goto L1;
+L2:
+  if (p1) {
+      a = 9;
+      for (; a; ++a) {
+         f = 5;
+         for (; f != 32; ++f)
+           c = 8;
+L1:
+         if (b)
+           goto L2;
+      }
+  }
+}
+
+int main()
+{
+  fn1(1);
+  return 0;
+}
index 7eb71724e92e3406301798f03d047cfc39cb9ee9..94a172fa98e494efeb552c9903e7c456f16e31d4 100644 (file)
@@ -739,6 +739,11 @@ cleanup_tree_cfg_1 (void)
   return retval;
 }
 
+static bool
+mfb_keep_latches (edge e)
+{
+  return ! dominated_by_p (CDI_DOMINATORS, e->src, e->dest);
+}
 
 /* Remove unreachable blocks and other miscellaneous clean up work.
    Return true if the flowgraph was modified, false otherwise.  */
@@ -766,6 +771,64 @@ cleanup_tree_cfg_noloop (void)
       changed = false;
     }
 
+  /* Ensure that we have single entries into loop headers.  Otherwise
+     if one of the entries is becoming a latch due to CFG cleanup
+     (from formerly being part of an irreducible region) then we mess
+     up loop fixup and associate the old loop with a different region
+     which makes niter upper bounds invalid.  See for example PR80549.
+     This needs to be done before we remove trivially dead edges as
+     we need to capture the dominance state before the pending transform.  */
+  if (current_loops)
+    {
+      loop_p loop;
+      unsigned i;
+      FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop)
+       if (loop && loop->header)
+         {
+           basic_block bb = loop->header;
+           edge_iterator ei;
+           edge e;
+           bool found_latch = false;
+           bool any_abnormal = false;
+           unsigned n = 0;
+           /* We are only interested in preserving existing loops, but
+              we need to check whether they are still real and of course
+              if we need to add a preheader at all.  */
+           FOR_EACH_EDGE (e, ei, bb->preds)
+             {
+               if (e->flags & EDGE_ABNORMAL)
+                 {
+                   any_abnormal = true;
+                   break;
+                 }
+               if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
+                 {
+                   found_latch = true;
+                   continue;
+                 }
+               n++;
+             }
+           /* If we have more than one entry to the loop header
+              create a forwarder.  */
+           if (found_latch && ! any_abnormal && n > 1)
+             {
+               edge fallthru = make_forwarder_block (bb, mfb_keep_latches,
+                                                     NULL);
+               loop->header = fallthru->dest;
+               if (! loops_state_satisfies_p (LOOPS_NEED_FIXUP))
+                 {
+                   /* The loop updating from the CFG hook is incomplete
+                      when we have multiple latches, fixup manually.  */
+                   remove_bb_from_loops (fallthru->src);
+                   loop_p cloop = loop;
+                   FOR_EACH_EDGE (e, ei, fallthru->src->preds)
+                     cloop = find_common_loop (cloop, e->src->loop_father);
+                   add_bb_to_loop (fallthru->src, cloop);
+                 }
+             }
+         }
+    }
+
   changed |= cleanup_tree_cfg_1 ();
 
   gcc_assert (dom_info_available_p (CDI_DOMINATORS));