While digging in the mode switching stuff I ran across this one. It's an
easy fix, just for the sake of it. Nothing really seems to be using or
relying on this and I'm planning to axe the -mfmovd option in the near
future.
Committed to master.
Best regards,
Oleg Endo
gcc/ChangeLog:
PR target/67643
* config/sh/sh.cc (fpscr_set_from_mem): Specify a post-inc memory
operand for lds_fpscr after RA.
gcc/testsuite/ChangeLog:
PR target/67643
* gcc.target/sh/pr67643.c: New test.
From b6b9318ac9e72d6e3c9c400a98ce446846ed79d6 Mon Sep 17 00:00:00 2001
From: Oleg Endo <[email protected]>
Date: Sun, 5 Jul 2026 16:23:26 +0900
Subject: [PATCH] SH: Fix PR 67643
gcc/ChangeLog:
PR target/67643
* config/sh/sh.cc (fpscr_set_from_mem): Specify a post-inc memory
operand for lds_fpscr after RA.
gcc/testsuite/ChangeLog:
PR target/67643
* gcc.target/sh/pr67643.c: New test.
---
gcc/config/sh/sh.cc | 24 ++++++++++++++++--------
gcc/testsuite/gcc.target/sh/pr67643.c | 11 +++++++++++
2 files changed, 27 insertions(+), 8 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/sh/pr67643.c
diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
index 9e488bf..abc073c 100644
--- a/gcc/config/sh/sh.cc
+++ b/gcc/config/sh/sh.cc
@@ -8873,8 +8873,6 @@ fpscr_set_from_mem (int mode, HARD_REG_SET regs_live)
enum attr_fp_mode norm_mode = ACTUAL_NORMAL_MODE (FP_MODE);
int index = fp_mode == norm_mode;
- rtx scratch = !can_create_pseudo_p () ? get_free_reg (regs_live) : NULL_RTX;
-
if (fpscr_values == NULL)
{
tree t = build_index_type (integer_one_node);
@@ -8892,17 +8890,27 @@ fpscr_set_from_mem (int mode, HARD_REG_SET regs_live)
}
rtx src = DECL_RTL (fpscr_values);
- if (!can_create_pseudo_p ())
+
+ if (can_create_pseudo_p ())
+ {
+ // Before RA the plain address can be used and RA will adjust it for
+ // the post-inc constraint.
+ src = adjust_address (src, SImode, index * 4);
+ emit_insn (gen_lds_fpscr (force_reg (SImode, src)));
+ }
+ else
{
+ // After RA it needs the address with a post-inc mem or else it will
+ // result in an unrecognizable insn.
+ rtx scratch = get_free_reg ();
emit_move_insn (scratch, XEXP (src, 0));
if (index != 0)
emit_insn (gen_addsi3 (scratch, scratch, GEN_INT (index * 4)));
- src = adjust_automodify_address (src, SImode, scratch, index * 4);
+ src = adjust_automodify_address (src, SImode,
+ gen_rtx_POST_INC (Pmode, scratch),
+ index * 4);
+ add_reg_note (emit_insn (gen_lds_fpscr (src)), REG_INC, scratch);
}
- else
- src = adjust_address (src, SImode, index * 4);
-
- emit_insn (gen_lds_fpscr (src));
}
/* Is the given character a logical line separator for the assembler? */
diff --git a/gcc/testsuite/gcc.target/sh/pr67643.c b/gcc/testsuite/gcc.target/sh/pr67643.c
new file mode 100644
index 0000000..d2f04f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr67643.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-m4 -mfmovd -O1" } */
+/* { dg-final { scan-assembler "lds.l\t@r\[0-9\]+\\+,fpscr" } } */
+
+extern double g;
+
+void __attribute__ ((interrupt_handler))
+isr (void)
+{
+ g += 1.0;
+}
--
libgit2 1.9.0