https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84206

Andrey Belevantsev <abel at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
                 CC|                            |abel at gcc dot gnu.org
           Assignee|unassigned at gcc dot gnu.org      |abel at gcc dot gnu.org

--- Comment #1 from Andrey Belevantsev <abel at gcc dot gnu.org> ---
The code that fails here tries to skip the inner loop's body to get to the next
blocks in the outer loop.  The failing assert is designed to check that, if
we've skipped an inner loop, and we have hit an empty block, then this block
could only be the preheader of the next inner loop, whose body we should also
skip.  In the testcase the block is definitely a preheader, but not for the
inner loop; it starts the very outer loop we're working with in the first
place.

Fixed by adding code to check that we're not going in the outer direction of
the loop hierarchy via checking depths like below.

diff --git a/gcc/sel-sched-ir.h b/gcc/sel-sched-ir.h
index b5ec63cf94d..3943eee3468 100644
--- a/gcc/sel-sched-ir.h
+++ b/gcc/sel-sched-ir.h
@@ -1144,6 +1144,7 @@ get_all_loop_exits (basic_block bb)
       struct loop *this_loop;
       struct loop *pred_loop = NULL;
       int i;
+      unsigned this_depth;
       edge e;

       for (this_loop = bb->loop_father;
@@ -1155,11 +1156,14 @@ get_all_loop_exits (basic_block bb)
       gcc_assert (this_loop != NULL);

       exits = get_loop_exit_edges_unique_dests (this_loop);
+      this_depth = loop_depth (this_loop);

-      /* Traverse all loop headers.  */
+      /* Traverse all loop headers.  Be careful not to go back
+        to the outer loop's header (see PR 84206).  */
       for (i = 0; exits.iterate (i, &e); i++)
-       if (in_current_region_p (e->dest)
-           || inner_loop_header_p (e->dest))
+       if ((in_current_region_p (e->dest)
+            || (inner_loop_header_p (e->dest)))
+           && loop_depth (e->dest->loop_father) >= this_depth)
          {
            vec<edge> next_exits = get_all_loop_exits (e->dest);

Reply via email to