Re: [MIPS] Use soft-fp for libgcc floating-point routines

2014-02-06 Thread Ian Lance Taylor
Richard Sandiford  writes:

> libgcc/
>   * configure.ac (libgcc_cv_mips_hard_float): New.
>   * configure: Regenerate.
>   * config.host (mips*-*-*): Use t-hardfp-sfdf rather than
>   t-softfp-sfdf for hard-float targets.
>   * config/mips/t-mips (LIB2_SIDITI_CONV_FUNCS): Reinstate.
>   (softfp_float_modes, softfp_int_modes, softfp_extensions)
>   (softfp_truncations, softfp_exclude_libgcc2): New.
>   * config/t-hardfp: New file.
>   * config/t-hardfp-sfdf: Likewise.
>   * config/hardfp.c: Likewise.

This is OK.

Thanks.

Ian


Re: [MIPS] Use soft-fp for libgcc floating-point routines

2014-02-06 Thread Richard Sandiford
"Joseph S. Myers"  writes:
> On Tue, 4 Feb 2014, Richard Sandiford wrote:
>> So here I just provide simple C functions for each operation that has
>> hard-float support.  We can then restrict the softfp stuff to functions
>> that really do need softfp support, meaning that softfp_exclude_libgcc2 := n
>> should always be OK.  As an added bonus it reduces the footprint of
>> libgcc_s.so
>> on hard-float targets.
>
> Simple C functions are indeed the best thing for cases where the functions 
> are only part of the ABI at all because of historical accident of it being 
> hard to build fp-bit only for soft-float multilibs.  But they're also 
> useful for more than just MIPS - 32-bit powerpc hard float could use them 
> as well, for example (it seems likely there are other cases, but powerpc 
> is one I know about).  So I think the implementation and a makefile 
> fragment for them should be outside config/mips, although targets may need 
> to configure exactly which functions to build from this set.  (For 
> example, e500v1 would want simple C functions for SFmode but soft-fp for 
> DFmode, and for __unordsf2; e500v2 would want soft-fp for __unordsf2 and 
> __unorddf2 but otherwise simple C functions.  I don't think the initial 
> patch needs to build out the full configurability, as long as the files 
> are in the right place, outside config/mips.)
>
> A patch putting the files in an architecture-independent place should 
> probably then be reviewed by Ian as libgcc maintainer.

OK, done in the patch below.  I went for the same style of configuration
macros as softfp, but like you say we might need to tweak it when other
targets start using it.

Ian: the short(ish) version is that I switched MIPS over from fpbit.c
to softfp in order to handle exceptions for TFmode with -mhard-float.
This fixes some c11-atomic-exec-5.c failures.  The setup we now want
for hard-float is:

(1) conversions between SF/DF and DI/TI are provided by libgcc2.c,
  which unlike softfp and fpbit.c can take advantage of the FPU
(2) other SF and DF functions are provided by the new functions added below
(3) all functions involving TF are provided by softfp.  

The longer version is that, for historical reasons, hard-float MIPS
provides a full set of libgcc floating-point routines, even if there's
hardware support for them.  For example, __addsf3 is defined even though
that's just ADD.S.  It used to be that all the functions in (2) were
provided by fpbit.c, but it's not currently possible to have softfp
provide (2) and (3) but not (1).

One fix would have been to tweak the softfp_exclude_libgcc2 handling
so that softfp could provide only (2) and (3).  But with that setup --
and also with the old setup -- conversions to and from DImode and TImode
would use fast hardware support but conversions to and from SImode wouldn't.
libgcc_s.so would also be bloated with large emulated routines that
would never normally be called.  So the idea was instead to define
simple C functions for (2) that can exploit the hardware instructions.
E.g. __addsf3 does just become an ADD.S and a return instruction.

