【发布时间】:2014-11-21 01:21:12
【问题描述】:
这是我的代码:
int f(double x)
{
return isnan(x);
}
如果我 #include <cmath> 我得到这个程序集:
xorl %eax, %eax
ucomisd %xmm0, %xmm0
setp %al
这相当聪明:ucomisd 如果 x 与自身的比较是无序的,则设置奇偶校验标志,这意味着 x 是 NAN。然后setp 将奇偶校验标志复制到结果中(只有一个字节,因此%eax 的初始清除)。
但如果我 #include <math.h> 我得到这个程序集:
jmp __isnan
现在代码不是内联的,__isnan 函数肯定没有ucomisd 指令快,所以我们进行了一次跳转,没有任何好处。如果我将代码编译为 C,我会得到同样的结果。
现在,如果我将isnan() 调用更改为__builtin_isnan(),无论我包含哪个标头,我都会得到简单的ucomisd 指令指令,并且它也适用于C。同样,如果我只是 return x != x.
所以我的问题是,为什么 C <math.h> 标头提供的 isnan() 实现效率低于 C++ <cmath> 标头?人们真的希望使用__builtin_isnan(),如果是,为什么?
我在 x86-64 上使用 -O2 和 -O3 优化测试了 GCC 4.7.2 和 4.9.0。
【问题讨论】:
-
这是我的推测:c99之前,c中没有内联函数。没有内联函数意味着函数必须由 jmp/call(或某种分支)调用。 __builtin_isnan 不是 c 的一部分。它可能是特定于平台的内在因素。
-
但像
<math.h>这样的系统头文件肯定可以使用特定于平台的内置插件。 -
我很确定
isnan会尽可能使用__builtin_isnan。我认为您没有理由必须手动调用它。 -
也许当 C99 出现时,没有人想过要回去更新 isnan
标签: c++ c optimization nan constantfolding