You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
2.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 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();
for (auto* phi : phis) {
// 根据 PHI 节点的类型选择正确的 undef 值
Value* undef_val = phi->GetType()->IsFloat32()
? static_cast<Value*>(ctx.GetConstFloat(0.0f))
: static_cast<Value*>(ctx.GetConstInt(0));
// 收集已有的 incoming 块
std::unordered_set<BasicBlock*> existing;
for (size_t i = 0; i < phi->GetNumIncoming(); ++i) {
existing.insert(phi->GetIncomingBlock(i));
}
// 为每个前驱补齐缺失的 incomingLLVM 要求 PHI 覆盖所有前驱)
for (auto* pred : preds) {
if (!existing.count(pred)) {
phi->AddIncoming(undef_val, pred);
}
}
// 修复无效的 incoming仅修复确实为 null 的操作数
for (size_t i = 0; i < phi->GetNumIncoming(); ++i) {
auto* inc_val = phi->GetIncomingValue(i);
auto* inc_bb = phi->GetIncomingBlock(i);
if (!inc_val) phi->SetOperand(i * 2, undef_val);
if (!inc_bb) 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