为什么编译器不能优化0浮点加法? [英] Why can the compiler not optimize floating point addition with 0?
问题描述
我有四个身份函数,它们基本上什么都不做。通过clang只能将 1
的乘法优化为单个 ret
语句。
I have four identity functions which do essentially nothing. Only multiplication with 1
could be optimized by clang to a single ret
statement.
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)
And the following compiler output is: (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
I可以理解为什么 id0
和 id2
无法优化。它们会增加值,然后变成正无穷大,第二个操作不会将其改回。
I can understand why id0
and id2
can't be optimized. They increase the value which could then turn into positive infinity and the second operation would not change it back.
但是为什么不能 id1
是否可以优化?具有无穷大的加法将产生无穷大,具有任何常规数的加法将产生该数,具有 NaN
的加法将产生 NaN
。那么为什么它不是像 * 1
这样的真实身份操作。
But why can't id1
be optimized? Additon with infinity would yield infinity, addition with any regular number would yield that number and addition with NaN
would yield NaN
. So why is it not a "true" identity operation like * 1
.
推荐答案
IEEE 754个浮点数具有两个零值,一个负数,一个正数。
IEEE 754 floating-point numbers have two zero values, one negative, one positive. When added together, the result is the positive one.
所以 id1(-0.f)
是 0.f
,而不是 -0.f
。
请注意, id1 (-0.f)== -0.f
,因为 0.f == -0.f
。
So id1(-0.f)
is 0.f
, not -0.f
.
Note that id1(-0.f) == -0.f
because 0.f == -0.f
.
另外,请注意,在GCC中使用 -ffast-math
进行编译确实可以进行优化并更改结果。
Also, note that compiling with -ffast-math
in GCC does make the optimization and changes the result.
这篇关于为什么编译器不能优化0浮点加法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!