-
Notifications
You must be signed in to change notification settings - Fork 111
Logical error performed by the Optimization of double to float conversion. #101
Comments
You can use four backticks to properly escape multiline code like that. I assume the issue is that sometimes optimizations end up avoiding a store to memory. When stored to f32, rounding occurs, but when still in a variable, it doesn't. Yes, this can be surprising. The only real solution is to enable |
Thank you for the fast answer. My solution for now will be to enable PRECISE_F32 and disable it only where performances will be potentially an issue. |
You can find more about this behavior in floating point and the nonguarantees there from http://gcc.gnu.org/wiki/x87note , which discusses the same behavior in native x87 fpu. Instead of 80bit vs 32/64bit issue in native, in Emscripten when compiling without PRECISE_F32, the "cpu register" contains a 64bit float, and the memory contains a 32bit float. That behavior is valid by the IEEE floating point spec, although it is extremely unintuitive and difficult to reason about. A good rule of thumb to avoid these issues is to follow these rules:
It seems that these rules, although being quite on the strict side of assumptions, avoid the float issues in practice. |
Perhaps we should add this (or a link to this) to the FAQ? |
I agree that this would be very useful to have in a FAQ. |
Yeah agreed. I'll write a note about this, since this does seem to come up quite often. |
Hi,
I am Alexandre and have been working with Emscripten for a little while and I am quite impressed to the capabilities of Emscripten. We have been working on prototyping a port of the Wwise sound engine to Emscripten. So far so good.
(Currently using \1.29.0 straight from the installer as my Emscripten environment.)
I have been investigating on an issue that was initially blamed to be caused by a rounding error on a Float32 type variable. (internally js will use doubles)
It was clear from the start that this was caused by optimizations -O1 -O2 or -O3, and it is already sorted out that specifying -s PRECISE_F32=1 or --llvm-opts 0 do make the problem go away.
Understanding that we wanted to preserve the optimizations we proceeded to pad the code against bad rounding and imprecisions, but I ended up on this:
The simplified behavior I am witnessing is the following:
I understand the passing of double to float can make a rounding inaccuracy and taht fValueA and fValueB could be >=1 after conversion.
But then surprisingly I get:
-------OUTPUT:---------
Values are the same
B >= 1
My understanding is that the optimizer made two optimizations, each one was valid separately, but not if both was done because they were self invalidating.
Optimization 1: the double is never used and is only assigned to floatA, so we can consider is the same value.
Optimization 2: the floatB is same as the floatA
But then the optimizer preserved floatA in the double world and kept supposing floatB was in the float world because the format was enforced by the type that was passed in reference to the function, which was an illegal assumption since then float A was not same as floatB anymore.
The conversions from double to float that was supposed to be executed on the line:
float fValueA = dblVal;
But optimization did not think it mattered and only made it in the floatB.
And the real code to repro the problem is the following, but it needs some more repro stepd to repro it:
The text was updated successfully, but these errors were encountered: