diff --git a/llvm/include/llvm/Support/GenericDomTree.h b/llvm/include/llvm/Support/GenericDomTree.h --- a/llvm/include/llvm/Support/GenericDomTree.h +++ b/llvm/include/llvm/Support/GenericDomTree.h @@ -14,7 +14,8 @@ /// /// Unlike ADT/* graph algorithms, generic dominator tree has more requirements /// on the graph's NodeRef. The NodeRef should be a pointer and, -/// NodeRef->getParent() must return the parent node that is also a pointer. +/// either NodeRef->getParent() must return the parent node that is also a +/// pointer or DomTreeNodeTraitsCustom needs to be implemented. /// /// FIXME: Maybe GenericDomTree needs a TreeTraits, instead of GraphTraits. /// @@ -220,6 +221,42 @@ bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL); } // namespace DomTreeBuilder +template struct DomTreeNodeTraitsCustom {}; + +/// Default DomTreeNode traits for used when DomTreeTraitsCustom is not defined +/// for NodeT. The default implementation assume a Function-like NodeT. +template struct DomTreeNodeTraits { + using NodeType = NodeT; + using NodePtr = NodeT *; + using ParentPtr = decltype(std::declval()->getParent()); + static_assert(std::is_pointer::value, + "Currently NodeT's parent must be a pointer type"); + using ParentType = std::remove_pointer_t; + + static NodeT *getEntryNode(ParentPtr Parent) { return &Parent->front(); } + static ParentPtr getParent(NodePtr BB) { return BB->getParent(); } +}; + +/// DomTreeNode traits specialization to use DomTreeTraitsCustom if it is +/// defined for NodeT. +template +struct DomTreeNodeTraits< + NodeT, std::void_t::ParentPtrTy>> { + using NodeType = NodeT; + using NodePtr = NodeT *; + using ParentPtr = typename DomTreeNodeTraitsCustom::ParentPtrTy; + static_assert(std::is_pointer::value, + "Currently NodeT's parent must be a pointer type"); + using ParentType = std::remove_pointer_t; + + static NodePtr getEntryNode(ParentPtr Parent) { + return DomTreeNodeTraitsCustom::getEntryNode(Parent); + } + static ParentPtr getParent(NodePtr BB) { + return DomTreeNodeTraitsCustom::getParent(BB); + } +}; + /// Core dominator tree base class. /// /// This class is a generic template over graph nodes. It is instantiated for @@ -229,9 +266,10 @@ public: static_assert(std::is_pointer::NodeRef>::value, "Currently DominatorTreeBase supports only pointer nodes"); - using NodeType = NodeT; - using NodePtr = NodeT *; - using ParentPtr = decltype(std::declval()->getParent()); + using NodeTrait = DomTreeNodeTraits; + using NodeType = typename NodeTrait::NodeType; + using NodePtr = typename NodeTrait::NodePtr; + using ParentPtr = typename NodeTrait::ParentPtr; static_assert(std::is_pointer::value, "Currently NodeT's parent must be a pointer type"); using ParentType = std::remove_pointer_t; @@ -467,13 +505,14 @@ /// must have tree nodes. NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) const { assert(A && B && "Pointers are not valid"); - assert(A->getParent() == B->getParent() && + assert(NodeTrait::getParent(A) == NodeTrait::getParent(B) && "Two blocks are not in same function"); // If either A or B is a entry block then it is nearest common dominator // (for forward-dominators). if (!isPostDominator()) { - NodeT &Entry = A->getParent()->front(); + NodeT &Entry = + *DomTreeNodeTraits::getEntryNode(NodeTrait::getParent(A)); if (A == &Entry || B == &Entry) return &Entry; } @@ -584,8 +623,8 @@ void insertEdge(NodeT *From, NodeT *To) { assert(From); assert(To); - assert(From->getParent() == Parent); - assert(To->getParent() == Parent); + assert(NodeTrait::getParent(From) == Parent); + assert(NodeTrait::getParent(To) == Parent); DomTreeBuilder::InsertEdge(*this, From, To); } @@ -602,8 +641,8 @@ void deleteEdge(NodeT *From, NodeT *To) { assert(From); assert(To); - assert(From->getParent() == Parent); - assert(To->getParent() == Parent); + assert(NodeTrait::getParent(From) == Parent); + assert(NodeTrait::getParent(To) == Parent); DomTreeBuilder::DeleteEdge(*this, From, To); } diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -2111,12 +2111,6 @@ EntryBlock->setParent(this); } - // FIXME: DominatorTreeBase is doing 'A->getParent()->front()'. 'front' is a - // specific interface of llvm::Function, instead of using - // GraphTraints::getEntryNode. We should add a new template parameter to - // DominatorTreeBase representing the Graph type. - VPBlockBase &front() const { return *Entry; } - const VPBlockBase *getExiting() const { return Exiting; } VPBlockBase *getExiting() { return Exiting; } diff --git a/llvm/lib/Transforms/Vectorize/VPlanCFG.h b/llvm/lib/Transforms/Vectorize/VPlanCFG.h --- a/llvm/lib/Transforms/Vectorize/VPlanCFG.h +++ b/llvm/lib/Transforms/Vectorize/VPlanCFG.h @@ -29,10 +29,12 @@ // successors/predecessors but not to the blocks inside the region. template <> struct GraphTraits { + using ParentPtrTy = VPRegionBlock *; using NodeRef = VPBlockBase *; using ChildIteratorType = SmallVectorImpl::iterator; static NodeRef getEntryNode(NodeRef N) { return N; } + static NodeRef getEntryNode(VPRegionBlock *R) { return R->getEntry(); } static inline ChildIteratorType child_begin(NodeRef N) { return N->getSuccessors().begin(); diff --git a/llvm/lib/Transforms/Vectorize/VPlanDominatorTree.h b/llvm/lib/Transforms/Vectorize/VPlanDominatorTree.h --- a/llvm/lib/Transforms/Vectorize/VPlanDominatorTree.h +++ b/llvm/lib/Transforms/Vectorize/VPlanDominatorTree.h @@ -22,6 +22,17 @@ namespace llvm { +template <> struct DomTreeNodeTraitsCustom { + using ParentPtrTy = VPRegionBlock *; + + static VPBlockBase *getEntryNode(ParentPtrTy Parent) { + return Parent->getEntry(); + } + + static ParentPtrTy getParent(VPBlockBase *B) { return B->getParent(); } +}; + +/// /// Template specialization of the standard LLVM dominator tree utility for /// VPBlockBases. using VPDominatorTree = DomTreeBase;