https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128346

            Bug ID: 128346
           Summary: Debug markers change gcov CFG checksums across -g and
                    -g0 with suppress_coverage
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: gcov-profile
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yqtian668 at gmail dot com
  Target Milestone: ---
              Host: x86_64-pc-linux-gnu
            Target: x86_64-pc-linux-gnu
             Build: x86_64-pc-linux-gnu

GCC master cf6e20578339f81bb1a029dedd2d3248337aabba on x86_64-pc-linux-gnu
emits different gcov CFG checksums for the same source when debug information
is enabled.  The generated ordinary code is unchanged, so -fcompare-debug does
not detect the difference.

int bar (int);

#pragma GCC suppress_coverage begin
int
foo (int a)
{
  a;
#pragma GCC suppress_coverage end
  if (a > 3)
    a = bar (a);
  return bar (a);
}

Compile the source twice with the same output name:

gcc -O1 -fno-thread-jumps -fprofile-arcs -frandom-seed=fixed -g  -S source.c -o
g/source.s
gcc -O1 -fno-thread-jumps -fprofile-arcs -frandom-seed=fixed -g0 -S source.c -o
g0/source.s

The two __gcov_.foo records contain different CFG checksums.  With reproducible
gcov stamps, data generated by either build is rejected when it is read with
the other build's notes.  The ordinary instructions are the same.

build_gimple_cfg inserts a GIMPLE_NOP at the boundary between the suppressed
and unsuppressed coverage regions.  gimple_can_merge_blocks_p normally sees
that nop and refuses to merge the two blocks.  Under -g, a trailing DEBUG
BEGIN_STMT becomes the last statement in the first block, so the check at
gcc/tree-cfg.cc:1877 misses the nop and permits the merge.  The different CFG
then produces a different gcov checksum.

As a causal check, changing

  stmt = *gsi_last_bb (a);

to

  stmt = *gsi_last_nondebug_bb (a);

makes the gcov CFG checksum independent of -g.  A focused regression test fails
before this change and passes after it.  The complete C gcov.exp suite also
passes with the change.  An x86_64-pc-linux-gnu bootstrap and full make -k
check completed; no unexpected failure involved this patch.

Expected result: debug markers should not affect whether a coverage-suppression
boundary is preserved or change the gcov CFG checksum.

The test case was found by a non-AI automated testing tool.  AI assisted with
the investigation and development of the candidate fix.

Reply via email to