以下所有说明都做同样的事情:设置%eax为零.哪种方式最佳(需要最少的机器周期)?
xorl %eax, %eax
mov $0, %eax
andl $0, %eax
Run Code Online (Sandbox Code Playgroud) 使用GCC 5.3,以下代码符合 -O3 -fma
float mul_add(float a, float b, float c) {
return a*b + c;
}
Run Code Online (Sandbox Code Playgroud)
生成以下程序集
vfmadd132ss %xmm1, %xmm2, %xmm0
ret
Run Code Online (Sandbox Code Playgroud)
Clang 3.7带-O3 -mfma产品
vmulss %xmm1, %xmm0, %xmm0
vaddss %xmm2, %xmm0, %xmm0
retq
Run Code Online (Sandbox Code Playgroud)
但Clang 3.7与-Ofast -mfmaGCC生成的代码相同-O3 fast.
我很惊讶GCC的确如此,-O3因为从这个答案来看
除非允许使用宽松的浮点模型,否则不允许编译器融合分离的加法和乘法.
这是因为FMA只有一个舍入,而ADD + MUL有两个舍入.因此,编译器将通过融合违反严格的IEEE浮点行为.
但是,从这个链接说
无论FLT_EVAL_METHOD的值如何,任何浮点表达式都可以收缩,即,计算好像所有中间结果都具有无限范围和精度.
所以现在我感到困惑和担忧.
-O3?__STDC_IEC_559__不是一个矛盾吗?由于FMA 可以在软件中进行仿真,因此似乎应该有两个用于FMA的编译器开关:一个用于告诉编译器在计算中使用FMA,一个用于告诉编译器硬件具有FMA.
显然,这可以通过选项进行控制-ffp-contract.对于GCC,默认是-ffp-contract=fast和Clang不一样.其他选项例如 …