https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123061
--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #5)
> The issue is with fill_always_executed_in which works outer-to-inner loop and
> does not re-consider blocks of inner loops iff its header is always executed
> in an outer loop. So it correctly computes the division is executed for
> all outer loop iterations, but what's relevant for the hoisting is that
> it's executed for all iterations of all loops of the nest involved.
>
> I will see if the improvement to inner loop handling can be fixed. Sth
> as simple as the following does, but this might increase compile-time
> a lot since we then process all inner loops again. Testing this
> nevertheless.
>
> diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
> index b9b1d92b518..27f53436ca1 100644
> --- a/gcc/tree-ssa-loop-im.cc
> +++ b/gcc/tree-ssa-loop-im.cc
> @@ -3569,10 +3569,13 @@ fill_always_executed_in_1 (class loop *loop, sbitmap
> contains_call)
>
> while (1)
> {
> - if (dump_enabled_p ())
> - dump_printf (MSG_NOTE, "BB %d is always executed in loop %d\n",
> - last->index, loop->num);
> - SET_ALWAYS_EXECUTED_IN (last, loop);
> + if (last->loop_father == loop)
> + {
> + if (dump_enabled_p ())
> + dump_printf (MSG_NOTE, "BB %d is always executed in loop
> %d\n",
> + last->index, loop->num);
> + SET_ALWAYS_EXECUTED_IN (last, loop);
> + }
> if (last == loop->header)
> break;
> last = get_immediate_dominator (CDI_DOMINATORS, last);
Of course that's too pessimistic - we'll never have an inner loop block
always executed in an outer loop then. Will come back to this later.