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