#include <stdio.h> #include <math.h> int main() { double a= 10.0; double b= 1e+308; printf("%d %d %d\n", isinf(a*b), __builtin_isinf(a*b), __isinf(a*b)); return 0; }
mtay...@drizzle-dev:~$ gcc -o test test.c mtay...@drizzle-dev:~$ ./test 0 0 1 mtay...@drizzle-dev:~$ gcc -o test test.c -std=c99 mtay...@drizzle-dev:~$ ./test 1 0 1 mtay...@drizzle-dev:~$ gcc -o test test.c -mfpmath=sse -march=pentium4 mtay...@drizzle-dev:~$ ./test 1 1 1 mtay...@drizzle-dev:~$ g++ -o test test.c mtay...@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. mtay...@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("%d\n", isinf(c)); return 0; } mtay...@drizzle-dev:~$ gcc -o test-simple test-simple.c mtay...@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. -- Summary: 387 optimised __builtin_isinf() gives incorrect result Product: gcc Version: 4.3.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: regression AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: stewart at flamingspork dot com GCC build triplet: gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12) GCC host triplet: i486-linux-gnu GCC target triplet: i486-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39228