我一直认为,测试 NAN 通过
NAN
x!=x
或
std::isnan(x)
但是,GCC为这两个版本提供了不同的汇编程序。( live on 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
但是,我很难理解这两个版本。我的天真尝试编译 STD::ISNANN(X) 将是:
STD::ISNANN(X)
ucomisd %xmm0, %xmm0 setne %al ;return true when not equal ret
但我一定错过了什么。
可能,在 X!= X -版本(编辑:可能是 regression in gcc-8.1 )
X!= X
我的问题是,为什么是均等标志( setp , PF=1 )而不是平等的旗帜( setne , ZF=0 )在第二个版本中使用?
setp
PF=1
setne
ZF=0
结果 x!=x 是由于 regression introduced to gcc-8 ,clang为两个版本生成相同的汇编程序。
我对路的误解 ucomisd @tkausl指出它的功能是否正常。此操作的结果可以是:
ucomisd
unordered < > == ZF 1 0 0 1 PF 1 0 1 0 CF 1 1 0 0
如果是 ucomisd %xmm0, %xmm 只有结果“无序”和“==”是可能的。
ucomisd %xmm0, %xmm
关于 NaN 是无序的,对于此ZF的设置与 == . 所以我们可以用旗子 PF 和 CF 区分两种可能的结果。
NaN
==
PF
CF