https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89463
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED Assignee|unassigned at gcc dot gnu.org |rguenth at gcc dot gnu.org --- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> --- <bb 6> : # i_5 = PHI <_11(5), 0(8)> # DEBUG i => i_5 if (i_5 != 6) goto <bb 5>; [INV] else goto <bb 7>; [100.00%] <bb 5> : # DEBUG BEGIN_STMT # DEBUG i => i_5 + 1 So it goes like so the following. First we remove the iterator update in BB5 (unrelated). Then we remove the control stmt, removing the edge 6 -> 5. This leaves us with # i_5 = PHI <0(8)> # DEBUG i => i_5 then we remove the PHI node which inserts the bogus debug stmt. Stmt and control-flow removal in DCE is somewhat a twisted maze but the fix has to be there, avoiding the above situation. For simple IVs we could compute the final value and insert a debug stmt after the loop. But for IVs we cannot analyze a similar situation will arise and thus we have to somehow compute a # DEBUG i => NULL stmt from the above. But that means we have to queue edges we want to remove (plus eventually blocks we can avoid looking at for stmt removal) and perform CFG pruning only afterwards (like leave it to CFG cleanup by changing conditionals to if (true/false)). Doing that (just for conditions) gives us the expected @@ -24,22 +52,10 @@ if (a.1_3 <= 9) goto <bb 3>; [INV] else - goto <bb 6>; [INV] - - <bb 5> : - # DEBUG BEGIN_STMT - i_11 = i_5 + 1; - # DEBUG i => i_11 - - <bb 6> : - # i_5 = PHI <i_11(5), 0(4)> - # DEBUG i => i_5 - if (i_5 != 6) goto <bb 5>; [INV] - else - goto <bb 7>; [INV] - <bb 7> : + <bb 5> : + # DEBUG i => NULL # DEBUG BEGIN_STMT optimize_me_not (); return 0; but that's not because of CFG cleanup but because we do not remove the edge so at PHI removal time we still have both values. A non-loopy testcase may also go wrong I guess but it's usually optimized earlier and not by DCE. I have a patch.