https://gcc.gnu.org/g:fb178543e19ac88d254aa255cbe4376dd47701b7
commit r17-3942-gfb178543e19ac88d254aa255cbe4376dd47701b7 Author: Takayuki 'January June' Suwa <[email protected]> Date: Fri Sep 4 18:54:28 2026 +0900 xtensa: Revise xtensa_zero_call_used_regs When the target-specific implementation for the "-fzero-call-used-regs" option was introduced in a previous commit (00e551bf "xtensa: Implement TARGET_ZERO_CALL_USED_REGS"), it was assumed that at least one address (general-purpose) register would always be cleared to zero, and that register was then used to wipe out other non-GP registers. However, it turns out that this approach fails in very simple cases: /* example (-fzero-call-used-regs=used ; TARGET_HARD_FLOAT) */ void test(void) { asm volatile("":::"f0"); } This patch resolves the issue by modifying the implementation so that, if no address registers are cleared, the A9 register (already adopted for various adjustments in the prologue/epilogue) is zeroed out instead and used to clear other non-GP registers. gcc/ChangeLog: * config/xtensa/xtensa.cc (xtensa_zero_call_used_regs): Change to assign 0 to the A9 register and then use it to clear other non-GP registers, instead of triggering a gcc_assert() failure when the address register is not zeroed out at all. gcc/testsuite: * gcc.target/xtensa/zero-scratch-regs-1.c: New test. Diff: --- gcc/config/xtensa/xtensa.cc | 28 +++++++++------------- .../gcc.target/xtensa/zero-scratch-regs-1.c | 20 ++++++++++++++++ 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 254661c9e28e..f4b1151d2e0e 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -5601,9 +5601,11 @@ xtensa_zero_call_used_regs (HARD_REG_SET selected_regs) zeroed_regno = regno; continue; } + if (zeroed_regno < 0) + emit_move_insn (gen_rtx_REG (SImode, zeroed_regno = A9_REG), + const0_rtx); if (TARGET_BOOLEANS && BR_REG_P (regno)) { - gcc_assert (zeroed_regno >= 0); argvec = rtvec_alloc (1); RTVEC_ELT (argvec, 0) = gen_rtx_REG (SImode, zeroed_regno); convec = rtvec_alloc (1); @@ -5612,23 +5614,15 @@ xtensa_zero_call_used_regs (HARD_REG_SET selected_regs) "", 0, argvec, convec, rtvec_alloc (0), UNKNOWN_LOCATION)); - continue; - } - if (TARGET_HARD_FLOAT && FP_REG_P (regno)) - { - gcc_assert (zeroed_regno >= 0); - emit_move_insn (gen_rtx_REG (SFmode, regno), - gen_rtx_REG (SFmode, zeroed_regno)); - continue; } - if (TARGET_MAC16 && ACC_REG_P (regno)) - { - gcc_assert (zeroed_regno >= 0); - emit_move_insn (gen_rtx_REG (SImode, regno), - gen_rtx_REG (SImode, zeroed_regno)); - continue; - } - CLEAR_HARD_REG_BIT (selected_regs, regno); + else if (TARGET_HARD_FLOAT && FP_REG_P (regno)) + emit_move_insn (gen_rtx_REG (SFmode, regno), + gen_rtx_REG (SFmode, zeroed_regno)); + else if (TARGET_MAC16 && ACC_REG_P (regno)) + emit_move_insn (gen_rtx_REG (SImode, regno), + gen_rtx_REG (SImode, zeroed_regno)); + else + CLEAR_HARD_REG_BIT (selected_regs, regno); } return selected_regs; diff --git a/gcc/testsuite/gcc.target/xtensa/zero-scratch-regs-1.c b/gcc/testsuite/gcc.target/xtensa/zero-scratch-regs-1.c new file mode 100644 index 000000000000..6cef35d667db --- /dev/null +++ b/gcc/testsuite/gcc.target/xtensa/zero-scratch-regs-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fzero-call-used-regs=used" } */ + +void test_f0(void) { +#if __XCHAL_HAVE_FP + asm volatile("":::"f0"); +#endif +} + +void test_b0(void) { +#if __XCHAL_HAVE_BOOLEANS + asm volatile("":::"b0"); +#endif +} + +void test_acc(void) { +#if __XCHAL_HAVE_MAC16 + asm volatile("":::"acc"); +#endif +}
