fenv.h fixes for softfloat

David Schultz das at freebsd.org
Tue Jan 17 20:15:10 UTC 2012


On Tue, Jan 17, 2012, Ian Lepore wrote:
> To get that output, I had to change __softfloat_float_exception_flags to
> be declared as volatile in all 3 places it's mentioned (two extern decls
> and the definition).  I tried just casting to volatile in
> fetestexception() and that alone wasn't enough to printf everything
> correctly.
[...]
> You can see the insanity there that drove me to try using volatile:
> rint() says it has raised INEXACT just before returning, but printing
> the flags immediately upon return from rint() showed 0.  But, note that
> the flag variable was correct because the final feupdateenv() raised it
> again, so the second feholdenv() must have seen it set, right?  
> 
> But if you can't print the right values along the way, then the compiler
> is somehow feeling free to re-order the code in such a way that the
> printfs don't show the right values.  If it could do that in such a way
> as to mess up the printfs, could it do so in a way that had more serious
> side effects?

You've hit on an old problem that affects more than just arm.
Unfortunately, gcc assumes that floating-point arithmetic has no
side effects, and consequently, at higher optimization levels, it
often reorders computations incorrectly.  C99 specifies an
FENV_ACCESS pragma intended to enable or disable such
optimizations, but only commercial compilers implement it.
You can often force gcc to do the right thing with -frounding-math
or lower optimization levels.

If declaring the flags variable volatile is enough to get things
working, more or less, then perhaps we ought to do that until we
have a real 21st-century compiler.

Even with the FENV_ACCESS issues fixed, there's another problem.
The routines that emulate fp-to-integer conversions (__fixdfdi et al.)
are traditionally in the compiler runtime library (libgcc), not libc.
If your program links against the symbol from libgcc, that implementation
has no way of signaling exceptions, since the rest of the softfloat
stuff is in libc.  FreeBSD and Linux have most of the symbols in libc
as well (for reasons that are mysterious to me), so if you get the libc
version, then it might work.  See also:

	 http://gcc.gnu.org/wiki/Software_floating_point

I can fix some inadequacies in the emulation in FreeBSD's libc, but
if programs are getting linked properly, that won't have any effect.

I wouldn't worry too much about the exceptions for now, in any
case.  Programs that actually check them are pretty rare, although
that's partly due to the lack of compiler support.  If libm
functions are producing the right answers, more or less, then
things are working well enough for most purposes.


More information about the freebsd-arm mailing list