libgcc, i386: Add __fix{,uns}bfti and __float{,un}tibf [PR107703]

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.
This commit is contained in:
Jakub Jelinek 2023-03-10 20:39:54 +01:00
parent 60b6f5c0a3
commit 246127ab23
5 changed files with 142 additions and 3 deletions

View 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. */

View 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

View 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

View File

@ -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;
}

View File

@ -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;
}