]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libgcc, i386: Add __fix{,uns}bfti and __float{,un}tibf [PR107703]
authorJakub Jelinek <jakub@redhat.com>
Fri, 10 Mar 2023 19:39:54 +0000 (20:39 +0100)
committerJakub Jelinek <jakub@redhat.com>
Fri, 10 Mar 2023 19:39:54 +0000 (20:39 +0100)
While DI <-> BF conversions can be handled (and are) through
DI <-> XF <-> BF and for narrower integral modes even sometimes
through DF or SF, because XFmode has 64-bit mantissa and so all
the DImode values are exactly representable in XFmode.
That is not the case for TImode, and while e.g. the HF -> TI
conversions are IMHO useless in libgcc, because HFmode has
-65504.0f16, 65504.0f16 range, all the integers will be already
representable in SImode (or even HImode for unsigned) and so
I think HF -> DI -> TI conversions are faster and valid,
BFmode has roughly the same range as SFmode and so we absolutely need
the TI -> BF conversions to avoid double rounding.

As for BF -> TI conversions, they can be either also implemented
in libgcc, or they can be implemented (as done in this commit)
as BF -> SF -> TI conversions with the same code generation used
elsewhere, just doing the 16-bit left shift of the bits - I think
we don't need to handle sNaNs during the BF -> SF part because
SF -> TI (which is already a libcall too) will handle that too.

The BF -> SF -> TI path avoids wasting
    32: 0000000000015e10   321 FUNC    GLOBAL DEFAULT   13 __fixbfti@@GCC_13.0.0
    89: 0000000000015f60   299 FUNC    GLOBAL DEFAULT   13 __fixunsbfti@@GCC_13.0.0

2023-03-10  Jakub Jelinek  <jakub@redhat.com>

PR target/107703
* optabs.cc (expand_fix): For conversions from BFmode to integral,
use shifts to convert it to SFmode first and then convert SFmode
to integral.

* soft-fp/floattibf.c: New file.
* soft-fp/floatuntibf.c: New file.
* config/i386/libgcc-glibc.ver: Export __float{,un}tibf @ GCC_13.0.0.
* config/i386/64/t-softfp (softfp_extras): Add floattibf and
floatuntibf.
(CFLAGS-floattibf.c, CFLAGS-floatunstibf.c): Add -msse2.

gcc/optabs.cc
libgcc/config/i386/64/t-softfp
libgcc/config/i386/libgcc-glibc.ver
libgcc/soft-fp/floattibf.c [new file with mode: 0644]
libgcc/soft-fp/floatuntibf.c [new file with mode: 0644]

index 4c641cab192d543838721cd8e56a51d0b4c5d0f7..c725f357b7fc9de5eac905b03474ef72d2297375 100644 (file)
@@ -5674,7 +5674,21 @@ expand_fix (rtx to, rtx from, int unsignedp)
            rtx_insn *last = get_last_insn ();
            rtx from1 = from;
            if (fmode != GET_MODE (from))
-             from1 = convert_to_mode (fmode, from, 0);
+             {
+               if (REAL_MODE_FORMAT (GET_MODE (from))
+                   == &arm_bfloat_half_format
+                   && REAL_MODE_FORMAT (fmode) == &ieee_single_format)
+                 /* The BF -> SF conversions can be just a shift, doesn't
+                    need to handle sNANs.  */
+                 {
+                   int save_flag_finite_math_only = flag_finite_math_only;
+                   flag_finite_math_only = true;
+                   from1 = convert_to_mode (fmode, from, 0);
+                   flag_finite_math_only = save_flag_finite_math_only;
+                 }
+               else
+                 from1 = convert_to_mode (fmode, from, 0);
+             }
 
            if (must_trunc)
              {
@@ -5746,7 +5760,21 @@ expand_fix (rtx to, rtx from, int unsignedp)
            lab2 = gen_label_rtx ();
 
            if (fmode != GET_MODE (from))
-             from = convert_to_mode (fmode, from, 0);
+             {
+               if (REAL_MODE_FORMAT (GET_MODE (from))
+                   == &arm_bfloat_half_format
+                   && REAL_MODE_FORMAT (fmode) == &ieee_single_format)
+                 /* The BF -> SF conversions can be just a shift, doesn't
+                    need to handle sNANs.  */
+                 {
+                   int save_flag_finite_math_only = flag_finite_math_only;
+                   flag_finite_math_only = true;
+                   from = convert_to_mode (fmode, from, 0);
+                   flag_finite_math_only = save_flag_finite_math_only;
+                 }
+               else
+                 from = convert_to_mode (fmode, from, 0);
+             }
 
            /* See if we need to do the subtraction.  */
            do_pending_stack_adjust ();
@@ -5790,6 +5818,22 @@ expand_fix (rtx to, rtx from, int unsignedp)
          }
       }
 
+#ifdef HAVE_SFmode
+  if (REAL_MODE_FORMAT (GET_MODE (from)) == &arm_bfloat_half_format
+      && REAL_MODE_FORMAT (SFmode) == &ieee_single_format)
+    /* We don't have BF -> TI library functions, use BF -> SF -> TI
+       instead but the BF -> SF conversion can be just a shift, doesn't
+       need to handle sNANs.  */
+    {
+      int save_flag_finite_math_only = flag_finite_math_only;
+      flag_finite_math_only = true;
+      from = convert_to_mode (SFmode, from, 0);
+      flag_finite_math_only = save_flag_finite_math_only;
+      expand_fix (to, from, unsignedp);
+      return;
+    }
+#endif
+
   /* We can't do it with an insn, so use a library call.  But first ensure
      that the mode of TO is at least as wide as SImode, since those are the
      only library calls we know about.  */
index 3bec464d7867c3f46c796e915c29155a06b5072f..197fa1131f3904207bcc3f0ae482cac395481d85 100644 (file)
@@ -1,6 +1,9 @@
-softfp_extras := fixhfti fixunshfti floattihf floatuntihf
+softfp_extras := fixhfti fixunshfti floattihf floatuntihf \
+                floattibf floatuntibf
 
 CFLAGS-fixhfti.c += -msse2
 CFLAGS-fixunshfti.c += -msse2
 CFLAGS-floattihf.c += -msse2
 CFLAGS-floatunstihf.c += -msse2
+CFLAGS-floattibf.c += -msse2
+CFLAGS-floatunstibf.c += -msse2
index fa8934b9bf400e868611406363866fa5dbdf99eb..d84d075cf9f6a9d26eeae991838942040d5a5e76 100644 (file)
@@ -218,6 +218,8 @@ GCC_12.0.0 {
 %inherit GCC_13.0.0 GCC_12.0.0
 GCC_13.0.0 {
   __extendbfsf2
+  __floattibf
+  __floatuntibf
   __truncdfbf2
   __truncsfbf2
   __trunctfbf2
diff --git a/libgcc/soft-fp/floattibf.c b/libgcc/soft-fp/floattibf.c
new file mode 100644 (file)
index 0000000..f3336a9
--- /dev/null
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert a 128bit signed integer to bfloat16
+   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "brain.h"
+
+BFtype
+__floattibf (TItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_B (A);
+  BFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_B (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_B (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
diff --git a/libgcc/soft-fp/floatuntibf.c b/libgcc/soft-fp/floatuntibf.c
new file mode 100644 (file)
index 0000000..362b0f6
--- /dev/null
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert a 128bit unsigned integer to bfloat16
+   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "brain.h"
+
+BFtype
+__floatuntibf (UTItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_B (A);
+  BFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_B (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_B (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}