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

            Bug ID: 127935
           Summary: RISC-V: debug insns break -msave-restore call removal
                    and tail-call formation
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: compare-debug-failure
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yqtian668 at gmail dot com
  Target Milestone: ---
            Target: riscv64-unknown-linux-gnu

Created attachment 65868
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65868&action=edit
Proposed patch and regression tests

On RISC-V, adding debug information can prevent GCC from removing unneeded
`-msave-restore` helper calls.  In one case it also prevents an ordinary call
from becoming a tail call.  The resulting program is still correct, but it is
larger and executes extra save/restore work only because it was built with
debug information.

Tested revision:

```text
40b414ce63a5448495df9161aea0bfb495b47c11
```

The two triggering configurations are:

```sh
riscv64-unknown-linux-gnu-gcc -Os -msave-restore \
  -fno-var-tracking -fcompare-debug -S source.c

riscv64-unknown-linux-gnu-gcc -Os -msave-restore \
  -fcompare-debug -S source-vartrack.c
```

Each reports the corresponding input name, for example:

```text
cc1: error: <input>: '-fcompare-debug' failure (length)
```

A minimal noreturn case is:

```c
void fail (void) __attribute__ ((noreturn));

void
f (void)
{
  fail ();
}
```

With `-g -fno-var-tracking`, a debug marker can sit between the prologue and
the call.  The save/restore pass then fails to recognize the call and leaves
the `__riscv_save_0` helper in the output.  The same kind of marker before the
epilogue can hide a final ordinary call, preventing its conversion into a
tail call and retaining `__riscv_restore_0`.

There is also a plain `-g` trigger in the existing
`gcc.dg/torture/pr111000.c`: variable tracking places a
`NOTE_INSN_VAR_LOCATION` between the save instruction and
`NOTE_INSN_PROLOGUE_END`, so `riscv_sr_match_prologue` rejects the otherwise
valid prologue.

The candidate patch treats only debug-only RTL as transparent where the pass
still needs to distinguish structural notes, and uses GCC's existing
non-note, non-debug neighbor helpers where all notes may be ignored.  Two new
DejaGNU tests cover the `-fno-var-tracking` noreturn/tail-call forms and the
plain variable-tracking form.  Both fail on the revision above and pass with
the patch.

Expected result: non-executing debug RTL should not affect removal of
unneeded save/restore stubs or sibling-call formation.

Reply via email to