https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109237
--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> --- For delete_trivially_dead_insns we have for (insn = get_last_insn (); insn; insn = prev) { int live_insn = 0; prev = PREV_INSN (insn); if (!INSN_P (insn)) continue; live_insn = insn_live_p (insn, counts); /* If this is a dead insn, delete it and show registers in it aren't being used. */ if (! live_insn && dbg_cnt (delete_trivial_dead)) { if (DEBUG_INSN_P (insn)) ... but insn_live_p has "interesting" behavior for debug_insns: else if (DEBUG_INSN_P (insn)) { rtx_insn *next; if (DEBUG_MARKER_INSN_P (insn)) return true; for (next = NEXT_INSN (insn); next; next = NEXT_INSN (next)) if (NOTE_P (next)) continue; else if (!DEBUG_INSN_P (next)) return true; /* If we find an inspection point, such as a debug begin stmt, we want to keep the earlier debug insn. */ else if (DEBUG_MARKER_INSN_P (next)) return true; else if (INSN_VAR_LOCATION_DECL (insn) == INSN_VAR_LOCATION_DECL (next)) return false; return true; that's ending up doing quadratic work that would have been better done by keeping track of some state during the backwards walk of the insn stream.