https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72772
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> --- Ok, so we record a correct upper bound for a loop but then later thread1 makes a mess of the loop structures, introducing multiple back-edges by mashing an outer loop of said loop into it, making the number of iteration upper bound obviously incorrect. And it is CFG cleanup which introduces those multiple back-edges, mashing the two loops! It does this by treating the outer loop header as "forwarder". Now we could detect this situation in redirect_edge_and_branch or avoid this loop smashing (in the end loop init will disambiguate the latches again if requested, re-creating the outer loop). I think we at least want such smashing late (more aggressive cleanup was introduced because otherwise we create worse initial RTL and assembler). The issue is how to detect this reliably in redirect_edge_and_branch given it has to work when LOOPS_NEED_FIXUP is set ... we have to reset niter info and estimates / upper bound whenever we redirect a latch - of both the source and destination loop. With LOOPS_NEED_FIXUP we only can rely on headers (well, not even that, and all other cfghook loop fixup stuff has a similar issue). The other option is to simply wipe niter info whenever we fixup loops (loop fixup is unfortunately a global thing). I believe I saw this issue on another PR as well.