This question already has answers here:
Why doesn't GCC optimize a*a*a*a*a*a to (a*a*a)*(a*a*a)?
(12个答案)
7年前关闭。
看上面。我写了一些示例函数:
为什么当我使用两个函数优化时
的
是由于标志设置不同吗?我知道
我正在使用LLVM 3.1。
第一行可以安全地转换为
该行可以转换为
这是第一行,不能合法地转换为常数* x。
同上
唯一可以进行有益转换的行是将
(12个答案)
7年前关闭。
看上面。我写了一些示例函数:
source.ll:
define i32 @bleh(i32 %x) {
entry:
%addtmp = add i32 %x, %x
%addtmp1 = add i32 %addtmp, %x
%addtmp2 = add i32 %addtmp1, %x
%addtmp3 = add i32 %addtmp2, %x
%addtmp4 = add i32 %addtmp3, 1
%addtmp5 = add i32 %addtmp4, 2
%addtmp6 = add i32 %addtmp5, 3
%multmp = mul i32 %x, 3
%addtmp7 = add i32 %addtmp6, %multmp
ret i32 %addtmp7
}
source-fp.ll:
define double @bleh(double %x) {
entry:
%addtmp = fadd double %x, %x
%addtmp1 = fadd double %addtmp, %x
%addtmp2 = fadd double %addtmp1, %x
%addtmp3 = fadd double %addtmp2, %x
%addtmp4 = fadd double %addtmp3, 1.000000e+00
%addtmp5 = fadd double %addtmp4, 2.000000e+00
%addtmp6 = fadd double %addtmp5, 3.000000e+00
%multmp = fmul double %x, 3.000000e+00
%addtmp7 = fadd double %addtmp6, %multmp
ret double %addtmp7
}
为什么当我使用两个函数优化时
opt -O3 source[-fp].ll -o opt.source[-fp].ll -S
的
i32
进行了优化,而double
却没有进行优化?我期望fadd
可以合并为一个fmul
。相反,它看起来完全一样。是由于标志设置不同吗?我知道
i32
可能无法使用double
进行某些优化。但是缺少简单的恒定折叠是我无法理解的。我正在使用LLVM 3.1。
最佳答案
说没有优化是不可能的。我将浏览前几行,以显示在何处和不允许进行转换:
%addtmp = fadd double %x, %x
第一行可以安全地转换为
fmul double %x 2.0e+0
,但这实际上并不是大多数体系结构上的优化(fadd
通常比fmul
快或快,并且不需要生成常量2.0
)。请注意,除非发生溢出,否则此操作是精确的(就像所有按2的幂进行缩放一样)。 %addtmp1 = fadd double %addtmp, %x
该行可以转换为
fmul double %x 3.0e+0
。为什么这是合法的转变?因为产生%addtmp
的计算是精确的,所以无论将其作为x * 3
还是x + x + x
进行计算,都仅会进行一次舍入。由于这些是IEEE-754基本操作,因此可以正确舍入,因此两种方法的结果都是相同的。那溢出呢?除非对方也没有,否则任何一方都不会溢出。 %addtmp2 = fadd double %addtmp1, %x
这是第一行,不能合法地转换为常数* x。
4 * x
将精确计算,不进行任何舍入,而x + x + x + x
则进行两次舍入:x + x + x
舍入一次,然后添加x
可能会舍入第二次。 %addtmp3 = fadd double %addtmp2, %x
同上
5 * x
将导致四舍五入; x + x + x + x + x
产生三个。唯一可以进行有益转换的行是将
x + x + x
替换为3 * x
。但是,子表达式x + x
已经存在于其他位置,因此优化器可以轻松地选择不采用此转换(因为如果不这样做,则可以利用现有的部分结果)。关于floating-point - LLVM为什么不通过优化浮点指令?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11942527/