https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87273
--- Comment #5 from Andrey Belevantsev <abel at gcc dot gnu.org> --- In this PR we're pipelining a loop with a conditional that has lots of code on the left arm and just a few blocks on the right arm. In this situation it is natural for the right scheduling fence to end up fast below the conditional (on its postdominating block), and for the left fences to get there much later. When this happens, we merge the fences, and in that code there is an assert that basically says (as far as I remember, this is the code that goes back to the original sel-sched commit) that, if we're merging two fences and one came from a fallthrough block, then another is supposed to come from the second block. But it is not the case here, because the left fence (the later one) has already scheduled an insn from the code that was processed by the right fence (the earlier one), and this insn therefore has moved from block 7 of the earlier fence to block 6 of the later one. So both fences are saying that previously they have scheduled some code from the same block 6, and that fires the assert. As I said, the situation is completely normal and I don't see the point in keeping the assert anymore. So just removing it fixes the issue as with the below patch. diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c index e8e508ef692..a6583017c9d 100644 --- a/gcc/sel-sched-ir.c +++ b/gcc/sel-sched-ir.c @@ -703,11 +703,6 @@ merge_fences (fence_t f, insn_t insn, else if (candidate->src == BLOCK_FOR_INSN (last_scheduled_insn)) { - /* Would be weird if same insn is successor of several fallthrough - edges. */ - gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb - != BLOCK_FOR_INSN (last_scheduled_insn_old)); - state_free (FENCE_STATE (f)); FENCE_STATE (f) = state;