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
+}

Reply via email to