f00*_*0id 4 floating-point llvm compiler-optimization
往上看.我写了示例函数:
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
}
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
为什么我使用时优化两个函数
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
Run Code Online (Sandbox Code Playgroud)
第一行可以安全地转换为fmul double %x 2.0e+0,但这实际上并不是大多数体系结构的优化(fadd通常是快速或快速fmul,并且不需要生成常量2.0).请注意,除非溢出,否则此操作是精确的(就像所有按2的幂缩放一样).
%addtmp1 = fadd double %addtmp, %x
Run Code Online (Sandbox Code Playgroud)
这条线可以转换为fmul double %x 3.0e+0.为什么这是法律转型?因为所产生的计算%addtmp是精确的,所以只有一个舍入尚未发生,这是否被计算为x * 3或x + x + x.因为这些是IEEE-754基本操作,因此正确舍入,结果是相同的.溢出怎么样?除非对方也这样做,否则两者都不会溢出.
%addtmp2 = fadd double %addtmp1, %x
Run Code Online (Sandbox Code Playgroud)
这是第一行不能合法地转换为常数*x. 4 * x将完全计算,没有任何舍入,而x + x + x + x导致两个舍入:x + x + x舍入一次,然后添加x可能第二次.
%addtmp3 = fadd double %addtmp2, %x
Run Code Online (Sandbox Code Playgroud)
同上这里; 5 * x会产生一个四舍五入; x + x + x + x + x招致三个.
这可能是有益的转化唯一的线可能会被替换x + x + x用3 * x.但是,子表达式x + x已存在于其他位置,因此优化器很容易选择不使用此转换(因为如果不这样,它可以利用现有的部分结果).