Variable assignment and truncation of floats on x86
Joe Murray
jmurray@dsrnet.com
Mon Apr 23 09:35:00 GMT 2001
All,
Intel has provided the following explanation. Is there a flag in GCC that
may do something similar? Is there a mechanism that supports forcing a
register assignment when an exectuable is run?
Intel response:
Hi Joseph,
Here's what we've found.
When running C language on Intel processors, the most popular compilers
including Microsoft* Visual C++, Borland C, Turbo C and GNU would encounter
rounding errors when doing floating point calculations.
The floating point unit located within the processor has 4 rounding modes
(round to nearest, round down, round up and truncate) and 3 precision modes
(24-bit, 53-bit and 64-bit). The default mode for Intel processors is round
to nearest. Unfortunately, the rounding mode would get changed to truncate,
resulting in a round-off error.
The easiest solution would be to add a few lines of inline assembly that
would change the round mode to round to nearest.
short example;
//Loads the FPU Control register to X.
_asm
{
fstsw ax
mov x,ax
}
//Perform a bitwise OR to change rounding mode (bit 10-11) to "To nearest
(00). //48D=0000001100000000B
//For more information on the FPU control reference refer to the Software
Developer's Manual
x=x|48;
//Takes X back to the FPU Control Register
_asm
{
fldcw x;
}
Randy S.
Intel(R) Technical Support Engineer
*Other names and brands may be claimed as the property of others.
-----Original Message-----
From: Joe Murray [ mailto:jmurray@dsrnet.com ]
Sent: Wednesday, April 18, 2001 6:41 PM
To: 'Toshi Morita'; Joe Murray
Cc: gcc-bugs@gcc.gnu.org
Subject: RE: Variable assignment and truncation of floats on x86
Toshi,
Remove the -O2 from the compile line. The program is simple and the compiler
optimization precomputes the variables and you can't see the problem.
If you look at the assembly with optimization it will simple write the
results. In any reasonable program where all values can not be precomputed
the bug is evident.
Thanks,
Joe.
-----Original Message-----
From: Toshi Morita [ mailto:tm2@best.com ]
Sent: Wednesday, April 18, 2001 6:28 PM
To: jmurray@dsrnet.com
Cc: gcc-bugs@gcc.gnu.org
Subject: Re: Variable assignment and truncation of floats on x86
> A routine that demonstrates the problem is below. I can provide several
> other examples. It was suggested previously that the floating point unit
was
> being put into truncate mode from its default round-to mode. I don't know
> how to overcome this without major ramifications on the code baseline.
.
> 3 results in: 7.0000000000 (actually probably 6.999999? rounded to
> 7.00000000)
> 4 results in: 6 <------- PROBLEM WITH INPLACE ASSIGNMENT
> 5 results in: 7 (correct answer)
[tm@localhost tm]$ uname -a
Linux localhost.localdomain 2.2.17-14smp #1 SMP Mon Feb 5 15:48:47 EST 2001
i686 unknown
[tm@localhost tm]$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/i686-linux/2.95.3/specs
gcc version 2.95.3 20010315 (release)
[tm@localhost tm]$ gcc -O2 test2.c
[tm@localhost tm]$ ./a.out
Direct assign float to float = 7.0000000000
Inplace assign float to int = 7
Direct assign float to int = 7
[tm@localhost tm]$
This doesn't seem to occur on all versions of gcc.
It would probably help if you specified an exact version
which fails, instead of "gcc on x86".
Toshi
More information about the Gcc-bugs
mailing list