了解std :: isnan的编译结果

ead*_*ead 9 c++ optimization x86 gcc ieee-754

我一直认为,测试NANvia 之间几乎没有区别

  • x!=x

要么

  • std::isnan(x)

但是,gcc为这两个版本提供了不同的汇编程序(在godbolt.org上直播):

  ;x!=x:
  ucomisd %xmm0, %xmm0
  movl $1, %edx
  setne %al
  cmovp %edx, %eax
  ret

  ;std::isnan(x)
  ucomisd %xmm0, %xmm0
  setp %al
  ret
Run Code Online (Sandbox Code Playgroud)

但是,我很难理解这两个版本.我天真的尝试编译std::isnan(x)将是:

  ucomisd %xmm0, %xmm0
  setne %al   ;return true when not equal
  ret
Run Code Online (Sandbox Code Playgroud)

但我必须遗漏一些东西.

可能在x!=x-version中缺少优化(编辑:它可能是gcc-8.1中回归).

是,是我的问题,为什么奇偶标志(setp,PF=1(),而不是平等的标志setne,ZF=0)用在第二个版本?

ead*_*ead 2

结果x!=x是由于gcc-8 引入的回归,clang 为两个版本生成相同的汇编程序。

ucomisd@tkausl 指出了我对运行方式的误解。该操作的结果可以是:

        unordered       <       >       ==
ZF         1            0       0       1
PF         1            0       1       0
CF         1            1       0       0
Run Code Online (Sandbox Code Playgroud)

ucomisd %xmm0, %xmm在只有结果“无序”和“==”的情况下是可能的。

的情况NaN是无序的,并且该 ZF 的设置与 的情况相同==。因此,我们可以使用标志PFCF来区分两种可能的结果。