diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-03-10 20:39:54 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-03-10 20:39:54 +0100 |
commit | 246127ab238bac6aa71a9b4ee1f6fabf776b5ccb (patch) | |
tree | 19f2dd70c6885c304c5a5e4f9f0dfe9c19597a3e /gcc | |
parent | 60b6f5c0a334db3f8f6dffaf0b9aab42fd5c54a2 (diff) | |
download | gcc-246127ab238bac6aa71a9b4ee1f6fabf776b5ccb.zip gcc-246127ab238bac6aa71a9b4ee1f6fabf776b5ccb.tar.gz gcc-246127ab238bac6aa71a9b4ee1f6fabf776b5ccb.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/optabs.cc | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/gcc/optabs.cc b/gcc/optabs.cc index 4c641ca..c725f35 100644 --- a/gcc/optabs.cc +++ b/gcc/optabs.cc @@ -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. */ |