Floating point trouble with x86's extended precision

Jim Wilson wilson@tuliptree.org
Wed Aug 20 22:40:00 GMT 2003


Volker Reichelt wrote:
> In the process of revamping the non-bugs section of the bug reporting
> instructions I came across a problem with the excess precision of the
> x86 FPU:

This is a complicated issue.

There is a bug in the x86 port that causes it to emit buggy FP code. 
This is partly a flaw in the x86 hardware; it lacks SFmode/DFmode 
operations on the floating point register stack.  This is partly a flaw 
in the x86 backend.  It lies, and claims that SFmode/DFmode operations 
are available.  Thus the gcc optimizer thinks it is emitting 
SFmode/DFmode instructions when it is actually emitting XFmode 
instructions, and this causes unexpected rounding problems.  The easiest 
way to see this is to write an expression that needs more than 8 
register to evaluate.  Reload will spill registers in the middle of the 
expression, and they will be truncated to 64-bits when spilled because 
the optimizer thinks we have 64-bit values.  This results in rounding 
error.  The same expression can give different results at different 
optimization levels because different pseudos get spilled.  This is 
clearly a gcc bug.  This problem has been known for over a decade, and 
has not yet been fixed, and probably never will be.  Getting correct 
results will require emitting a lot of explicitly rounding operations 
which will reduce performance noticably, and may cause more complaints 
than the rounding bug.

The easiest way to fix this problem is to fix the hardware.  Both Intel 
and AMD have done so, but in different ways.  Intel has the IPF (aka 
IA-64) architecture which has explicit SFmode/DFmode operations and thus 
no problem.  AMD has the AMD64 architecture which has an ABI that 
requires use of the SSE registers instead of the floating point register 
stack, and the SSE registers have explicit SFmode/DFmode operations and 
hence do not have this problem.

There is also another problem here that excess precision can cause 
problems even when it doesn't result in rounding errors.  This is the 
immediate case you are discussing with Brad Lucier.  Ideally, we should 
have no excess precision, and the testcase should work.  However, due to 
the design of the x86, eliminating the excess precision is a burden on 
the compiler, and hurts performance, hence it is easier to ask users to 
program around it.  Excess precision has even been accepted by the IEEE 
FP standard in some cases.  For instance, the powerpc has a multiply 
accumulate instruction that doesn't round the intermediate result.  This 
means you get a different answer with separate multiply and add 
instructions than you do if you use the multiply accumulate instruction. 
  This was officially blessed by the IEEE FP committee as being OK, 
because the multiply accumulate result was more accurate even though it 
is different.  In most numerical calculations, you have to expect some 
rounding error, and one could argue that this case is no different. 
In this case, I think we have to admit that both viewpoints are valid, 
and then agree to disagree.

As for solutions to the problem...
1) If you care about numerical accuraccy, don't use x86.  Seriously. 
AMD64 and IPF (aka IA-64) are OK, but IA-32 is not.  I realize this is 
impractical in most cases, but it is something that should be mentioned. 
  If you must use x86 FP hardware then...
2) Do FP arithmetic in the SSE registers via the -mfpmath=sse option.  I 
haven't tried this myself, so I don't know how practical it is.
3) Set the FP reg rounding precision to 64 bits.  This has the flaw that 
you can no longer perform XFmode operations.  This is only a partial 
fix, in that we still have excess precision problems for SFmode operations.
4) Try using -ffloat-store.  This works for some but not all programs. 
-ffloat-store forces user declared variables to be allocated on the 
stack, and hence avoid the in register excess precision problems. 
However, temporaries are still allocated to registers, and can still 
cause rounding errors due to excess precision, so this is not a complete 
solution.
5) Fix the x86 backend to stop lying about availability of SFmode/DFmode 
operations, probably via an option, since this will reduce performance 
so much as to cause other problems.  This would at least give people the 
option of getting slow but correct code instead of the current fast but 
incorrect code.

I've found FP bugs in all of the x86 compilers that I've ever used.  I 
am not sure if there are any that get it right, so I am skeptical that 
gcc will ever get it right.  I haven't tried any of the compilers from 
companies that specialize in FP though, maybe some of them get it right.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com



More information about the Gcc mailing list