考虑以下函数:
static inline float Eps(const float x) {
const float eps = std::numeric_limits<float>::epsilon();
return (1.0f + eps) * x - x;
}
float Eps1() {
return Eps(0xFFFFFFp-24f);
}
float Eps2() {
const float eps = std::numeric_limits<float>::epsilon();
const float x = 0xFFFFFFp-24f;
return (1.0f + eps) * x - x;
}
Run Code Online (Sandbox Code Playgroud)
在-O2with中-std=c++20,这两个函数都编译为一个函数,movss后跟一个ret针对 x86 的 using clang 16.0.0 和mov一个bx针对 ARM 的 with gcc 11.2.1。为 ARM 生成的程序集与返回值 ~5.96e-8 一致,但为 x86 生成的程序集则不然。 …
如clang 14.0.0 浮点优化的答案所示,自版本 14 起,Clang 即使对于在编译时执行的常量计算也应用融合乘法加法 (FMA) 指令。
同时,我们可以观察到结果取决于表达式参数的形式恒定性:
#include <stdio.h>
int main() {
const float A = 2.1f;
const float B = 0.1f;
float C = 0.1f;
float V = A * B - A * B;
float W = A * C - A * C;
printf( "%g %g", V, W );
}
Run Code Online (Sandbox Code Playgroud)
在 Clang 中,程序打印0 1.49011e-10,在线演示:https://godbolt.org/z/a3fcYG7ob
从汇编代码可以看出, 和V都是W在编译时求值的。是否有一些规则规定只能W使用 FMA 指令进行评估?
添加-mno-fma用于禁用 FMA 指令的命令行选项不会改变结果中的任何内容。
我刚刚了解到,C 中的加法运算比乘法运算更快。因此,我很好奇(a+b)*c计算速度是否会比 C 更快a*c+b*c?