Вот мой код:Почему 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 устанавливает флаг четности, если сравнение х с самим собой неупорядоченным, что означает х это NAN. Затем setp копирует флаг четности в результат (только один байт, следовательно, начальный сброс %eax
).
Но если I #include <math.h>
я получаю эту сборку:
jmp __isnan
Теперь код не является встроенным, а функция __isnan
, конечно, не быстрее Поручение ucomisd
, поэтому мы понесли прыгать никакой пользы. Я получаю то же самое, если я компиляции кода, как C.
Теперь, если я изменю isnan()
вызов __builtin_isnan()
, я получаю простую инструкцию ucomisd
инструкции независимо от заголовка включаю, и он работает в C тоже. Точно так же, если я просто return x != x
.
Итак, мой вопрос: почему заголовок C <math.h>
обеспечивает менее эффективную реализацию isnan()
, чем заголовок C++ <cmath>
? Действительно ли люди должны использовать __builtin_isnan()
, и если да, то почему?
Я тестировал GCC 4.7.2 и 4.9.0 на x86-64 с -O2
и -O3
оптимизацией.
вот моя спекуляция: pre c99, нет встроенной функции в c. никакая встроенная функция означает, что функции должны быть вызваны jmp/call (или каким-то разветвлением). __builtin_isnan не входит в c. это, вероятно, определенная платформа. – thang
Но, конечно, системный заголовок, например '', может использовать встроенные встроенные платформы. –
Я уверен, что 'isnan' будет использовать' __builtin_isnan', если это возможно. Я не вижу причин, почему вам придется называть это вручную. – Rapptz