Skip to content

Commit 2eb5ab2

Browse files
committed
Update dominator pass to use bit vectors
Result is >100x speedup in some cases
1 parent ee9ba90 commit 2eb5ab2

4 files changed

Lines changed: 64 additions & 20 deletions

File tree

codon/cir/analyze/dataflow/cfg.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,9 @@ class CFGraph {
330330
/// Constructs a control-flow graph.
331331
explicit CFGraph(const BodiedFunc *f);
332332

333+
/// @return number of blocks in this CFG
334+
auto size() const { return blocks.size(); }
335+
333336
/// @return an iterator to the first block
334337
auto begin() { return util::raw_ptr_adaptor(blocks.begin()); }
335338
/// @return an iterator beyond the last block

codon/cir/analyze/dataflow/dominator.cpp

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,81 @@
22

33
#include "dominator.h"
44

5+
#include "codon/cir/llvm/llvm.h"
6+
57
namespace codon {
68
namespace ir {
79
namespace analyze {
810
namespace dataflow {
911

1012
void DominatorInspector::analyze() {
11-
auto changed = true;
13+
const auto numBlocks = cfg->size();
14+
std::unordered_map<id_t, size_t> mapping; // id -> sequential id
15+
std::vector<id_t> mappingInv(numBlocks); // sequential id -> id
16+
std::vector<llvm::BitVector> bitvecs(numBlocks); // sequential id -> bitvector
17+
18+
mapping.reserve(numBlocks);
19+
size_t next = 0;
20+
for (auto *blk : *cfg) {
21+
auto id = blk->getId();
22+
mapping[id] = next;
23+
mappingInv[next] = id;
24+
++next;
25+
}
26+
27+
// Initialize: all blocks dominate themselves; others start with universal set
28+
for (auto *blk : *cfg) {
29+
auto id = mapping[blk->getId()];
30+
llvm::BitVector &bv = bitvecs[id];
31+
bv.resize(numBlocks, true);
32+
if (blk == cfg->getEntryBlock()) { // entry block only dominated by itself
33+
bv.reset();
34+
bv.set(id);
35+
}
36+
}
37+
38+
// Run simple domination algorithm
39+
bool changed = true;
1240
while (changed) {
1341
changed = false;
1442
for (auto *blk : *cfg) {
15-
auto init = false;
16-
std::set<id_t> old = sets[blk->getId()];
17-
std::set<id_t> working;
43+
auto id = mapping[blk->getId()];
44+
llvm::BitVector old = bitvecs[id];
45+
llvm::BitVector newSet;
46+
47+
if (blk->predecessors_begin() == blk->predecessors_end())
48+
newSet.resize(numBlocks);
1849

50+
bool first = true;
1951
for (auto it = blk->predecessors_begin(); it != blk->predecessors_end(); ++it) {
20-
auto &predDoms = sets[(*it)->getId()];
21-
if (!init) {
22-
init = true;
23-
working = std::set<id_t>(predDoms.begin(), predDoms.end());
52+
auto predId = mapping[(*it)->getId()];
53+
const auto &predSet = bitvecs[predId];
54+
if (first) {
55+
newSet = predSet;
56+
first = false;
57+
} else {
58+
newSet &= predSet;
2459
}
25-
26-
std::set<id_t> newWorking;
27-
std::set_intersection(working.begin(), working.end(), predDoms.begin(),
28-
predDoms.end(),
29-
std::inserter(newWorking, newWorking.begin()));
30-
working = newWorking;
3160
}
3261

33-
working.insert(blk->getId());
62+
newSet.set(id); // a block always dominates itself
3463

35-
if (working != old) {
64+
if (newSet != old) {
65+
bitvecs[id] = newSet;
3666
changed = true;
37-
sets[blk->getId()] = working;
3867
}
3968
}
4069
}
70+
71+
// Map back to canonical id
72+
sets.reserve(numBlocks);
73+
for (unsigned id = 0; id < numBlocks; id++) {
74+
auto &bv = bitvecs[id];
75+
auto &set = sets[mappingInv[id]];
76+
for (auto n = bv.find_first(); n != -1; n = bv.find_next(n)) {
77+
set.insert(mappingInv[n]);
78+
}
79+
}
4180
}
4281

4382
bool DominatorInspector::isDominated(const Value *v, const Value *dominator) {
@@ -52,7 +91,8 @@ bool DominatorInspector::isDominated(const Value *v, const Value *dominator) {
5291
return dDist <= vDist;
5392
}
5493

55-
return sets[vBlock->getId()].find(dBlock->getId()) != sets[vBlock->getId()].end();
94+
auto &set = sets[vBlock->getId()];
95+
return set.find(dBlock->getId()) != set.end();
5696
}
5797

5898
const std::string DominatorAnalysis::KEY = "core-analyses-dominator";

codon/cir/analyze/dataflow/dominator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
#pragma once
44

5-
#include <set>
65
#include <unordered_map>
6+
#include <unordered_set>
77
#include <utility>
88

99
#include "codon/cir/analyze/analysis.h"
@@ -17,7 +17,7 @@ namespace dataflow {
1717
/// Helper to query the dominators of a particular function.
1818
class DominatorInspector {
1919
private:
20-
std::unordered_map<id_t, std::set<id_t>> sets;
20+
std::unordered_map<id_t, std::unordered_set<id_t>> sets;
2121
CFGraph *cfg;
2222

2323
public:

codon/cir/llvm/llvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#pragma once
44

5+
#include "llvm/ADT/BitVector.h"
56
#include "llvm/ADT/FunctionExtras.h"
67
#include "llvm/ADT/SmallSet.h"
78
#include "llvm/ADT/SmallVector.h"

0 commit comments

Comments
 (0)