@@ -258,37 +258,40 @@ class DominatorTreeBase {
258
258
// Dominators always have a single root, postdominators can have more.
259
259
SmallVector<NodeT *, IsPostDom ? 4 : 1 > Roots;
260
260
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;
264
266
DomTreeNodeBase<NodeT> *RootNode = nullptr ;
265
267
ParentPtr Parent = nullptr ;
266
268
267
269
mutable bool DFSInfoValid = false ;
268
270
mutable unsigned int SlowQueries = 0 ;
271
+ unsigned BlockNumberEpoch = 0 ;
269
272
270
273
friend struct DomTreeBuilder ::SemiNCAInfo<DominatorTreeBase>;
271
274
272
275
public:
273
276
DominatorTreeBase () = default ;
274
277
275
278
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) {
282
283
Arg.wipe ();
283
284
}
284
285
285
286
DominatorTreeBase &operator =(DominatorTreeBase &&RHS) {
286
287
Roots = std::move (RHS.Roots );
287
288
DomTreeNodes = std::move (RHS.DomTreeNodes );
289
+ NodeNumberMap = std::move (RHS.NodeNumberMap );
288
290
RootNode = RHS.RootNode ;
289
291
Parent = RHS.Parent ;
290
292
DFSInfoValid = RHS.DFSInfoValid ;
291
293
SlowQueries = RHS.SlowQueries ;
294
+ BlockNumberEpoch = RHS.BlockNumberEpoch ;
292
295
RHS.wipe ();
293
296
return *this ;
294
297
}
@@ -333,35 +336,70 @@ class DominatorTreeBase {
333
336
if (!std::is_permutation (Roots.begin (), Roots.end (), Other.Roots .begin ()))
334
337
return true ;
335
338
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 ())))
345
345
return true ;
346
+ NumNodes++;
347
+ }
346
348
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
+ }
349
356
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;
352
373
}
374
+ }
353
375
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
+ }
355
393
}
356
394
395
+ public:
357
396
// / getNode - return the (Post)DominatorTree node for the specified basic
358
397
// / block. This is the same as using operator[] on this class. The result
359
398
// / may (but is not required to) be null for a forward (backwards)
360
399
// / statically unreachable block.
361
400
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 ();
365
403
return nullptr ;
366
404
}
367
405
@@ -678,8 +716,10 @@ class DominatorTreeBase {
678
716
// / dominate any other blocks. Removes node from its immediate dominator's
679
717
// / children list. Deletes dominator node associated with basic block BB.
680
718
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 ();
683
723
assert (Node->isLeaf () && " Node is not a leaf node." );
684
724
685
725
DFSInfoValid = false ;
@@ -695,7 +735,8 @@ class DominatorTreeBase {
695
735
IDom->Children .pop_back ();
696
736
}
697
737
698
- DomTreeNodes.erase (BB);
738
+ DomTreeNodes[*IdxOpt] = nullptr ;
739
+ NodeNumberMap.erase (BB);
699
740
700
741
if (!IsPostDom) return ;
701
742
@@ -786,17 +827,48 @@ class DominatorTreeBase {
786
827
DFSInfoValid = true ;
787
828
}
788
829
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:
789
838
// / recalculate - compute a dominator tree for the given function
790
839
void recalculate (ParentType &Func) {
791
840
Parent = &Func;
841
+ updateBlockNumberEpoch ();
792
842
DomTreeBuilder::Calculate (*this );
793
843
}
794
844
795
845
void recalculate (ParentType &Func, ArrayRef<UpdateType> Updates) {
796
846
Parent = &Func;
847
+ updateBlockNumberEpoch ();
797
848
DomTreeBuilder::CalculateWithUpdates (*this , Updates);
798
849
}
799
850
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
+
800
872
// / verify - checks if the tree is correct. There are 3 level of verification:
801
873
// / - Full -- verifies if the tree is correct by making sure all the
802
874
// / properties (including the parent and the sibling property)
@@ -817,6 +889,7 @@ class DominatorTreeBase {
817
889
818
890
void reset () {
819
891
DomTreeNodes.clear ();
892
+ NodeNumberMap.clear ();
820
893
Roots.clear ();
821
894
RootNode = nullptr ;
822
895
Parent = nullptr ;
@@ -831,7 +904,8 @@ class DominatorTreeBase {
831
904
DomTreeNodeBase<NodeT> *IDom = nullptr ) {
832
905
auto Node = std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDom);
833
906
auto *NodePtr = Node.get ();
834
- DomTreeNodes[BB] = std::move (Node);
907
+ unsigned NodeIdx = getNodeIndexForInsert (BB);
908
+ DomTreeNodes[NodeIdx] = std::move (Node);
835
909
if (IDom)
836
910
IDom->addChild (NodePtr);
837
911
return NodePtr;
@@ -915,6 +989,7 @@ class DominatorTreeBase {
915
989
// / assignable and destroyable state, but otherwise invalid.
916
990
void wipe () {
917
991
DomTreeNodes.clear ();
992
+ NodeNumberMap.clear ();
918
993
RootNode = nullptr ;
919
994
Parent = nullptr ;
920
995
}
0 commit comments