Move DominatorTree to immediately follow DominatorTreeBase
[oota-llvm.git] / include / llvm / Analysis / Dominators.h
1 //===- llvm/Analysis/Dominators.h - Dominator Info Calculation --*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the following classes:
11 //  1. ImmediateDominators: Calculates and holds a mapping between BasicBlocks
12 //     and their immediate dominator.
13 //  2. DominatorSet: Calculates the [reverse] dominator set for a function
14 //  3. DominatorTree: Represent the ImmediateDominator as an explicit tree
15 //     structure.
16 //  4. ETForest: Efficient data structure for dominance comparisons and 
17 //     nearest-common-ancestor queries.
18 //  5. DominanceFrontier: Calculate and hold the dominance frontier for a
19 //     function.
20 //
21 //  These data structures are listed in increasing order of complexity.  It
22 //  takes longer to calculate the dominator frontier, for example, than the
23 //  ImmediateDominator mapping.
24 //
25 //===----------------------------------------------------------------------===//
26
27 #ifndef LLVM_ANALYSIS_DOMINATORS_H
28 #define LLVM_ANALYSIS_DOMINATORS_H
29
30 #include "llvm/Analysis/ET-Forest.h"
31 #include "llvm/Pass.h"
32 #include <set>
33
34 namespace llvm {
35
36 class Instruction;
37
38 template <typename GraphType> struct GraphTraits;
39
40 //===----------------------------------------------------------------------===//
41 /// DominatorBase - Base class that other, more interesting dominator analyses
42 /// inherit from.
43 ///
44 class DominatorBase : public FunctionPass {
45 protected:
46   std::vector<BasicBlock*> Roots;
47   const bool IsPostDominators;
48
49   inline DominatorBase(bool isPostDom) : Roots(), IsPostDominators(isPostDom) {}
50 public:
51   /// getRoots -  Return the root blocks of the current CFG.  This may include
52   /// multiple blocks if we are computing post dominators.  For forward
53   /// dominators, this will always be a single block (the entry node).
54   ///
55   inline const std::vector<BasicBlock*> &getRoots() const { return Roots; }
56
57   /// isPostDominator - Returns true if analysis based of postdoms
58   ///
59   bool isPostDominator() const { return IsPostDominators; }
60 };
61
62
63 //===----------------------------------------------------------------------===//
64 /// ImmediateDominators - Calculate the immediate dominator for each node in a
65 /// function.
66 ///
67 class ImmediateDominatorsBase : public DominatorBase {
68 protected:
69   struct InfoRec {
70     unsigned Semi;
71     unsigned Size;
72     BasicBlock *Label, *Parent, *Child, *Ancestor;
73     
74     std::vector<BasicBlock*> Bucket;
75     
76     InfoRec() : Semi(0), Size(0), Label(0), Parent(0), Child(0), Ancestor(0){}
77   };
78   
79   std::map<BasicBlock*, BasicBlock*> IDoms;
80
81   // Vertex - Map the DFS number to the BasicBlock*
82   std::vector<BasicBlock*> Vertex;
83   
84   // Info - Collection of information used during the computation of idoms.
85   std::map<BasicBlock*, InfoRec> Info;
86 public:
87   ImmediateDominatorsBase(bool isPostDom) : DominatorBase(isPostDom) {}
88
89   virtual void releaseMemory() { IDoms.clear(); }
90
91   // Accessor interface:
92   typedef std::map<BasicBlock*, BasicBlock*> IDomMapType;
93   typedef IDomMapType::const_iterator const_iterator;
94   inline const_iterator begin() const { return IDoms.begin(); }
95   inline const_iterator end()   const { return IDoms.end(); }
96   inline const_iterator find(BasicBlock* B) const { return IDoms.find(B);}
97
98   /// operator[] - Return the idom for the specified basic block.  The start
99   /// node returns null, because it does not have an immediate dominator.
100   ///
101   inline BasicBlock *operator[](BasicBlock *BB) const {
102     return get(BB);
103   }
104   
105   /// dominates - Return true if A dominates B.
106   ///
107   bool dominates(BasicBlock *A, BasicBlock *B) const;
108
109   /// properlyDominates - Return true if A dominates B and A != B.
110   ///
111   bool properlyDominates(BasicBlock *A, BasicBlock *B) const {
112     return A != B || properlyDominates(A, B);
113   }
114   
115   /// get() - Synonym for operator[].
116   ///
117   inline BasicBlock *get(BasicBlock *BB) const {
118     std::map<BasicBlock*, BasicBlock*>::const_iterator I = IDoms.find(BB);
119     return I != IDoms.end() ? I->second : 0;
120   }
121
122   //===--------------------------------------------------------------------===//
123   // API to update Immediate(Post)Dominators information based on modifications
124   // to the CFG...
125
126   /// addNewBlock - Add a new block to the CFG, with the specified immediate
127   /// dominator.
128   ///
129   void addNewBlock(BasicBlock *BB, BasicBlock *IDom) {
130     assert(get(BB) == 0 && "BasicBlock already in idom info!");
131     IDoms[BB] = IDom;
132   }
133
134   /// setImmediateDominator - Update the immediate dominator information to
135   /// change the current immediate dominator for the specified block to another
136   /// block.  This method requires that BB already have an IDom, otherwise just
137   /// use addNewBlock.
138   ///
139   void setImmediateDominator(BasicBlock *BB, BasicBlock *NewIDom) {
140     assert(IDoms.find(BB) != IDoms.end() && "BB doesn't have idom yet!");
141     IDoms[BB] = NewIDom;
142   }
143
144   /// print - Convert to human readable form
145   ///
146   virtual void print(std::ostream &OS, const Module* = 0) const;
147 };
148
149 //===-------------------------------------
150 /// ImmediateDominators Class - Concrete subclass of ImmediateDominatorsBase
151 /// that is used to compute a normal immediate dominator set.
152 ///
153 class ImmediateDominators : public ImmediateDominatorsBase {
154 public:
155   ImmediateDominators() : ImmediateDominatorsBase(false) {}
156
157   BasicBlock *getRoot() const {
158     assert(Roots.size() == 1 && "Should always have entry node!");
159     return Roots[0];
160   }
161
162   virtual bool runOnFunction(Function &F);
163
164   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
165     AU.setPreservesAll();
166   }
167
168 private:
169   unsigned DFSPass(BasicBlock *V, InfoRec &VInfo, unsigned N);
170   void Compress(BasicBlock *V, InfoRec &VInfo);
171   BasicBlock *Eval(BasicBlock *v);
172   void Link(BasicBlock *V, BasicBlock *W, InfoRec &WInfo);
173 };
174
175
176
177 //===----------------------------------------------------------------------===//
178 /// DominatorSet - Maintain a set<BasicBlock*> for every basic block in a
179 /// function, that represents the blocks that dominate the block.  If the block
180 /// is unreachable in this function, the set will be empty.  This cannot happen
181 /// for reachable code, because every block dominates at least itself.
182 ///
183 class DominatorSetBase : public DominatorBase {
184 public:
185   typedef std::set<BasicBlock*> DomSetType;    // Dom set for a bb
186   // Map of dom sets
187   typedef std::map<BasicBlock*, DomSetType> DomSetMapType;
188 protected:
189   DomSetMapType Doms;
190 public:
191   DominatorSetBase(bool isPostDom) : DominatorBase(isPostDom) {}
192
193   virtual void releaseMemory() { Doms.clear(); }
194
195   // Accessor interface:
196   typedef DomSetMapType::const_iterator const_iterator;
197   typedef DomSetMapType::iterator iterator;
198   inline const_iterator begin() const { return Doms.begin(); }
199   inline       iterator begin()       { return Doms.begin(); }
200   inline const_iterator end()   const { return Doms.end(); }
201   inline       iterator end()         { return Doms.end(); }
202   inline const_iterator find(BasicBlock* B) const { return Doms.find(B); }
203   inline       iterator find(BasicBlock* B)       { return Doms.find(B); }
204
205
206   /// getDominators - Return the set of basic blocks that dominate the specified
207   /// block.
208   ///
209   inline const DomSetType &getDominators(BasicBlock *BB) const {
210     const_iterator I = find(BB);
211     assert(I != end() && "BB not in function!");
212     return I->second;
213   }
214
215   /// isReachable - Return true if the specified basicblock is reachable.  If
216   /// the block is reachable, we have dominator set information for it.
217   ///
218   bool isReachable(BasicBlock *BB) const {
219     return !getDominators(BB).empty();
220   }
221
222   /// dominates - Return true if A dominates B.
223   ///
224   inline bool dominates(BasicBlock *A, BasicBlock *B) const {
225     return getDominators(B).count(A) != 0;
226   }
227
228   /// properlyDominates - Return true if A dominates B and A != B.
229   ///
230   bool properlyDominates(BasicBlock *A, BasicBlock *B) const {
231     return dominates(A, B) && A != B;
232   }
233
234   /// print - Convert to human readable form
235   ///
236   virtual void print(std::ostream &OS, const Module* = 0) const;
237
238   /// dominates - Return true if A dominates B.  This performs the special
239   /// checks necessary if A and B are in the same basic block.
240   ///
241   bool dominates(Instruction *A, Instruction *B) const;
242
243   //===--------------------------------------------------------------------===//
244   // API to update (Post)DominatorSet information based on modifications to
245   // the CFG...
246
247   /// addBasicBlock - Call to update the dominator set with information about a
248   /// new block that was inserted into the function.
249   ///
250   void addBasicBlock(BasicBlock *BB, const DomSetType &Dominators) {
251     assert(find(BB) == end() && "Block already in DominatorSet!");
252     Doms.insert(std::make_pair(BB, Dominators));
253   }
254
255   /// addDominator - If a new block is inserted into the CFG, then method may be
256   /// called to notify the blocks it dominates that it is in their set.
257   ///
258   void addDominator(BasicBlock *BB, BasicBlock *NewDominator) {
259     iterator I = find(BB);
260     assert(I != end() && "BB is not in DominatorSet!");
261     I->second.insert(NewDominator);
262   }
263 };
264
265
266 //===-------------------------------------
267 /// DominatorSet Class - Concrete subclass of DominatorSetBase that is used to
268 /// compute a normal dominator set.
269 ///
270 class DominatorSet : public DominatorSetBase {
271 public:
272   DominatorSet() : DominatorSetBase(false) {}
273
274   virtual bool runOnFunction(Function &F);
275
276   BasicBlock *getRoot() const {
277     assert(Roots.size() == 1 && "Should always have entry node!");
278     return Roots[0];
279   }
280
281   /// getAnalysisUsage - This simply provides a dominator set
282   ///
283   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
284     AU.addRequired<ImmediateDominators>();
285     AU.setPreservesAll();
286   }
287
288   // stub - dummy function, just ignore it
289   static int stub;
290 };
291
292
293 //===----------------------------------------------------------------------===//
294 /// DominatorTree - Calculate the immediate dominator tree for a function.
295 ///
296 class DominatorTreeBase : public DominatorBase {
297 public:
298   class Node;
299 protected:
300   std::map<BasicBlock*, Node*> Nodes;
301   void reset();
302   typedef std::map<BasicBlock*, Node*> NodeMapType;
303
304   Node *RootNode;
305 public:
306   class Node {
307     friend struct DominatorTree;
308     friend struct PostDominatorTree;
309     friend struct DominatorTreeBase;
310     BasicBlock *TheBB;
311     Node *IDom;
312     std::vector<Node*> Children;
313   public:
314     typedef std::vector<Node*>::iterator iterator;
315     typedef std::vector<Node*>::const_iterator const_iterator;
316
317     iterator begin()             { return Children.begin(); }
318     iterator end()               { return Children.end(); }
319     const_iterator begin() const { return Children.begin(); }
320     const_iterator end()   const { return Children.end(); }
321
322     inline BasicBlock *getBlock() const { return TheBB; }
323     inline Node *getIDom() const { return IDom; }
324     inline const std::vector<Node*> &getChildren() const { return Children; }
325
326     /// properlyDominates - Returns true iff this dominates N and this != N.
327     /// Note that this is not a constant time operation!
328     ///
329     bool properlyDominates(const Node *N) const {
330       const Node *IDom;
331       if (this == 0 || N == 0) return false;
332       while ((IDom = N->getIDom()) != 0 && IDom != this)
333         N = IDom;   // Walk up the tree
334       return IDom != 0;
335     }
336
337     /// dominates - Returns true iff this dominates N.  Note that this is not a
338     /// constant time operation!
339     ///
340     inline bool dominates(const Node *N) const {
341       if (N == this) return true;  // A node trivially dominates itself.
342       return properlyDominates(N);
343     }
344     
345   private:
346     inline Node(BasicBlock *BB, Node *iDom) : TheBB(BB), IDom(iDom) {}
347     inline Node *addChild(Node *C) { Children.push_back(C); return C; }
348
349     void setIDom(Node *NewIDom);
350   };
351
352 public:
353   DominatorTreeBase(bool isPostDom) : DominatorBase(isPostDom) {}
354   ~DominatorTreeBase() { reset(); }
355
356   virtual void releaseMemory() { reset(); }
357
358   /// getNode - return the (Post)DominatorTree node for the specified basic
359   /// block.  This is the same as using operator[] on this class.
360   ///
361   inline Node *getNode(BasicBlock *BB) const {
362     NodeMapType::const_iterator i = Nodes.find(BB);
363     return (i != Nodes.end()) ? i->second : 0;
364   }
365
366   inline Node *operator[](BasicBlock *BB) const {
367     return getNode(BB);
368   }
369
370   /// getRootNode - This returns the entry node for the CFG of the function.  If
371   /// this tree represents the post-dominance relations for a function, however,
372   /// this root may be a node with the block == NULL.  This is the case when
373   /// there are multiple exit nodes from a particular function.  Consumers of
374   /// post-dominance information must be capable of dealing with this
375   /// possibility.
376   ///
377   Node *getRootNode() { return RootNode; }
378   const Node *getRootNode() const { return RootNode; }
379
380   //===--------------------------------------------------------------------===//
381   // API to update (Post)DominatorTree information based on modifications to
382   // the CFG...
383
384   /// createNewNode - Add a new node to the dominator tree information.  This
385   /// creates a new node as a child of IDomNode, linking it into the children
386   /// list of the immediate dominator.
387   ///
388   Node *createNewNode(BasicBlock *BB, Node *IDomNode) {
389     assert(getNode(BB) == 0 && "Block already in dominator tree!");
390     assert(IDomNode && "Not immediate dominator specified for block!");
391     return Nodes[BB] = IDomNode->addChild(new Node(BB, IDomNode));
392   }
393
394   /// changeImmediateDominator - This method is used to update the dominator
395   /// tree information when a node's immediate dominator changes.
396   ///
397   void changeImmediateDominator(Node *N, Node *NewIDom) {
398     assert(N && NewIDom && "Cannot change null node pointers!");
399     N->setIDom(NewIDom);
400   }
401
402   /// removeNode - Removes a node from the dominator tree.  Block must not
403   /// dominate any other blocks.  Invalidates any node pointing to removed
404   /// block.
405   void removeNode(BasicBlock *BB) {
406     assert(getNode(BB) && "Removing node that isn't in dominator tree.");
407     Nodes.erase(BB);
408   }
409
410   /// print - Convert to human readable form
411   ///
412   virtual void print(std::ostream &OS, const Module* = 0) const;
413 };
414
415 //===-------------------------------------
416 /// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to
417 /// compute a normal dominator tree.
418 ///
419 class DominatorTree : public DominatorTreeBase {
420 public:
421   DominatorTree() : DominatorTreeBase(false) {}
422   
423   BasicBlock *getRoot() const {
424     assert(Roots.size() == 1 && "Should always have entry node!");
425     return Roots[0];
426   }
427   
428   virtual bool runOnFunction(Function &F) {
429     reset();     // Reset from the last time we were run...
430     ImmediateDominators &ID = getAnalysis<ImmediateDominators>();
431     Roots = ID.getRoots();
432     calculate(ID);
433     return false;
434   }
435   
436   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
437     AU.setPreservesAll();
438     AU.addRequired<ImmediateDominators>();
439   }
440 private:
441   void calculate(const ImmediateDominators &ID);
442   Node *getNodeForBlock(BasicBlock *BB);
443 };
444
445 //===-------------------------------------
446 /// DominatorTree GraphTraits specialization so the DominatorTree can be
447 /// iterable by generic graph iterators.
448 ///
449 template <> struct GraphTraits<DominatorTree::Node*> {
450   typedef DominatorTree::Node NodeType;
451   typedef NodeType::iterator  ChildIteratorType;
452   
453   static NodeType *getEntryNode(NodeType *N) {
454     return N;
455   }
456   static inline ChildIteratorType child_begin(NodeType* N) {
457     return N->begin();
458   }
459   static inline ChildIteratorType child_end(NodeType* N) {
460     return N->end();
461   }
462 };
463
464 template <> struct GraphTraits<DominatorTree*>
465   : public GraphTraits<DominatorTree::Node*> {
466   static NodeType *getEntryNode(DominatorTree *DT) {
467     return DT->getRootNode();
468   }
469 };
470
471
472 //===-------------------------------------
473 /// ET-Forest Class - Class used to construct forwards and backwards 
474 /// ET-Forests
475 ///
476 class ETForestBase : public DominatorBase {
477 public:
478   ETForestBase(bool isPostDom) : DominatorBase(isPostDom), Nodes(), 
479                                  DFSInfoValid(false), SlowQueries(0) {}
480   
481   virtual void releaseMemory() { reset(); }
482
483   typedef std::map<BasicBlock*, ETNode*> ETMapType;
484
485   void updateDFSNumbers();
486     
487   /// dominates - Return true if A dominates B.
488   ///
489   inline bool dominates(BasicBlock *A, BasicBlock *B) {
490     if (A == B)
491       return true;
492     
493     ETNode *NodeA = getNode(A);
494     ETNode *NodeB = getNode(B);
495     
496     if (DFSInfoValid)
497       return NodeB->DominatedBy(NodeA);
498     else {
499       // If we end up with too many slow queries, just update the
500       // DFS numbers on the theory that we are going to keep querying.
501       SlowQueries++;
502       if (SlowQueries > 32) {
503         updateDFSNumbers();
504         return NodeB->DominatedBy(NodeA);
505       }
506       return NodeB->DominatedBySlow(NodeA);
507     }
508   }
509
510   /// properlyDominates - Return true if A dominates B and A != B.
511   ///
512   bool properlyDominates(BasicBlock *A, BasicBlock *B) {
513     return dominates(A, B) && A != B;
514   }
515
516   /// Return the nearest common dominator of A and B.
517   BasicBlock *nearestCommonDominator(BasicBlock *A, BasicBlock *B) const  {
518     ETNode *NodeA = getNode(A);
519     ETNode *NodeB = getNode(B);
520     
521     ETNode *Common = NodeA->NCA(NodeB);
522     if (!Common)
523       return NULL;
524     return Common->getData<BasicBlock>();
525   }
526
527   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
528     AU.setPreservesAll();
529     AU.addRequired<ImmediateDominators>();
530   }
531   //===--------------------------------------------------------------------===//
532   // API to update Forest information based on modifications
533   // to the CFG...
534
535   /// addNewBlock - Add a new block to the CFG, with the specified immediate
536   /// dominator.
537   ///
538   void addNewBlock(BasicBlock *BB, BasicBlock *IDom);
539
540   /// setImmediateDominator - Update the immediate dominator information to
541   /// change the current immediate dominator for the specified block
542   /// to another block.  This method requires that BB for NewIDom
543   /// already have an ETNode, otherwise just use addNewBlock.
544   ///
545   void setImmediateDominator(BasicBlock *BB, BasicBlock *NewIDom);
546   /// print - Convert to human readable form
547   ///
548   virtual void print(std::ostream &OS, const Module* = 0) const;
549 protected:
550   /// getNode - return the (Post)DominatorTree node for the specified basic
551   /// block.  This is the same as using operator[] on this class.
552   ///
553   inline ETNode *getNode(BasicBlock *BB) const {
554     ETMapType::const_iterator i = Nodes.find(BB);
555     return (i != Nodes.end()) ? i->second : 0;
556   }
557
558   inline ETNode *operator[](BasicBlock *BB) const {
559     return getNode(BB);
560   }
561
562   void reset();
563   ETMapType Nodes;
564   bool DFSInfoValid;
565   unsigned int SlowQueries;
566
567 };
568
569 //==-------------------------------------
570 /// ETForest Class - Concrete subclass of ETForestBase that is used to
571 /// compute a forwards ET-Forest.
572
573 class ETForest : public ETForestBase {
574 public:
575   ETForest() : ETForestBase(false) {}
576
577   BasicBlock *getRoot() const {
578     assert(Roots.size() == 1 && "Should always have entry node!");
579     return Roots[0];
580   }
581
582   virtual bool runOnFunction(Function &F) {
583     reset();     // Reset from the last time we were run...
584     ImmediateDominators &ID = getAnalysis<ImmediateDominators>();
585     Roots = ID.getRoots();
586     calculate(ID);
587     return false;
588   }
589
590   void calculate(const ImmediateDominators &ID);
591   ETNode *getNodeForBlock(BasicBlock *BB);
592 };
593
594 //===----------------------------------------------------------------------===//
595 /// DominanceFrontierBase - Common base class for computing forward and inverse
596 /// dominance frontiers for a function.
597 ///
598 class DominanceFrontierBase : public DominatorBase {
599 public:
600   typedef std::set<BasicBlock*>             DomSetType;    // Dom set for a bb
601   typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map
602 protected:
603   DomSetMapType Frontiers;
604 public:
605   DominanceFrontierBase(bool isPostDom) : DominatorBase(isPostDom) {}
606
607   virtual void releaseMemory() { Frontiers.clear(); }
608
609   // Accessor interface:
610   typedef DomSetMapType::iterator iterator;
611   typedef DomSetMapType::const_iterator const_iterator;
612   iterator       begin()       { return Frontiers.begin(); }
613   const_iterator begin() const { return Frontiers.begin(); }
614   iterator       end()         { return Frontiers.end(); }
615   const_iterator end()   const { return Frontiers.end(); }
616   iterator       find(BasicBlock *B)       { return Frontiers.find(B); }
617   const_iterator find(BasicBlock *B) const { return Frontiers.find(B); }
618
619   void addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
620     assert(find(BB) == end() && "Block already in DominanceFrontier!");
621     Frontiers.insert(std::make_pair(BB, frontier));
622   }
623
624   void addToFrontier(iterator I, BasicBlock *Node) {
625     assert(I != end() && "BB is not in DominanceFrontier!");
626     I->second.insert(Node);
627   }
628
629   void removeFromFrontier(iterator I, BasicBlock *Node) {
630     assert(I != end() && "BB is not in DominanceFrontier!");
631     assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB");
632     I->second.erase(Node);
633   }
634
635   /// print - Convert to human readable form
636   ///
637   virtual void print(std::ostream &OS, const Module* = 0) const;
638 };
639
640
641 //===-------------------------------------
642 /// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is
643 /// used to compute a forward dominator frontiers.
644 ///
645 class DominanceFrontier : public DominanceFrontierBase {
646 public:
647   DominanceFrontier() : DominanceFrontierBase(false) {}
648
649   BasicBlock *getRoot() const {
650     assert(Roots.size() == 1 && "Should always have entry node!");
651     return Roots[0];
652   }
653
654   virtual bool runOnFunction(Function &) {
655     Frontiers.clear();
656     DominatorTree &DT = getAnalysis<DominatorTree>();
657     Roots = DT.getRoots();
658     assert(Roots.size() == 1 && "Only one entry block for forward domfronts!");
659     calculate(DT, DT[Roots[0]]);
660     return false;
661   }
662
663   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
664     AU.setPreservesAll();
665     AU.addRequired<DominatorTree>();
666   }
667 private:
668   const DomSetType &calculate(const DominatorTree &DT,
669                               const DominatorTree::Node *Node);
670 };
671
672
673 } // End llvm namespace
674
675 // Make sure that any clients of this file link in Dominators.cpp
676 FORCE_DEFINING_FILE_TO_BE_LINKED(DominatorSet)
677
678 #endif