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