codon/codon/cir/analyze/dataflow/dominator.cpp

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