The check whether two blocks are in the same irreducible region
and thus post-dominance checks being unreliable was incomplete
since an irreducible region can contain reducible sub-regions but
if one block is in the irreducible part and one not the check
still doesn't work as expected.

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

2021-06-22  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/101151
        * tree-ssa-sink.c (statement_sink_location): Expand irreducible
        region check.

        * gcc.dg/torture/pr101151.c: New testcase.
---
 gcc/testsuite/gcc.dg/torture/pr101151.c | 19 +++++++++++++++++++
 gcc/tree-ssa-sink.c                     |  9 ++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr101151.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr101151.c 
b/gcc/testsuite/gcc.dg/torture/pr101151.c
new file mode 100644
index 00000000000..15c9a7b7f57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr101151.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+int a, *b = &a, c, d;
+int main() {
+  *b;
+  if (a) {
+  L1:
+    a = 0;
+  L2:
+    if (d) {
+      while (b)
+        ;
+      goto L1;
+    }
+  }
+  if (c)
+    goto L2;
+  return 0;
+}
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index d252cbb5c51..92f444ec1c8 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -398,7 +398,14 @@ statement_sink_location (gimple *stmt, basic_block frombb,
                      && 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))
+                     && !((bb->flags & commondom->flags & BB_IRREDUCIBLE_LOOP)
+                          && bb->loop_father == commondom->loop_father)
+                     && !((commondom->flags & BB_IRREDUCIBLE_LOOP)
+                          && flow_loop_nested_p (commondom->loop_father,
+                                                 bb->loop_father))
+                     && !((bb->flags & BB_IRREDUCIBLE_LOOP)
+                          && flow_loop_nested_p (bb->loop_father,
+                                                 commondom->loop_father)))
                    continue;
                  bb = EDGE_PRED (bb, PHI_ARG_INDEX_FROM_USE (use_p))->src;
                }
-- 
2.26.2

Reply via email to