------- Comment #14 from iano at apple dot com 2006-08-22 18:25 -------
For your amusement: [ollmia:/tmp] iano% cat main.c #include <stdio.h> extern int __isnand( double ); static __inline__ int __inline_isnan( double __a ) { if( __builtin_isnan( __builtin_nan("") ) ) return __builtin_isnan( __a ); return __isnand( __a); //this is our isnan() compiled in a separate compilation unit that always works } int main( void ) { volatile double g = __builtin_nan(""); printf( "isnan(%g) = %d\n", g, __inline_isnan( g ) ); return 0; } [ollmia:/tmp] iano% gcc main.c -O0 -g -ffast-math ; ./a.out isnan(nan) = 0 If you step through in gdb, we see that what the compiler has done here is use the IEEE compare result to determine that __builtin_isnan( __builtin_nan("") ) is always true. It faills through to the next line where, __builtin_isnan() returns always false. For reasons I can't explain, we also see this: [ollmia:/tmp] iano% cat main.c #include <stdio.h> extern int __isnand( double ); static __inline__ int __inline_isnan( double __a ) { static const double nan = __builtin_nan(""); if( nan != nan ) return __a != __a; return __isnand( __a); } int main( void ) { volatile double g = __builtin_nan(""); printf( "isnan(%g) = %d\n", g, __inline_isnan( g ) ); return 0; } [ollmia:/tmp] iano% gcc main.c -O0 -g -ffast-math ; ./a.out isnan(nan) = 1 [ollmia:/tmp] iano% gcc main.c -O3 -g -ffast-math ; ./a.out isnan(nan) = 0 [ollmia:/tmp] iano% gcc main.c -O0 -g -ffinite-math-only ; ./a.out isnan(nan) = 1 [ollmia:/tmp] iano% gcc main.c -O3 -g -ffinite-math-only ; ./a.out isnan(nan) = 0 -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28796