Filed GCC bug 39228:
#include <stdio.h> #include <math.h> int main() { Â Â Â Â Â Â Â double a= 10.0; Â Â Â Â Â Â Â double b= 1e+308; Â Â Â Â Â Â Â printf("%d %d %dn", isinf(a*b), __builtin_isinf(a*b), __isinf(a*b)); Â Â Â Â Â Â Â return 0; }
mtaylor@drizzle-dev:~$ gcc -o test test.c
mtaylor@drizzle-dev:~$ ./test
0 0 1
mtaylor@drizzle-dev:~$ gcc -o test test.c -std=c99
mtaylor@drizzle-dev:~$ ./test
1 0 1
mtaylor@drizzle-dev:~$ gcc -o test test.c  -mfpmath=sse -march=pentium4
mtaylor@drizzle-dev:~$ ./test
1 1 1
mtaylor@drizzle-dev:~$ g++ -o test test.c
mtaylor@drizzle-dev:~$ ./test
1 0 1
Originally I found the simple isinf() case to be different on x86 than x86-64, ppc32 and sparc (32 and 64).
After more research, I found that x86-64 uses the sse instructions to do it (and using sse is the only way for __builtin_isinf() to produce correct results). For the g++ built version, it calls __isinf() instead of inlining (and as can be seen, the __isinf() version is always correct).
Specifically, it’s because the optimised 387 code is doing the math in double extended precision inside the FPU. 10.0*1e308 fits in 80bits but not in 64bit. Any code that forces it to be stored and loaded gets the correct result too. e.g.
mtaylor@drizzle-dev:~$ cat test-simple.c
#include <stdio.h> #include <math.h> int main() {        double a= 10.0;        double b= 1e+308;    volatile   double c= a*b;        printf("%dn", isinf(c));        return 0; }
mtaylor@drizzle-dev:~$ gcc -o test-simple test-simple.c
mtaylor@drizzle-dev:~$ ./test-simple
1
With this code you can easily see the load and store:
 8048407:      dc 0d 18 85 04 08      fmull 0x8048518 804840d:      dd 5d f0               fstpl -0x10(%ebp)  8048410:      dd 45 f0               fldl  -0x10(%ebp)  8048413:      d9 e5                  fxam
While if you remove volatile, the load and store doesn’t happen (at least on -O3, on -O0 it hasn’t been optimised away):
 8048407:      dc 0d 18 85 04 08      fmull 0x8048518  804840d:      c7 44 24 04 10 85 04   movl  $0x8048510,0x4(%esp)  8048414:      08  8048415:      c7 04 24 01 00 00 00   movl  $0x1,(%esp)  804841c:      d9 e5                  fxam
This is also a regression from 4.2.4 as it just calls isinf() and doesn’t expand the 387 code inline. My guess is the 387 optimisation was added in 4.3.
Recommended fix: store and load in the 387 version so to operate on same precision as elsewhere.
Now I just have to make a patch I like that makes Drizzle behave because of this (showed up as a failure in the SQL func_math test) and then submit to MySQL as well… as this may happen there if “correctly” built.