Hello,

Attempting to use __builtin_sh_{get,set}_fpscr with sh-elf-gcc on targets 
without
TARGET_FPU_ANY results in an ICE because the built-ins are enabled when 
TARGET_SH1
is set, but their RTL expansions require TARGET_FPU_ANY.
I noticed this while playing around with rounding modes in the SH-4 backend.
I am waiting on a Bugzilla account, so I can't post it there yet or get a PR,
but the error looks like this:

```
int
error (void)
{
  return __builtin_sh_get_fpscr ();
}
```
```
error.c: In function ‘error’:
error.c:5:1: error: unrecognizable insn:
    5 | }
      | ^
(insn 5 2 6 2 (parallel [
            (set (reg:SI 162 [ _1 ])
                (reg:SI 151 ))
            (use (reg:SI 155 fpscr1))
            (use (reg:SI 154 fpscr0))
        ]) "error.c":4:10 -1
     (nil))
during RTL pass: vregs
error.c:5:1: internal compiler error: in extract_insn, at recog.cc:2894
0x230d29f internal_error(char const*, ...)
        ../../combined/gcc/diagnostic-global-context.cc:787
0x970feb fancy_abort(char const*, int, char const*)
        ../../combined/gcc/diagnostics/context.cc:1813
0x7cd66a _fatal_insn(char const*, rtx_def const*, char const*, int, char const*)
        ../../combined/gcc/rtl-error.cc:108
0x7cd686 _fatal_insn_not_found(rtx_def const*, char const*, int, char const*)
        ../../combined/gcc/rtl-error.cc:116
0x7cb617 extract_insn(rtx_insn*)
        ../../combined/gcc/recog.cc:2894
0xd11ee7 instantiate_virtual_regs_in_insn
        ../../combined/gcc/function.cc:1611
0xd11ee7 instantiate_virtual_regs
        ../../combined/gcc/function.cc:1987
0xd11ee7 execute
        ../../combined/gcc/function.cc:2034
/home/jack/sh-patch/install/libexec/gcc/sh-elf/17.0.0/cc1 -quiet error.c -quiet 
-dumpbase error.c -dumpbase-ext .c -o /tmp/ccfh7qBZ.s
```
If you pass -m4, then the snippet compiles correctly, but passing -m1 for 
example
results in an ICE.

The fix is to replace sh1_builtin_p with a new sh_fpu_p in the built-in 
descriptions
so that the built-ins are disabled on targets without an FPU.
I just renamed sh1_builtin_p as sh_fpu_p since it was not used anywhere else.

I also added some tests to ensure that the compiler properly handles the
built-ins on targets without an FPU instead of an ICE, and I added another
test to check that the builtins compile on targets with an FPU.
One issue with the tests is that floating-point instructions can only be
enabled by selecting a target with an FPU, so the tests are run with -m1
and -m4 since the SH-1 doesn't have an FPU, but the SH-4 does have one.
To avoid test failures in configurations that don't support -m1 or -m4,
I added some effective target checks, but maybe there is a better way.
I ran the tests on my PC with sh-elf and sh4-linux-gnu configurations.
About 13% of the tests under sh4-linux-gnu (check-gcc and
check-target-libstdc++v3) were unexpected failures both with and without
the patch, but the patch did not change any of the test results except for
the new tests, and the sh-elf tests looked good.

This is my first GCC patch, so if anything could be better, please let me know.

Jack

gcc/ChangeLog:
        * config/sh/sh.cc
        (sh1_builtin_p): Rename to sh_fpu_p.
        (sh_fpu_p): Check TARGET_FPU_ANY instead of TARGET_SH1.
        (bdesc): Update sh1_builtin_p to sh_fpu_p.
gcc/testsuite/ChangeLog:
        * gcc.target/sh/getset-fpscr-1.c: Verify no ICE.
        * gcc.target/sh/getset-fpscr-2.c: Verify built-ins work.
        * lib/target-supports.exp
        (check_effective_target_sh_sh1): -m1 target check.
        (check_effective_target_sh_sh4): Likewise for -m4.

