This fixes sinking of loads when irreducible regions are involved
and the heuristics to find stores on the path along the sink
breaks down since that uses dominator queries.

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

2020-12-08  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/97559
        * tree-ssa-sink.c (statement_sink_location): Never ignore
        PHIs on sink paths in irreducible regions.

        * gcc.dg/torture/pr97559-1.c: New testcase.
        * gcc.dg/torture/pr97559-2.c: Likewise.
---
 gcc/testsuite/gcc.dg/torture/pr97559-1.c | 21 +++++++++++++++++++++
 gcc/testsuite/gcc.dg/torture/pr97559-2.c | 18 ++++++++++++++++++
 gcc/tree-ssa-sink.c                      | 14 +++++++++-----
 3 files changed, 48 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr97559-1.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr97559-2.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr97559-1.c 
b/gcc/testsuite/gcc.dg/torture/pr97559-1.c
new file mode 100644
index 00000000000..d5de3bdb39e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr97559-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+int printf (char *, ...);
+
+int a, b, c, d;
+
+void e () {
+  int f = a;
+  if (b) {
+  L1:
+    b = 0;
+  L2:
+    if (c) {
+      if (f)
+        printf("0");
+      goto L1;
+    }
+  }
+  if (d)
+    goto L2;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr97559-2.c 
b/gcc/testsuite/gcc.dg/torture/pr97559-2.c
new file mode 100644
index 00000000000..b512e6db7ca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr97559-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+
+int a, b, c, d;
+
+void e() {
+  int f = b;
+  if (a) {
+  L1:
+    a = 0;
+  L2:
+    if (a) {
+      c = b;
+      goto L1;
+    }
+  }
+  if (d)
+    goto L2;
+}
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index 207aae2818a..b0abf4147d6 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -390,12 +390,15 @@ statement_sink_location (gimple *stmt, basic_block frombb,
                 with the use.  */
              if (gimple_code (use_stmt) == GIMPLE_PHI)
                {
-                 /* In case the PHI node post-dominates the current insert 
location
-                    we can disregard it.  But make sure it is not dominating
-                    it as well as can happen in a CFG cycle.  */
+                 /* In case the PHI node post-dominates the current insert
+                    location we can disregard it.  But make sure it is not
+                    dominating it as well as can happen in a CFG cycle.  */
                  if (commondom != bb
                      && !dominated_by_p (CDI_DOMINATORS, commondom, bb)
-                     && dominated_by_p (CDI_POST_DOMINATORS, commondom, bb))
+                     && dominated_by_p (CDI_POST_DOMINATORS, commondom, bb)
+                     /* If the blocks are possibly within the same irreducible
+                        cycle the above check breaks down.  */
+                     && !(bb->flags & commondom->flags & BB_IRREDUCIBLE_LOOP))
                    continue;
                  bb = EDGE_PRED (bb, PHI_ARG_INDEX_FROM_USE (use_p))->src;
                }
@@ -407,7 +410,8 @@ statement_sink_location (gimple *stmt, basic_block frombb,
                continue;
              /* There is no easy way to disregard defs not on the path from
                 frombb to commondom so just consider them all.  */
-             commondom = nearest_common_dominator (CDI_DOMINATORS, bb, 
commondom);
+             commondom = nearest_common_dominator (CDI_DOMINATORS,
+                                                   bb, commondom);
              if (commondom == frombb)
                return false;
            }
-- 
2.26.2

Reply via email to