|
|
|
|
@ -1,3 +1,5 @@
|
|
|
|
|
#include "ir/analysis/DominatorTree.h"
|
|
|
|
|
|
|
|
|
|
#include "ir/IR.h"
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
@ -5,313 +7,254 @@
|
|
|
|
|
#include <unordered_set>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
namespace ir
|
|
|
|
|
{
|
|
|
|
|
namespace ir {
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
std::unordered_map<BasicBlock *, std::vector<BasicBlock *>> ComputePredecessors(Function *func)
|
|
|
|
|
{
|
|
|
|
|
std::unordered_map<BasicBlock *, std::vector<BasicBlock *>> preds;
|
|
|
|
|
for (const auto &bb : func->GetBlocks())
|
|
|
|
|
{
|
|
|
|
|
preds[bb.get()] = {};
|
|
|
|
|
}
|
|
|
|
|
for (const auto &bb : func->GetBlocks())
|
|
|
|
|
{
|
|
|
|
|
if (!bb->HasTerminator())
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
auto *terminator = bb->GetInstructions().back().get();
|
|
|
|
|
if (auto *br = dynamic_cast<BranchInst *>(terminator))
|
|
|
|
|
{
|
|
|
|
|
preds[br->GetTarget()].push_back(bb.get());
|
|
|
|
|
}
|
|
|
|
|
else if (auto *condbr = dynamic_cast<CondBranchInst *>(terminator))
|
|
|
|
|
{
|
|
|
|
|
preds[condbr->GetTrueTarget()].push_back(bb.get());
|
|
|
|
|
preds[condbr->GetFalseTarget()].push_back(bb.get());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return preds;
|
|
|
|
|
std::unordered_map<BasicBlock*, std::vector<BasicBlock*>> ComputePredecessors(
|
|
|
|
|
Function* func) {
|
|
|
|
|
std::unordered_map<BasicBlock*, std::vector<BasicBlock*>> preds;
|
|
|
|
|
for (const auto& bb : func->GetBlocks()) {
|
|
|
|
|
preds[bb.get()] = {};
|
|
|
|
|
}
|
|
|
|
|
for (const auto& bb : func->GetBlocks()) {
|
|
|
|
|
if (!bb->HasTerminator()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
auto* terminator = bb->GetInstructions().back().get();
|
|
|
|
|
if (auto* br = dynamic_cast<BranchInst*>(terminator)) {
|
|
|
|
|
preds[br->GetTarget()].push_back(bb.get());
|
|
|
|
|
} else if (auto* condbr = dynamic_cast<CondBranchInst*>(terminator)) {
|
|
|
|
|
preds[condbr->GetTrueTarget()].push_back(bb.get());
|
|
|
|
|
preds[condbr->GetFalseTarget()].push_back(bb.get());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return preds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_map<BasicBlock *, std::vector<BasicBlock *>> ComputeSuccessors(Function *func)
|
|
|
|
|
{
|
|
|
|
|
std::unordered_map<BasicBlock *, std::vector<BasicBlock *>> succs;
|
|
|
|
|
for (const auto &bb : func->GetBlocks())
|
|
|
|
|
{
|
|
|
|
|
succs[bb.get()] = {};
|
|
|
|
|
if (!bb->HasTerminator())
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
auto *terminator = bb->GetInstructions().back().get();
|
|
|
|
|
if (auto *br = dynamic_cast<BranchInst *>(terminator))
|
|
|
|
|
{
|
|
|
|
|
succs[bb.get()].push_back(br->GetTarget());
|
|
|
|
|
}
|
|
|
|
|
else if (auto *condbr = dynamic_cast<CondBranchInst *>(terminator))
|
|
|
|
|
{
|
|
|
|
|
succs[bb.get()].push_back(condbr->GetTrueTarget());
|
|
|
|
|
succs[bb.get()].push_back(condbr->GetFalseTarget());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return succs;
|
|
|
|
|
std::unordered_map<BasicBlock*, std::vector<BasicBlock*>> ComputeSuccessors(
|
|
|
|
|
Function* func) {
|
|
|
|
|
std::unordered_map<BasicBlock*, std::vector<BasicBlock*>> succs;
|
|
|
|
|
for (const auto& bb : func->GetBlocks()) {
|
|
|
|
|
succs[bb.get()] = {};
|
|
|
|
|
if (!bb->HasTerminator()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
auto* terminator = bb->GetInstructions().back().get();
|
|
|
|
|
if (auto* br = dynamic_cast<BranchInst*>(terminator)) {
|
|
|
|
|
succs[bb.get()].push_back(br->GetTarget());
|
|
|
|
|
} else if (auto* condbr = dynamic_cast<CondBranchInst*>(terminator)) {
|
|
|
|
|
succs[bb.get()].push_back(condbr->GetTrueTarget());
|
|
|
|
|
succs[bb.get()].push_back(condbr->GetFalseTarget());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return succs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<BasicBlock *> PostOrder(Function *func,
|
|
|
|
|
const std::unordered_map<BasicBlock *, std::vector<BasicBlock *>> &succs)
|
|
|
|
|
{
|
|
|
|
|
std::vector<BasicBlock *> order;
|
|
|
|
|
std::unordered_set<BasicBlock *> visited;
|
|
|
|
|
std::vector<std::pair<BasicBlock *, size_t>> stack;
|
|
|
|
|
|
|
|
|
|
auto *entry = func->GetEntry();
|
|
|
|
|
if (!entry)
|
|
|
|
|
{
|
|
|
|
|
return order;
|
|
|
|
|
}
|
|
|
|
|
std::vector<BasicBlock*> PostOrder(
|
|
|
|
|
Function* func,
|
|
|
|
|
const std::unordered_map<BasicBlock*, std::vector<BasicBlock*>>& succs) {
|
|
|
|
|
std::vector<BasicBlock*> order;
|
|
|
|
|
std::unordered_set<BasicBlock*> visited;
|
|
|
|
|
std::vector<std::pair<BasicBlock*, size_t>> stack;
|
|
|
|
|
|
|
|
|
|
stack.push_back({entry, 0});
|
|
|
|
|
visited.insert(entry);
|
|
|
|
|
|
|
|
|
|
while (!stack.empty())
|
|
|
|
|
{
|
|
|
|
|
auto &top = stack.back();
|
|
|
|
|
auto *bb = top.first;
|
|
|
|
|
auto &idx = top.second;
|
|
|
|
|
|
|
|
|
|
auto it = succs.find(bb);
|
|
|
|
|
const auto &children = (it != succs.end()) ? it->second : std::vector<BasicBlock *>{};
|
|
|
|
|
|
|
|
|
|
bool found_next = false;
|
|
|
|
|
while (idx < children.size())
|
|
|
|
|
{
|
|
|
|
|
auto *child = children[idx++];
|
|
|
|
|
if (visited.find(child) == visited.end())
|
|
|
|
|
{
|
|
|
|
|
visited.insert(child);
|
|
|
|
|
stack.push_back({child, 0});
|
|
|
|
|
found_next = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
auto* entry = func->GetEntry();
|
|
|
|
|
if (!entry) {
|
|
|
|
|
return order;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found_next)
|
|
|
|
|
{
|
|
|
|
|
order.push_back(bb);
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
}
|
|
|
|
|
stack.push_back({entry, 0});
|
|
|
|
|
visited.insert(entry);
|
|
|
|
|
|
|
|
|
|
while (!stack.empty()) {
|
|
|
|
|
auto& top = stack.back();
|
|
|
|
|
auto* bb = top.first;
|
|
|
|
|
auto& idx = top.second;
|
|
|
|
|
|
|
|
|
|
auto it = succs.find(bb);
|
|
|
|
|
const auto& children =
|
|
|
|
|
(it != succs.end()) ? it->second : std::vector<BasicBlock*>{};
|
|
|
|
|
|
|
|
|
|
bool found_next = false;
|
|
|
|
|
while (idx < children.size()) {
|
|
|
|
|
auto* child = children[idx++];
|
|
|
|
|
if (visited.find(child) == visited.end()) {
|
|
|
|
|
visited.insert(child);
|
|
|
|
|
stack.push_back({child, 0});
|
|
|
|
|
found_next = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return order;
|
|
|
|
|
if (!found_next) {
|
|
|
|
|
order.push_back(bb);
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_set<BasicBlock *> Intersect(const std::unordered_set<BasicBlock *> &a,
|
|
|
|
|
const std::unordered_set<BasicBlock *> &b)
|
|
|
|
|
{
|
|
|
|
|
std::unordered_set<BasicBlock *> result;
|
|
|
|
|
for (auto *bb : a)
|
|
|
|
|
{
|
|
|
|
|
if (b.find(bb) != b.end())
|
|
|
|
|
{
|
|
|
|
|
result.insert(bb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
return order;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_set<BasicBlock*> Intersect(
|
|
|
|
|
const std::unordered_set<BasicBlock*>& a,
|
|
|
|
|
const std::unordered_set<BasicBlock*>& b) {
|
|
|
|
|
std::unordered_set<BasicBlock*> result;
|
|
|
|
|
for (auto* bb : a) {
|
|
|
|
|
if (b.find(bb) != b.end()) {
|
|
|
|
|
result.insert(bb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void DominatorTree::Compute(Function* func) {
|
|
|
|
|
doms_.clear();
|
|
|
|
|
idom_.clear();
|
|
|
|
|
children_.clear();
|
|
|
|
|
df_.clear();
|
|
|
|
|
|
|
|
|
|
auto preds = ComputePredecessors(func);
|
|
|
|
|
auto succs = ComputeSuccessors(func);
|
|
|
|
|
auto post_order = PostOrder(func, succs);
|
|
|
|
|
|
|
|
|
|
std::unordered_map<BasicBlock*, size_t> post_order_idx;
|
|
|
|
|
for (size_t i = 0; i < post_order.size(); ++i) {
|
|
|
|
|
post_order_idx[post_order[i]] = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DominatorTree
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
void Compute(Function *func)
|
|
|
|
|
{
|
|
|
|
|
doms_.clear();
|
|
|
|
|
idom_.clear();
|
|
|
|
|
children_.clear();
|
|
|
|
|
df_.clear();
|
|
|
|
|
|
|
|
|
|
auto preds = ComputePredecessors(func);
|
|
|
|
|
auto succs = ComputeSuccessors(func);
|
|
|
|
|
auto post_order = PostOrder(func, succs);
|
|
|
|
|
|
|
|
|
|
std::unordered_map<BasicBlock *, size_t> post_order_idx;
|
|
|
|
|
for (size_t i = 0; i < post_order.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
post_order_idx[post_order[i]] = i;
|
|
|
|
|
}
|
|
|
|
|
auto* entry = func->GetEntry();
|
|
|
|
|
if (!entry) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto *entry = func->GetEntry();
|
|
|
|
|
if (!entry)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
std::unordered_set<BasicBlock*> all_blocks;
|
|
|
|
|
for (const auto& bb : func->GetBlocks()) {
|
|
|
|
|
all_blocks.insert(bb.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_set<BasicBlock *> all_blocks;
|
|
|
|
|
for (const auto &bb : func->GetBlocks())
|
|
|
|
|
{
|
|
|
|
|
all_blocks.insert(bb.get());
|
|
|
|
|
}
|
|
|
|
|
doms_[entry] = {entry};
|
|
|
|
|
for (auto* bb : post_order) {
|
|
|
|
|
if (bb != entry) {
|
|
|
|
|
doms_[bb] = all_blocks;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
doms_[entry] = {entry};
|
|
|
|
|
for (auto *bb : post_order)
|
|
|
|
|
{
|
|
|
|
|
if (bb != entry)
|
|
|
|
|
{
|
|
|
|
|
doms_[bb] = all_blocks;
|
|
|
|
|
}
|
|
|
|
|
bool changed = true;
|
|
|
|
|
while (changed) {
|
|
|
|
|
changed = false;
|
|
|
|
|
for (auto it = post_order.rbegin(); it != post_order.rend(); ++it) {
|
|
|
|
|
auto* bb = *it;
|
|
|
|
|
if (bb == entry) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool changed = true;
|
|
|
|
|
while (changed)
|
|
|
|
|
{
|
|
|
|
|
changed = false;
|
|
|
|
|
for (auto it = post_order.rbegin(); it != post_order.rend(); ++it)
|
|
|
|
|
{
|
|
|
|
|
auto *bb = *it;
|
|
|
|
|
if (bb == entry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto pred_it = preds.find(bb);
|
|
|
|
|
if (pred_it == preds.end() || pred_it->second.empty())
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_set<BasicBlock *> new_dom;
|
|
|
|
|
bool first = true;
|
|
|
|
|
for (auto *pred : pred_it->second)
|
|
|
|
|
{
|
|
|
|
|
auto dom_it = doms_.find(pred);
|
|
|
|
|
if (dom_it == doms_.end())
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (first)
|
|
|
|
|
{
|
|
|
|
|
new_dom = dom_it->second;
|
|
|
|
|
first = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
new_dom = Intersect(new_dom, dom_it->second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
new_dom.insert(bb);
|
|
|
|
|
|
|
|
|
|
if (doms_[bb] != new_dom)
|
|
|
|
|
{
|
|
|
|
|
doms_[bb] = new_dom;
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
auto pred_it = preds.find(bb);
|
|
|
|
|
if (pred_it == preds.end() || pred_it->second.empty()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto *bb : post_order)
|
|
|
|
|
{
|
|
|
|
|
if (bb == entry)
|
|
|
|
|
{
|
|
|
|
|
idom_[bb] = nullptr;
|
|
|
|
|
std::unordered_set<BasicBlock*> new_dom;
|
|
|
|
|
bool first = true;
|
|
|
|
|
for (auto* pred : pred_it->second) {
|
|
|
|
|
auto dom_it = doms_.find(pred);
|
|
|
|
|
if (dom_it == doms_.end()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto &dom_set = doms_[bb];
|
|
|
|
|
BasicBlock *idom = nullptr;
|
|
|
|
|
size_t min_idx = post_order.size();
|
|
|
|
|
|
|
|
|
|
for (auto *d : dom_set)
|
|
|
|
|
{
|
|
|
|
|
if (d == bb)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
auto idx_it = post_order_idx.find(d);
|
|
|
|
|
if (idx_it != post_order_idx.end() && idx_it->second < min_idx)
|
|
|
|
|
{
|
|
|
|
|
min_idx = idx_it->second;
|
|
|
|
|
idom = d;
|
|
|
|
|
}
|
|
|
|
|
if (first) {
|
|
|
|
|
new_dom = dom_it->second;
|
|
|
|
|
first = false;
|
|
|
|
|
} else {
|
|
|
|
|
new_dom = Intersect(new_dom, dom_it->second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
new_dom.insert(bb);
|
|
|
|
|
|
|
|
|
|
idom_[bb] = idom;
|
|
|
|
|
if (idom)
|
|
|
|
|
{
|
|
|
|
|
children_[idom].push_back(bb);
|
|
|
|
|
}
|
|
|
|
|
if (doms_[bb] != new_dom) {
|
|
|
|
|
doms_[bb] = new_dom;
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto *bb : post_order)
|
|
|
|
|
{
|
|
|
|
|
if (bb == entry)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
for (auto* bb : post_order) {
|
|
|
|
|
if (bb == entry) {
|
|
|
|
|
idom_[bb] = nullptr;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto pred_it = preds.find(bb);
|
|
|
|
|
if (pred_it == preds.end())
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
auto& dom_set = doms_[bb];
|
|
|
|
|
BasicBlock* idom = nullptr;
|
|
|
|
|
size_t min_idx = post_order.size();
|
|
|
|
|
|
|
|
|
|
for (auto *pred : pred_it->second)
|
|
|
|
|
{
|
|
|
|
|
auto *runner = pred;
|
|
|
|
|
while (runner && runner != idom_[bb])
|
|
|
|
|
{
|
|
|
|
|
df_[runner].insert(bb);
|
|
|
|
|
runner = idom_[runner];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (auto* d : dom_set) {
|
|
|
|
|
if (d == bb) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Dominates(BasicBlock *a, BasicBlock *b) const
|
|
|
|
|
{
|
|
|
|
|
auto it = doms_.find(b);
|
|
|
|
|
if (it == doms_.end())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
auto idx_it = post_order_idx.find(d);
|
|
|
|
|
if (idx_it != post_order_idx.end() && idx_it->second < min_idx) {
|
|
|
|
|
min_idx = idx_it->second;
|
|
|
|
|
idom = d;
|
|
|
|
|
}
|
|
|
|
|
return it->second.find(a) != it->second.end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BasicBlock *GetIdom(BasicBlock *bb) const
|
|
|
|
|
{
|
|
|
|
|
auto it = idom_.find(bb);
|
|
|
|
|
return (it != idom_.end()) ? it->second : nullptr;
|
|
|
|
|
idom_[bb] = idom;
|
|
|
|
|
if (idom) {
|
|
|
|
|
children_[idom].push_back(bb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::vector<BasicBlock *> &GetChildren(BasicBlock *bb) const
|
|
|
|
|
{
|
|
|
|
|
static const std::vector<BasicBlock *> empty;
|
|
|
|
|
auto it = children_.find(bb);
|
|
|
|
|
return (it != children_.end()) ? it->second : empty;
|
|
|
|
|
for (auto* bb : post_order) {
|
|
|
|
|
if (bb == entry) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::unordered_set<BasicBlock *> &GetDominanceFrontier(BasicBlock *bb) const
|
|
|
|
|
{
|
|
|
|
|
static const std::unordered_set<BasicBlock *> empty;
|
|
|
|
|
auto it = df_.find(bb);
|
|
|
|
|
return (it != df_.end()) ? it->second : empty;
|
|
|
|
|
auto pred_it = preds.find(bb);
|
|
|
|
|
if (pred_it == preds.end()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::unordered_map<BasicBlock *, std::unordered_set<BasicBlock *>> &GetAllDominanceFrontiers() const
|
|
|
|
|
{
|
|
|
|
|
return df_;
|
|
|
|
|
for (auto* pred : pred_it->second) {
|
|
|
|
|
auto* runner = pred;
|
|
|
|
|
while (runner && runner != idom_[bb]) {
|
|
|
|
|
df_[runner].insert(bb);
|
|
|
|
|
runner = idom_[runner];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::unordered_map<BasicBlock *, std::unordered_set<BasicBlock *>> doms_;
|
|
|
|
|
std::unordered_map<BasicBlock *, BasicBlock *> idom_;
|
|
|
|
|
std::unordered_map<BasicBlock *, std::vector<BasicBlock *>> children_;
|
|
|
|
|
std::unordered_map<BasicBlock *, std::unordered_set<BasicBlock *>> df_;
|
|
|
|
|
};
|
|
|
|
|
bool DominatorTree::Dominates(BasicBlock* a, BasicBlock* b) const {
|
|
|
|
|
auto it = doms_.find(b);
|
|
|
|
|
if (it == doms_.end()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return it->second.find(a) != it->second.end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BasicBlock* DominatorTree::GetIdom(BasicBlock* bb) const {
|
|
|
|
|
auto it = idom_.find(bb);
|
|
|
|
|
return (it != idom_.end()) ? it->second : nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::vector<BasicBlock*>& DominatorTree::GetChildren(
|
|
|
|
|
BasicBlock* bb) const {
|
|
|
|
|
static const std::vector<BasicBlock*> empty;
|
|
|
|
|
auto it = children_.find(bb);
|
|
|
|
|
return (it != children_.end()) ? it->second : empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::unordered_set<BasicBlock*>& DominatorTree::GetDominanceFrontier(
|
|
|
|
|
BasicBlock* bb) const {
|
|
|
|
|
static const std::unordered_set<BasicBlock*> empty;
|
|
|
|
|
auto it = df_.find(bb);
|
|
|
|
|
return (it != df_.end()) ? it->second : empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::unordered_map<BasicBlock*, std::unordered_set<BasicBlock*>>&
|
|
|
|
|
DominatorTree::GetAllDominanceFrontiers() const {
|
|
|
|
|
return df_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace ir
|
|
|
|
|
|