Rework dominator and post dominator information so that we do not have to
[oota-llvm.git] / include / llvm / Analysis / Dominators.h
index af2a0e384c90810c931c0e08c257ec58c1d33ffd..17b5efa52a0bcd2afc7b13cf89da041f5066f5e8 100644 (file)
@@ -1,4 +1,4 @@
-//===- llvm/Analysis/Dominators.h - Dominator Info Calculation ---*- C++ -*--=//
+//===- llvm/Analysis/Dominators.h - Dominator Info Calculation --*- C++ -*-===//
 //
 // This file defines the following classes:
 //  1. DominatorSet: Calculates the [reverse] dominator set for a function
 
 #include "llvm/Pass.h"
 #include <set>
+
 class Instruction;
 
+template <typename GraphType> struct GraphTraits;
+
 //===----------------------------------------------------------------------===//
 //
 // DominatorBase - Base class that other, more interesting dominator analyses
@@ -29,12 +32,15 @@ class Instruction;
 //
 class DominatorBase : public FunctionPass {
 protected:
-  BasicBlock *Root;
+  std::vector<BasicBlock*> Roots;
   const bool IsPostDominators;
 
-  inline DominatorBase(bool isPostDom) : Root(0), IsPostDominators(isPostDom) {}
+  inline DominatorBase(bool isPostDom) : Roots(), IsPostDominators(isPostDom) {}
 public:
-  inline BasicBlock *getRoot() const { return Root; }
+  // Return the root blocks of the current CFG.  This may include multiple
+  // blocks if we are computing post dominators.  For forward dominators, this
+  // will always be a single block (the entry node).
+  inline const std::vector<BasicBlock*> &getRoots() const { return Roots; }
 
   // Returns true if analysis based of postdoms
   bool isPostDominator() const { return IsPostDominators; }
@@ -43,7 +49,9 @@ public:
 //===----------------------------------------------------------------------===//
 //
 // DominatorSet - Maintain a set<BasicBlock*> for every basic block in a
-// function, that represents the blocks that dominate the block.
+// function, that represents the blocks that dominate the block.  If the block
+// is unreachable in this function, the set will be empty.  This cannot happen
+// for reachable code, because every block dominates at least itself.
 //
 class DominatorSetBase : public DominatorBase {
 public:
@@ -77,6 +85,12 @@ public:
     return I->second;
   }
 
+  /// isReachable - Return true if the specified basicblock is reachable.  If
+  /// the block is reachable, we have dominator set information for it.
+  bool isReachable(BasicBlock *BB) const {
+    return !getDominators(BB).empty();
+  }
+
   /// dominates - Return true if A dominates B.
   ///
   inline bool dominates(BasicBlock *A, BasicBlock *B) const {
@@ -93,7 +107,7 @@ public:
   virtual void print(std::ostream &OS) const;
 
   /// dominates - Return true if A dominates B.  This performs the special
-  /// checks neccesary if A and B are in the same basic block.
+  /// checks necessary if A and B are in the same basic block.
   ///
   bool dominates(Instruction *A, Instruction *B) const;
 
@@ -128,6 +142,16 @@ struct DominatorSet : public DominatorSetBase {
 
   virtual bool runOnFunction(Function &F);
 
+  /// recalculate - This method may be called by external passes that modify the
+  /// CFG and then need dominator information recalculated.  This method is
+  /// obviously really slow, so it should be avoided if at all possible.
+  void recalculate();
+
+  BasicBlock *getRoot() const {
+    assert(Roots.size() == 1 && "Should always have entry node!");
+    return Roots[0];
+  }
+
   // getAnalysisUsage - This simply provides a dominator set
   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
     AU.setPreservesAll();
@@ -183,6 +207,14 @@ public:
     IDoms[BB] = IDom;
   }
 
+  /// setImmediateDominator - Update the immediate dominator information to
+  /// change the current immediate dominator for the specified block to another
+  /// block.  This method requires that BB already have an IDom, otherwise just
+  /// use addNewBlock.
+  void setImmediateDominator(BasicBlock *BB, BasicBlock *NewIDom) {
+    assert(IDoms.find(BB) != IDoms.end() && "BB doesn't have idom yet!");
+    IDoms[BB] = NewIDom;
+  }
 
   // print - Convert to human readable form
   virtual void print(std::ostream &OS) const;
@@ -195,10 +227,15 @@ public:
 struct ImmediateDominators : public ImmediateDominatorsBase {
   ImmediateDominators() : ImmediateDominatorsBase(false) {}
 
+  BasicBlock *getRoot() const {
+    assert(Roots.size() == 1 && "Should always have entry node!");
+    return Roots[0];
+  }
+
   virtual bool runOnFunction(Function &F) {
     IDoms.clear();     // Reset from the last time we were run...
     DominatorSet &DS = getAnalysis<DominatorSet>();
-    Root = DS.getRoot();
+    Roots = DS.getRoots();
     calcIDoms(DS);
     return false;
   }
@@ -223,17 +260,28 @@ protected:
   std::map<BasicBlock*, Node*> Nodes;
   void reset();
   typedef std::map<BasicBlock*, Node*> NodeMapType;
+
+  Node *RootNode;
 public:
-  class Node2 : public std::vector<Node*> {
+  class Node2 {
     friend class DominatorTree;
     friend class PostDominatorTree;
     friend class DominatorTreeBase;
     BasicBlock *TheNode;
     Node2 *IDom;
+    std::vector<Node*> Children;
   public:
+    typedef std::vector<Node*>::iterator iterator;
+    typedef std::vector<Node*>::const_iterator const_iterator;
+
+    iterator begin()             { return Children.begin(); }
+    iterator end()               { return Children.end(); }
+    const_iterator begin() const { return Children.begin(); }
+    const_iterator end()   const { return Children.end(); }
+
     inline BasicBlock *getNode() const { return TheNode; }
     inline Node2 *getIDom() const { return IDom; }
-    inline const std::vector<Node*> &getChildren() const { return *this; }
+    inline const std::vector<Node*> &getChildren() const { return Children; }
 
     // dominates - Returns true iff this dominates N.  Note that this is not a 
     // constant time operation!
@@ -247,7 +295,9 @@ public:
   private:
     inline Node2(BasicBlock *node, Node *iDom) 
       : TheNode(node), IDom(iDom) {}
-    inline Node2 *addChild(Node *C) { push_back(C); return C; }
+    inline Node2 *addChild(Node *C) { Children.push_back(C); return C; }
+
+    void setIDom(Node2 *NewIDom);
   };
 
 public:
@@ -268,6 +318,17 @@ public:
     return getNode(BB);
   }
 
+  // getRootNode - This returns the entry node for the CFG of the function.  If
+  // this tree represents the post-dominance relations for a function, however,
+  // this root may be a node with the block == NULL.  This is the case when
+  // there are multiple exit nodes from a particular function.  Consumers of
+  // post-dominance information must be capable of dealing with this
+  // possibility.
+  //
+  Node *getRootNode() { return RootNode; }
+  const Node *getRootNode() const { return RootNode; }
+
+  //===--------------------------------------------------------------------===//
   // API to update (Post)DominatorTree information based on modifications to
   // the CFG...
 
@@ -277,9 +338,16 @@ public:
   ///
   Node *createNewNode(BasicBlock *BB, Node *IDomNode) {
     assert(getNode(BB) == 0 && "Block already in dominator tree!");
-    Node *New = Nodes[BB] = new Node(BB, IDomNode);
-    if (IDomNode) IDomNode->addChild(New);
-    return New;
+    assert(IDomNode && "Not immediate dominator specified for block!");
+    return Nodes[BB] = IDomNode->addChild(new Node(BB, IDomNode));
+  }
+
+  /// changeImmediateDominator - This method is used to update the dominator
+  /// tree information when a node's immediate dominator changes.
+  ///
+  void changeImmediateDominator(Node *Node, Node *NewIDom) {
+    assert(Node && NewIDom && "Cannot change null node pointers!");
+    Node->setIDom(NewIDom);
   }
 
   /// print - Convert to human readable form
@@ -294,10 +362,15 @@ public:
 struct DominatorTree : public DominatorTreeBase {
   DominatorTree() : DominatorTreeBase(false) {}
 
+  BasicBlock *getRoot() const {
+    assert(Roots.size() == 1 && "Should always have entry node!");
+    return Roots[0];
+  }
+
   virtual bool runOnFunction(Function &F) {
     reset();     // Reset from the last time we were run...
     DominatorSet &DS = getAnalysis<DominatorSet>();
-    Root = DS.getRoot();
+    Roots = DS.getRoots();
     calculate(DS);
     return false;
   }
@@ -310,6 +383,31 @@ private:
   void calculate(const DominatorSet &DS);
 };
 
+//===-------------------------------------
+// DominatorTree GraphTraits specialization so the DominatorTree can be
+// iterable by generic graph iterators.
+
+template <> struct GraphTraits<DominatorTree::Node*> {
+  typedef DominatorTree::Node NodeType;
+  typedef NodeType::iterator  ChildIteratorType;
+
+  static NodeType *getEntryNode(NodeType *N) {
+    return N;
+  }
+  static inline ChildIteratorType child_begin(NodeType* N) {
+    return N->begin();
+  }
+  static inline ChildIteratorType child_end(NodeType* N) {
+    return N->end();
+  }
+};
+
+template <> struct GraphTraits<DominatorTree*>
+  : public GraphTraits<DominatorTree::Node*> {
+  static NodeType *getEntryNode(DominatorTree *DT) {
+    return DT->getRootNode();
+  }
+};
 
 //===----------------------------------------------------------------------===//
 //
@@ -327,10 +425,30 @@ public:
   virtual void releaseMemory() { Frontiers.clear(); }
 
   // Accessor interface:
+  typedef DomSetMapType::iterator iterator;
   typedef DomSetMapType::const_iterator const_iterator;
-  inline const_iterator begin() const { return Frontiers.begin(); }
-  inline const_iterator end()   const { return Frontiers.end(); }
-  inline const_iterator find(BasicBlock* B) const { return Frontiers.find(B); }
+  iterator       begin()       { return Frontiers.begin(); }
+  const_iterator begin() const { return Frontiers.begin(); }
+  iterator       end()         { return Frontiers.end(); }
+  const_iterator end()   const { return Frontiers.end(); }
+  iterator       find(BasicBlock *B)       { return Frontiers.find(B); }
+  const_iterator find(BasicBlock *B) const { return Frontiers.find(B); }
+
+  void addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
+    assert(find(BB) == end() && "Block already in DominanceFrontier!");
+    Frontiers.insert(std::make_pair(BB, frontier));
+  }
+
+  void addToFrontier(iterator I, BasicBlock *Node) {
+    assert(I != end() && "BB is not in DominanceFrontier!");
+    I->second.insert(Node);
+  }
+
+  void removeFromFrontier(iterator I, BasicBlock *Node) {
+    assert(I != end() && "BB is not in DominanceFrontier!");
+    assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB");
+    I->second.erase(Node);
+  }
 
   // print - Convert to human readable form
   virtual void print(std::ostream &OS) const;
@@ -344,11 +462,17 @@ public:
 struct DominanceFrontier : public DominanceFrontierBase {
   DominanceFrontier() : DominanceFrontierBase(false) {}
 
+  BasicBlock *getRoot() const {
+    assert(Roots.size() == 1 && "Should always have entry node!");
+    return Roots[0];
+  }
+
   virtual bool runOnFunction(Function &) {
     Frontiers.clear();
     DominatorTree &DT = getAnalysis<DominatorTree>();
-    Root = DT.getRoot();
-    calculate(DT, DT[Root]);
+    Roots = DT.getRoots();
+    assert(Roots.size() == 1 && "Only one entry block for forward domfronts!");
+    calculate(DT, DT[Roots[0]]);
     return false;
   }