[PATCH 1/8] math: Do not use __builtin_isgreater* and __builtin_isless* on clang

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Thu Dec 18 12:36:33 GMT 2025



On 17/12/25 20:18, H.J. Lu wrote:
> On Thu, Dec 18, 2025 at 1:56 AM Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>>
>> clang does not check for unordered numbers with builtins for 128-bit
>> float types (both _Float128 on x86_64 or long double on aarch64) [1].
> 
> Is this a clang bug?  If yes, please reference the clang issue and add
> a configure time check.

The bug reference is at [1] and it is an installed header, we can't really 
only limit this change to glibc build since users will potentially use
this optimization with clang.

> 
>> For instance, the code:
>>
>>   #ifdef __x86_64__
>>   typedef __float128 FLOAT128_TYPE;
>>   #elif defined (__aarch64__)
>>   typedef long double FLOAT128_TYPE;
>>   #endif
>>
>>   int foo (FLOAT128_TYPE x, FLOAT128_TYPE y)
> 
> Is this issue limited to _Float128?  If yes, please limit the workaround
> to _Float128.

The problem is the macro accepts different types and the current way to 
around it, and the way I did for fpclassify and isinf, is to use a quite 
complex macro to either call the builtin or the function. It uses 
_Generic (when supports), or some fallback code with either
__builtin_choose_expr and __builtin_types_compatible_p.

And the problem with isgreater is the since it has two arguments, the
resulting macro to correctly select the correct function would be
really complex (a _Generic with an anotehr _Generic selection), plus
the extra handling for compiler without _Generic support.

I decided to use this simpler solution because the resulting code is
not as bad for float/double (it would have an extra unordered comparison)
and pretty similar for _Float128.

This should not be hard to be fixed on clang, and we can re-enable it
once it is fixed.

> 
>>   {
>>     return __builtin_isgreater (x, y);
>>   }
>>
>> Will issue a __gttf2 call instead of a __unordtf2 followed by the
>> comparison.
>>
>> Using the generic implementation fixes multiple issues with math tests,
>> such as:
>>
>> Failure: fmax (0, qNaN): Exception "Invalid operation" set
>> Failure: fmax (0, -qNaN): Exception "Invalid operation" set
>> Failure: fmax (-0, qNaN): Exception "Invalid operation" set
>> Failure: fmax (-0, -qNaN): Exception "Invalid operation" set
>> Failure: fmax (9, qNaN): Exception "Invalid operation" set
>> Failure: fmax (9, -qNaN): Exception "Invalid operation" set
>> Failure: fmax (-9, qNaN): Exception "Invalid operation" set
>> Failure: fmax (-9, -qNaN): Exception "Invalid operation" set
>>
>> It has a small performance overhead due to the extra isunordered (which
>> could be omitted for float and double types). Using _Generic (similar to
>> how __MATH_TG) on a bivariadic function requires a lot of boilerplate
>> macros.
>>
>> [1] https://github.com/llvm/llvm-project/issues/172499
>> ---
>>  math/math.h | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/math/math.h b/math/math.h
>> index 26cea186fc..74b064d96e 100644
>> --- a/math/math.h
>> +++ b/math/math.h
>> @@ -1433,7 +1433,7 @@ iszero (__T __val)
>>  #endif
>>
>>  #ifdef __USE_ISOC99
>> -# if __GNUC_PREREQ (3, 1)
>> +# if __GNUC_PREREQ (3, 1) && !defined __clang__
>>  /* ISO C99 defines some macros to compare number while taking care for
>>     unordered numbers.  Many FPUs provide special instructions to support
>>     these operations.  Generic support in GCC for these as builtins went
>> --
>> 2.43.0
>>
> 
> 



More information about the Libc-alpha mailing list