[PATCH] libm/math: Use __math_xflow in obsolete math code

Szabolcs Nagy szabolcs.nagy@arm.com
Mon Aug 3 21:35:34 GMT 2020


The 08/03/2020 11:07, Keith Packard wrote:
> Szabolcs Nagy <szabolcs.nagy@arm.com> writes:
> 
> > note1: i used c99 code when i wrote the
> > new math code and currently the old math
> > code can be compiled with older compilers,
> > this change might prevent that.
> 
> Hrm. I just learned about "#pragma STDC FENV_ACCESS on" this morning and
> am wondering if we shouldn't just patch the old math library to use that
> instead of calling the __math_xflow functions. Would be a simpler patch
> and provide precise compatibility with the previous version.

i don't know of any c compiler that correctly
implements that pragma and some compilers
(clang) warn about it so i don't use it myself.

but the correct iso c way is to use it on every
code that may run in non-default fenv (non-nearest
rounding mode) or may run between exception
setting and getting operations. (i.e. not just for
math code that has fenv functions in it).

the drawback is that it means that any call may
access the fenv (i.e. if you mark a function
implementation with the pragma then any call
within that function may change the rounding mode
unless the compiler can prove otherwise), so all
extern calls become floating-point barriers which
prevents some useful optimizations (most calls
don't change the rounding mode). and this still
does not give complete fenv safety, because it's
not clear if inline asm or other language
extensions may access fenv or not and how
compilers will deal with that: currently float
operations are reordered across inline asm.

> 
> Here's an example of how that works:
> 
>         #include <fenv.h>
>         #include <stdio.h>
> 
>         #pragma STDC FENV_ACCESS on
> 
>         int main(void)
>         {
>                 double x;
>                 int e;
>                 feclearexcept(FE_ALL_EXCEPT);
>                 x = 0.0 / 0.0;
>                 e = fetestexcept(FE_ALL_EXCEPT);
>                 printf("x %g e %x\n", x, e);
>                 return 0;
>         }
> 
> $ cc except.c -lm
> $ ./a.out
> x -nan e 1
> $
> 
> As you can see, even using constants still raise the appropriate
> exception.

either you got lucky or you use another compiler
than i do.

(gcc gets close to exception safe operation if
you use -frounding-math: then it assumes the
compiled code itself does not change the rounding
mode, but its caller might, which e.g. means that
constant folding is not allowed: inexact arithmetic
operations are rounding mode dependent. so the
generated code mostly preserves fenv exceptions,
but this can break if the result does not depend
on rounding: nextafter(DBL_MIN,0) should raise
underflow but it may be const folded, or
relational operations may not preserve exceptions)



More information about the Newlib mailing list