>> +#elif defined (OP_eq2)
>> +int FUNC (TYPE x, TYPE y) { return x == y; }
>> +#elif defined (OP_ne2)
>> +int FUNC (TYPE x, TYPE y) { return x != y; }
>> +#elif defined (OP_ge2)
>> +int FUNC (TYPE x, TYPE y) { return x >= y; }
>> +#elif defined (OP_gt2)
>> +int FUNC (TYPE x, TYPE y) { return x > y; }
>> +#elif defined (OP_le2)
>> +int FUNC (TYPE x, TYPE y) { return x <= y; }
>> +#elif defined (OP_lt2)
>> +int FUNC (TYPE x, TYPE y) { return x < y; }
>
> That's not the semantics of the comparison functions.  They return an 
> integer value that can be compared to 0 with the original operation to get 
> the final result, rather than returning the result of the comparison 
> directly.  See libgcc.texi.

Gah, forgot about that sorry.

Tested on mips64-linux-gnu and mipsisa64-sde-elf.  OK to install?

Thanks,
Richard

libgcc/
* configure.ac (libgcc_cv_mips_hard_float): New.
* configure: Regenerate.
* config.host (mips*-*-*): Use t-hardfp-sfdf rather than
t-softfp-sfdf for hard-float targets.
* config/mips/t-mips (LIB2_SIDITI_CONV_FUNCS): Reinstate.
(softfp_float_modes, softfp_int_modes, softfp_extensions)
(softfp_truncations, softfp_exclude_libgcc2): New.
* config/t-hardfp: New file.
* config/t-hardfp-sfdf: Likewise.
* config/hardfp.c: Likewise.

Index: libgcc/configure.ac
===
--- libgcc/configure.ac 2014-02-04 18:11:37.078922650 +
+++ libgcc/configure.ac 2014-02-04 18:11:41.534950708 +
@@ -292,6 +292,18 @@ EOF
 eval `${CC-cc} -E conftest.c | grep host_address=`
 rm -f conftest.c
 
