Bootstrapped and regtested on mips64el-linux-gnuabi64.
I'm not sure if it's "correct" to clobber other registers during the
zeroing of scratch registers. But I can't really come up with a better
idea: on MIPS there is no simple way to clear one bit in FCSR (i. e.
FCC[x]). We can't just use "c.f.s $fccx,$f0,$f0" because it will raise
an exception if $f0 contains a sNaN.
--
This fixes the ICEs using -fzero-call-used-regs=all for MIPS target.
OpenSSH-8.9p1 has started to enable this by default, giving us a reason
to fix -fzero-call-used-regs for more targets.
gcc/
PR target/104817
PR target/104820
* config/mips/mips.cc (mips_zero_call_used_regs): New function.
(TARGET_ZERO_CALL_USED_REGS): Define.
* config/mips/mips.md (mips_zero_fcc): New insn.
gcc/testsuite
* c-c++-common/zero-scratch-regs-8.c: Enable for MIPS.
* c-c++-common/zero-scratch-regs-9.c: Likewise.
* c-c++-common/zero-scratch-regs-10.c: Likewise.
* c-c++-common/zero-scratch-regs-11.c: Likewise.
---
gcc/config/mips/mips.cc | 47 +++++++++++++++++++
gcc/config/mips/mips.md | 6 +++
.../c-c++-common/zero-scratch-regs-10.c | 2 +-
.../c-c++-common/zero-scratch-regs-11.c | 2 +-
.../c-c++-common/zero-scratch-regs-8.c | 2 +-
.../c-c++-common/zero-scratch-regs-9.c | 2 +-
6 files changed, 57 insertions(+), 4 deletions(-)
diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 4f9683e8bf4..f0d6c8f564c 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -22611,6 +22611,51 @@ mips_asm_file_end (void)
if (NEED_INDICATE_EXEC_STACK)
file_end_indicate_exec_stack ();
}
+
+static HARD_REG_SET
+mips_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+ HARD_REG_SET zeroed_hardregs;
+ CLEAR_HARD_REG_SET (zeroed_hardregs);
+
+ if (TEST_HARD_REG_BIT (need_zeroed_hardregs, HI_REGNUM))
+ {
+ /* Clear HI and LO altogether. MIPS target treats HILO as a
+ double-word register. */
+ machine_mode dword_mode = TARGET_64BIT ? TImode : DImode;
+ rtx hilo = gen_rtx_REG (dword_mode, MD_REG_FIRST);
+ rtx zero = CONST0_RTX (dword_mode);
+ emit_move_insn (hilo, zero);
+
+ SET_HARD_REG_BIT (zeroed_hardregs, HI_REGNUM);
+ if (TEST_HARD_REG_BIT (need_zeroed_hardregs, LO_REGNUM))
+ SET_HARD_REG_BIT (zeroed_hardregs, LO_REGNUM);
+ else
+ emit_clobber (gen_rtx_REG (word_mode, LO_REGNUM));
+ }
+
+ bool zero_fcc = false;
+ for (int i = ST_REG_FIRST; i <= ST_REG_LAST; i++)
+ if (TEST_HARD_REG_BIT (need_zeroed_hardregs, i))
+ zero_fcc = true;
+
+ /* MIPS does not have a simple way to clear one bit in FCC. We just
+ clear FCC with ctc1 and clobber all FCC bits. */
+ if (zero_fcc)
+ {
+ emit_insn (gen_mips_zero_fcc ());
+ for (int i = ST_REG_FIRST; i <= ST_REG_LAST; i++)
+ if (TEST_HARD_REG_BIT (need_zeroed_hardregs, i))
+ SET_HARD_REG_BIT (zeroed_hardregs, i);
+ else
+ emit_clobber (gen_rtx_REG (CCmode, i));
+ }
+
+ need_zeroed_hardregs &= ~zeroed_hardregs;
+ return zeroed_hardregs |
+ default_zero_call_used_regs (need_zeroed_hardregs);
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -22919,6 +22964,8 @@ mips_asm_file_end (void)
#undef TARGET_ASM_FILE_END
#define TARGET_ASM_FILE_END mips_asm_file_end
+#undef TARGET_ZERO_CALL_USED_REGS
+#define TARGET_ZERO_CALL_USED_REGS mips_zero_call_used_regs
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index e0f0a582732..edf58710cdd 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -96,6 +96,7 @@ (define_c_enum "unspec" [
;; Floating-point environment.
UNSPEC_GET_FCSR
UNSPEC_SET_FCSR
+ UNSPEC_ZERO_FCC
;; HI/LO moves.
UNSPEC_MFHI
@@ -7670,6 +7671,11 @@ (define_insn "*mips_set_fcsr"
"TARGET_HARD_FLOAT"
"ctc1\t%0,$31")
+(define_insn "mips_zero_fcc"
+ [(unspec_volatile [(const_int 0)] UNSPEC_ZERO_FCC)]
+ "TARGET_HARD_FLOAT"
+ "ctc1\t$0,$25")
+
;; See tls_get_tp_mips16_<mode> for why this form is used.
(define_insn "mips_set_fcsr_mips16_<mode>"
[(unspec_volatile:SI [(match_operand:P 0 "call_insn_operand" "dS")
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-10.c
b/gcc/testsuite/c-c++-common/zero-scratch-regs-10.c
index 96e0b79b328..c23b2ceb391 100644
--- a/gcc/testsuite/c-c++-common/zero-scratch-regs-10.c
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-10.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-skip-if "not implemented" { ! { i?86*-*-* x86_64*-*-* sparc*-*-*
aarch64*-*-* nvptx*-*-* s390*-*-* } } } */
+/* { dg-skip-if "not implemented" { ! { i?86*-*-* x86_64*-*-* sparc*-*-*
aarch64*-*-* nvptx*-*-* s390*-*-* mips*-*-* } } } */
/* { dg-options "-O2" } */
#include <assert.h>
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-11.c
b/gcc/testsuite/c-c++-common/zero-scratch-regs-11.c
index 0714f95a04f..f51f5a2161c 100644
--- a/gcc/testsuite/c-c++-common/zero-scratch-regs-11.c
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-11.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-skip-if "not implemented" { ! { i?86*-*-* x86_64*-*-* sparc*-*-*
aarch64*-*-* arm*-*-* nvptx*-*-* s390*-*-* } } } */
+/* { dg-skip-if "not implemented" { ! { i?86*-*-* x86_64*-*-* sparc*-*-*
aarch64*-*-* arm*-*-* nvptx*-*-* s390*-*-* mips*-*-* } } } */
/* { dg-options "-O2 -fzero-call-used-regs=all" } */
#include "zero-scratch-regs-10.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-8.c
b/gcc/testsuite/c-c++-common/zero-scratch-regs-8.c
index aceda7e5cb8..3e5e59b3c79 100644
--- a/gcc/testsuite/c-c++-common/zero-scratch-regs-8.c
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-8.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-skip-if "not implemented" { ! { i?86*-*-* x86_64*-*-* sparc*-*-*
aarch64*-*-* arm*-*-* nvptx*-*-* s390*-*-* } } } */
+/* { dg-skip-if "not implemented" { ! { i?86*-*-* x86_64*-*-* sparc*-*-*
aarch64*-*-* arm*-*-* nvptx*-*-* s390*-*-* mips*-*-* } } } */
/* { dg-options "-O2 -fzero-call-used-regs=all-arg" } */
#include "zero-scratch-regs-1.c"
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-9.c
b/gcc/testsuite/c-c++-common/zero-scratch-regs-9.c
index f3152a7a732..d88d61accb2 100644
--- a/gcc/testsuite/c-c++-common/zero-scratch-regs-9.c
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-9.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-skip-if "not implemented" { ! { i?86*-*-* x86_64*-*-* sparc*-*-*
aarch64*-*-* arm*-*-* nvptx*-*-* s390*-*-* } } } */
+/* { dg-skip-if "not implemented" { ! { i?86*-*-* x86_64*-*-* sparc*-*-*
aarch64*-*-* arm*-*-* nvptx*-*-* s390*-*-* mips*-*-* } } } */
/* { dg-options "-O2 -fzero-call-used-regs=all" } */
#include "zero-scratch-regs-1.c"
--
2.35.1