【发布时间】:2020-09-19 13:52:53
【问题描述】:
我有四个本质上什么都不做的恒等函数。只有与 1 的乘法可以通过 clang 优化为单个 ret 语句。
float id0(float x) {
return x + 1 - 1;
}
float id1(float x) {
return x + 0;
}
float id2(float x) {
return x * 2 / 2;
}
float id3(float x) {
return x * 1;
}
以下编译器输出为:(clang 10, at -O3)
.LCPI0_0:
.long 1065353216 # float 1
.LCPI0_1:
.long 3212836864 # float -1
id0(float): # @id0(float)
addss xmm0, dword ptr [rip + .LCPI0_0]
addss xmm0, dword ptr [rip + .LCPI0_1]
ret
id1(float): # @id1(float)
xorps xmm1, xmm1
addss xmm0, xmm1
ret
.LCPI2_0:
.long 1056964608 # float 0.5
id2(float): # @id2(float)
addss xmm0, xmm0
mulss xmm0, dword ptr [rip + .LCPI2_0]
ret
id3(float): # @id3(float)
ret
我可以理解为什么id0 和id2 无法优化。他们增加这个值,然后可以变成正无穷大,第二次操作不会把它改回来。
但是为什么id1 不能优化呢?具有无穷大的加法将产生无穷大,与任何常规数字相加将产生该数字,而与NaN 相加将产生NaN。那么为什么它不是像* 1这样的“真实”身份操作。
【问题讨论】:
-
这是一个非常好的问题。我不明白为什么我是唯一的支持者。
-
不适用于这些具体示例,但请记住,这些结果仅由运算符关联性保证。也就是说,例如,加法运算符 + 和 - 保证从左到右进行评估。因此,隐式转换为浮点数发生在它应该发生的地方,可能是运气(?)。
x + 1 - 1与1 - 1 + x具有不同的含义。前者相当于(x + (float)1) - (float)1,后者相当于(float)((int)1 - (int)1) + x;。为避免此类错误,请使用浮点常量1.0f。
标签: c++ c optimization compilation compiler-optimization