1 #include <unordered_set>
3 #include "../IRContextPass.h"
4 #include "tir/BasicBlock.h"
5 #include "tir/Instructions.h"
6 #include "utils/PassManager.h"
8 using std::string_view;
10 using utils::PassManager;
15 bool eliminateAfterFirstTerminator(tir::BasicBlock& bb) {
16 auto firstTerminator = bb.begin();
17 for(
auto it = bb.begin(); it != bb.end(); ++it) {
18 if(it->isTerminator()) {
23 if(firstTerminator == --bb.end())
return false;
24 auto instr = *(++firstTerminator);
25 while(instr !=
nullptr) {
26 auto next = instr->next();
35 bool mergeSinglePredSingleSucc(tir::BasicBlock& bb) {
37 auto term = dyn_cast<tir::BranchInst>(bb.terminator());
38 if(term ==
nullptr)
return false;
39 auto succ = term->getSuccessor(0);
40 if(term->getSuccessor(1) != succ)
return false;
42 for(
auto pred : succ->users()) {
43 if(pred != term)
return false;
46 term->eraseFromParent();
49 auto next = instr->next();
51 bb.appendAfterEnd(instr);
55 succ->eraseFromParent();
74 bool replaceSucessorInOneBranch(tir::BasicBlock& bb) {
76 auto term = dyn_cast<tir::BranchInst>(bb.terminator());
77 if(term ==
nullptr)
return changed;
79 for(
int i = 0; i < 2; i++) {
80 auto succ = term->getSuccessor(i);
82 if(++succ->begin() != succ->end())
continue;
84 auto sterm = dyn_cast<tir::BranchInst>(succ->terminator());
85 if(sterm ==
nullptr)
continue;
86 if(sterm->getSuccessor(0) != sterm->getSuccessor(1))
continue;
88 term->replaceSuccessor(i, sterm->getSuccessor(0));
100 class SimplifyCFG
final :
public Pass {
102 SimplifyCFG(PassManager& PM)
noexcept : Pass(PM) {}
105 std::vector<tir::BasicBlock*> toRemove;
106 for(
auto func : CU.functions()) {
108 bool changed =
false;
112 if(func->getEntryBlock()) {
113 changed = visitBB(*func->getEntryBlock());
118 for(
auto bb : func->body()) {
119 if(visited.count(bb))
continue;
120 toRemove.push_back(bb);
123 for(
auto bb : toRemove) {
124 bb->eraseFromParent();
132 bool visitBB(tir::BasicBlock& bb) {
133 bool changed =
false;
134 if(visited.count(&bb))
return false;
137 changed |= eliminateAfterFirstTerminator(bb);
138 changed |= mergeSinglePredSingleSucc(bb);
139 changed |= replaceSucessorInOneBranch(bb);
141 auto term = dyn_cast<tir::BranchInst>(bb.terminator());
142 if(term ==
nullptr)
return false;
143 changed |= visitBB(*term->getSuccessor(0));
144 changed |= visitBB(*term->getSuccessor(1));
149 void computeDependencies()
override {
150 ComputeDependency(GetPass<IRContextPass>());
152 std::unordered_set<tir::BasicBlock*> visited;