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

Reply via email to