On Mon, Jun 13, 2016 at 11:54 PM, Joseph Myers <jos...@codesourcery.com> wrote:

>> Attached patch intriduces __builtin_signbitq built-in function, so the
>> compiler will be able to use SSE4.1 PTEST instruction to determine
>> sign bit of __float128 value.
>
> The __builtin_signbit function is type-generic from GCC 6 onwards, so I
> don't see any need for this type-specific function.  (The .md pattern may
> still be useful, of course, for better expansion of type-generic
> __builtin_signbit on float128 arguments.)
>
>> The patch introduces complete infrastructure, including fallback to
>> __signbittf2 libgcc function for non-SSE4.1 targets.
>
> I don't see any need for a libgcc fallback either.  Generic code in GCC
> should always be able to implement signbit using bit-manipulation, without
> needing any library fallback.

The problem is in fact that on x86_64 __float128 values live
exclusively in SSE registers exclusively. Apart from PTEST, there are
no convenient instructions to test bits in high part of the SSE
register. So, we would have to move SSE value to memory, load
high-part to an integer register, test the bit in the integer register
and set the flag in the output register to obtain setCC -> jCC
optimization.

Also, please note that there is no generic support for __float128 or
TFmode optimizations in the compiler. Long-double functions (e.g.
signbitl) that are supported by generic functionality correspond to
80bit XFmode. All bit manipulations involving__float128 have to be
done by hand.

Due to above reasons, I have taken the path that is already
implemented in libgcc (__builtin_fabsq and __builtin_copysignq
fallbacks when SSE is not present). Fallback functions actually
implement exactly the same functionalty as fabsq, copysignq and
signbitq functions in libquadmath. *If* we really want to avoid
fallbacks, it is possible to add RTL code to the relevant expanders,
but it will be quite some work for a questionable gain.

>> I have changed libquadmath to use __builtin_signbitq, and there were
>> numerous places, where the call to signbitq + test + conditional jump
>> reduced to e.g.:
>
> Current glibc systematically uses type-generic classification macros such
> as signbit where they exist in <math.h>, rather than direct calls to
> __signbitl etc. such as were formerly used.

Please note that we are dealing with __float128 types. In contrast to
float, double and long double, this type is non-standard and not known
to glibc, as evident from the code snippet below:

/* Return nonzero value if sign of X is negative.  */
# ifdef __NO_LONG_DOUBLE_MATH
#  define signbit(x) \
     (sizeof (x) == sizeof (float) ? __signbitf (x) : __signbit (x))
# else
#  define signbit(x) \
     (sizeof (x) == sizeof (float)                          \
      ? __signbitf (x)                                  \
      : sizeof (x) == sizeof (double)                          \
      ? __signbit (x) : __signbitl (x))
# endif

> Thus, I don't think changes to use __builtin_signbitq should go into
> libquadmath.  Rather, it should be updated for the past few years' changes
> in glibc (this is long overdue), with some header used in building
> libquadmath being made to define signbit, isfinite etc. to use the
> type-generic built-in functions, and such type-generic macro calls (as in
> glibc) replacing libquadmath's calls to signbitq, finiteq, isinfq etc.

I don't see other way to instruct the compiler to overload e.g.
signbitq. This is non-standard, made-up function name, and the
compiler has no knowledge what to do with it. As far as the compiler
is concerned, it is just a function that happens to have TFmode
arguments.

Uros.

Reply via email to