https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128571
Bug ID: 128571
Summary: RISC-V: -msave-restore places -fzero-call-used-regs
zeroing after tail __riscv_restore_0
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: 220245569 at seu dot edu.cn
CC: 220255623 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
Target Milestone: ---
Target: riscv64-*-*
Summary
-------
With -msave-restore, the register-zeroing instructions for foo are emitted
after the unconditional tail transfer to __riscv_restore_0. They cannot execute
on the return path. This occurs with GCC 16.2.0 targeting riscv64-linux-gnu.
Reproducer
----------
$ cat trigger.c
int ext(int);
int foo(int x) {
return ext(x + 1) + 2;
}
Compile flag:
$ riscv64-linux-gnu-gcc -O2 -msave-restore -fzero-call-used-regs=all -S
trigger.c -o trigger.s
$ cat trigger.s
# Relevant instructions; CFI and most zeroing instructions omitted.
foo:
call t0,__riscv_save_0
addiw a0,a0,1
call ext
addiw a0,a0,2
tail __riscv_restore_0
li t0,0 # unreachable
li t1,0
li t2,0
li a1,0
# ... remaining GPR and floating-point zeroing ...
fmv.d.x ft11,zero
Expected behavior
-----------------
The requested register clearing should execute before foo returns.
__riscv_restore_0 is an epilogue helper; this is not a source-level sibling
call to ext.
Possible cause / Suggested Fix
-----------------------------
In riscv_expand_epilogue, gen_gpr_restore emits a non-jump instruction whose
assembly is "tail __riscv_restore_%0", followed by gen_gpr_restore_return, a
return instruction with an empty assembly template. pass_zero_call_used_regs
inserts its sequence before the latter RETURN_P instruction, so the sequence
appears after the actual tail transfer.
Please make the RTL return boundary match the emitted control transfer, or
otherwise insert clearing before that transfer. Any change also needs to
account for scratch registers used by the restore helper; simply moving the
sequence without reviewing the helper's register contract may be insufficient.