+case ${host} in
+mips*-*-*)
+  AC_CACHE_CHECK([whether the target is hard-float],
+[libgcc_cv_mips_hard_float],
+[AC_COMPILE_IFELSE(
+[#ifndef __mips_hard_float
+ #error FOO
+ #endif],
+

Re: [MIPS] Use soft-fp for libgcc floating-point routines

2014-02-04 Thread Joseph S. Myers
On Tue, 4 Feb 2014, Richard Sandiford wrote:

> So here I just provide simple C functions for each operation that has
> hard-float support.  We can then restrict the softfp stuff to functions
> that really do need softfp support, meaning that softfp_exclude_libgcc2 := n
> should always be OK.  As an added bonus it reduces the footprint of 
> libgcc_s.so
> on hard-float targets.

Simple C functions are indeed the best thing for cases where the functions 
are only part of the ABI at all because of historical accident of it being 
hard to build fp-bit only for soft-float multilibs.  But they're also 
useful for more than just MIPS - 32-bit powerpc hard float could use them 
as well, for example (it seems likely there are other cases, but powerpc 
is one I know about).  So I think the implementation and a makefile 
fragment for them should be outside config/mips, although targets may need 
to configure exactly which functions to build from this set.  (For 
example, e500v1 would want simple C functions for SFmode but soft-fp for 
DFmode, and for __unordsf2; e500v2 would want soft-fp for __unordsf2 and 
__unorddf2 but otherwise simple C functions.  I don't think the initial 
patch needs to build out the full configurability, as long as the files 
are in the right place, outside config/mips.)

A patch putting the files in an architecture-independent place should 
probably then be reviewed by Ian as libgcc maintainer.

> +#elif defined (OP_eq2)
> +int FUNC (TYPE x, TYPE y) { return x == y; }
> +#elif defined (OP_ne2)
> +int FUNC (TYPE x, TYPE y) { return x != y; }
> +#elif defined (OP_ge2)
> +int FUNC (TYPE x, TYPE y) { return x >= y; }
> +#elif defined (OP_gt2)
> +int FUNC (TYPE x, TYPE y) { return x > y; }
> +#elif defined (OP_le2)
> +int FUNC (TYPE x, TYPE y) { return x <= y; }
> +#elif defined (OP_lt2)
> +int FUNC (TYPE x, TYPE y) { return x < y; }

That's not the semantics of the comparison functions.  They return an 
integer value that can be compared to 0 with the original operation to get 
the final result, rather than returning the result of the comparison 
directly.  See libgcc.texi.

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: [MIPS] Use soft-fp for libgcc floating-point routines

2014-02-04 Thread Richard Sandiford
"Joseph S. Myers"  writes:
> I note that you're not using t-softfp-excl.  Logically, it's best to use 
> the libgcc2.c functions in the cases where hardware floating point is 
> involved (when they are providing conversions to/from DImode/TImode, and 
> to/from unsigned, based on conversions to/from a narrower type or to/from 
> signed, and the floating-point type involved is a hardware type), because 
> that will be more efficient than a fully software implementation.  But 
> when building for a soft-float multilib, and in any case when TFmode is 
> involved, it's best to use the soft-fp functions rather than the libgcc2.c 
> versions.

Thanks, I'd missed that.

> Thus:
>
> * For soft-float, what you have seems optimal.
>
> * For hard-float o32, using t-softfp-excl would be best.
>
> * For hard-float n32 and n64, what's optimal would be a hybrid the 
> makefile code doesn't yet support, so would need custom handling in MIPS 
> fragments; see above, and the t-softfp comment "This list is taken from 
> mklibgcc.in and doesn't presently allow for 64-bit targets where si should 
> become di and di should become ti.".  How much this matters (and indeed 
> how much it matters for hard-float o32) depends on which of the 
> conversions involving SFmode / DFmode do actually end up using a libgcc 
> function (for which the libgcc2.c version would be better than the soft-fp 
> version).

I agree that would work but in the end I went for a slightly different
approach.  The main reason was that although libgcc2.c provides those
good di and ti conversion routines you mentioned, it doesn't AFAICT
provide any si routines; they used to come from fpbit.c instead.
So if we're going to provide fast di and ti routines we should probably
try to do the same for si.  TBH, I also didn't fancy trying to change
anything as sensitive as that list of exclusions in t-softfp.

As you say, most of the functions with hard-float support should be used
rarely if at all.  I think the only reason we ended up providing a full
set of routines for hard-float was because, back in the bad old days when
libgcc was in gcc/, it was very difficult to tailor it to individual
multilibs.  That includes the set of exported symbols.

So here I just provide simple C functions for each operation that has
hard-float support.  We can then restrict the softfp stuff to functions
that really do need softfp support, meaning that softfp_exclude_libgcc2 := n
should always be OK.  As an added bonus it reduces the footprint of libgcc_s.so
on hard-float targets.

Tested on mips64-linux-gnu and mipsisa64-sde-elf.  I checked all the
new o32, n32 and n64 functions to make sure that they produced the
expected asm and (in particular) didn't have any recursive calls.
I also rechecked the list of exported symbols in each case.

Does this look OK?

Thanks,
Richard


libgcc/
* configure.ac (libgcc_cv_mips_hard_float): New.
* configure: Regenerate.
* config.host (mips*-*-*): Use t-hardfp-sfdf rather than
t-softfp-sfdf for hard-float targets.
* config/mips/t-mips (LIB2_SIDITI_CONV_FUNCS): Reinstate.
(softfp_float_modes, softfp_int_modes, softfp_extensions)
(softfp_truncations, softfp_exclude_libgcc2): New.
* config/mips/t-hardfp-sfdf: New file.
* config/mips/hardfp.c: Likewise.

Index: libgcc/configure.ac
===
--- libgcc/configure.ac 2014-02-04 18:11:37.078922650 +
+++ libgcc/configure.ac 2014-02-04 18:11:41.534950708 +
@@ -292,6 +292,18 @@ EOF
 eval `${CC-cc} -E conftest.c | grep host_address=`
 rm -f conftest.c
 
+case ${host} in
+mips*-*-*)
+  AC_CACHE_CHECK([whether the target is hard-float],
+[libgcc_cv_mips_hard_float],
+[AC_COMPILE_IFELSE(
+[#ifndef __mips_hard_float
+ #error FOO
+ #endif],
+[libgcc_cv_mips_hard_float=yes],
+[libgcc_cv_mips_hard_float=no])])
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 
Index: libgcc/config.host
===
--- libgcc/config.host  2014-02-04 18:11:37.077922644 +
+++ libgcc/config.host  2014-02-04 18:11:41.434950078 +
@@ -142,7 +142,12 @@ microblaze*-*-*)
 mips*-*-*)
# All MIPS targets provide a full set of FP routines.
cpu_type=mips
-   tmake_file="mips/t-mips t-softfp-sfdf"
+   tmake_file="mips/t-mips"
+   if test "${libgcc_cv_mips_hard_float}" = yes; then
+   tmake_file="${tmake_file} mips/t-hardfp-sfdf"
+   else
+   tmake_file="${tmake_file} t-softfp-sfdf"
+   fi
if test "${ac_cv_sizeof_long_double}" = 16; then
tmake_file="${tmake_file} mips/t-softfp-tf"
fi
Index: libgcc/config/mips/t-mips
===
--- libgcc/config/mips/t-mips   2014-02-04 18:11:37.077922644 +
+++ libgcc/config/mips/t-mips   20

Re: [MIPS] Use soft-fp for libgcc floating-point routines

2014-02-02 Thread Joseph S. Myers
On Sun, 2 Feb 2014, Joseph S. Myers wrote:

> On Sun, 2 Feb 2014, Richard Sandiford wrote:
> 
> > This patch (finally!) moves MIPS over to the soft-fp routines.  The main
> > advantage is that we now handle 128-bit long-double exceptions properly
> > on hard-float targets.
> 
> Thanks for doing this.  At some point I intend to add soft-fp support for 
> after-rounding tininess detection, so this can then get underflow 

Now submitted: 
.

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: [MIPS] Use soft-fp for libgcc floating-point routines

2014-02-02 Thread Joseph S. Myers
On Sun, 2 Feb 2014, Richard Sandiford wrote:

> This patch (finally!) moves MIPS over to the soft-fp routines.  The main
> advantage is that we now handle 128-bit long-double exceptions properly
> on hard-float targets.

Thanks for doing this.  At some point I intend to add soft-fp support for 
after-rounding tininess detection, so this can then get underflow 
exceptions exactly right (per IEEE 754, all binary floating-point 
operations need to detect tininess in the same way, and MIPS is an 
after-rounding architecture, and soft-fp only does before-rounding at 
present - this is also wrong for x86 __float128, as x86 is also 
after-rounding).  I'll also update glibc (ports/sysdeps/mips/math-tests.h) 
to know that exceptions and rounding modes for long double are supported 
for MIPS with GCC >= 4.9 (once I've done the after-rounding support, 
otherwise some fma tests will fail).

I note that you're not using t-softfp-excl.  Logically, it's best to use 
the libgcc2.c functions in the cases where hardware floating point is 
involved (when they are providing conversions to/from DImode/TImode, and 
to/from unsigned, based on conversions to/from a narrower type or to/from 
signed, and the floating-point type involved is a hardware type), because 
that will be more efficient than a fully software implementation.  But 
when building for a soft-float multilib, and in any case when TFmode is 
involved, it's best to use the soft-fp functions rather than the libgcc2.c 
versions.  Thus:

* For soft-float, what you have seems optimal.

* For hard-float o32, using t-softfp-excl would be best.

* For hard-float n32 and n64, what's optimal would be a hybrid the 
makefile code doesn't yet support, so would need custom handling in MIPS 
fragments; see above, and the t-softfp comment "This list is taken from 
mklibgcc.in and doesn't presently allow for 64-bit targets where si should 
become di and di should become ti.".  How much this matters (and indeed 
how much it matters for hard-float o32) depends on which of the 
conversions involving SFmode / DFmode do actually end up using a libgcc 
function (for which the libgcc2.c version would be better than the soft-fp 
version).

