#define LLVM_ANALYSIS_DOMINATORS_H
#include "llvm/Pass.h"
-#include "llvm/BasicBlock.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::iterator iterator;
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::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(); }
-
+
NodeT *getBlock() const { return TheBB; }
DomTreeNodeBase<NodeT> *getIDom() const { return IDom; }
const std::vector<DomTreeNodeBase<NodeT>*> &getChildren() const {
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom)
: TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { }
-
+
DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) {
Children.push_back(C);
return C;
void clearAllChildren() {
Children.clear();
}
-
+
bool compare(DomTreeNodeBase<NodeT> *Other) {
if (getNumChildren() != Other->getNumChildren())
return true;
IDom->Children.push_back(this);
}
}
-
+
/// getDFSNumIn/getDFSNumOut - These are an internal implementation detail, do
/// not call them.
unsigned getDFSNumIn() const { return DFSNumIn; }
WriteAsOperand(o, Node->getBlock(), false);
else
o << " <<exit node>>";
-
+
o << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "}";
-
+
return o << "\n";
}
Vertex.clear();
RootNode = 0;
}
-
+
// NewBB is split and now it has one successor. Update dominator tree to
// reflect this change.
template<class N, class GraphT>
if (DomTreeNodes.size() != OtherDomTreeNodes.size())
return true;
- SmallPtrSet<const NodeT *,4> MyBBs;
for (typename DomTreeNodeMapType::const_iterator
I = this->DomTreeNodes.begin(),
E = this->DomTreeNodes.end(); I != E; ++I) {
DomTreeNodeBase<NodeT>* MyNd = I->second;
DomTreeNodeBase<NodeT>* OtherNd = OI->second;
-
+
if (MyNd->compare(OtherNd))
return true;
}
/// Note that this is not a constant time operation!
///
bool properlyDominates(const DomTreeNodeBase<NodeT> *A,
- DomTreeNodeBase<NodeT> *B) const {
+ const DomTreeNodeBase<NodeT> *B) const {
if (A == 0 || B == 0) return false;
return dominatedBySlowTreeWalk(A, B);
}
&& "This is not implemented for post dominators");
return dominates(&A->getParent()->front(), A);
}
-
+
/// dominates - Returns true iff A dominates B. Note that this is not a
/// constant time operation!
///
inline bool dominates(const DomTreeNodeBase<NodeT> *A,
- DomTreeNodeBase<NodeT> *B) {
+ const DomTreeNodeBase<NodeT> *B) {
if (B == A)
return true; // A node trivially dominates itself.
return dominatedBySlowTreeWalk(A, B);
}
- inline bool dominates(NodeT *A, NodeT *B) {
+ inline bool dominates(const NodeT *A, const NodeT *B) {
if (A == B)
return true;
-
- return dominates(getNode(A), getNode(B));
+
+ // Cast away the const qualifiers here. This is ok since
+ // this function doesn't actually return the values returned
+ // from getNode.
+ return dominates(getNode(const_cast<NodeT *>(A)),
+ getNode(const_cast<NodeT *>(B)));
}
-
+
NodeT *getRoot() const {
assert(this->Roots.size() == 1 && "Should always have entry node!");
return this->Roots[0];
assert(getNode(BB) && "Removing node that isn't in dominator tree.");
DomTreeNodes.erase(BB);
}
-
+
/// splitBlock - BB is split and now it has one successor. Update dominator
/// tree to reflect this change.
void splitBlock(NodeT* NewBB) {
o << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
o << "\n";
- PrintDomTree<NodeT>(getRootNode(), o, 1);
+ // The postdom tree can have a null root if there are no returns.
+ if (getRootNode())
+ PrintDomTree<NodeT>(getRootNode(), o, 1);
}
-
+
protected:
template<class GraphT>
friend void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT,
friend void Link(DominatorTreeBase<typename GraphT::NodeType>& DT,
unsigned DFSNumV, typename GraphT::NodeType* W,
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo);
-
+
template<class GraphT>
friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* V,
unsigned N);
-
+
template<class FuncT, class N>
friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
FuncT& F);
-
+
/// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
/// dominator tree in dfs order.
void updateDFSNumbers() {
// Otherwise, recursively visit this child.
DomTreeNodeBase<NodeT> *Child = *ChildIt;
++WorkStack.back().second;
-
+
WorkStack.push_back(std::make_pair(Child, Child->begin()));
Child->DFSNumIn = DFSNum++;
}
}
}
-
+
SlowQueries = 0;
DFSInfoValid = true;
}
-
+
DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) {
typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.find(BB);
if (I != this->DomTreeNodes.end() && I->second)
DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode);
return this->DomTreeNodes[BB] = IDomNode->addChild(C);
}
-
+
inline NodeT *getIDom(NodeT *BB) const {
typename DenseMap<NodeT*, NodeT*>::const_iterator I = IDoms.find(BB);
return I != IDoms.end() ? I->second : 0;
}
-
+
inline void addRoot(NodeT* BB) {
this->Roots.push_back(BB);
}
-
+
public:
/// recalculate - compute a dominator tree for the given function
template<class FT>
void recalculate(FT& F) {
if (!this->IsPostDominators) {
reset();
-
+
// Initialize roots
this->Roots.push_back(&F.front());
this->IDoms[&F.front()] = 0;
this->DomTreeNodes[&F.front()] = 0;
this->Vertex.push_back(0);
-
+
Calculate<FT, NodeT*>(*this, F);
-
+
updateDFSNumbers();
} else {
reset(); // Reset from the last time we were run...
}
this->Vertex.push_back(0);
-
+
Calculate<FT, Inverse<NodeT*> >(*this, F);
}
}
public:
static char ID; // Pass ID, replacement for typeid
DominatorTreeBase<BasicBlock>* DT;
-
+
DominatorTree() : FunctionPass(&ID) {
DT = new DominatorTreeBase<BasicBlock>(false);
}
-
+
~DominatorTree() {
DT->releaseMemory();
delete DT;
}
-
+
DominatorTreeBase<BasicBlock>& getBase() { return *DT; }
-
+
/// getRoots - 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 DT->getRoots();
}
-
+
inline BasicBlock *getRoot() const {
return DT->getRoot();
}
-
+
inline DomTreeNode *getRootNode() const {
return DT->getRootNode();
}
inline bool compare(DominatorTree &Other) const {
DomTreeNode *R = getRootNode();
DomTreeNode *OtherR = Other.getRootNode();
-
+
if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
return true;
-
+
if (DT->compare(Other.getBase()))
return true;
}
virtual bool runOnFunction(Function &F);
-
+
+ virtual void verifyAnalysis() const;
+
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
-
+
inline bool dominates(DomTreeNode* A, DomTreeNode* B) const {
return DT->dominates(A, B);
}
-
- inline bool dominates(BasicBlock* A, BasicBlock* B) const {
+
+ inline bool dominates(const BasicBlock* A, const BasicBlock* B) const {
return DT->dominates(A, B);
}
-
+
// dominates - Return true if A dominates B. This performs the
// special checks necessary if A and B are in the same basic block.
- bool dominates(Instruction *A, Instruction *B) const {
- BasicBlock *BBA = A->getParent(), *BBB = B->getParent();
- if (BBA != BBB) return DT->dominates(BBA, BBB);
+ bool dominates(const Instruction *A, const Instruction *B) const;
- // It is not possible to determine dominance between two PHI nodes
- // based on their ordering.
- if (isa<PHINode>(A) && isa<PHINode>(B))
- return false;
-
- // Loop through the basic block until we find A or B.
- BasicBlock::iterator I = BBA->begin();
- for (; &*I != A && &*I != B; ++I) /*empty*/;
-
- //if(!DT.IsPostDominators) {
- // A dominates B if it is found first in the basic block.
- return &*I == A;
- //} else {
- // // A post-dominates B if B is found first in the basic block.
- // return &*I == B;
- //}
- }
-
- inline bool properlyDominates(const DomTreeNode* A, DomTreeNode* B) const {
+ bool properlyDominates(const DomTreeNode *A, const DomTreeNode *B) const {
return DT->properlyDominates(A, B);
}
-
- inline bool properlyDominates(BasicBlock* A, BasicBlock* B) const {
+
+ bool properlyDominates(BasicBlock *A, BasicBlock *B) const {
return DT->properlyDominates(A, B);
}
-
+
/// findNearestCommonDominator - Find nearest common dominator basic block
/// for basic block A and B. If there is no such block then return NULL.
inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
-
+
inline DomTreeNode *operator[](BasicBlock *BB) const {
return DT->getNode(BB);
}
-
+
/// getNode - return the (Post)DominatorTree node for the specified basic
/// block. This is the same as using operator[] on this class.
///
inline DomTreeNode *getNode(BasicBlock *BB) const {
return DT->getNode(BB);
}
-
+
/// addNewBlock - Add a new node to the dominator tree information. This
/// creates a new node as a child of DomBB dominator node,linking it into
/// the children list of the immediate dominator.
inline DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) {
return DT->addNewBlock(BB, DomBB);
}
-
+
/// changeImmediateDominator - This method is used to update the dominator
/// tree information when a node's immediate dominator changes.
///
inline void changeImmediateDominator(BasicBlock *N, BasicBlock* NewIDom) {
DT->changeImmediateDominator(N, NewIDom);
}
-
+
inline void changeImmediateDominator(DomTreeNode *N, DomTreeNode* NewIDom) {
DT->changeImmediateDominator(N, NewIDom);
}
-
+
/// eraseNode - Removes a node from the dominator tree. Block must not
/// domiante any other blocks. Removes node from its immediate dominator's
/// children list. Deletes dominator node associated with basic block BB.
inline void eraseNode(BasicBlock *BB) {
DT->eraseNode(BB);
}
-
+
/// splitBlock - BB is split and now it has one successor. Update dominator
/// tree to reflect this change.
inline void splitBlock(BasicBlock* NewBB) {
DT->splitBlock(NewBB);
}
-
+
bool isReachableFromEntry(BasicBlock* A) {
return DT->isReachableFromEntry(A);
}
-
-
+
+
virtual void releaseMemory() {
DT->releaseMemory();
}
-
- virtual void print(std::ostream &OS, const Module* M= 0) const;
+
+ virtual void print(raw_ostream &OS, const Module* M= 0) const;
};
//===-------------------------------------
/// DominatorTree GraphTraits specialization so the DominatorTree can be
/// iterable by generic graph iterators.
///
-template <> struct GraphTraits<DomTreeNode *> {
+template <> struct GraphTraits<DomTreeNode*> {
typedef DomTreeNode NodeType;
typedef NodeType::iterator ChildIteratorType;
-
+
static NodeType *getEntryNode(NodeType *N) {
return N;
}
- static inline ChildIteratorType child_begin(NodeType* N) {
+ static inline ChildIteratorType child_begin(NodeType *N) {
return N->begin();
}
- static inline ChildIteratorType child_end(NodeType* N) {
+ static inline ChildIteratorType child_end(NodeType *N) {
return N->end();
}
+
+ typedef df_iterator<DomTreeNode*> nodes_iterator;
+
+ static nodes_iterator nodes_begin(DomTreeNode *N) {
+ return df_begin(getEntryNode(N));
+ }
+
+ static nodes_iterator nodes_end(DomTreeNode *N) {
+ return df_end(getEntryNode(N));
+ }
};
template <> struct GraphTraits<DominatorTree*>
- : public GraphTraits<DomTreeNode *> {
+ : public GraphTraits<DomTreeNode*> {
static NodeType *getEntryNode(DominatorTree *DT) {
return DT->getRootNode();
}
+
+ static nodes_iterator nodes_begin(DominatorTree *N) {
+ return df_begin(getEntryNode(N));
+ }
+
+ static nodes_iterator nodes_end(DominatorTree *N) {
+ return df_end(getEntryNode(N));
+ }
};
DomSetMapType Frontiers;
std::vector<BasicBlock*> Roots;
const bool IsPostDominators;
-
+
public:
DominanceFrontierBase(void *ID, bool isPostDom)
: FunctionPass(ID), IsPostDominators(isPostDom) {}
/// dominators, this will always be a single block (the entry node).
///
inline const std::vector<BasicBlock*> &getRoots() const { return Roots; }
-
+
/// isPostDominator - Returns true if analysis based of postdoms
///
bool isPostDominator() const { return IsPostDominators; }
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) {
+ iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
assert(find(BB) == end() && "Block already in DominanceFrontier!");
- Frontiers.insert(std::make_pair(BB, frontier));
+ return Frontiers.insert(std::make_pair(BB, frontier)).first;
}
/// removeBlock - Remove basic block BB's frontier.
/// print - Convert to human readable form
///
- virtual void print(std::ostream &OS, const Module* = 0) const;
+ virtual void print(raw_ostream &OS, const Module* = 0) const;
};
return false;
}
+ virtual void verifyAnalysis() const;
+
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<DominatorTree>();