Compiler construction 将条件分支转换为跳转的优化过程

Compiler construction 将条件分支转换为跳转的优化过程,compiler-construction,compiler-optimization,Compiler Construction,Compiler Optimization,在优化编译器中,冗余代码可以通过不同的算法多次检测和消除,如值编号、稀疏条件常数传播等。在这种情况下,我感兴趣的是检测冗余分支。假设目标代码是 block1: cmp r1, r2 jne block3 block2: cmp r1, r2 je block4 block3: ... block4: ... ... 在这种情况下,如果控制达到block2,则意味着r1和r2相等,因此je block4可以替换为jmp bl

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

block1:
    cmp r1, r2
    jne block3

block2:
    cmp r1, r2
    je block4

block3:
    ...     
block4:
    ...     
...
在这种情况下,如果控制达到
block2
,则意味着
r1
r2
相等,因此
je block4
可以替换为
jmp block4
。此外,如果在block2中表示
jne block4
,那么我们可以完全删除
je

那么我的问题是,什么样的优化过程可以捕获这种代码?我想价值编号可以扩展以解决这个问题,但在参考书目中从未见过,所以也许有更好的方法


Edit:更正了第一个跳转,它说的是
je block3
它应该说
jne block3
好吧,假设没有其他分支从任何地方进入block2,编译器的布尔传播应该会捕捉到这一点。当然,根据编译器的不同,还有其他各种阶段也可以进行优化

根据bool-prop算法,块3可能会保存一个“R1!=R2”的数据流值,该值将传播到它下面的所有块。块2将类似地具有“R1==R2”的值,该值也将传播到后续块(根据数据流),从而移除途中的死分支


希望这能有所帮助。

我不确定优化过程的名称是否完全标准化,目前我无法找到的副本,但在我上一次使用的编译器中,您描述的情况将分两个阶段检测到-一个优化过程将检测到二次比较是冗余的,并将其删除,随后的过程将检测到相等跳转不需要是有条件的


但并不是每个编译器都会进行这种类型的优化。

优化通常发生在您开始汇编之前很久,而是某种形式的中间表示

不同形式的IR各不相同,但一个典型的方面是,它们在无限多个寄存器上运行,而不是在机器寄存器上运行,并且每个寄存器不能更改,只能初始化一次。(如果您需要可变变量,则需要
alloca
堆栈上的指针,然后
加载
/
存储
。优化的第一个也是最困难的阶段是从基于alloca转换为基于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
(这是布尔
而不是
看起来的样子),然后常数可以在通向
块2
的唯一边上分布