优化传递将条件分支转换为跳转

时间:2014-09-26 19:58:28

标签: compiler-construction compiler-optimization

在优化编译器中,冗余代码可以被多次检测并通过不同的算法消除,例如值编号,稀疏条件常数传播等。在这种情况下,我对检测冗余分支感兴趣。假设目标代码是

block1:
    cmp r1, r2
    jne block3

block2:
    cmp r1, r2
    je block4

block3:
    ...     
block4:
    ...     
...

在这种情况下,如果控件达到block2,则表示r1r2相等,因此je block4可以替换为jmp block4。此外,如果在block2中说jne block4,那么我们可以完全删除je

然后我的问题是,什么优化传递捕获这种代码?我想可以扩展价值编号以解决这个问题,但从未在参考书目中看到它,所以也许有更好的方法。

修改:更正了第一次跳转,其中说je block3它应该说jne block3

3 个答案:

答案 0 :(得分:1)

好吧,假设在其他地方没有其他分支到block2中,编译器的布尔传播应该捕获它。当然,根据编译器的不同,还有其他各种阶段也可以做优化。

取决于bool prop算法,可能发生的情况是块3保持数据流值为" R1!= R2"它将传播到它下面的所有块。块2同样具有值" R1 == R2"它也会传播到后续的块(根据数据流),从而在途中移除死枝。

希望这有帮助。

答案 1 :(得分:0)

我不确定优化通行证的名称是否完全标准化,我现在无法找到Muchnick的副本,但在我上次编写的编译器中,您描述的情况会在两个阶段中检测 - 一个优化过程将检测到二次比较是多余的,并将其删除,后续传递将检测到相等跳转不需要是有条件的。

但并非每个编译器都进行此类优化。

答案 2 :(得分:0)

优化通常在您进行装配之前很久就会发生,而是某种形式的中间表示。

不同形式的IR会有所不同,但一个典型的方面是它们在无限的寄存器集上运行,而不是在机器寄存器上运行,并且每个寄存器都不能更改,只能初始化一次。 (如果你需要可变变量,你需要在堆栈上alloca指针,然后通过它load / store。优化的第一个也是最困难的阶段是从分配转换基于SSA,以便所有其他优化,如此,可以完成)

此示例使用LLVM IR。

define void @func2(i32 %r1, i32 %r2) {
block1:
  %0 = icmp ne i32 %r1, %r2
  br i1 %0, label %block3, label %block2

block2:                                           ; preds = %block1
  %1 = icmp eq i32 %r1, %r2
  br i1 %1, label %block4, label %block3

block3:                                           ; preds = %block2, %block1
  unreachable

block4:                                           ; preds = %block2
  unreachable
}

现在应该相当直观%1的定义可以用%1 = xor i1 %1, true替换(这是布尔not看起来像),然后可以传播常量通往block2的唯一边缘。