This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Improving math function wrappers


On 16/03/17 14:29, Joseph Myers wrote:
> On Thu, 16 Mar 2017, Wilco Dijkstra wrote:
> 
>> Given other languages don't even have the concept of errno, C99 doesn't 
>> require it, and no application ever reads errno, it is inefficient to 
>> force the use of the wrappers in almost all cases.
> 
> C99 not requiring it was an incompatible quiet change from C90.
> 

i think glibc only has to set errno when user code is
compiled with c89 compatibility and even then only for
math functions that were defined in c89 and then only
guarantee correct errno setting in default rounding mode
(c89 code cannot access the fenv).

aiming for more math errno support has little use since
it is a non-portable and thus obsolete feature.

i think gcc should do this too: sqrt(x) should be
inlined as a single instruction by default, instead of
calling libc just in case it may want to set errno
(i.e. -std=c99 and -std=c11 can and thus should imply
-fno-math-errno). i saw various targets wanting this,
but it would be better to do this in general.
https://gcc.gnu.org/ml/gcc/2011-02/msg00095.html

>> Another possibility would be to merge the wrappers into their respective 
>> math functions. This is feasible since the IEEE versions must check for 
>> the same exceptional cases anyway. While this would increase complexity 
>> of math functions, it shouldn't affect the critical path for the common 
>> cases. However it would mean errno is sometimes set when it otherwise 
>> wouldn't be (with Ofast or when an IEEE math function is called 
>> internally). Also on some odd systems it might even result in extra 
>> messages being printed by __kernel_standard (can we obsolete that???).
> 
> My view is that merging errno-setting into the main implementations of the 
> various functions is reasonable - but it also involves a significant 
> amount of architecture-specific work where architecture-specific 
> implementations of those functions are involved, and it's quite likely the 
> code to set the TLS errno might vary depending on PIC versus non-PIC, with 
> the non-PIC case then not being well-tested.  The case for it is a lot 
> more straightforward where there aren't any assembly implementations for 
> particular architectures.  Adding *_noerrno exports for selected 
> functions, based on performance evidence, would also be reasonable (GCC 5 
> and above define __NO_MATH_ERRNO__ for -fno-math-errno, which can be used 
> to select such variants; of course for non-C-family languages the compiler 
> would need to know about such function variants).
> 
> (There may be cases where errno setting in the main implementations will 
> require adding checks there not currently present, if e.g. the function 
> does "return x - x;" in the non-finite argument case to return NaN and 
> also raise "invalid" for Inf arguments - but such cases should not 
> generally be significant for performance; the performance relevant cases 
> are those involving finite arguments and results, not error cases or NaNs 
> as arguments.)
> 

i don't think setting errno in asm would be necessary,
just turn "return x-x;" into "return specialcase1(x);"
where specialcase1 is generic c code shared by targets,
these are only called in cold code paths (if the errno
setting is in a hot path then wrapper vs no wrapper
does not make much difference and a wrapper can always
be in c)

one issue is that underflow/overflow thresholds can depend
on the rounding mode if errno is set based on inputs (instead
of based on the result in a wrapper), but i think errno
can be set spuriously in general so it should be possible
to choose one threshold covering all rounding modes or
alternatively only supporting errno in default rounding mode.

i think we need to decide to either (1) make it easy (default)
to call math functions without errno wrapper or (2) always
set errno, but optimize it so it does not affect performance
for common inputs (by merging the wrapper into the math code).

> As for __kernel_standard obsoletion, there are several useful steps that 
> can be done towards that:
> 
> * We now have the new wrappers that avoid checking _LIB_VERSION or calling 
> __kernel_standard, used for float128 to avoid matherr / _LIB_VERSION 
> support ever being part of the ABI for new types.
> 
> * The next step would be to make _LIB_VERSION, matherr and the ia64 
> variants matherrf, matherrl into compat symbols, so that new programs 
> cannot use that functionality.  Documentation for matherr error handling 
> would be removed.  libieee.a would no longer be installed.  Something 
> would need to be done about the test for matherr support.  Things would be 
> arranged so that new architectures no longer get exported symbols (even 
> compat symbols) for _LIB_VERSION or matherr (although some related code 
> might still be present internally).
> 
> * The next step after that would be to ensure that the new wrappers are 
> used in static libm, and in shared libm when the minimum symbol version 
> postdates the making of _LIB_VERSION into a compat symbol.  New 
> architectures, and static libm would no longer have any __kernel_standard 
> code or code related to _LIB_VERSION / matherr.
> 
> * An optional step would be to use the new wrappers also on existing 
> architectures as new symbol versions for existing symbols that have 
> _LIB_VERSION / matherr support at their old symbol versions.
> 
> * If a function is changed to set errno directly in all its 
> implementations, so it no longer needs a wrapper except for legacy 
> _LIB_VERSION / matherr support, of course in the above for "new wrappers" 
> you can read "direct export of the main implementation without a wrapper" 
> (and the compat symbols for _LIB_VERSION / matherr support would just end 
> up setting errno redundantly in both the main implementation and the 
> wrapper).
> 
> * Given the different structure of ia64 libm, it seems plausible that 
> while the making into compat symbols of _LIB_VERSION etc. should be done 
> globally (to keep the API exported the same everywhere), some of the 
> subsequent steps might only be applied to non-ia64 architectures.
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]