forked from hn2602439437/nudt-compiler-cpp
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.
108 lines
2.5 KiB
108 lines
2.5 KiB
#include "ir/PassManager.h"
|
|
|
|
#include "ir/IR.h"
|
|
#include "PassUtils.h"
|
|
|
|
#include <vector>
|
|
|
|
namespace ir {
|
|
namespace {
|
|
|
|
bool TryGetConstBranchTarget(CondBrInst* br, BasicBlock*& target, BasicBlock*& removed) {
|
|
if (!br) {
|
|
return false;
|
|
}
|
|
auto* then_block = br->GetThenBlock();
|
|
auto* else_block = br->GetElseBlock();
|
|
if (then_block == else_block) {
|
|
target = then_block;
|
|
removed = nullptr;
|
|
return true;
|
|
}
|
|
if (auto* cond = dyncast<ConstantI1>(br->GetCondition())) {
|
|
target = cond->GetValue() ? then_block : else_block;
|
|
removed = cond->GetValue() ? else_block : then_block;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool SimplifyBlockTerminator(BasicBlock* block) {
|
|
if (!block || block->GetInstructions().empty()) {
|
|
return false;
|
|
}
|
|
auto* term = block->GetInstructions().back().get();
|
|
auto* condbr = dyncast<CondBrInst>(term);
|
|
if (!condbr) {
|
|
return false;
|
|
}
|
|
|
|
BasicBlock* target = nullptr;
|
|
BasicBlock* removed = nullptr;
|
|
if (!TryGetConstBranchTarget(condbr, target, removed)) {
|
|
return false;
|
|
}
|
|
|
|
if (removed) {
|
|
passutils::RemoveIncomingFromSuccessor(removed, block);
|
|
removed->RemovePredecessor(block);
|
|
block->RemoveSuccessor(removed);
|
|
}
|
|
passutils::ReplaceTerminatorWithBr(block, target);
|
|
return true;
|
|
}
|
|
|
|
bool SimplifyPhiNodes(Function& function) {
|
|
bool changed = false;
|
|
for (const auto& block_ptr : function.GetBlocks()) {
|
|
bool local_changed = true;
|
|
while (local_changed) {
|
|
local_changed = false;
|
|
for (const auto& inst_ptr : block_ptr->GetInstructions()) {
|
|
auto* phi = dyncast<PhiInst>(inst_ptr.get());
|
|
if (!phi) {
|
|
break;
|
|
}
|
|
if (!passutils::SimplifyPhiInst(phi)) {
|
|
continue;
|
|
}
|
|
local_changed = true;
|
|
changed = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
bool RunCFGSimplifyOnFunction(Function& function) {
|
|
if (function.IsExternal() || function.GetEntryBlock() == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
bool changed = false;
|
|
|
|
for (const auto& block_ptr : function.GetBlocks()) {
|
|
changed |= SimplifyBlockTerminator(block_ptr.get());
|
|
}
|
|
|
|
changed |= passutils::RemoveUnreachableBlocks(function);
|
|
changed |= SimplifyPhiNodes(function);
|
|
|
|
return changed;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool RunCFGSimplify(Module& module) {
|
|
bool changed = false;
|
|
for (const auto& function : module.GetFunctions()) {
|
|
if (function) {
|
|
changed |= RunCFGSimplifyOnFunction(*function);
|
|
}
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
} // namespace ir
|