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