¿Por qué GCC implementa isnan () de manera más eficiente para C ++ <cmath> que C <math.h>?

Aquí está mi código:

int f(double x)
{
  return isnan(x);
}

Si yo#include <cmath> Me sale esta asamblea:

xorl    %eax, %eax
ucomisd %xmm0, %xmm0
setp    %al

Esto es razonablemente inteligente:ucomisd establece el indicador de paridad si la comparación de x consigo misma no está ordenada, lo que significa que x es NAN. Entoncessetp copia el indicador de paridad en el resultado (solo un byte, de ahí el borrado inicial de%eax)

Pero si yo#include <math.h> Me sale esta asamblea:

jmp     __isnan

Ahora el código no está en línea, y el__isnan la función ciertamente no es más rápida que laucomisd instrucción, por lo que hemos incurrido en un salto sin beneficio. Me sale lo mismo si compilo el código como C.

Ahora si cambio elisnan() llamar a__builtin_isnan(), Me sale lo simpleucomisd instrucción, independientemente del encabezado que incluya, y también funciona en C. Del mismo modo si soloreturn x != x.

Entonces mi pregunta es, ¿por qué la C<math.h> el encabezado proporciona una implementación menos eficiente deisnan() que el C ++<cmath> ¿encabezamiento? ¿Se espera que la gente realmente use__builtin_isnan()y si es así, ¿por qué?

Probé GCC 4.7.2 y 4.9.0 en x86-64 con-O2 y-O3 mejoramiento.

Respuestas a la pregunta(1)

Su respuesta a la pregunta