On 8/5/2026 8:31 AM, Kito Cheng wrote:
The popretz pass scans backwards from cm.popret for the "li a0, 0" that
feeds the (use a0), but nothing stopped the scan at a call: the argument
registers of a call live in CALL_INSN_FUNCTION_USAGE, which
reg_referenced_p does not look at, and the a0 set by a call_value hides
in a PARALLEL, which the bare SET test did not match. A "li a0, 0" that
sets up the first argument of a call was therefore deleted and cm.popret
became cm.popretz, so the callee got garbage in a0 and the caller
returned 0 instead of the result of the callee.
Use insn level helpers instead, find_reg_fusage for the uses and
reg_set_p for the definitions, and ask them about the word_mode a0
rather than about the a0 of the (use a0), whose mode covers a0 and a1
for a DImode return value on rv32.
gcc/ChangeLog:
PR target/126454
* config/riscv/riscv-opt-popretz.cc (pass_combine_popretz::execute):
Stop the backward scan at any use or definition of a0, including
those hidden in CALL_INSN_FUNCTION_USAGE or in a PARALLEL.
gcc/testsuite/ChangeLog:
PR target/126454
* gcc.target/riscv/pr126454.c: New test.
Looks sensible, but you know this code far better than I. Presumably
it's run after register allocation, so you don't have to worry about
something like (subreg (reg A0)) as that will have been simplified as we
leave register allocation.
OK by me.
jeff