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/config/xtensa/xtensa.cc | 28 +++++++++++-----------------
 1 file changed, 11 insertions(+), 17 deletions(-)

diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index 254661c9e28..f4b1151d2e0 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;
--
2.39.5

Reply via email to