mirror of https://github.com/exaloop/codon.git
75 lines
2.2 KiB
C++
75 lines
2.2 KiB
C++
// Copyright (C) 2022-2023 Exaloop Inc. <https://exaloop.io>
|
|
|
|
#include "dominator.h"
|
|
|
|
namespace codon {
|
|
namespace ir {
|
|
namespace analyze {
|
|
namespace dataflow {
|
|
|
|
void DominatorInspector::analyze() {
|
|
auto changed = true;
|
|
while (changed) {
|
|
changed = false;
|
|
for (auto *blk : *cfg) {
|
|
auto init = false;
|
|
std::set<id_t> old = sets[blk->getId()];
|
|
std::set<id_t> working;
|
|
|
|
for (auto it = blk->predecessors_begin(); it != blk->predecessors_end(); ++it) {
|
|
auto &predDoms = sets[(*it)->getId()];
|
|
if (!init) {
|
|
init = true;
|
|
working = std::set<id_t>(predDoms.begin(), predDoms.end());
|
|
}
|
|
|
|
std::set<id_t> newWorking;
|
|
std::set_intersection(working.begin(), working.end(), predDoms.begin(),
|
|
predDoms.end(),
|
|
std::inserter(newWorking, newWorking.begin()));
|
|
working = newWorking;
|
|
}
|
|
|
|
working.insert(blk->getId());
|
|
|
|
if (working != old) {
|
|
changed = true;
|
|
sets[blk->getId()] = working;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool DominatorInspector::isDominated(const Value *v, const Value *dominator) {
|
|
auto *vBlock = cfg->getBlock(v);
|
|
auto *dBlock = cfg->getBlock(dominator);
|
|
|
|
if (vBlock->getId() == dBlock->getId()) {
|
|
auto vDist =
|
|
std::distance(vBlock->begin(), std::find(vBlock->begin(), vBlock->end(), v));
|
|
auto dDist = std::distance(vBlock->begin(),
|
|
std::find(vBlock->begin(), vBlock->end(), dominator));
|
|
return dDist <= vDist;
|
|
}
|
|
|
|
return sets[vBlock->getId()].find(dBlock->getId()) != sets[vBlock->getId()].end();
|
|
}
|
|
|
|
const std::string DominatorAnalysis::KEY = "core-analyses-dominator";
|
|
|
|
std::unique_ptr<Result> DominatorAnalysis::run(const Module *m) {
|
|
auto *cfgResult = getAnalysisResult<CFResult>(cfAnalysisKey);
|
|
auto ret = std::make_unique<DominatorResult>(cfgResult);
|
|
for (const auto &graph : cfgResult->graphs) {
|
|
auto inspector = std::make_unique<DominatorInspector>(graph.second.get());
|
|
inspector->analyze();
|
|
ret->results[graph.first] = std::move(inspector);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // namespace dataflow
|
|
} // namespace analyze
|
|
} // namespace ir
|
|
} // namespace codon
|