Obviously any change to this would best be tested including comparisons of 
the libgcc_s.so exported symbols before and after the patch, like you did 
for the present patch.

-- 
Joseph S. Myers
jos...@codesourcery.com


[MIPS] Use soft-fp for libgcc floating-point routines

2014-02-02 Thread Richard Sandiford
This patch (finally!) moves MIPS over to the soft-fp routines.  The main
advantage is that we now handle 128-bit long-double exceptions properly
on hard-float targets.

This also removes the last use of TPBIT in libgcc.  It might be worth
removing support for that at some point -- including the associated
libgcc2.c routines -- but probably not at this stage of 4.9.

Tested on mips64-linux-gnu and mipsisa64-sde-elf.  It fixes the
c11-atomic-exec-5.c failures for n32 and n64.  I also checked that
the exported libgcc.so symbols were unchanged for all 3 GNU/Linux ABIs,
just to be sure.  I also did some spot checking of FCSR values after
long-double operations, as well as checking that SIGFPE was raised
for long-double operations when the associated enable bit was set.
Applied.

Thanks,
Richard


libgcc/
* configure.ac: Check __mips64 when setting host_address.
* configure: Regenerate.
* config.host (mips*-*-*): Add t-softfp-sfdf, mips/t-softfp-tf,
mips/t-mips64 and t-softfp.
(mips*-*-linux*): Don't add mips/t-tpbit.
* config/mips/t-mips (LIB2_SIDITI_CONV_FUNCS, FPBIT, FPBIT_CFLAGS)
(DPBIT, DPBIT_CFLAGS): Delete.
* config/mips/sfp-machine.h: New file.
* config/mips/t-mips64: Likewise.
* config/mips/t-softfp-tf: Likewise.
* config/mips/t-tpbit: Delete.

