Search code examples
coptimizationnan

Is `isnan()` as fast as testing equality?


In C, is testing if a float is NaN as fast as testing if two floats are equal? That is is isnan() as fast a simple equality test between two floats?

My particular interest is using gcc on a standard modern Intel/AMD platform.

Here is a sample piece of C code.

#include <math.h>
int main(double x)
{
  return isnan(x);
}

Solution

  • Using GCC on x64, math.h's isnan(float) compiles to

    jmp __isnanf
    

    Using tail-call optimization, but effectively calling a function. The called function will have to do something equivalent to the code a bit down, at least I don't see any faster way to implement it. That leaves the question how it compares to a comparison unanswered however.

    But that doesn't say anything about how fast "testing if a float is NaN" is, because there isn't just the one way to do it. The most direct way,

    int isnan2(float x)
    {
      return x != x;
    }
    

    Is literally the same thing as comparing floats at the C level. But GCC makes this:

    xor eax, eax
    ucomiss xmm0, xmm0
    setp    al
    ret
    

    Which is not quite the same thing as comparing two floats, but close, and in fact a bit faster. Testing for equality means the unordered case tested, as it is here, but then the z flag also has to be tested, like this (from gcc again)

    xor eax, eax
    mov edx, 1
    ucomiss xmm0, xmm1
    setp    al
    cmovne  eax, edx
    ret
    

    Bonus: using <cmath> makes isnan compile to the same thing as comparing a float to itself, see the linked question for why.

    Godbolt link for convenience

    I now see you actually had double, but that doesn't change anything qualitatively.