了解 std::isnan 的编译结果

Understanding compilation result for std::isnan

我一直认为,通过

测试 NAN 之间几乎没有区别

但是,gcc 为两个版本 (live on godbolt.org) 提供了不同的汇编器:

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

  ;std::isnan(x)
  ucomisd %xmm0, %xmm0
  setp %al
  ret

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

  ucomisd %xmm0, %xmm0
  setne %al   ;return true when not equal
  ret

但我一定是漏掉了什么。

可能 x!=x 版本中缺少优化(编辑:可能是 regression in gcc-8.1)。

我的问题是,为什么在第二个版本中使用奇偶校验标志(setp, PF=1) and not the equal flag (setneZF=0)?

x!=x的结果是由于regression introduced to gcc-8,clang为两个版本生成相同的汇编器。

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

        unordered       <       >       ==
ZF         1            0       0       1
PF         1            0       1       0
CF         1            1       0       0

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

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