After r12-5300-gf98f373dd822b3, phiopt could get the following bb structure:
      |
    middle-bb -----|
      |            |
      |   |----|   |
    phi<1, 2>  |   |
    cond       |   |
      |        |   |
      |--------+---|

Which was considered 2 loops. The inner loop had esimtate of upper_bound to be 
8,
due to the original `for (b = 0; b <= 7; b++)`. The outer loop was already an
infinite one.
So phiopt would come along and change the condition to be unconditionally true
and cleanup cfg would remove the condition and remove the outer loop but not
update the inner one becoming an infinite loop.
I decided it was easier to avoid this inside phiopt rather than figuring out how
to fix up cleanup cfg.

This patch avoids the issue by rejecting edges back to the condition bb before
loop optmiizations have been run.

Bootstrapped and tested on x86_64-linux-gnu.

Note since the testcases depend on the loop being infinite, I used the alarm 
signal trick.

        PR tree-optimization/117243
        PR tree-optimization/116749

gcc/ChangeLog:

        * tree-ssa-phiopt.cc (execute_over_cond_phis): Reject edges back
        to the conditional bb before loop optimizers have been run.

gcc/testsuite/ChangeLog:

        * gcc.dg/torture/pr117243-1.c: New test.
        * gcc.dg/torture/pr117243-2.c: New test.

Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
---
 gcc/testsuite/gcc.dg/torture/pr117243-1.c | 44 ++++++++++++++++++
 gcc/testsuite/gcc.dg/torture/pr117243-2.c | 54 +++++++++++++++++++++++
 gcc/tree-ssa-phiopt.cc                    |  7 +++
 3 files changed, 105 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-2.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr117243-1.c 
b/gcc/testsuite/gcc.dg/torture/pr117243-1.c
new file mode 100644
index 00000000000..46723132553
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr117243-1.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-require-effective-target signal } */
+
+/* PR tree-optimization/117243 */
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+
+void do_exit (int i)
+{
+  exit (0);
+}
+
+/* foo should be an infinite but sometimes it gets optimized incorrectly into
+   an __builtin_unreachable(); which is not valid.  */
+void
+foo (unsigned int a, unsigned char b)
+{
+  lbl:
+  for (b = 0; b <= 7; b++)
+    {
+      unsigned char c[1][1];
+      int i, j;
+      for (i = 0; i < 1; i++)
+        for (j = 0; j < 1; j++)
+          c[i][j] = 1;
+      if (b)
+       goto lbl;
+    }
+}
+
+int
+main ()
+{
+  struct sigaction s;
+  sigemptyset (&s.sa_mask);
+  s.sa_handler = do_exit;
+  s.sa_flags = 0;
+  sigaction (SIGALRM, &s, NULL);
+  alarm (1);
+
+  foo (1, 2);
+}
+
diff --git a/gcc/testsuite/gcc.dg/torture/pr117243-2.c 
b/gcc/testsuite/gcc.dg/torture/pr117243-2.c
new file mode 100644
index 00000000000..5cb864b467d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr117243-2.c
@@ -0,0 +1,54 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fno-tree-ch" } */
+/* { dg-require-effective-target signal } */
+
+/* PR tree-optimization/117243 */
+/* PR tree-optimization/116749 */
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+
+void do_exit (int i)
+{
+  exit (0);
+}
+
+/* main1 should be an infinite but sometimes it gets optimized incorrectly into
+   an __builtin_unreachable(); which is not valid.  */
+int main1 (void)
+{
+    int g=0;
+    int l1[1];
+    int *l2 = &g;
+    int i;
+    for (i=0; i<1; i++)
+        l1[i] = (1);
+    for (g=0; g; ++g)
+    {
+        int *l3[1] = {&l1[0]};
+    }
+    *l2 = *l1;
+b:
+    for (i=0; i<2; ++i)
+    { 
+        if (i)
+            goto b;
+        if (g)
+            continue;
+    }
+    return 0;
+}
+
+int
+main (void)
+{
+  struct sigaction s;
+  sigemptyset (&s.sa_mask);
+  s.sa_handler = do_exit;
+  s.sa_flags = 0;
+  sigaction (SIGALRM, &s, NULL);
+  alarm (1);
+
+  main1 ();
+}
+
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 15651809d71..a2649590d29 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -4178,6 +4178,13 @@ execute_over_cond_phis (func_type func)
       e2 = EDGE_SUCC (bb, 1);
       bb2 = e2->dest;
 
+      /* If loop opts are not done, then don't handle a loop back to itself.
+         The loop estimates sometimes are not updated correctly when changing
+        a loop into an infinite loop.  */
+      if (!(cfun->curr_properties & PROP_loop_opts_done)
+         && (bb1 == bb || bb2 == bb))
+       continue;
+
       /* We cannot do the optimization on abnormal edges.  */
       if ((e1->flags & EDGE_ABNORMAL) != 0
          || (e2->flags & EDGE_ABNORMAL) != 0)
-- 
2.43.0

Reply via email to