使用{setp`而不是`setb`有优势吗?

时间:2018-07-16 19:18:44

标签: c gcc x86 clang compiler-optimization

编译时

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有什么优势吗?还是巧合的是,两个编译器都使用奇偶校验标志?

PS:以下是Understanding compilation result for std::isnan之后的问题

1 个答案:

答案 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)