From fad1e8b1b9fd423544fa01314bfff58991d643ff Mon Sep 17 00:00:00 2001 From: mirror Date: Tue, 19 May 2026 20:34:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=AD=BB=E4=BB=A3=E7=A0=81=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/ir/IR.h | 7 +++ src/ir/passes/DCE.cpp | 130 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/include/ir/IR.h b/include/ir/IR.h index ed230a3..8b2ec34 100644 --- a/include/ir/IR.h +++ b/include/ir/IR.h @@ -524,3 +524,10 @@ class IRBuilder { Context& ctx_; BasicBlock* insert_block_; }; + +class IRPrinter { + public: + void Print(const Module& module, std::ostream& os); +}; + +} // namespace ir diff --git a/src/ir/passes/DCE.cpp b/src/ir/passes/DCE.cpp index e69de29..f1d3ef3 100644 --- a/src/ir/passes/DCE.cpp +++ b/src/ir/passes/DCE.cpp @@ -0,0 +1,130 @@ +// 死代码删除(DCE): +// - 删除无用指令与无用基本块 +// - 通常与 CFG 简化配合使用 +// +// 算法:标记 + 清扫 +// 1. 标记所有有副作用的指令为"有用"(ret, br, condbr, store, call) +// 2. 沿数据依赖反向传播,将有用指令依赖的定义也标记为有用 +// 3. 删除所有未被标记的非终结指令 + +#include "ir/IR.h" + +#include +#include +#include + +namespace ir { +namespace passes { + +// 判断一条指令是否有副作用(不可随意删除) +static bool HasSideEffect(Instruction* inst) { + Opcode op = inst->GetOpcode(); + // 终结指令、store、call 均有副作用 + if (op == Opcode::Ret || op == Opcode::Br || op == Opcode::CondBr || + op == Opcode::Store || op == Opcode::Call) { + return true; + } + return false; +} + +bool RunDCE(Function& func) { + if (func.IsExternal()) return false; + + bool changed = false; + + // 标记阶段 + std::unordered_set useful; + std::queue worklist; + + // 初始标记:所有有副作用的指令 + for (const auto& bb : func.GetBlocks()) { + if (!bb) continue; + for (const auto& inst_ptr : bb->GetInstructions()) { + auto* inst = inst_ptr.get(); + if (HasSideEffect(inst)) { + useful.insert(inst); + worklist.push(inst); + } + } + } + + // 反向传播:有用指令的操作数定义也标记为有用 + while (!worklist.empty()) { + auto* inst = worklist.front(); + worklist.pop(); + + for (size_t i = 0; i < inst->GetNumOperands(); ++i) { + auto* operand = inst->GetOperand(i); + if (!operand) continue; + auto* def_inst = dynamic_cast(operand); + if (def_inst && !useful.count(def_inst)) { + useful.insert(def_inst); + worklist.push(def_inst); + } + } + } + + // 清扫阶段:删除未标记为有用的指令 + for (const auto& bb : func.GetBlocks()) { + if (!bb) continue; + std::vector to_remove; + for (const auto& inst_ptr : bb->GetInstructions()) { + auto* inst = inst_ptr.get(); + if (!useful.count(inst)) { + to_remove.push_back(inst); + } + } + for (auto* inst : to_remove) { + // 如果还有使用者,不能直接删除(用 undef/0 替换) + // 在标记-清扫正确的前提下,未标记的指令不应有有用的使用者 + // 但安全起见,先检查 + if (!inst->GetUses().empty()) { + // 仍有使用者 —— 跳过(可能是循环引用的 phi) + continue; + } + bb->RemoveInstruction(inst); + changed = true; + } + } + + return changed; +} + +// 简化版 DCE:只删除没有使用者且无副作用的指令(更安全的实现) +bool RunSimpleDCE(Function& func) { + if (func.IsExternal()) return false; + + bool changed = false; + bool local_changed = true; + + while (local_changed) { + local_changed = false; + for (const auto& bb : func.GetBlocks()) { + if (!bb) continue; + std::vector to_remove; + + for (const auto& inst_ptr : bb->GetInstructions()) { + auto* inst = inst_ptr.get(); + // 跳过有副作用的指令 + if (HasSideEffect(inst)) continue; + // 跳过 alloca(可能后续还会用到) + if (inst->GetOpcode() == Opcode::Alloca) continue; + // 如果没有使用者,可以安全删除 + if (inst->GetUses().empty()) { + to_remove.push_back(inst); + } + } + + for (auto* inst : to_remove) { + bb->RemoveInstruction(inst); + local_changed = true; + changed = true; + } + } + } + + return changed; +} + +} // namespace passes +} // namespace ir