#ifndef domtree_h
#define domtree_h
#include "cfg-traversal.h"
#include "wasm.h"
namespace wasm {
template<typename BasicBlock> struct DomTree {
std::vector<Index> iDoms;
enum { nonsense = Index(-1) };
DomTree(std::vector<std::unique_ptr<BasicBlock>>& blocks);
};
template<typename BasicBlock>
DomTree<BasicBlock>::DomTree(std::vector<std::unique_ptr<BasicBlock>>& blocks) {
Index numBlocks = blocks.size();
if (numBlocks == 0) {
return;
}
std::unordered_map<BasicBlock*, Index> blockIndices;
for (Index i = 0; i < numBlocks; i++) {
blockIndices[blocks[i].get()] = i;
}
iDoms.resize(numBlocks, nonsense);
iDoms[0] = 0;
auto processBlocks = [&]() {
bool changed = false;
for (Index index = 1; index < numBlocks; index++) {
auto& preds = blocks[index]->in;
Index newParent = nonsense;
for (auto* pred : preds) {
auto predIndex = blockIndices[pred];
if (predIndex > index) {
continue;
}
if (iDoms[predIndex] == nonsense) {
continue;
}
if (newParent == nonsense) {
newParent = predIndex;
continue;
}
auto left = newParent;
auto right = predIndex;
while (left != right) {
while (left > right) {
left = iDoms[left];
}
while (right > left) {
right = iDoms[right];
}
}
newParent = left;
}
if (newParent != iDoms[index]) {
iDoms[index] = newParent;
changed = true;
assert(newParent <= index);
}
}
return changed;
};
processBlocks();
assert(!processBlocks());
iDoms[0] = nonsense;
}
}
#endif