4 ms·
Are you sure? The FPU instruction set is the same.
by tbodt 6y ago
Are you sure? The FPU instruction set is the same.
- dpwm 6y agoI just checked on the linked Compiler Explorer session [0], and if you take out the -m32 then GCC does indeed use divsd instead of fdiv. [0] https://godbolt.org/z/py3Dw0 https://godbolt.org/z/py3Dw0
- nwallin 6y agoYes. Toggle -m32 (compiles to 32 bit) or deleting it. (defaults to 64 bit, because it's not 2005 anymore) It also works with -m32 -mfpmath=sse, even though the author of the article incorrectly states otherwise. https://godbolt.org/z/py3Dw0 https://godbolt.org/z/py3Dw0
- olliej 6y agoThe platform ABI can differ on the same cpu. I originally had the wrong answer here, but I'm including below for historical purposes and embarrassment. Re-reading on my laptop meant I didn't misread/read-the-expected? Basically by default when compiling for IA32 gcc assumes that there is no SSE unit, and so must use the x87 fpu. Alas the x87 unit doesn't have either 32 or 64 bit ieee floating point types, so the calculation at runtime must be rounded to float/double at the end of the computation. That results in a double round that is incorrect. Minor additional comment - x87's reduced precision modes (that reduce mantissa precision to ieee754-32/64) don't reduce the exponent size so it's conceivable you could get multiple-rounding derived errors even then. But no one would be toggling x87 state like that anyway, so theoretically not something that would matter in most cases. Old incorrect answer: On ia32 long double is the x87 80bit ieee754 numeric type. On x86_64 on windows, and maybe Linux, long double is just a 64bit ieee float. So my guess is that GCC computes constant evaluation of floating point expressions in “long double” for maximum precision, and then rounds to the required precision at the end. This is not valid going from 64->32 bit floats and you could probably induce this bug if you tried hard enough. Anyway it is not sound to round twice in any numeric operation, and by doing the calculation at one precision and then rounding that to the required precision that is what gcc is doing. This is a bug in GCC, floating point is well defined, there isn’t randomness to it, and they’ve introduced additional rounding that is not valid.
- moonchild 6y agoPer the sysv abi[1] (bottom of page 11): > The long double type uses a 15 bit exponent, a 64-bit mantissa with an explicit high order significant bit and an exponent bias of 16383. So it is an 80-bit float. https://uclibc.org/docs/psABI-x86_64.pdf https://uclibc.org/docs/psABI-x86_64.pdf
- olliej 6y agoThe question was "The FPU instruction set is the same", to which the response my response is correct, the same architecture can have different ABIs on different systems. For example on osx it is 80bit ieee, but on win64 it is a 64bit ieee. That ABI difference means that having the same instruction set is not the only thing that matters.
- bonzini 6y ago> Anyway it is not sound to round twice in any numeric operation, and by doing the calculation at one precision and then rounding that to the required precision that is what gcc is doing. > > This is a bug in GCC, floating point is well defined, there isn’t randomness to it, and they’ve introduced additional rounding that is not valid. Except the C standard has a way to communicate how the extra rounding is being introduced, and it's not random (for C, not C++). There is simply no way around this issue with the x87 instruction set, GCC (again only for C only, not C++) implements FLT_EVAL_METHOD==2 which is the most sensible that can be implemented with decent performance and without breaking 80-bit long double. If you are sure you don't need long doubles, use -mpc64.
- olliej 6y agoas my edit said the problem was gcc was confined to using x87 as the compile args required x87 - the older version of the comment incorrectly thought it was the optimizer going wrong, rather than runtime. If you are constrained to x87 your only option is multiple roundings which is bad. Ideally you'd just keep processing in the x87 stack as long as possible, but that would result in a different version of "incorrect" results. Honestly if you're a compiler required to use x87 with non-80bit floating point I'm not sure how you can do the right thing :-/ I don't know what gcc has but llvm has a full software floating point implementation to handle cross compiling so it can match native arithmetic.
- chrisseaton 6y agoWho's going to use FPU on AMD64? Why on earth would you do that?