Joh*_*nck 42 c c++ optimization nan constantfolding
这是我的代码:
int f(double x)
{
return isnan(x);
}
Run Code Online (Sandbox Code Playgroud)
如果我#include <cmath>得到这个集会:
xorl %eax, %eax
ucomisd %xmm0, %xmm0
setp %al
Run Code Online (Sandbox Code Playgroud)
这是相当聪明的:如果x与其自身的比较是无序的,则ucomisd设置奇偶校验标志,意味着x是NAN.然后setp将奇偶校验标志复制到结果中(只有一个字节,因此最初清除%eax).
但是,如果我#include <math.h>得到这个集会:
jmp __isnan
Run Code Online (Sandbox Code Playgroud)
现在代码不是内联的,并且__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 .
Rap*_*ptz 17
查看<cmath>gcc 4.9附带的libstdc ++,你会得到:
constexpr bool
isnan(double __x)
{ return __builtin_isnan(__x); }
Run Code Online (Sandbox Code Playgroud)
一个constexpr功能可以积极内联,当然,该功能仅委派过工作__builtin_isnan.
该<math.h>头不使用__builtin_isnan,而它使用的__isnan是一种长在这里贴上实现,但它是线430 math.h在我的机器上™.由于C99标准要求使用宏isnan等(C99标准的第7.12节),'功能'定义如下:
#define isnan(x) (sizeof (x) == sizeof (float) ? __isnanf (x) \
: sizeof (x) == sizeof (double) ? __isnan (x) \
: __isnanl (x))
Run Code Online (Sandbox Code Playgroud)
但是,我认为没有理由不能使用它__builtin_isnan,__isnan所以我怀疑这是一种疏忽.正如Marc Glisse在评论中指出的那样,有一个相关的错误报告用于isinf代替类似的问题isnan.