本文介绍了为什么GCC实现isnan()更有效地用于C ++<&CMATH GT;比C<&math.h中GT ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的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 ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 18:36