x87 floating-point results are effectively unstable due to possible excess precision. Without -fexcess-precision=standard, this instability can taint everything around and lead to nonsense. Instability is not limited to FP numbers, it extends to integers too: ---------------------------------------------------------------------- #include <stdio.h> __attribute__((noipa,optnone)) // imagine it in a separate TU static int opaque(int i) { return i; } int main() { int z = opaque(1) + 0x1p-60 == 1; printf("z = %d\n", z); if (z) puts("z is one"); } ---------------------------------------------------------------------- $ gcc -std=gnu11 -pedantic -Wall -Wextra -Wno-attributes -m32 -march=i686 -O3 test.c && ./a.out z = 0 z is one ---------------------------------------------------------------------- gcc x86-64 version: gcc (GCC) 10.0.1 20200211 (experimental) ----------------------------------------------------------------------
And instability of integers then easily taints surrounding code: ---------------------------------------------------------------------- #include <stdio.h> __attribute__((noipa)) // imagine it in a separate TU static int opaque(int i) { return i; } int main() { int z = opaque(0); int a = opaque(1) + 0x1p-60 == 1; printf("z = %d\n", z); opaque(a); if (z == a) { opaque(0); if (a) printf("z = %d\n", z); } } ---------------------------------------------------------------------- $ gcc -std=gnu11 -pedantic -Wall -Wextra -m32 -march=i686 -O3 test.c && ./a.out z = 0 z = 1 ---------------------------------------------------------------------- gcc x86-64 version: gcc (GCC) 10.0.1 20200211 (experimental) ---------------------------------------------------------------------- clang bug -- https://bugs.llvm.org/show_bug.cgi?id=44873
Similar to (dupe of?) https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85957
Bug 85957 is definitely similar. I've added it and a couple of others to "See Also". Some differences: - testcases here use comparisons to jump from FPs to integers while bug 85957 uses casts; - the exploited discrepancy here is between in-register and in-memory (run-time) results of type `double` while in bug 85957 it's between compile-time and run-time results; - it's probably possible to fix bug 85957 by enhancing the dom2 pass while it will probably not help here. Whether it warrants a separate bug report it's hard for me to say.
Instead of "-m32 -march=i686", one can also compile with "-mfpmath=387". This is useful if one does not have the 32-bit libs.