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.