编译时
double isnan(double x){
return x!=x
}
clang and gcc utilize和奇偶标志PF
:
_Z6is_nand: # @_Z6is_nand
ucomisd %xmm0, %xmm0
setp %al
retq
但是,the comparison的两个可能结果是:
NaN Not-Nan
ZF 1 1
PF 1 0
CF 1 0
这意味着也可以使用CF
标志作为替代,即使用setb
代替setp
。
与setp
相比,使用setb
有什么优势吗?还是巧合的是,两个编译器都使用奇偶校验标志?
答案 0 :(得分:8)
优点是,编译器自然会发出此代码,而无需特殊情况来识别x!=x
并将其转换为!(x >= x)
。
没有-ffast-math的情况下,x != y
必须检查PF以查看比较是否已排序,然后检查ZF是否相等。在两个输入相同的特殊情况下,大概的常规优化机制(如CSE)可以摆脱ZF检查,而仅留下PF。
在这种情况下,setb
不会更糟,但它绝对没有优势,对人类来说更令人困惑,并且可能需要更多特殊情况的代码供编译器发出
建议的转换仅在将结果与使用adc
之类的使用CF的特殊指令一起使用时才有用。例如,nan_counter += arr[i] != arr[i]
。可以自动矢量化(cmp_unord_ps
/ psubd
),但是标量清理(或非数组输入的标量用例)可以使用 ucomiss
/ {{1} },而不是adc $0, %eax
/ ucomiss
/ setp
。
这样可以保存一条指令,以及在Broadwell和更高版本以及AMD上的uop。 (较早的Intel CPU具有2 uop adc,除非它们是特殊情况的add
,因为它们不支持3输入uops)