If I understand correctly, you have an environment in which a function returning double is actually returning 80-bit floating point. The key section of code is: double d = f(A, B, C, D), e = f(A, B, C, D); int d_gt_e = d > e, d_lt_e = d < e; Notice that d would tend to be stored (demoted to a true double) before the second call to f() because the second call to f() does not preserve the 80-bit register in which the first call to f() returned its result. But the comparisons don't need to trash that register, so d can be reloaded from double (having been changed by being stored as double) while e was never stored nor reloaded. So the values are consistently different. So it is just as expected that d != e and that d>e gives an answer consistent with d<e (one is true so the other must be false). The trick is that after calling another function, the 80-bit value of e will also be demoted to match d. On 01/25/15, Vladimir A. Pavlov wrote: Hello. I've found a strange behaviour of gcc (4.8.5-20150122) optimizer relating floating-point on x86 (32 bit). I have two files (a.c and f.c, look below). In a.c:main() there are two variables, d and e, assigned the same function call result. But the optimizer causes their values to be different. I understand that all floating-point operations are actually calculated by the processor using long double type then casting the result to the target type (double in our case). But in our case both variables are of type double and the same casting should happen which would lead to the equal values. Is it gcc bug or do I misunderstand how floating-point arithmetics works in C and what is allowed for optimizer? If it's my fault can anyone explain (e.g. provide links) please why it's an allowed behaviour of optimizer? I met the similar issue in spead-dreams-2 2.1.0 (in SOLID-2.0 library) where it makes playing almost impossible leading to game hangs after 10-60 seconds of playing. Roughly speaking, in SOLID-2.0 code the issue causes a function to think that in an array every value is greater than the next one and the last value is greater than the first one (which is obviously not possible). (I can provide the details if necessary). How to reproduce the issue: $ cat >a.c <<EOF #include <stdio.h> #define A 0.0026963419787128717 #define B 820.72515869140625 #define C 0.02293671065653248 #define D 398.6868896484375 double f (double a, double b, double c, double d); double g (double a, double b, double c, double d) { return a*b + c*d; } int main () { double d = f(A, B, C, D), e = f(A, B, C, D); int d_gt_e = d > e, d_lt_e = d < e; printf("d>e=%d d<e=%d\n%.40lf\n%.40lf\n", d_gt_e, d_lt_e, d, e); return 0; } EOF $ cat >f.c <<EOF double g (double a, double b, double c, double d); double f (double a, double b, double c, double d) { return g(a, b, c, d); } EOF $ cc -O1 a.c f.c $ ./a.out d>e=1 d<e=0 11.3575215287845274758637970080599188804626 11.3575215287845274758637970080599188804626 $ cc -v Using built-in specs. COLLECT_GCC=cc COLLECT_LTO_WRAPPER=/usr/lbin/gcc/i686-pc-linux-gnu/4.8.5/lto-wrapper Target: i686-pc-linux-gnu Configured with: ../gcc-4.8-20131128/configure --target=i686-pc-linux-gnu --prefix=/usr --libexecdir=/usr/lbin --with-native-system-header-dir=/usr/include --with-gxx-include-dir=/usr/include/c++/4.8.5 --enable-languages=c,c++,objc,obj-c++ --with-linker-hash-style=gnu --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-objc-gc --disable-checking --disable-nls --with-system-zlib Thread model: posix gcc version 4.8.5 20150122 (prerelease) (GCC) Actual output: d>e=1 d<e=0 Expected output: d>e=0 d<e=0 Or expected output (it's still incorrect but I would understand it; what I don't understand is why the comparison results are different): d>e=1 d<e=1 -- Vladimir A. Pavlov