Почему GCC реализует isnan () более эффективно для C ++ <cmath>, чем C <math.h>?
Вот мой код:
int f(double x)
{
return isnan(x);
}
Если я#include <cmath>
Я получаю эту сборку:
xorl %eax, %eax
ucomisd %xmm0, %xmm0
setp %al
Это достаточно умно:ucomisd устанавливает флаг четности, если сравнение x с самим собой неупорядочено, что означает, что x равен NAN. затемЗАД копирует флаг четности в результат (только один байт, следовательно, начальная очистка%eax
).
Но если я#include <math.h>
Я получаю эту сборку:
jmp __isnan
Теперь код не является встроенным, и__isnan
Функция, конечно, не быстрее, чемucomisd
инструкция, поэтому мы понесли скачок без пользы. Я получаю то же самое, если я компилирую код как C.
Теперь, если я изменюisnan()
позвонить__builtin_isnan()
Я получаю простоеucomisd
инструкция инструкция независимо от того, какой заголовок я включаю, и она работает в Си тоже. Точно так же, если я простоreturn x != x
.
Итак, мой вопрос, почему C<math.h>
заголовок обеспечивает менее эффективную реализациюisnan()
чем C ++<cmath>
заголовок? Люди действительно должны использовать__builtin_isnan()
и если да, то почему?
Я тестировал GCC 4.7.2 и 4.9.0 на x86-64 с-O2
а также-O3
оптимизация.