Perhaps the title should mention that this is 32-bit x86, which is rather obsolete. This should work okay on x86_64.
GNU GCC does not round floating-point divisions to the nearest value
81–87 of 87 posts
Re: GNU GCC does not round floating-point divisions to the nearest value
#82Earlier quoted context omitted.
But then why does python and JavaScript on the same machines get it right?
Because they're compiled to use SSE instructions instead of x87 FPU instructions. If you are still writing 32 bit x86 C code, it's probably some embedded or legacy CPU, and it's wrong to assume SSE instructions are available. So GCC correctly defaults to using FPU instructions instead of SSE instructions on 32 bit x86. Javascript and python will basically never be run in embedded environments, and their legacy enviro…
Re: GNU GCC does not round floating-point divisions to the nearest value
#83Earlier quoted context omitted.
Why would there be any difference?
Because every x86_64 CPU supports SSE2, so compilers can assume it exists and the ABI passes floating point arguments in SSE2’s FP registers. This means that every sane compiler for x86_64 will use SSE2 and won’t use x87, and the problem won’t occur. In contrast, the 32-bit C ABI passes floating point args in x87 registers, and there are 32-bit CPUs without SSE2, so x87 is used by default. x87 is, in quite a few resp…
Re: GNU GCC does not round floating-point divisions to the nearest value
#84As I understand it, the IEEE floating point standards do not require exact rounding for binary to decimal conversions. See What Every Computer Scientist Should Know About Floating-Point Arithmetic https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.h... The behavior appears to be consistent with the standard. Keep in mind that GCC needs to provide the same result irrespective of the architecture it runs on and…
Look for the heading, “The IEEE Standard” in “What Every Computer Scientist Should Know About Floating-Point Arithmetic,” then scroll down to the subheading “Operations.” That section begins, “The IEEE standard requires that the result of addition, subtraction, multiplication and division be exactly rounded. That is, the result must be computed exactly and then rounded to the nearest floating-point number (using roun…
Reading down thread, I see that the behavior might be related to x87 since the build script references i386...which makes IEEE 754 conformance moot. The methods of achieving conformance when targeting i386 are described in the GCC documentation.
Re: GNU GCC does not round floating-point divisions to the nearest value
#85Earlier quoted context omitted.
It’s normally not more correct.
I thought fast-math meant (among other things) that the compiler could algebraically simplify things using some rules for real numbers that don't apply to 32-/64-bit floating point numbers. I'd expect that reducing the number of operations would more often than not reduce the error due to rounding, which is what most people would want when they talk about "correctness". Which step in this (very naive) argument is wro…
Imagine the analogue for integers. You might use code like this to round down to a multiple of 2:
int i = 7;
int j = (i / 2) * 2;
If a compiler optimized that to j = i then that's more mathematically accurate but less correct.Re: GNU GCC does not round floating-point divisions to the nearest value
#86Earlier quoted context omitted.
Because every x86_64 CPU supports SSE2, so compilers can assume it exists and the ABI passes floating point arguments in SSE2’s FP registers. This means that every sane compiler for x86_64 will use SSE2 and won’t use x87, and the problem won’t occur. In contrast, the 32-bit C ABI passes floating point args in x87 registers, and there are 32-bit CPUs without SSE2, so x87 is used by default. x87 is, in quite a few resp…
For the Linux kernel, things get slightly more complicated with -mgeneral-regs-only. ( https://bugs.llvm.org/show_bug.cgi?id=30792 / https://reviews.llvm.org/D38479 ). A few drivers use floating point values/calculations. Which way are they rounded when expressions are folded at compile time? Does that match what would happen at runtime? The x86 kernel also disables SSE generally (kernel_fpu_{begin|end} via -mno-{x87…
That looks like an ARM issue.
> Further, it uses an 8B stack alignment, which makes it so that when FP is used, the compiler cannot select instructions that require 16B aligned operands to be loaded/stored from/to the stack.
On x86_64, on a recent GCC, this all works correctly. If you end up with a 16-byte-aligned variable (like an SSE vector) on the stack, GCC will correctly align the stack in the prologue. On older GCCs, there were a serious of obnoxious I-know-better-than-you-isms in the command line option handling that made this all malfunction.
I seem to be missing the Share button on godbolt.org, so no link. But you can test with:
typedef int v4si __attribute__ ((vector_size (16)));
v4si *v;
int func(void)
{
v4si z;
v = &z;
return 0;
}
Add -mpreferred-stack-boundary=3 to the options.Re: GNU GCC does not round floating-point divisions to the nearest value
#87This seems like a property of the Intel 8087 math coprocessor and its distant descendants found in x86 chips, not anything to do with gcc?
But then why does python and JavaScript on the same machines get it right?
JavaScript JITs blindly use SSE without checking if it is available. Bytecode interpreters behave the same as above.