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.

Reply via email to