/// 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.
///
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,
/// 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;
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;
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)
}
/// 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
// 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);
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.
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))
};
SemiNCAInfo SNCA;
- SNCA.runDFS<IsPostDom>(Root, 0, UnreachableDescender, 0);
+ SNCA.runDFS(Root, 0, UnreachableDescender, 0);
SNCA.runSemiNCA(DT);
SNCA.attachNewSubtree(DT, Incoming);
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);
SemiNCAInfo SNCA;
unsigned LastDFSNum =
- SNCA.runDFS<IsPostDom>(ToTN->getBlock(), 0, DescendAndCollect, 0);
+ SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0);
TreeNodePtr MinNode = ToTN;
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");
}
};
-
-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>