Fix 2 bugs mentioned in Bugzilla 119300:
1. When compiling with `-msoft-float -mfpmath=387`, `-msoft-float` turns off
387.
With neither FPMATH_SSE nor FPMATH_387 enabled, no unit can do FP arithmetics.
The i386-options.cc omits this kind of check, so ICE is triggered. We need
to add check in i386-options.cc to cover FPMATH_387 scenario when FPMATH_SSE
is false.
2. When compiling with `-std=c11 -mfpmath=387`, `-std=c11` denies XFmode
arithmetics
for SFmode. When encountering: `(mult:SF (xx)(xx))`, `*fop_<mode>_comm` is not
allowed to be chosen (because `X87_ENABLE_ARITH (<MODE>mode)` is false), which
triggers an "unrecognizable insn". So we need to check whether SFmode
arithmetics
are allowed before calling `ix86_emit_swsqrtsf` and use alternative methods if
not.
gcc/ChangeLog:
PR target/119300
* config/i386/i386-options.cc (ix86_option_override_internal): Add
check for
FPMATH_SSE == 0 scenario to enable 387 (if available).
* config/i386/i386.md (rsqrthf2): Generate a software library call if
387 is
not enabled for SFmode.
gcc/testsuite/ChangeLog:
PR target/119300
* gcc.target/i386/pr119300-1.c: New test.
* gcc.target/i386/pr119300-2.c: Ditto.
* gcc.target/i386/pr119300-3.c: Ditto.
---
gcc/config/i386/i386-options.cc | 13 ++++++++
gcc/config/i386/i386.md | 36 +++++++++++++++++++++-
gcc/testsuite/gcc.target/i386/pr119300-1.c | 11 +++++++
gcc/testsuite/gcc.target/i386/pr119300-2.c | 6 ++++
gcc/testsuite/gcc.target/i386/pr119300-3.c | 7 +++++
5 files changed, 72 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/i386/pr119300-1.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr119300-2.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr119300-3.c
diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
index 480862c7134..67c73d2ec6a 100644
--- a/gcc/config/i386/i386-options.cc
+++ b/gcc/config/i386/i386-options.cc
@@ -2823,6 +2823,19 @@ ix86_option_override_internal (bool main_args_p,
opts->x_ix86_fpmath = FPMATH_SSE;
}
}
+ else if (opts->x_ix86_fpmath & FPMATH_387)
+ {
+ if (!TARGET_80387_P (opts->x_target_flags))
+ {
+ if (TARGET_SSE_P (opts->x_ix86_isa_flags))
+ {
+ warning (0, "387 instruction set disabled, using SSE
arithmetics");
+ opts->x_ix86_fpmath = FPMATH_SSE;
+ }
+ else
+ error ("387 and SSE instruction sets disabled, no FP math
units");
+ }
+ }
}
/* For all chips supporting SSE2, -mfpmath=sse performs better than
fpmath=387. The second is however default at many targets since the
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 81517eff7ec..484021855bb 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -25159,7 +25159,41 @@
UNSPEC_RSQRT))]
"TARGET_SSE && TARGET_SSE_MATH"
{
- ix86_emit_swsqrtsf (operands[0], operands[1], SFmode, 1);
+ /* Since builtin will call gen_* function directly, we need a guard
+ "if" to avoid a ix86_emit_swsqrtsf call if SFmode mul is not
+ supported. In this situation, we compute 1.0 / sqrt (a) in XFmode
+ if TARGET_USE_FANCY_MATH_387 is on; and generate SW library call
+ otherwise. */
+ if (!(TARGET_SSE && TARGET_SSE_MATH)
+ && !(TARGET_80387 && X87_ENABLE_ARITH(SFmode)))
+ {
+ if (TARGET_USE_FANCY_MATH_387)
+ {
+ /* TARGET_USE_FANCY_MATH_387 implies TARGET_80387 */
+ rtx op0 = gen_reg_rtx (XFmode);
+ rtx op1 = gen_reg_rtx (XFmode);
+ rtx one = force_reg (XFmode, CONST1_RTX (XFmode));
+ rtx res = gen_reg_rtx (XFmode);
+
+ emit_insn (gen_extendsfxf2 (op1, operands[1]));
+ emit_insn (gen_sqrtxf2 (op0, op1));
+ emit_insn (gen_divxf3 (res, one, op0));
+ emit_insn (gen_truncxfsf2_i387_noop_unspec (operands[0], res));
+ }
+ else
+ {
+ rtx a = force_reg (SFmode, operands[1]);
+ rtx sqrt = emit_library_call_value (init_one_libfunc ("sqrtf"),
+ NULL_RTX, LCT_CONST, SFmode,
+ a, SFmode);
+ rtx recip = expand_binop (SFmode, sdiv_optab, CONST1_RTX (SFmode),
+ sqrt, operands[0], 0, OPTAB_LIB_WIDEN);
+ if (recip != operands[0])
+ emit_move_insn (operands[0], recip);
+ }
+ }
+ else
+ ix86_emit_swsqrtsf (operands[0], operands[1], SFmode, 1);
DONE;
})
diff --git a/gcc/testsuite/gcc.target/i386/pr119300-1.c
b/gcc/testsuite/gcc.target/i386/pr119300-1.c
new file mode 100644
index 00000000000..aa10b5e2314
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr119300-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -msse -mfpmath=387" } */
+
+float
+foo (float f)
+{
+ return __builtin_ia32_rsqrtf (f);
+}
+
+/* { dg-final { scan-assembler "fsqrt" } } */
+/* { dg-final { scan-assembler "fdiv" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr119300-2.c
b/gcc/testsuite/gcc.target/i386/pr119300-2.c
new file mode 100644
index 00000000000..db0129e4b0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr119300-2.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-msoft-float -mfpmath=387" } */
+
+#include "pr119300-1.c"
+
+/* { dg-warning "387 instruction set disabled, using SSE arithmetics" "" {
target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/i386/pr119300-3.c
b/gcc/testsuite/gcc.target/i386/pr119300-3.c
new file mode 100644
index 00000000000..e21ab7d517e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr119300-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-std=c11 -msse -mfpmath=387 -mno-fancy-math-387 -mtune=i486"
} */
+
+#include "pr119300-1.c"
+
+/* { dg-final { scan-assembler "call\[ \t\]*sqrtf" } } */
+/* { dg-final { scan-assembler-not "fsqrt" } } */
--
2.25.1