ead*_*ead 5 c x86 gcc clang compiler-optimization
编译时
double isnan(double x){
return x!=x
}
Run Code Online (Sandbox Code Playgroud)
既铛和gcc利用奇偶标志PF:
_Z6is_nand: # @_Z6is_nand
ucomisd %xmm0, %xmm0
setp %al
retq
Run Code Online (Sandbox Code Playgroud)
然而,这两个可能的结果比较如下:
NaN Not-Nan
ZF 1 1
PF 1 0
CF 1 0
Run Code Online (Sandbox Code Playgroud)
这意味着也可以使用CF-flag作为替代,即setb代替setp.
是否有使用任何优势setp了setb,或者是一个巧合,这两个编译器使用奇偶标志?
PS:这个问题是了解std :: isnan的编译结果
优点是编译器自然地发出此代码,而无需特殊情况来识别x!=x和转换它!(x >= x).
如果没有-ffast-math,x != y必须检查PF以查看比较是否有序,然后检查ZF是否相等.在两个输入都相同的特殊情况下,可能正常的优化机制(如CSE)可以摆脱ZF检查,只留下PF.
在这种情况下,情况setb可能不会更糟,但它绝对没有优势,而且它对人类来说更加混乱,并且可能需要更多特殊情况代码才能让编译器发出它.
只有在使用带有使用CF的特殊指令的结果时,您建议的转换才有用adc.例如,nan_counter += arr[i] != arr[i].这是自动向量化(cmp_unord_ps/ psubd),但标量清理(或非数组输入的标量用例)可以使用ucomiss/ adc $0, %eax而不是ucomiss/ setp/ add.
这节省了一条指令,并且在Broadwell以及后来和AMD上都有所帮助.(早期英特尔CPU有2个uop adc,除非它们是特殊情况$0,因为它们不支持3输入uop)