Explorar o código

gcc: add sh FPSCR mode-switching rematerialisation patch

Mode switching runs before ira and reload (gcc/passes.def), and reload
can rematerialise a REG_EQUAL constant into a move after the mode sets
are placed.  For an SFmode 0.0 that turns an fmov, which needs no
particular precision, into fldi0, which is only valid with FPSCR.PR
clear -- so the program dies of SIGILL.  Ask for single precision at the
insns carrying such a note, while mode switching can still act on it.

Seen on sh4 with the uClibc-ng test suite: tst-sinh-ulp and tst-erf-ulp
exit 132 at -O2.  Only SH parts with a double-precision FPU are affected,
since OPTIMIZE_MODE_SWITCHING is TARGET_FPU_DOUBLE.

Measured over 27 of those tests, -O2 -m4: 25 compile byte-identically,
the two that change are exactly the two that were miscompiled, and the
whole cost is 35 instructions in 21573.  Both register allocators are
affected and both are fixed; -mlra behaves like the default reload.

Not upstream yet -- gcc trunk 17.0.0 still has it, and the patch and its
reproducer are prepared for submission in the uclibc-ng workspace under
git/gcc-submit/sh4-fpscr-mode-switching.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
ramin hai 1 semana
pai
achega
908938a712
Modificáronse 1 ficheiros con 32 adicións e 0 borrados
  1. 32 0
      toolchain/gcc/patches/13.4.0/0010-sh-fpscr-mode-remat.patch

+ 32 - 0
toolchain/gcc/patches/13.4.0/0010-sh-fpscr-mode-remat.patch

@@ -0,0 +1,32 @@
+diff -Nur gcc-13.4.0.orig/gcc/config/sh/sh.cc gcc-13.4.0/gcc/config/sh/sh.cc
+--- gcc-13.4.0.orig/gcc/config/sh/sh.cc	2026-08-25 11:48:19.356289134 +0200
++++ gcc-13.4.0/gcc/config/sh/sh.cc	2026-08-25 11:48:19.497292738 +0200
+@@ -12543,7 +12543,27 @@
+ static int
+ sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn)
+ {
+-  return recog_memoized (insn) >= 0  ? get_attr_fp_mode (insn) : FP_MODE_NONE;
++  if (recog_memoized (insn) < 0)
++    return FP_MODE_NONE;
++
++  int mode = get_attr_fp_mode (insn);
++
++  /* Mode switching runs before ira and reload, and reload can rematerialise
++     a REG_EQUAL constant into a move after the mode sets are placed.  For
++     SFmode 0.0 and 1.0 that turns an fmov, which needs no particular mode,
++     into fldi0 or fldi1, which are only valid with FPSCR.PR clear.  Ask for
++     single precision now, while there is still someone to ask.  */
++  if (mode == FP_MODE_NONE)
++    {
++      rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
++
++      if (note != NULL_RTX && CONST_DOUBLE_P (XEXP (note, 0))
++	  && (fp_zero_operand (XEXP (note, 0))
++	      || fp_one_operand (XEXP (note, 0))))
++	return FP_MODE_SINGLE;
++    }
++
++  return mode;
+ }
+ 
+ static int