https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126454
Bug ID: 126454
Summary: RISCV: cm.popretz pass deletes "li a0,0" and gives
wrong return value
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: alexey.lapshin at espressif dot com
Target Milestone: ---
On RISC-V with Zcmp enabled, GCC miscompiles a function that ends with a call
whose first argument is 0 and whose return value is returned. The popretz RTL
pass turns the epilogue cm.popret into cm.popretz and deletes the li a0,0 insn,
but that insn is the argument setup for the preceding call, not a return-value
assignment.
Two things break at once: the callee receives garbage in a0 instead of 0, and
the caller returns 0 instead of the callee's result.
Reproducer https://godbolt.org/z/4vxcvfjME:
// test.c
// compile: gcc -Os -march=rv32i_zcmp
int callee(int a, int *p);
int wrapper(int mode)
{
int local = mode;
return callee(0, &local);
}