@@ -258,37 +258,40 @@ class DominatorTreeBase {
258258 // Dominators always have a single root, postdominators can have more.
259259 SmallVector<NodeT *, IsPostDom ? 4 : 1 > Roots;
260260
261- using DomTreeNodeMapType =
262- DenseMap<NodeT *, std::unique_ptr<DomTreeNodeBase<NodeT>>>;
263- DomTreeNodeMapType DomTreeNodes;
261+ using DomTreeNodeStorageTy =
262+ SmallVector<std::unique_ptr<DomTreeNodeBase<NodeT>>>;
263+ DomTreeNodeStorageTy DomTreeNodes;
264+ // For graphs where blocks don't have numbers, create a numbering here.
265+ DenseMap<const NodeT *, unsigned > NodeNumberMap;
264266 DomTreeNodeBase<NodeT> *RootNode = nullptr ;
265267 ParentPtr Parent = nullptr ;
266268
267269 mutable bool DFSInfoValid = false ;
268270 mutable unsigned int SlowQueries = 0 ;
271+ unsigned BlockNumberEpoch = 0 ;
269272
270273 friend struct DomTreeBuilder ::SemiNCAInfo<DominatorTreeBase>;
271274
272275 public:
273276 DominatorTreeBase () = default ;
274277
275278 DominatorTreeBase (DominatorTreeBase &&Arg)
276- : Roots(std::move(Arg.Roots)),
277- DomTreeNodes (std::move(Arg.DomTreeNodes)),
278- RootNode(Arg.RootNode),
279- Parent(Arg.Parent),
280- DFSInfoValid(Arg.DFSInfoValid),
281- SlowQueries(Arg.SlowQueries) {
279+ : Roots(std::move(Arg.Roots)), DomTreeNodes(std::move(Arg.DomTreeNodes)),
280+ NodeNumberMap (std::move(Arg.NodeNumberMap)), RootNode(Arg.RootNode),
281+ Parent(Arg.Parent), DFSInfoValid(Arg.DFSInfoValid),
282+ SlowQueries(Arg.SlowQueries), BlockNumberEpoch(Arg.BlockNumberEpoch) {
282283 Arg.wipe ();
283284 }
284285
285286 DominatorTreeBase &operator =(DominatorTreeBase &&RHS) {
286287 Roots = std::move (RHS.Roots );
287288 DomTreeNodes = std::move (RHS.DomTreeNodes );
289+ NodeNumberMap = std::move (RHS.NodeNumberMap );
288290 RootNode = RHS.RootNode ;
289291 Parent = RHS.Parent ;
290292 DFSInfoValid = RHS.DFSInfoValid ;
291293 SlowQueries = RHS.SlowQueries ;
294+ BlockNumberEpoch = RHS.BlockNumberEpoch ;
292295 RHS.wipe ();
293296 return *this ;
294297 }
@@ -333,35 +336,70 @@ class DominatorTreeBase {
333336 if (!std::is_permutation (Roots.begin (), Roots.end (), Other.Roots .begin ()))
334337 return true ;
335338
336- const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes ;
337- if (DomTreeNodes.size () != OtherDomTreeNodes.size ())
338- return true ;
339-
340- for (const auto &DomTreeNode : DomTreeNodes) {
341- NodeT *BB = DomTreeNode.first ;
342- typename DomTreeNodeMapType::const_iterator OI =
343- OtherDomTreeNodes.find (BB);
344- if (OI == OtherDomTreeNodes.end ())
339+ size_t NumNodes = 0 ;
340+ // All nodes we have must exist and be equal in the other tree.
341+ for (const auto &Node : DomTreeNodes) {
342+ if (!Node)
343+ continue ;
344+ if (Node->compare (Other.getNode (Node->getBlock ())))
345345 return true ;
346+ NumNodes++;
347+ }
346348
347- DomTreeNodeBase<NodeT> &MyNd = *DomTreeNode.second ;
348- DomTreeNodeBase<NodeT> &OtherNd = *OI->second ;
349+ // If the other tree has more nodes than we have, they're not equal.
350+ size_t NumOtherNodes = 0 ;
351+ for (const auto &OtherNode : Other.DomTreeNodes )
352+ if (OtherNode)
353+ NumOtherNodes++;
354+ return NumNodes != NumOtherNodes;
355+ }
349356
350- if (MyNd.compare (&OtherNd))
351- return true ;
357+ private:
358+ template <typename T>
359+ using has_number_t =
360+ decltype (GraphTraits<T *>::getNumber(std::declval<T *>()));
361+
362+ std::optional<unsigned > getNodeIndex (const NodeT *BB) const {
363+ if constexpr (is_detected<has_number_t , NodeT>::value) {
364+ // BB can be nullptr, map nullptr to index 0.
365+ assert (BlockNumberEpoch ==
366+ GraphTraits<ParentPtr>::getNumberEpoch (Parent) &&
367+ " dominator tree used with outdated block numbers" );
368+ return BB ? GraphTraits<const NodeT *>::getNumber (BB) + 1 : 0 ;
369+ } else {
370+ if (auto It = NodeNumberMap.find (BB); It != NodeNumberMap.end ())
371+ return It->second ;
372+ return std::nullopt ;
352373 }
374+ }
353375
354- return false ;
376+ unsigned getNodeIndexForInsert (const NodeT *BB) {
377+ if constexpr (is_detected<has_number_t , NodeT>::value) {
378+ // getNodeIndex will never fail if nodes have getNumber().
379+ unsigned Idx = *getNodeIndex (BB);
380+ if (Idx >= DomTreeNodes.size ()) {
381+ unsigned Max = GraphTraits<ParentPtr>::getMaxNumber (Parent);
382+ DomTreeNodes.resize (Max > Idx + 1 ? Max : Idx + 1 );
383+ }
384+ return Idx;
385+ } else {
386+ // We might already have a number stored for BB.
387+ unsigned Idx =
388+ NodeNumberMap.try_emplace (BB, DomTreeNodes.size ()).first ->second ;
389+ if (Idx >= DomTreeNodes.size ())
390+ DomTreeNodes.resize (Idx + 1 );
391+ return Idx;
392+ }
355393 }
356394
395+ public:
357396 // / getNode - return the (Post)DominatorTree node for the specified basic
358397 // / block. This is the same as using operator[] on this class. The result
359398 // / may (but is not required to) be null for a forward (backwards)
360399 // / statically unreachable block.
361400 DomTreeNodeBase<NodeT> *getNode (const NodeT *BB) const {
362- auto I = DomTreeNodes.find (BB);
363- if (I != DomTreeNodes.end ())
364- return I->second .get ();
401+ if (auto Idx = getNodeIndex (BB); Idx && *Idx < DomTreeNodes.size ())
402+ return DomTreeNodes[*Idx].get ();
365403 return nullptr ;
366404 }
367405
@@ -678,8 +716,10 @@ class DominatorTreeBase {
678716 // / dominate any other blocks. Removes node from its immediate dominator's
679717 // / children list. Deletes dominator node associated with basic block BB.
680718 void eraseNode (NodeT *BB) {
681- DomTreeNodeBase<NodeT> *Node = getNode (BB);
682- assert (Node && " Removing node that isn't in dominator tree." );
719+ std::optional<unsigned > IdxOpt = getNodeIndex (BB);
720+ assert (IdxOpt && DomTreeNodes[*IdxOpt] &&
721+ " Removing node that isn't in dominator tree." );
722+ DomTreeNodeBase<NodeT> *Node = DomTreeNodes[*IdxOpt].get ();
683723 assert (Node->isLeaf () && " Node is not a leaf node." );
684724
685725 DFSInfoValid = false ;
@@ -695,7 +735,8 @@ class DominatorTreeBase {
695735 IDom->Children .pop_back ();
696736 }
697737
698- DomTreeNodes.erase (BB);
738+ DomTreeNodes[*IdxOpt] = nullptr ;
739+ NodeNumberMap.erase (BB);
699740
700741 if (!IsPostDom) return ;
701742
@@ -786,17 +827,48 @@ class DominatorTreeBase {
786827 DFSInfoValid = true ;
787828 }
788829
830+ private:
831+ void updateBlockNumberEpoch () {
832+ // Nothing to do for graphs that don't number their blocks.
833+ if constexpr (is_detected<has_number_t , NodeT>::value)
834+ BlockNumberEpoch = GraphTraits<ParentPtr>::getNumberEpoch (Parent);
835+ }
836+
837+ public:
789838 // / recalculate - compute a dominator tree for the given function
790839 void recalculate (ParentType &Func) {
791840 Parent = &Func;
841+ updateBlockNumberEpoch ();
792842 DomTreeBuilder::Calculate (*this );
793843 }
794844
795845 void recalculate (ParentType &Func, ArrayRef<UpdateType> Updates) {
796846 Parent = &Func;
847+ updateBlockNumberEpoch ();
797848 DomTreeBuilder::CalculateWithUpdates (*this , Updates);
798849 }
799850
851+ // / Update dominator tree after renumbering blocks.
852+ template <class T_ = NodeT>
853+ std::enable_if_t <is_detected<has_number_t , T_>::value, void >
854+ updateBlockNumbers () {
855+ updateBlockNumberEpoch ();
856+
857+ unsigned MaxNumber = GraphTraits<ParentPtr>::getMaxNumber (Parent);
858+ DomTreeNodeStorageTy NewVector;
859+ NewVector.resize (MaxNumber + 1 ); // +1, because index 0 is for nullptr
860+ for (auto &Node : DomTreeNodes) {
861+ if (!Node)
862+ continue ;
863+ unsigned Idx = *getNodeIndex (Node->getBlock ());
864+ // getMaxNumber is not necessarily supported
865+ if (Idx >= NewVector.size ())
866+ NewVector.resize (Idx + 1 );
867+ NewVector[Idx] = std::move (Node);
868+ }
869+ DomTreeNodes = std::move (NewVector);
870+ }
871+
800872 // / verify - checks if the tree is correct. There are 3 level of verification:
801873 // / - Full -- verifies if the tree is correct by making sure all the
802874 // / properties (including the parent and the sibling property)
@@ -817,6 +889,7 @@ class DominatorTreeBase {
817889
818890 void reset () {
819891 DomTreeNodes.clear ();
892+ NodeNumberMap.clear ();
820893 Roots.clear ();
821894 RootNode = nullptr ;
822895 Parent = nullptr ;
@@ -831,7 +904,8 @@ class DominatorTreeBase {
831904 DomTreeNodeBase<NodeT> *IDom = nullptr ) {
832905 auto Node = std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDom);
833906 auto *NodePtr = Node.get ();
834- DomTreeNodes[BB] = std::move (Node);
907+ unsigned NodeIdx = getNodeIndexForInsert (BB);
908+ DomTreeNodes[NodeIdx] = std::move (Node);
835909 if (IDom)
836910 IDom->addChild (NodePtr);
837911 return NodePtr;
@@ -915,6 +989,7 @@ class DominatorTreeBase {
915989 // / assignable and destroyable state, but otherwise invalid.
916990 void wipe () {
917991 DomTreeNodes.clear ();
992+ NodeNumberMap.clear ();
918993 RootNode = nullptr ;
919994 Parent = nullptr ;
920995 }
0 commit comments