Files
nudt-compiler-cpp/doc/Lab5-基本标量优化.md
2026-03-09 20:36:26 +08:00

158 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Lab5基本标量优化
## 1. 本实验定位
Lab5 的目标是让 IR 从“能跑”变成“跑的更好”。
在当前编译器基础上,做基础标量优化,框架中给出了三种,可以按需补充:
1. 常量相关优化(常量折叠/传播)
2. 无用代码删除DCE
3. CFG 简化与不可达代码删除
---
## 2. IR 的 use-def 关系
LLVM 中通常维护完整 `Use-User` 双向关系;当前仓库是最小 IR实现较轻量。
### 什么是 use-def
use-def或 def-use描述的是“值在哪里被定义、又在哪里被使用”的关系
1. `def`:某条指令产生了一个值(定义点)。
2. `use`:其他指令把这个值当作操作数使用(使用点)。
在 IR 中维护好这层关系后,优化遍就能快速回答:
“这个值还有人用吗?”、“我要把旧值替换成新值,需要改哪些地方?”
### use-def 的作用
在优化阶段use-def 关系的价值主要体现在:
1. 判断“是否还被使用”更直接
DCE 可以直接依据某个值是否还有用户来决定是否可删,而不必每次全函数扫描。
2. 支持局部重写与传播
常量折叠、常量传播、复制传播时,需要把“旧值的所有使用点”替换为“新值”;有 use-def 后可以精准定位使用点。
3. 降低优化遍实现复杂度
没有 use-def 时,很多优化都要反复做全局查找;有 use-def 后可把复杂度和代码量都压下来。
4. 便于后续扩展更多优化
例如代数化简、CSE、部分冗余消除等都依赖稳定的 def-use/use-def 信息。
这会明显降低 DCE、常量传播等优化的实现复杂度也更利于后续扩展。
---
## 3. Lab5 要求
需要同学完成:
1. 理解当前 IR/CFG 结构,明确“有用代码、无用代码、不可达代码”的定义。
2. 完成可运行标量优化代码。
3. 将优化串联到 `PassManager`,形成可重复执行的优化流程。
4. 保证优化前后语义一致(功能不回归)。
---
## 4. 当前代码框架(与 Lab5 相关)
1. IR 核心
- `src/ir/IR.h`
- `src/ir/Instruction.cpp`
- `src/ir/BasicBlock.cpp`
- `src/ir/Function.cpp`
- `src/ir/Module.cpp`
- `src/ir/IRPrinter.cpp`
2. 分析与优化
- `src/ir/analysis/DominatorTree.cpp`
- `src/ir/analysis/LoopInfo.cpp`
- `src/ir/passes/ConstFold.cpp`
- `src/ir/passes/DCE.cpp`
- `src/ir/passes/CFGSimplify.cpp`
- `src/ir/passes/PassManager.cpp`
3. 入口
- `src/main.cpp`
---
## 5. 需要修改的文件
1. 核心优化实现
- `src/ir/passes/ConstFold.cpp`
- `src/ir/passes/DCE.cpp`
- `src/ir/passes/CFGSimplify.cpp`
- `src/ir/passes/PassManager.cpp`
2. 视实现需要可能修改
- `src/ir/IR.h``src/ir/Instruction.cpp`(补充副作用/可删除性信息)
- `src/ir/IRPrinter.cpp`(调试输出增强)
- `src/ir/analysis/DominatorTree.cpp``src/ir/analysis/LoopInfo.cpp`(辅助分析)
- `src/ir/Value.cpp`(若补充 use-def 关系)
---
## 6. 算法说明
### 6.1 Dead无用代码删除
可以采用“标记 + 清扫”思路:
1. 从关键操作出发标记“有用”指令
2. 沿数据依赖和必要控制依赖扩展标记
3. 删除未标记指令
> 本实验不限定具体思路,实现可自由设计。
### 6.2 Clean
在 DCE 后对 CFG 做结构化清理,常见包括:
1. 冗余分支改写
2. 空块删除/绕过
3. 线性可合并块合并
4. 不可达块删除
### 6.3 优化顺序建议
可采用迭代顺序:
1. `ConstFold`
2. `DCE`
3. `CFGSimplify`
...
必要时重复多轮,直到 IR 不再变化。
---
## 7. 构建与验证
```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j "$(nproc)"
```
### 7.1 观察 IR
```bash
./build/bin/compiler --emit-ir test/test_case/simple_add.sy
```
### 7.2 语义回归
```bash
./scripts/verify_ir_with_llvm.sh test/test_case/simple_add.sy out/ir --run
./scripts/verify_asm_with_qemu.sh test/test_case/simple_add.sy out/asm --run
```
目标:优化后程序行为与优化前保持一致。
---