Floating point problems (accuracy).

James E Wilson wilson@specifixinc.com
Tue Jan 18 22:03:00 GMT 2005


Phil Prentice wrote:
>   We are having a few problems regarding floating point inaccuracies under
>   Linux.  Please see the code below.

This is PR 323 in our bug database.  One of our most commonly reported 
problems.  We call this the excess precision problem.
	http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323

This problem has been known for about 15 years now, and hasn't been 
fixed yet.  My suspicion is that it never will be.

The problem here is partly due to the design of the x87 FP unit, which 
supports full precision 80-bit operations, but not 32-bit or 64-bit 
operations.  The problem is also partly due to the design of the FSF gcc 
i386 backend, which lies, and says we do have 32-bit and 64-bit 
operations.  This results in a mismatch between what the compiler does 
and what the hardware does, which results in various FP accuracy problems.

Unfortunately, there are no good fixes for this.  If we fix the gcc i386 
backend, then we will likely have a significant FP performance loss, 
which may annoy more people than the excess precision problem does.  And 
we will still be left with double rounding problems, which means we 
still won't have completely correct FP problems.  The double rounding 
problem can't be fixed in gcc, it requires a hardware solution.  A new 
x87 FP optimization pass may help performance, but would require a lot 
of work, and it isn't clear that all of the work is worth the benefit.

The only fool proof solution is to avoid use of the x87 FP unit.  The 
good news is that if you have an AMD AMD64 or Intel EM64T system, and 
run x86_64-linux on it, then you will get correct FP code by default. 
So we do have a solution, of sorts, though it requires the whole world 
to migrate from x86-linux to x86_64-linux.  x86_64-linux does not have a 
problem because it uses the SSE registers instead of the x87 registers 
by default for 64-bit code.

Meanwhile, there are a few workarounds
1) You can try changing the hardware FP rounding mode to double 
precision.  You lose long double support, but you now get correct double 
precision FP.  You still have excess precision problems for float.  This 
may break libraries (e.g. glibc math library) that depend on long double 
support.
2) Use -ffloat-store.  This forces variables to be allocated to memory 
instead of FP registers, so that they will be corrected rounded.  This 
will eliminate the excess precision problem for some programs, but not 
all of them, as you may still have excess precision problems for 
temporaries.  This will reduce FP performance.
3) Use -fpmath=sse.  Only works for recent compilers, and recent processors.

If you are ambitious, you could try adding an option to the x86 backend 
that disables all of the 32-bit and 64-bit x87 FP instruction patterns. 
  This should result in slow but more correct FP code which may be 
useful to some people.  This is a probably a significant amount of work 
though, and it isn't clear how useful the result will be.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com



More information about the Gcc mailing list