Index: libgcc/configure.ac
===
--- libgcc/configure.ac 2014-02-02 08:29:06.963467177 +
+++ libgcc/configure.ac 2014-02-02 08:37:35.15815 +
@@ -279,9 +279,11 @@ AC_CACHE_CHECK([whether assembler suppor
   [libgcc_cv_cfi=yes],
   [libgcc_cv_cfi=no])])
 
-# Check 32bit or 64bit
+# Check 32bit or 64bit.  In the case of MIPS, this really determines the
+# word size rather than the address size.
 cat > conftest.c .  */
+
+#ifdef __mips64
+#define _FP_W_TYPE_SIZE64
+#define _FP_W_TYPE unsigned long long
+#define _FP_WS_TYPEsigned long long
+#define _FP_I_TYPE long long
+
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+#define TI_BITS (__CHAR_BIT__ * (int) sizeof (TItype))
+
+#define _FP_MUL_MEAT_S(R,X,Y)  \
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)  \
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)  \
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)  _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)  _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#ifdef __mips_nan2008
+# define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+# define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1)
+# define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1
+#else
+# define _FP_NANFRAC_S (_FP_QNANBIT_S - 1)
+# define _FP_NANFRAC_D (_FP_QNANBIT_D - 1)
+# define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1
+#endif
+#else
+#define _FP_W_TYPE_SIZE32
+#define _FP_W_TYPE unsigned int
+#define _FP_WS_TYPEsigned int
+#define _FP_I_TYPE int
+
+#define _FP_MUL_MEAT_S(R,X,Y)  \
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)  \
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)  \
+  _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)  _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)  _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#ifdef __mips_nan2008
+# define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+# define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
+# define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#else
+# define _FP_NANFRAC_S (_FP_QNANBIT_S - 1)
+# define _FP_NANFRAC_D (_FP_QNANBIT_D - 1), -1
+# define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1, -1, -1
+#endif
+#endif
+
+/* The type of the result of a floating point comparison.  This must
+   match __libgcc_cmp_return__ in GCC for the target.  */
+typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
+#define CMPtype __gcc_CMPtype
+
+#define _FP_NANSIGN_S  0
+#define _FP_NANSIGN_D  0
+#define _FP_NANSIGN_Q  0
+
+#define _FP_KEEPNANFRACP 1
+#ifdef __mips_nan2008
+# define _FP_QNANNEGATEDP 0
+#else
+# define _FP_QNANNEGATEDP 1
+#endif
+
+/* Comment from glibc: */
+/* From my experiments it seems X is chosen unless one of the
+   NaNs is sNaN,  in which case the result is NANSIGN/NANFRAC.  */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+  do {