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);