On Wed, 3 Oct 2018, Jeff Law wrote:

> That led me to wonder if we could prove that for the majority of FP
> intensive codes that even if the library set errno that nobody could
> possibly be reading it, then we could in large part treat those builtin
> calls as -fno-math-errno (we'd mark them somehow and check the mark at
> GIMPLE->RTL expansion time (and possibly other points) to allow us to
> generate machine instructions rather than library calls).  That would
> get most of the benefit without the possibility to breaking user code.

I doubt you could prove that without LTO of the whole program because an 
errno value set by a libm function call could always be checked in the 
caller of whatever function is being compiled.

I think it's reasonable to have a default (outside C90 mode) of not 
requiring libm functions to set errno - but as discussed that's different 
from the present effects of -fno-math-errno.  There seem to be three 
reasonable modes here:

(a) Assume errno setting from libm functions in error cases may be 
required by the user; avoid inlining them in ways that would lose such 
errno setting.  This is -fmath-errno.

(b) Assume libm functions may set errno in error cases but this is not 
required by the user, so such functions may be inlined in ways that lose 
errno setting.  This might be the new default outside C90 mode.  
Furthermore, for complex.h functions this can be the default even with 
-fmath-errno; complex.h functions are never required to set errno, 
regardless of the value of math_errhandling.

(c) Optimize on the basis that libm functions do not set errno and thus it 
is OK to move what might be loads and stores of errno across calls to libm 
functions.  Maybe -fno-math-errno does this in fact, but it's not the 
documented semantics, and it breaks valid C code in some cases.  This is 
OK as the default on platforms where libm functions never set errno 
(Darwin?).

(None of these modes should have anything to do with whether other 
standard library functions such as malloc set errno; if optimizations for 
that are useful, they should be controlled by an option whose name does 
not involve "math".)

If we distinguish (b) and (c) in order to change the default, we also need 
a new option name for whichever of them doesn't get the name 
-fno-math-errno.  Both options should result in __NO_MATH_ERRNO__ being 
defined.


In general, libm functions are "const/pure with exceptions".  Maybe there 
should be attributes to describe such a function property - of course, 
none of this is needed to change the math-errno default, it's simply a way 
in which more precise optimization in this area might be allowed.  If so, 
it's critical that no warnings (like those for declaring a function with 
both const and pure) should result from libraries declaring a function 
with properties stricter than those required by the standard, but still 
permitted by the standard semantics, when the built-in function is 
declared only with the properties required by the standard.  That is, it 
must be OK for the built-in function to declare that it may set errno but 
is otherwise pure, and for the library, based on headers seeing 
__NO_MATH_ERRNO__ defined, to select a variant that it declares never sets 
errno.

Here are some of the ways in which a function can be const/pure with 
exceptions (which may be converted by the compiler into being entirely 
const or pure based on command-line options).

* Function depends, or does not depend, on the rounding mode (but does not 
read other global state).  What this means in terms of being const versus 
pure depends on -frounding-math (which has no corresponding preprocessor 
macro, so it's not possible for library headers to choose a different 
attribute depending on -frounding-math).

* Function may set exceptions for no inputs (e.g. fabs, copysign), only 
for signaling NaNs (e.g. trunc) or for inputs other than signaling NaNs.  
There's no preprocessor macro for -f(no-)trapping-math.

* Function may set errno in error cases, or is guaranteed not to do so.

Apart from lgamma functions setting signgam, I think all math.h / 
complex.h functions without pointer arguments should be const apart from 
rounding mode, exceptions and errno.  (For this purpose I'm ignoring other 
error-handling mechanisms like SVID matherr / _LIB_VERSION that involve 
other global state - obsoleted in glibc 2.27 so that with glibc you can no 
longer link a new program or library to use that mechanism.  I think if 
you're using such mechanisms it's reasonable to require you to use 
-fno-builtin-* to avoid problematic optimizations, similar to if you're 
using printf hooks or interposed malloc that access global state visible 
in the caller - all of these things are going well outside the standard.)

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

Reply via email to