Skip to content

Commit

Permalink
[Dominators] Move root-finding out of DomTreeBase and simplify it
Browse files Browse the repository at this point in the history
Summary:
This patch moves root-finding logic from DominatorTreeBase to GenericDomTreeConstruction.h.
It makes the behavior simpler and more consistent by always adding a virtual root to PostDominatorTrees.

Reviewers: dberlin, davide, grosser, sanjoy

Reviewed By: dberlin

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D35597

llvm-svn: 309146
  • Loading branch information
kuhar committed Jul 26, 2017
1 parent b0c7809 commit c271dea
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 64 deletions.
5 changes: 2 additions & 3 deletions llvm/include/llvm/IR/Dominators.h
Expand Up @@ -41,9 +41,8 @@ namespace DomTreeBuilder {
using BBDomTree = DomTreeBase<BasicBlock>;
using BBPostDomTree = PostDomTreeBase<BasicBlock>;

extern template void Calculate<BBDomTree, Function>(BBDomTree &DT, Function &F);
extern template void Calculate<BBPostDomTree, Function>(BBPostDomTree &DT,
Function &F);
extern template void Calculate<BBDomTree>(BBDomTree &DT);
extern template void Calculate<BBPostDomTree>(BBPostDomTree &DT);

extern template void InsertEdge<BBDomTree>(BBDomTree &DT, BasicBlock *From,
BasicBlock *To);
Expand Down
45 changes: 18 additions & 27 deletions llvm/include/llvm/Support/GenericDomTree.h
Expand Up @@ -14,8 +14,8 @@
/// graph types.
///
/// Unlike ADT/* graph algorithms, generic dominator tree has more requirements
/// on the graph's NodeRef. The NodeRef should be a pointer and, depending on
/// the implementation, e.g. NodeRef->getParent() return the parent node.
/// on the graph's NodeRef. The NodeRef should be a pointer and,
/// NodeRef->getParent() must return the parent node that is also a pointer.
///
/// FIXME: Maybe GenericDomTree needs a TreeTraits, instead of GraphTraits.
///
Expand Down Expand Up @@ -187,8 +187,8 @@ void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &O,

namespace DomTreeBuilder {
// The routines below are provided in a separate header but referenced here.
template <typename DomTreeT, typename FuncT>
void Calculate(DomTreeT &DT, FuncT &F);
template <typename DomTreeT>
void Calculate(DomTreeT &DT);

template <class DomTreeT>
void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
Expand All @@ -208,14 +208,24 @@ bool Verify(const DomTreeT &DT);
/// various graphs in the LLVM IR or in the code generator.
template <typename NodeT, bool IsPostDom>
class DominatorTreeBase {
public:
static_assert(std::is_pointer<typename GraphTraits<NodeT *>::NodeRef>::value,
"Currently DominatorTreeBase supports only pointer nodes");
using NodeType = NodeT;
using NodePtr = NodeT *;
using ParentPtr = decltype(std::declval<NodeT *>()->getParent());
static_assert(std::is_pointer<ParentPtr>::value,
"Currently NodeT's parent must be a pointer type");
using ParentType = typename std::remove_pointer<ParentPtr>::type;
static constexpr bool IsPostDominator = IsPostDom;

protected:
std::vector<NodeT *> Roots;

using DomTreeNodeMapType =
DenseMap<NodeT *, std::unique_ptr<DomTreeNodeBase<NodeT>>>;
DomTreeNodeMapType DomTreeNodes;
DomTreeNodeBase<NodeT> *RootNode;
using ParentPtr = decltype(std::declval<NodeT *>()->getParent());
ParentPtr Parent = nullptr;

mutable bool DFSInfoValid = false;
Expand All @@ -224,12 +234,6 @@ class DominatorTreeBase {
friend struct DomTreeBuilder::SemiNCAInfo<DominatorTreeBase>;

public:
static_assert(std::is_pointer<typename GraphTraits<NodeT *>::NodeRef>::value,
"Currently DominatorTreeBase supports only pointer nodes");
using NodeType = NodeT;
using NodePtr = NodeT *;
static constexpr bool IsPostDominator = IsPostDom;

DominatorTreeBase() {}

DominatorTreeBase(DominatorTreeBase &&Arg)
Expand Down Expand Up @@ -650,23 +654,10 @@ class DominatorTreeBase {
}

/// recalculate - compute a dominator tree for the given function
template <class FT> void recalculate(FT &F) {
using TraitsTy = GraphTraits<FT *>;
void recalculate(ParentType &Func) {
reset();
Parent = &F;

if (!IsPostDominator) {
// Initialize root
NodeT *entry = TraitsTy::getEntryNode(&F);
addRoot(entry);
} else {
// Initialize the roots list
for (auto *Node : nodes(&F))
if (TraitsTy::child_begin(Node) == TraitsTy::child_end(Node))
addRoot(Node);
}

DomTreeBuilder::Calculate(*this, F);
Parent = &Func;
DomTreeBuilder::Calculate(*this);
}

/// verify - check parent and sibling property
Expand Down
64 changes: 36 additions & 28 deletions llvm/include/llvm/Support/GenericDomTreeConstruction.h
Expand Up @@ -131,7 +131,7 @@ struct SemiNCAInfo {
// Custom DFS implementation which can skip nodes based on a provided
// predicate. It also collects ReverseChildren so that we don't have to spend
// time getting predecessors in SemiNCA.
template <bool Inverse, typename DescendCondition>
template <typename DescendCondition>
unsigned runDFS(NodePtr V, unsigned LastNum, DescendCondition Condition,
unsigned AttachToNum) {
assert(V);
Expand All @@ -148,7 +148,7 @@ struct SemiNCAInfo {
BBInfo.Label = BB;
NumToNode.push_back(BB);

for (const NodePtr Succ : ChildrenGetter<NodePtr, Inverse>::Get(BB)) {
for (const NodePtr Succ : ChildrenGetter<NodePtr, IsPostDom>::Get(BB)) {
const auto SIT = NodeToInfo.find(Succ);
// Don't visit nodes more than once but remember to collect
// RerverseChildren.
Expand Down Expand Up @@ -260,42 +260,51 @@ struct SemiNCAInfo {
unsigned doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) {
unsigned Num = 0;

if (DT.Roots.size() > 1) {
// If the DT is a PostDomTree, always add a virtual root.
if (IsPostDom) {
auto &BBInfo = NodeToInfo[nullptr];
BBInfo.DFSNum = BBInfo.Semi = ++Num;
BBInfo.Label = nullptr;

NumToNode.push_back(nullptr); // NumToNode[n] = V;
}

if (DT.isPostDominator()) {
for (auto *Root : DT.Roots) Num = runDFS<true>(Root, Num, DC, 1);
} else {
assert(DT.Roots.size() == 1);
Num = runDFS<false>(DT.Roots[0], Num, DC, Num);
}
const unsigned InitialNum = Num;
for (auto *Root : DT.Roots) Num = runDFS(Root, Num, DC, InitialNum);

return Num;
}

void calculateFromScratch(DomTreeT &DT, const unsigned NumBlocks) {
static void FindAndAddRoots(DomTreeT &DT) {
assert(DT.Parent && "Parent pointer is not set");
using TraitsTy = GraphTraits<typename DomTreeT::ParentPtr>;

if (!IsPostDom) {
// Dominators have a single root that is the function's entry.
NodeT *entry = TraitsTy::getEntryNode(DT.Parent);
DT.addRoot(entry);
} else {
// Initialize the roots list for PostDominators.
for (auto *Node : nodes(DT.Parent))
if (TraitsTy::child_begin(Node) == TraitsTy::child_end(Node))
DT.addRoot(Node);
}
}

void calculateFromScratch(DomTreeT &DT) {
// Step #0: Number blocks in depth-first order and initialize variables used
// in later stages of the algorithm.
const unsigned LastDFSNum = doFullDFSWalk(DT, AlwaysDescend);
FindAndAddRoots(DT);
doFullDFSWalk(DT, AlwaysDescend);

runSemiNCA(DT);

if (DT.Roots.empty()) return;

// Add a node for the root. This node might be the actual root, if there is
// one exit block, or it may be the virtual exit (denoted by
// (BasicBlock *)0) which postdominates all real exits if there are multiple
// exit blocks, or an infinite loop.
// It might be that some blocks did not get a DFS number (e.g., blocks of
// infinite loops). In these cases an artificial exit node is required.
const bool MultipleRoots = DT.Roots.size() > 1 || (DT.isPostDominator() &&
LastDFSNum != NumBlocks);
NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr;
// Add a node for the root. If the tree is a PostDominatorTree it will be
// the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates
// all real exits (including multiple exit blocks, infinite loops).
NodePtr Root = IsPostDom ? nullptr : DT.Roots[0];

DT.RootNode = (DT.DomTreeNodes[Root] =
llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr))
Expand Down Expand Up @@ -523,7 +532,7 @@ struct SemiNCAInfo {
};

SemiNCAInfo SNCA;
SNCA.runDFS<IsPostDom>(Root, 0, UnreachableDescender, 0);
SNCA.runDFS(Root, 0, UnreachableDescender, 0);
SNCA.runSemiNCA(DT);
SNCA.attachNewSubtree(DT, Incoming);

Expand Down Expand Up @@ -638,7 +647,7 @@ struct SemiNCAInfo {
DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) << "\n");

SemiNCAInfo SNCA;
SNCA.runDFS<IsPostDom>(ToIDom, 0, DescendBelow, 0);
SNCA.runDFS(ToIDom, 0, DescendBelow, 0);
DEBUG(dbgs() << "\tRunning Semi-NCA\n");
SNCA.runSemiNCA(DT, Level);
SNCA.reattachExistingSubtree(DT, PrevIDomSubTree);
Expand Down Expand Up @@ -692,7 +701,7 @@ struct SemiNCAInfo {

SemiNCAInfo SNCA;
unsigned LastDFSNum =
SNCA.runDFS<IsPostDom>(ToTN->getBlock(), 0, DescendAndCollect, 0);
SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0);

TreeNodePtr MinNode = ToTN;

Expand Down Expand Up @@ -744,7 +753,7 @@ struct SemiNCAInfo {
const TreeNodePtr ToTN = DT.getNode(To);
return ToTN && ToTN->getLevel() > MinLevel;
};
SNCA.runDFS<IsPostDom>(MinNode->getBlock(), 0, DescendBelow, 0);
SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0);

DEBUG(dbgs() << "Previous IDom(MinNode) = " << BlockNamePrinter(PrevIDom)
<< "\nRunning Semi-NCA\n");
Expand Down Expand Up @@ -945,11 +954,10 @@ struct SemiNCAInfo {
}
};


template <class DomTreeT, class FuncT>
void Calculate(DomTreeT &DT, FuncT &F) {
template <class DomTreeT>
void Calculate(DomTreeT &DT) {
SemiNCAInfo<DomTreeT> SNCA;
SNCA.calculateFromScratch(DT, GraphTraits<FuncT *>::size(&F));
SNCA.calculateFromScratch(DT);
}

template <class DomTreeT>
Expand Down
10 changes: 4 additions & 6 deletions llvm/lib/IR/Dominators.cpp
Expand Up @@ -64,12 +64,10 @@ template class llvm::DomTreeNodeBase<BasicBlock>;
template class llvm::DominatorTreeBase<BasicBlock, false>; // DomTreeBase
template class llvm::DominatorTreeBase<BasicBlock, true>; // PostDomTreeBase

template void
llvm::DomTreeBuilder::Calculate<DomTreeBuilder::BBDomTree, Function>(
DomTreeBuilder::BBDomTree &DT, Function &F);
template void
llvm::DomTreeBuilder::Calculate<DomTreeBuilder::BBPostDomTree, Function>(
DomTreeBuilder::BBPostDomTree &DT, Function &F);
template void llvm::DomTreeBuilder::Calculate<DomTreeBuilder::BBDomTree>(
DomTreeBuilder::BBDomTree &DT);
template void llvm::DomTreeBuilder::Calculate<DomTreeBuilder::BBPostDomTree>(
DomTreeBuilder::BBPostDomTree &DT);

template void llvm::DomTreeBuilder::InsertEdge<DomTreeBuilder::BBDomTree>(
DomTreeBuilder::BBDomTree &DT, BasicBlock *From, BasicBlock *To);
Expand Down

0 comments on commit c271dea

Please sign in to comment.