1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[Dominators] Move root-finding out of DomTreeBase and simplify it

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
This commit is contained in:
Jakub Kuderski 2017-07-26 18:07:40 +00:00
parent c4e1589a7b
commit 5ad1cf8f51
4 changed files with 60 additions and 64 deletions

View File

@ -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);

View File

@ -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.
///
@ -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,
@ -208,6 +208,17 @@ 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;
@ -215,7 +226,6 @@ class DominatorTreeBase {
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;
@ -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)
@ -650,23 +654,10 @@ public:
}
/// 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

View File

@ -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);
@ -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.
@ -260,7 +260,8 @@ 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;
@ -268,34 +269,42 @@ struct SemiNCAInfo {
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))
@ -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);
@ -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);
@ -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;
@ -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");
@ -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>

View File

@ -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);