Почему GCC реализует isnan () более эффективно для C ++ <cmath>, чем C <math.h>?

Вот мой код:

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

Если я#include <cmath>&nbsp;Я получаю эту сборку:

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

Это достаточно умно:ucomisd&nbsp;устанавливает флаг четности, если сравнение x с самим собой неупорядочено, что означает, что x равен NAN. затемЗАД&nbsp;копирует флаг четности в результат (только один байт, следовательно, начальная очистка%eax).

Но если я#include <math.h>&nbsp;Я получаю эту сборку:

jmp     __isnan

Теперь код не является встроенным, и__isnan&nbsp;Функция, конечно, не быстрее, чемucomisd&nbsp;инструкция, поэтому мы понесли скачок без пользы. Я получаю то же самое, если я компилирую код как C.

Теперь, если я изменюisnan()&nbsp;позвонить__builtin_isnan()Я получаю простоеucomisd&nbsp;инструкция инструкция независимо от того, какой заголовок я включаю, и она работает в Си тоже. Точно так же, если я простоreturn x != x.

Итак, мой вопрос, почему C<math.h>&nbsp;заголовок обеспечивает менее эффективную реализациюisnan()&nbsp;чем C ++<cmath>&nbsp;заголовок? Люди действительно должны использовать__builtin_isnan()и если да, то почему?

Я тестировал GCC 4.7.2 и 4.9.0 на x86-64 с-O2&nbsp;а также-O3&nbsp;оптимизация.