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

Reply via email to