|
|
|
|
@ -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
|
|
|
|
|
// 这个步骤比较复杂,暂时不实现
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|