Why is GCC implementing isnan () more efficient for C ++ <cmath> than C <math.h>?
Here is my code:
int f(double x) { return isnan(x); } If I #include <cmath> , I get this assembly:
xorl %eax, %eax ucomisd %xmm0, %xmm0 setp %al This is reasonable: ucomisd sets the parity flag if the comparison of x with itself is unordered, that is, x is a NAN. Then setp copies the parity flag to the result (only one byte, hence the initial reset %eax ).
But if I #include <math.h> , I get this assembly:
jmp __isnan Now the code is not string, and the __isnan function, of course, does not speed up the ucomisd instruction, so we suffered a jump without any benefit. I get the same if I compile code like C.
Now, if I change the call of isnan() to __builtin_isnan() , I get a simple ucomisd instruction ucomisd , regardless of which heading I include, and it also works in C. Similarly, if I just return x != x
So my question is: why does the C <math.h> header provide a less efficient implementation of isnan() than the C ++ <cmath> header? Do people intend to use __builtin_isnan() , and if so, why?
I tested GCC 4.7.2 and 4.9.0 on x86-64 with optimizations of -O2 and -O3 .
Looking at the <cmath> for libstdc ++ shipped with gcc 4.9, you get the following:
constexpr bool isnan(double __x) { return __builtin_isnan(__x); } Function A constexpr can be aggressively built in and, of course, the function simply delegates work to __builtin_isnan .
The <math.h> header does not use __builtin_isnan , instead it uses the __isnan implementation, which has been inserted here for quite some time, but on my machine β’ line 430 math.h Because the C99 standard requires the use of a macro for isnan et al (section 7.12 of the C99 standard), a βfunctionβ is defined as follows:
#define isnan(x) (sizeof (x) == sizeof (float) ? __isnanf (x) \ : sizeof (x) == sizeof (double) ? __isnan (x) \ : __isnanl (x)) However, I see no reason why he cannot use __builtin_isnan instead of __isnan , so I suspect this is an oversight. As Mark Gliss notes in the comments, there is a corresponding error report for a similar problem, using isinf instead of isnan .