问题描述
下面是我的code:
int f(double x)
{
return isnan(x);
}
如果我的#include<&CMATH GT;
我得到这个组件:
If I #include <cmath>
I get this assembly:
xorl %eax, %eax
ucomisd %xmm0, %xmm0
setp %al
这是合理巧妙:设置奇偶标志如果x与自身的比较是无序的,意义x是NAN。然后复制奇偶标志到结果(仅一个字节,因此,初步明确的%EAX
)。
This is reasonably clever: ucomisd sets the parity flag if the comparison of x with itself is unordered, meaning x is NAN. Then setp copies the parity flag into the result (only a single byte, hence the initial clear of %eax
).
但是,如果我的#include&LT;&math.h中GT;
我得到这个组件:
But if I #include <math.h>
I get this assembly:
jmp __isnan
现在的code不是内联的,而 __ isnan
功能肯定是没有更快的 ucomisd
指令,所以我们发生的没有任何好处的跳跃。我得到同样的事情,如果我编译code为C
Now the code is not inline, and the __isnan
function is certainly no faster the the ucomisd
instruction, so we have incurred a jump for no benefit. I get the same thing if I compile the code as C.
现在,如果我更改 isnan()
来电 __ builtin_isnan()
,我得到了简单的 ucomisd
指令的指令,无论我包括头,和它的作品用C了。同样,如果我只是返回X!= X
。
Now if I change the isnan()
call to __builtin_isnan()
, I get the simple ucomisd
instruction instruction regardless of which header I include, and it works in C too. Likewise if I just return x != x
.
所以我的问题是,为什么而作C &LT;文件math.h&GT;
头提供了一个低效率的实施 isnan的()
比C ++ &LT;&CMATH GT;
头?难道人们真的指望用 __ builtin_isnan()
,如果是这样,为什么?
So my question is, why does the C <math.h>
header provide a less efficient implementation of isnan()
than the C++ <cmath>
header? Are people really expected to use __builtin_isnan()
, and if so, why?
我测试GCC 4.7.2和4.9.0的X86-64与 -O2
和 -O3
优化
I tested GCC 4.7.2 and 4.9.0 on x86-64 with -O2
and -O3
optimization.
推荐答案
看着&LT; CMATH&GT;
随海湾合作委员会的libstdc ++ 4.9你会得到这样的:
Looking at <cmath>
for libstdc++ shipped with gcc 4.9 you get this:
constexpr bool
isnan(double __x)
{ return __builtin_isnan(__x); }
A constexpr
函数可积极内联,当然,该功能仅委派到 __ builtin_isnan
工作
A constexpr
function could be aggressively inlined and, of course, the function just delegates the work over to __builtin_isnan
.
的&LT;文件math.h&GT;
头不使用 __ builtin_isnan
,而是使用了一个 __ isnan
实施这是一种长在这里贴,但它的线条文件math.h
430在我的机器上™。由于C99标准要求使用宏 isnan
等(C99标准第7.12)的功能的定义如下:
The <math.h>
header doesn't use __builtin_isnan
, rather it uses an __isnan
implementation which is kind of long to paste here but it's lines 430 of math.h
on my machine™. Since the C99 standard requires using a macro for isnan
et al (section 7.12 of the C99 standard) the 'function' is defined as follows:
#define isnan(x) (sizeof (x) == sizeof (float) ? __isnanf (x) \
: sizeof (x) == sizeof (double) ? __isnan (x) \
: __isnanl (x))
不过,我不明白为什么它不能使用 __ builtin_isnan
而不是 __ isnan
所以我怀疑它是一个监督。正如马克·Glisse在评论中指出,有一个 C $ C> isinf 而不是 isnan
。
However, I see no reason why it can't use __builtin_isnan
instead of __isnan
so I suspect it's an oversight. As Marc Glisse points out in the comments, there is a relevant bug report for a similar issue using isinf
instead of isnan
.
这篇关于为什么GCC实现isnan()更有效地用于C ++&LT;&CMATH GT;比C&LT;&math.h中GT ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!