https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104459
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> --- The divergence starts during jump_after_combine. With -g0, cfg_layout_merge_blocks is called on (note 53 51 56 13 [bb 13] NOTE_INSN_BASIC_BLOCK) and (code_label 56 53 57 14 8 (nil) [0 uses]) (note 57 56 79 14 [bb 14] NOTE_INSN_BASIC_BLOCK) while with -g on: (note 91 89 92 13 [bb 13] NOTE_INSN_BASIC_BLOCK) (debug_insn 92 91 93 13 (var_location:SI n (clobber (const_int 0 [0]))) "pr104459.c":29:17 -1 (nil)) (debug_insn 93 92 135 13 (debug_marker) "pr104459.c":31:17 -1 (nil)) (debug_insn 135 93 96 13 (var_location:SI D#3 (clobber (const_int 0 [0]))) -1 (nil)) (debug_insn 96 135 97 13 (var_location:SI y (debug_expr:SI D#3)) "pr104459.c":31:19 -1 (nil)) and (code_label 97 96 98 14 8 (nil) [0 uses]) (note 98 97 99 14 [bb 14] NOTE_INSN_BASIC_BLOCK) (debug_insn 99 98 100 14 (var_location:SI y (clobber (const_int 0 [0]))) -1 (nil)) (debug_insn 100 99 102 14 (debug_marker) "pr104459.c":22:33 -1 (nil)) (debug_insn 102 100 133 14 (var_location:SI q (clobber (const_int 0 [0]))) "pr104459.c":22:33 -1 (nil)) That function calls update_bb_for_insn_chain for note 98 through 102 for -g and note 57 through note 57 for -g0. 547 end = NEXT_INSN (end); 548 for (insn = begin; insn != end; insn = NEXT_INSN (insn)) 549 if (!BARRIER_P (insn)) 550 df_insn_change_bb (insn, bb); which means that for -g0 df_insn_change_bb isn't called, while for -g it is. df_insn_change_bb in turn calls df_set_bb_dirty and that sets bb(14)->flags |= BB_MODIFIED. Unfortunately, cfgcleanup.cc uses the BB_MODIFIED flag to decide on some stuff: try_forward_edges has: bool may_thread = first_pass || (b->flags & BB_MODIFIED) != 0; and may_thread |= (target->flags & BB_MODIFIED) != 0; and try_crossjump_bb has: /* If nothing changed since the last attempt, there is nothing we can do. */ if (!first_pass && !((e->src->flags & BB_MODIFIED) || (fallthru->src->flags & BB_MODIFIED))) continue; and /* If nothing changed since the last attempt, there is nothing we can do. */ if (!first_pass && !((e->src->flags & BB_MODIFIED) || (e2->src->flags & BB_MODIFIED))) continue; Seems this has been introduced in https://gcc.gnu.org/legacy-ml/gcc-patches/2010-08/txt00014.txt but before that we were using equally problematic df_get_bb_dirty. As BB_MODIFIED is only used in those places: cfgcleanup.cc: bool may_thread = first_pass || (b->flags & BB_MODIFIED) != 0; cfgcleanup.cc: may_thread |= (target->flags & BB_MODIFIED) != 0; cfgcleanup.cc: && !((e->src->flags & BB_MODIFIED) cfgcleanup.cc: || (fallthru->src->flags & BB_MODIFIED))) cfgcleanup.cc: && !((e->src->flags & BB_MODIFIED) cfgcleanup.cc: || (e2->src->flags & BB_MODIFIED))) df-core.cc: bb->flags |= BB_MODIFIED; I think best would be to introduce df_set_bb_dirty_for_debug or similar variant to df_set_bb_dirty that wouldn't set the BB_MODIFIED flag, and use that in df_insn_change_bb.