From: Takayuki 'January June' Suwa <[email protected]>
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.
---
Changes v1->v2:
- add test
gcc/config/xtensa/xtensa.cc | 28 ++++++++-----------
.../gcc.target/xtensa/zero-scratch-regs-1.c | 20 +++++++++++++
2 files changed, 31 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/xtensa/zero-scratch-regs-1.c
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
+}
--
2.47.3