zhm
zhm 1 day ago
parent 81f30300f3
commit beef9aabbe

@ -72,45 +72,100 @@ void RunCFGSimplify(Module& module) {
auto* func = func_ptr.get();
if (func->IsExternal()) continue;
// ===== 第一步:删除不可达的基本块 =====
auto reachable = FindReachableBlocks(func);
auto& blocks = const_cast<std::vector<std::unique_ptr<BasicBlock>>&>(func->GetBlocks());
blocks.erase(
std::remove_if(blocks.begin(), blocks.end(),
[&reachable](const std::unique_ptr<BasicBlock>& bb_ptr) {
return reachable.find(bb_ptr.get()) == reachable.end();
}
),
blocks.end()
);
// ===== 第二步:简化条件分支(如果条件为常量) =====
for (auto& bb_ptr : blocks) {
auto* bb = bb_ptr.get();
auto* term = GetTerminator(bb);
if (!term) continue;
bool changed = true;
while (changed) {
changed = false;
auto reachable = FindReachableBlocks(func);
if (auto* condbr = dynamic_cast<CondBranchInst*>(term)) {
auto* cond = condbr->GetCond();
std::unordered_set<BasicBlock*> unreachable;
for (auto& bb : blocks) {
if (reachable.find(bb.get()) == reachable.end()) {
unreachable.insert(bb.get());
}
}
for (auto& bb_ptr : blocks) {
auto* bb = bb_ptr.get();
if (unreachable.find(bb) != unreachable.end()) continue;
std::vector<std::pair<PhiInst*, Value*>> phi_replacements;
std::vector<PhiInst*> phi_to_delete;
// 如果条件是常量整数
if (auto* const_int = dynamic_cast<ConstantInt*>(cond)) {
auto* true_target = condbr->GetTrueTarget();
auto* false_target = condbr->GetFalseTarget();
for (auto& inst_ptr : bb->GetInstructions()) {
auto* phi = dynamic_cast<PhiInst*>(inst_ptr.get());
if (!phi) break;
// 根据常量值选择跳转目标
auto* target = (const_int->GetValue() != 0) ? true_target : false_target;
Value* valid_val = nullptr;
size_t valid_count = 0;
for (size_t i = 0; i < phi->GetNumOperands(); i += 2) {
auto* val = phi->GetOperand(i);
auto* pred = static_cast<BasicBlock*>(phi->GetOperand(i + 1));
if (unreachable.find(pred) == unreachable.end()) {
valid_val = val;
valid_count++;
}
}
// 删除旧的 CondBranchInst添加新的无条件 BranchInst
bb->RemoveInstruction(condbr);
bb->Append<BranchInst>(Type::GetVoidType(), target);
if (valid_count == 1 && valid_val) {
phi_replacements.push_back({phi, valid_val});
} else if (valid_count == 0) {
phi_to_delete.push_back(phi);
}
}
for (auto& [phi, val] : phi_replacements) {
phi->ReplaceAllUsesWith(val);
phi_to_delete.push_back(phi);
}
auto& insts = const_cast<std::vector<std::unique_ptr<Instruction>>&>(bb->GetInstructions());
auto new_end = std::remove_if(insts.begin(), insts.end(),
[&phi_to_delete](const std::unique_ptr<Instruction>& inst_ptr) {
return std::find(phi_to_delete.begin(), phi_to_delete.end(), inst_ptr.get()) != phi_to_delete.end();
}
);
insts.erase(new_end, insts.end());
}
size_t old_size = blocks.size();
blocks.erase(
std::remove_if(blocks.begin(), blocks.end(),
[&reachable](const std::unique_ptr<BasicBlock>& bb_ptr) {
return reachable.find(bb_ptr.get()) == reachable.end();
}
),
blocks.end()
);
if (blocks.size() != old_size) {
changed = true;
}
for (auto& bb_ptr : blocks) {
auto* bb = bb_ptr.get();
auto* term = GetTerminator(bb);
if (!term) continue;
if (auto* condbr = dynamic_cast<CondBranchInst*>(term)) {
auto* cond = condbr->GetCond();
if (auto* const_int = dynamic_cast<ConstantInt*>(cond)) {
auto* true_target = condbr->GetTrueTarget();
auto* false_target = condbr->GetFalseTarget();
auto* target = (const_int->GetValue() != 0) ? true_target : false_target;
bb->RemoveInstruction(condbr);
bb->Append<BranchInst>(Type::GetVoidType(), target);
changed = true;
}
}
}
}
// ===== 第三步:简化只有一个前驱的块中的 PHI 节点 =====
// 如果一个块只有一个前驱,那么它的 PHI 节点应该被替换为入边的值
for (auto& bb_ptr : blocks) {
auto* bb = bb_ptr.get();
const auto& preds = bb->GetPredecessors();
@ -120,21 +175,18 @@ void RunCFGSimplify(Module& module) {
for (auto& inst_ptr : bb->GetInstructions()) {
auto* phi = dynamic_cast<PhiInst*>(inst_ptr.get());
if (!phi) break; // PHI 节点必须在块的开头
if (!phi) break;
// 获取唯一入边的值
if (phi->GetNumOperands() >= 2) {
Value* incoming_val = phi->GetOperand(0);
phi_replacements.push_back({phi, incoming_val});
}
}
// 执行替换
for (auto& [phi, val] : phi_replacements) {
phi->ReplaceAllUsesWith(val);
}
// 删除已替换的 PHI 节点
auto& insts = const_cast<std::vector<std::unique_ptr<Instruction>>&>(bb->GetInstructions());
auto new_end = std::remove_if(insts.begin(), insts.end(),
[](const std::unique_ptr<Instruction>& inst_ptr) {
@ -144,11 +196,6 @@ void RunCFGSimplify(Module& module) {
insts.erase(new_end, insts.end());
}
}
// ===== 第四步:合并连续的空块 =====
// 如果块 A 以无条件分支跳转到块 B且块 A 和块 B 都为空,
// 则可以将块 A 的前驱的分支目标直接改为块 B 的后继,然后删除块 A
// 这个步骤比较复杂,暂时不实现
}
}

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save