https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67191
--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> --- Ok, reproduced with a cross. The assert means the DOM walk didn't visit the definition of an operand before its use which shouldn't happen. The use is in a loop nested in a loop which contains the definition dominating the nested loop entry. Ah, so we are detecting the outer loop as not executable. But then the DOM walk goes to a CFG part looking like <bb10> / \ / <bb11> <bb28> | \ | <bb20> \ | / <loop exit> <bb13> | \ | <other loop exit> <loop latch> and for some reason it visits this in order 10, 28, 13(!) instead of what I would expect (10, 28, 11, 20, 13). So we don't see bb13 as not executable and thus the assert triggers. In domwalk the sort using the postorder number is supposed to make sure that CFG merges inside the dominator children are visited last. Somehow this doesn't work here and thus results in non-optimal order for propagation. Of course due to the CFG the children are only 13, 28 and 11 (not 20) so there isn't a "merge" within the children :/ In the end the assert wasn't meant to stay - it's fine if it triggers for code that ends up being unreachable. So the immediate fix is to remove it but we still want to fix that dominator walk ordering issue IMHO, which of course would make it a non-dominator walk in some sense (walking bb11 children before completing bb10 children). PRE uses a worklist approach and defers blocks which have unvisited predecessors exactly to overcome this ordering issue which is bad for propagation passes (if only for compile-time reasons).