为什么不LLVM经过优化浮动点说明? [重复](Why don't LLVM passe

2019-09-21 04:47发布

这个问题已经在这里有一个答案:

  • 为什么不GCC优化A * A * A * A * A * A到(A * A * A)*(A * A * A)? 12个回答

往上看。 我写信给样品的功能:

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。

Answer 1:

这不是很肯定地说, 没有优化是可能的。 我会去通过第几行,以显示其中转换是和不允许:

  %addtmp = fadd double %x, %x

这第一条线可以安全地转化为fmul double %x 2.0e+0 ,但实际上并不是在大多数架构优化( fadd一般为快或快于fmul ,并且不需要产生恒定2.0 )。 请注意,除非溢出,此操作准确(如通过两个大国的所有缩放)。

  %addtmp1 = fadd double %addtmp, %x

这条线可以转化到fmul double %x 3.0e+0 。 为什么这是一个合法的转型? 因为所产生的计算%addtmp是精确的,所以只有一个舍入尚未发生,这是否被计算为x * 3x + x + x 。 因为这些是IEEE-754的基本操作,因此正确的舍入,结果是一样的两种方式。 怎么样溢出? 无论是可能溢出除非对方确实也是如此。

  %addtmp2 = fadd double %addtmp1, %x

这是一个不能被合法地转化为常量* X的第一行。 4 * x将计算准确,而没有任何舍入,而x + x + x + x招致2个圆角: x + x + x是圆形一次,然后添加x可以舍入的第二时间。

  %addtmp3 = fadd double %addtmp2, %x

这里同上; 5 * x会招致一个舍入; x + x + x + x + x即被三人。

这可能是有益的转化唯一的线可能会被替换x + x + x3 * x 。 然而,子表达式x + x是已经存在的其他地方,所以优化器很容易可以选择不采用这种转换(因为它可以利用现有的部分结果的优势,如果事实并非如此)。



文章来源: Why don't LLVM passes optimize floating point instructions? [duplicate]