我有四个恒等函数,它们基本上什么都不做。只有与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,-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
。 - Lundin