Request SSE floating-point math from GCC for x86 systems
authorparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Sat, 18 Oct 2008 22:24:34 +0000 (22:24 +0000)
committerparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Sat, 18 Oct 2008 22:24:34 +0000 (22:24 +0000)
commitcd75779746cf5247942f781b66a46007b2d79aab
treed8a7da1ab16071a4859a5ba1b0704c388f6c6e4f
parent0a92d6a1621f362c80cdd3f894652cfb12f19b8b
Request SSE floating-point math from GCC for x86 systems

Historically, Neverball has been plagued by floating-point related
replay playback issues.  Since the merging of the "lockstep" branch
which, among other things, attempted to solve some of the issues, the
problem has only become worse.  It is documented in more detail in
ticket #127.

The default way of doing floating-point arithmetic on x86 systems is
through the so-called x87 FPU using extended-precision (80-bit)
floating-point registers.  These registers are usually used to hold
intermediate results and to store values of floating-point variables.
The problem arises when the results of a computation are different
depending on whether floating-point values have been moved from
registers to memory (and thus rounded to single-precision, which is
the nominal precision of most variables in the code) between uses and
due to the fact that it is practically impossible to determine *when*
this has happened, as it heavily depends on the optimisation paths
taken by the compiler.

Although not exclusive to GCC, this non-determinism has been and
remains a well-known (and as it turns out, a documented) problem on
x86 in GCC for over a decade.

Several work-arounds exist:

The x87 FPU provides an instruction to adjust precision of the
significand in registers, while keeping the extended exponent range.
For instance, Windows apparently sets it to double-precision rather
than the default extended-precision.  While this does improve the
situation somewhat, there are still differences in the results of
replay playback using different builds on the same system.

Another work-around is to use the -ffloat-store option of GCC, which
prevents floating-point values from ever being stored in registers.
Before having any effect, though, this apparently requires
modification of source code to store all intermediate results into
variables.

Yet another is to use the "volatile" keyword to achieve the same
effect but on a per-variable basis, after making the same additional
source code modifications.

Finally, another possibility is to use the relatively recently (since
about 1999) introduced SSE extension for x86 to do floating-point
arithmetic that doesn't exhibit these problems.  This is the solution
implemented by this patch.  SSE floating-point math is already used by
default on x86_64.  A few tests indicate that minor differences can
arise across systems (but not across different builds on the same
system, as opposed to the x87 FPU) possibly depending on the version
of SSE available.

While this potentially solves most floating-point issues on x86
hardware with SSE available, additional replay format modifications
will still be necessary to minimise issues on non-SSE x86 hardware and
in cases when the game is compiled without SSE.

It is not clear what the situation is regarding non-x86 floating-point
arithmetic.

git-svn-id: https://s.snth.net/svn/neverball/trunk@2576 78b8d119-cf0a-0410-b17c-f493084dd1d7
Makefile
scripts/get-sse-cflags.sh [new file with mode: 0644]