我有四个标识函数,它们基本上什么也不做。通过clang仅可以将与1
的乘法优化为单个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
这样的“真实”身份操作。
Example with Compiler Explorer
我有四个标识函数,它们基本上什么也不做。只能通过clang优化单个ret语句来实现与1的乘法。 float id0(float x){return x +1-1; } float id1(...
IEEE 754浮点数具有两个零值,一个负数,一个正数。当加在一起时,结果是肯定的。