常量传播小结

tag:  编译, 编译原理,  优化, 常量传播


不多说 先看结果

//源文件

{ Sample program
in TINY language
}
x:=4;{read x;} { input an integer }
if 0 < x then { don't compute if x <= 0 }
fact := 1;
  repeat
    fact := fact * x; 
    x := x - 1 
  until x = 0; 
  write fact { output factorial of x } 
end



//parser之后未优化的结果

x:= 4
__compare_inner_1:= 0
__compare_inner_2:= x
__compare_inner_0:= __compare_inner_1 < __compare_inner_2
test __compare_inner_0
jz L-else 
fact:= 1
L-repeat: 
__compare_inner_3:= fact
__compare_inner_4:= x
fact:= __compare_inner_3 * __compare_inner_4
__compare_inner_5:= x
__compare_inner_6:= 1
x:= __compare_inner_5 - __compare_inner_6
__compare_inner_8:= x
__compare_inner_9:= 0
__compare_inner_7:= __compare_inner_8 = __compare_inner_9
test __compare_inner_7
jnz L-repeat 
write fact
jmp L-end 
L-esle: 
L-end: 

//常量传播之后

x:= 4
__compare_inner_1:= 0
__compare_inner_2:= 4
__compare_inner_0:= 1 < 4
fact:= 1
__compare_inner_3:= 24
__compare_inner_4:= 1
__compare_inner_5:= 1
__compare_inner_6:= 1
__compare_inner_7:= 1
__compare_inner_8:= 0
__compare_inner_9:= 0
fact:= 24
x:= 0
write fact

//去掉无用的代码

fact:= 24
write fact


if的常量传播只要取两个分支的交集就可以了

while的常量传播麻烦一些, 我是试着传播100次循环, 看在这之内有没有退出while. 如果退出就可以把这个while优化成 if(1), 如果不能退出就重新按while(1)来重新对while优化.

//已经上传到github

https://github.com/0x00-pl/my_prog/tree/dev/mtcc/mtcc

### 关于LLVM编译器中的常量传播Pass #### 常量传播的概念及其重要性 常量传播是一种重要的优化技术,旨在将已知的常量值尽可能广泛地替换到程序中相应的位置。这不仅有助于简化后续的优化过程,还能直接减少运行时不必要的计算开销[^4]。 #### LLVM中的`llvm::ConstantPropagation` Pass 在LLVM框架内,`llvm::ConstantPropagation`属于转换Pass的一种,其主要职责是对基本块内的指令执行常量替代操作。当检测到某条指令的操作数为常量时,则尝试用该常量的具体数值代替原指令的结果;对于条件分支结构,若能确定某一路径必然被执行,则可进一步精简控制流程图[^3]。 #### 实现细节 为了实现有效的常量传播,在编写自定义Pass时通常会遵循如下模式: 1. **继承自`FunctionPass`类** 自定义Pass需作为`llvm::FunctionPass`子类实例化,以便能够遍历函数内部的所有基本块和指令。 2. **重载虚方法runOnFunction()** 此处为核心逻辑所在位置,用于迭代访问每一个BasicBlock对象,并针对其中每一条二元运算符指令检查是否存在可以立即求解的情况——即两个操作数均为常量的情形下可以直接计算出结果并更新原有IR表示形式。 3. **调用API接口完成具体工作** 利用诸如`ReplaceInstWithValue()`这样的辅助工具函数来高效地实施替换动作而不必手动调整SSA形式下的Phi节点关系等复杂事项[^2]. ```cpp bool runOnFunction(Function &F) override { bool Changed = false; for (auto &BB : F){ for (auto I = BB.begin(), E = BB.end(); I != E; ++I){ Instruction *Inst = &*I; if (!isa<BinaryOperator>(Inst)) continue; BinaryOperator *BOp = cast<BinaryOperator>(Inst); Value *LHS = BOp->getOperand(0), *RHS = BOp->getOperand(1); ConstantInt *LCst = dyn_cast<ConstantInt>(LHS), *RCst = dyn_cast<ConstantInt>(RHS); if ((LCst && RCst)){ // 计算新值... Constant *NewVal = ... ; ReplaceInstWithValue(BB.getInstList(), Inst, NewVal); Changed |= true; } } } return Changed; } ``` 上述代码片段展示了如何在一个简单的场景下去识别并处理整型加法表达式的特殊情况,当然实际应用中还需要考虑更多边界情况以及与其他优化手段之间的协作问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值