|
|
// IR Pass 管理:按顺序执行优化遍,支持迭代至不动点
|
|
|
|
|
|
#include "ir/IR.h"
|
|
|
|
|
|
#include <queue>
|
|
|
#include <unordered_set>
|
|
|
|
|
|
namespace ir {
|
|
|
|
|
|
// 前向声明(定义在各 pass 文件中)
|
|
|
extern bool RunMem2Reg(Function& func, Context& ctx);
|
|
|
extern bool RunConstFold(Function& func, Context& ctx);
|
|
|
extern bool RunConstProp(Function& func, Context& ctx);
|
|
|
extern bool RunDCE(Function& func);
|
|
|
extern bool RunCFGSimplify(Function& func, Context& ctx);
|
|
|
extern bool RunCSE(Function& func);
|
|
|
|
|
|
// 清理 PHI 节点:修复无效的 incoming 值/块引用,补齐缺失的前驱条目
|
|
|
static void SanitizePhis(Function& func, Context& ctx) {
|
|
|
func.RebuildCFG();
|
|
|
auto* entry = func.GetEntry();
|
|
|
if (!entry) return;
|
|
|
|
|
|
for (auto& bb : func.GetBlocks()) {
|
|
|
// 收集 PHI 节点
|
|
|
std::vector<PhiInst*> phis;
|
|
|
for (auto& inst : bb->GetInstructions()) {
|
|
|
if (auto* phi = dynamic_cast<PhiInst*>(inst.get()))
|
|
|
phis.push_back(phi);
|
|
|
}
|
|
|
if (phis.empty()) continue;
|
|
|
|
|
|
auto& preds = bb->GetPredecessors();
|
|
|
Value* undef_val = ctx.GetConstInt(0);
|
|
|
|
|
|
for (auto* phi : phis) {
|
|
|
// 收集已有的 incoming 块
|
|
|
std::unordered_set<BasicBlock*> existing;
|
|
|
for (size_t i = 0; i < phi->GetNumIncoming(); ++i) {
|
|
|
existing.insert(phi->GetIncomingBlock(i));
|
|
|
}
|
|
|
|
|
|
// 为每个前驱补齐缺失的 incoming(LLVM 要求 PHI 覆盖所有前驱)
|
|
|
for (auto* pred : preds) {
|
|
|
if (!existing.count(pred)) {
|
|
|
phi->AddIncoming(undef_val, pred);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 修复无效的 incoming
|
|
|
for (size_t i = 0; i < phi->GetNumIncoming(); ++i) {
|
|
|
auto* inc_val = phi->GetIncomingValue(i);
|
|
|
auto* inc_bb = phi->GetIncomingBlock(i);
|
|
|
if (!inc_val || !inc_bb) {
|
|
|
phi->SetOperand(i * 2, undef_val);
|
|
|
phi->SetOperand(i * 2 + 1, entry);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void RunPasses(Module& module) {
|
|
|
Context& ctx = module.GetContext();
|
|
|
bool changed = true;
|
|
|
int iteration = 0;
|
|
|
const int kMaxIterations = 10;
|
|
|
|
|
|
for (auto& func : module.GetFunctions()) {
|
|
|
RunMem2Reg(*func, ctx);
|
|
|
}
|
|
|
|
|
|
while (changed && iteration < kMaxIterations) {
|
|
|
changed = false;
|
|
|
++iteration;
|
|
|
|
|
|
for (auto& func : module.GetFunctions()) {
|
|
|
changed |= RunConstFold(*func, ctx);
|
|
|
changed |= RunConstProp(*func, ctx);
|
|
|
changed |= RunCSE(*func);
|
|
|
// CFGSimplify 在处理 PHI 节点较多的 CFG 时会导致悬空指针
|
|
|
// 其功能(空块合并 + 不可达块删除)由后续 DCE + SanitizePhis 部分承担
|
|
|
changed |= RunDCE(*func);
|
|
|
SanitizePhis(*func, ctx);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} // namespace ir
|