The following fixes debugging experience (and coverage) for cases where CFG construction "optimizes" the CFG by squashing labels into the same basic-block, defeating the regular mechanism of dropping labels that are not reachable as done by CFG cleanup.
Writing coverage testcases is easy enough here, guality IIRC cannot test whether we stop at exactly a line - after the patch gdb when setting a breakpoint on line 4, stops at line 10 (stepping goes from 2 to 10 directly). Bootstrap & regtest running on x86_64-unknown-linux-gnu. The patch has no bad effects on code generation when optimizing, we just produce more "garbage" CFG upfront to leave optimizing the CFG to machinery that knows how to do it correctly. It does have code-generation effects when not optimizing where for the first testcase instead of nop .L2: cmpl $1, -4(%rbp) jne .L3 we now emit cmpl $0, -4(%rbp) .L3: cmpl $1, -4(%rbp) jne .L4 and CFG cleanup done after RTL expansion elides the jump but not the compare. Any objections? Thanks, Richard. 2019-06-06 Richard Biener <rguent...@suse.de> PR debug/90574 * tree-cfg.c (stmt_starts_bb_p): Split blocks at labels that appear after user labels. * gcc.misc-tests/gcov-pr90574-1.c: New testcase. * gcc.misc-tests/gcov-pr90574-2.c: Likewise. Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c (revision 271990) +++ gcc/tree-cfg.c (working copy) @@ -2722,10 +2722,10 @@ stmt_starts_bb_p (gimple *stmt, gimple * || FORCED_LABEL (gimple_label_label (label_stmt))) return true; - if (prev_stmt && gimple_code (prev_stmt) == GIMPLE_LABEL) + if (glabel *plabel = safe_dyn_cast <glabel *> (prev_stmt)) { - if (DECL_NONLOCAL (gimple_label_label ( - as_a <glabel *> (prev_stmt)))) + if (DECL_NONLOCAL (gimple_label_label (plabel)) + || !DECL_ARTIFICIAL (gimple_label_label (plabel))) return true; cfg_stats.num_merged_labels++; Index: gcc/testsuite/gcc.misc-tests/gcov-pr90574-1.c =================================================================== --- gcc/testsuite/gcc.misc-tests/gcov-pr90574-1.c (nonexistent) +++ gcc/testsuite/gcc.misc-tests/gcov-pr90574-1.c (working copy) @@ -0,0 +1,20 @@ +/* { dg-options "-fprofile-arcs -ftest-coverage" } */ +/* { dg-do run { target native } } */ + +int main(int argc, char **argv) +{ + if (argc == 0) + { + int *ptr; +label: /* count(#####) */ + { + } + } + if (argc == 1) + { + __builtin_printf("hello\n"); + } + return 0; +} + +/* { dg-final { run-gcov gcov-pr90574-1.c } } */ Index: gcc/testsuite/gcc.misc-tests/gcov-pr90574-2.c =================================================================== --- gcc/testsuite/gcc.misc-tests/gcov-pr90574-2.c (nonexistent) +++ gcc/testsuite/gcc.misc-tests/gcov-pr90574-2.c (working copy) @@ -0,0 +1,15 @@ +/* { dg-options "-fprofile-arcs -ftest-coverage" } */ +/* { dg-do run { target native } } */ + +int main(int argc, char **argv) +{ + switch (argc) + { + case 0: + foo: /* count(#####) */ + case 1:; + } + return 0; +} + +/* { dg-final { run-gcov gcov-pr90574-2.c } } */