Signed-off-by: Jack O'Donohue <[email protected]>
---
 gcc/config/sh/sh.cc                          | 10 ++++-----
 gcc/testsuite/gcc.target/sh/getset-fpscr-1.c | 12 +++++++++++
 gcc/testsuite/gcc.target/sh/getset-fpscr-2.c | 12 +++++++++++
 gcc/testsuite/lib/target-supports.exp        | 22 ++++++++++++++++++++
 4 files changed, 50 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/sh/getset-fpscr-1.c
 create mode 100644 gcc/testsuite/gcc.target/sh/getset-fpscr-2.c

diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
index 05b0060c0c1..cd0d60d5d4a 100644
--- a/gcc/config/sh/sh.cc
+++ b/gcc/config/sh/sh.cc
@@ -10104,12 +10104,10 @@ struct builtin_description
   tree fndecl;
 };
 
-/* This function can be used if there are any built-ins that are not for
-   SHmedia.  It's commented out to avoid the defined-but-unused warning.  */
 static bool
-sh1_builtin_p (void)
+sh_fpu_p (void)
 {
-  return TARGET_SH1;
+  return TARGET_FPU_ANY;
 }
 
 /* describe number and signedness of arguments; arg[0] == result
@@ -10184,9 +10182,9 @@ static const char signature_args[][4] =
 /* nsb: takes long long arg, returns unsigned char.  */
 static struct builtin_description bdesc[] =
 {
-  { sh1_builtin_p,
+  { sh_fpu_p,
     CODE_FOR_sts_fpscr, "__builtin_sh_get_fpscr", SH_BLTIN_UV, 0 },
-  { sh1_builtin_p,
+  { sh_fpu_p,
     CODE_FOR_set_fpscr, "__builtin_sh_set_fpscr", SH_BLTIN_VU, 0 },
 };
 
diff --git a/gcc/testsuite/gcc.target/sh/getset-fpscr-1.c 
b/gcc/testsuite/gcc.target/sh/getset-fpscr-1.c
new file mode 100644
index 00000000000..8a14eb908ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/getset-fpscr-1.c
@@ -0,0 +1,12 @@
+/* Verify that no ICE occurs if target doesn't have an FPU.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target sh_sh1 } */
+/* { dg-options "-m1 -Werror=implicit-function-declaration" } */
+
+void
+error (void)
+{
+  __builtin_sh_get_fpscr (); /* { dg-error "implicit declaration of function" 
} */
+  __builtin_sh_set_fpscr (0); /* { dg-error "implicit declaration of function" 
} */
+}
+
diff --git a/gcc/testsuite/gcc.target/sh/getset-fpscr-2.c 
b/gcc/testsuite/gcc.target/sh/getset-fpscr-2.c
new file mode 100644
index 00000000000..07f8e472966
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/getset-fpscr-2.c
@@ -0,0 +1,12 @@
+/* Verify that built-ins compile correctly if floating-point is supported.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target sh_sh4 } */
+/* { dg-options "-m4" } */
+
+void
+test (void)
+{
+  __builtin_sh_get_fpscr ();
+  __builtin_sh_set_fpscr (0);
+}
+
diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index ab726f729ab..63a436f6305 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -13702,6 +13702,28 @@ proc check_effective_target_s390_nnpa { } {
     } "-march=arch14 -mzarch" ]
 }
 
+# Return 1 if -m1 is supported.
+proc check_effective_target_sh_sh1 { } {
+    if { ![istarget sh*-*-*] && ![istarget sh*-*] } then {
+       return 0;
+    }
+
+    return [check_no_compiler_messages sh_check_sh1 object {
+       int main (void) { return 0; }
+    } "-m1" ]
+}
+
+# Return 1 if -m4 is supported.
+proc check_effective_target_sh_sh4 { } {
+    if { ![istarget sh*-*-*] && ![istarget sh*-*] } then {
+       return 0;
+    }
+
+    return [check_no_compiler_messages sh_check_sh4 object {
+       int main (void) { return 0; }
+    } "-m4" ]
+}
+
 #For versions of ARM architectures that have hardware div insn,
 #disable the divmod transform
 
-- 
2.43.0

Reply via email to