了解 std::isnan 的编译结果
Understanding compilation result for std::isnan
我一直认为,通过
测试 NAN
之间几乎没有区别
x!=x
或
std::isnan(x)
但是,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 (setne
、ZF=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 的设置与 ==
的情况相同。因此我们可以使用标志 PF
和 CF
来区分两种可能的结果。
我一直认为,通过
测试NAN
之间几乎没有区别
x!=x
或
std::isnan(x)
但是,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 (setne
、ZF=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 的设置与 ==
的情况相同。因此我们可以使用标志 PF
和 CF
来区分两种可能的结果。