#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"
Roots(), IsPostDominators(isPostDom) {}
public:
- /// getRoots - Return the root blocks of the current CFG. This may include
+ /// 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).
///
DenseMap<NodeT*, InfoRec> Info;
void reset() {
- for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(),
+ for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(),
E = DomTreeNodes.end(); I != E; ++I)
delete I->second;
DomTreeNodes.clear();
for (typename GraphTraits<Inverse<N> >::ChildIteratorType PI =
GraphTraits<Inverse<N> >::child_begin(NewBB),
PE = GraphTraits<Inverse<N> >::child_end(NewBB); PI != PE; ++PI)
- PredBlocks.push_back(*PI);
+ PredBlocks.push_back(*PI);
assert(!PredBlocks.empty() && "No predblocks??");
if (DomTreeNodes.size() != OtherDomTreeNodes.size())
return true;
- SmallPtrSet<const NodeT *,4> MyBBs;
- for (typename DomTreeNodeMapType::const_iterator
+ for (typename DomTreeNodeMapType::const_iterator
I = this->DomTreeNodes.begin(),
E = this->DomTreeNodes.end(); I != E; ++I) {
NodeT *BB = I->first;
return properlyDominates(getNode(A), getNode(B));
}
- bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
+ bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
const DomTreeNodeBase<NodeT> *B) const {
const DomTreeNodeBase<NodeT> *IDom;
if (A == 0 || B == 0) return false;
/// isReachableFromEntry - Return true if A is dominated by the entry
/// block of the function containing it.
bool isReachableFromEntry(NodeT* A) {
- assert (!this->isPostDominator()
+ assert (!this->isPostDominator()
&& "This is not implemented for post dominators");
return dominates(&A->getParent()->front(), A);
}
///
inline bool dominates(const DomTreeNodeBase<NodeT> *A,
const DomTreeNodeBase<NodeT> *B) {
- if (B == A)
+ if (B == A)
return true; // A node trivially dominates itself.
if (A == 0 || B == 0)
return false;
+ // Compare the result of the tree walk and the dfs numbers, if expensive
+ // checks are enabled.
+#ifdef XDEBUG
+ assert(!DFSInfoValid
+ || (dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A)));
+#endif
+
if (DFSInfoValid)
return B->DominatedBy(A);
}
inline bool dominates(const NodeT *A, const NodeT *B) {
- if (A == B)
+ if (A == B)
return true;
// Cast away the const qualifiers here. This is ok since
/// for basic block A and B. If there is no such block then return NULL.
NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) {
- assert (!this->isPostDominator()
+ assert (!this->isPostDominator()
&& "This is not implemented for post dominators");
- assert (A->getParent() == B->getParent()
+ assert (A->getParent() == B->getParent()
&& "Two blocks are not in same function");
// If either A or B is a entry block then it is nearest common dominator.
// the CFG...
/// 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
+ /// creates a new node as a child of DomBB dominator node,linking it into
/// the children list of the immediate dominator.
DomTreeNodeBase<NodeT> *addNewBlock(NodeT *BB, NodeT *DomBB) {
assert(getNode(BB) == 0 && "Block already in dominator tree!");
DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
assert(IDomNode && "Not immediate dominator specified for block!");
DFSInfoValid = false;
- return DomTreeNodes[BB] =
+ return DomTreeNodes[BB] =
IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode));
}
changeImmediateDominator(getNode(BB), getNode(NewBB));
}
- /// eraseNode - Removes a node from the dominator tree. Block must not
+ /// 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.
void eraseNode(NodeT *BB) {
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:
SmallVector<std::pair<DomTreeNodeBase<NodeT>*,
typename DomTreeNodeBase<NodeT>::iterator>, 32> WorkStack;
- for (unsigned i = 0, e = (unsigned)this->Roots.size(); i != e; ++i) {
- DomTreeNodeBase<NodeT> *ThisRoot = getNode(this->Roots[i]);
- WorkStack.push_back(std::make_pair(ThisRoot, ThisRoot->begin()));
- ThisRoot->DFSNumIn = DFSNum++;
-
- while (!WorkStack.empty()) {
- DomTreeNodeBase<NodeT> *Node = WorkStack.back().first;
- typename DomTreeNodeBase<NodeT>::iterator ChildIt =
- WorkStack.back().second;
-
- // If we visited all of the children of this node, "recurse" back up the
- // stack setting the DFOutNum.
- if (ChildIt == Node->end()) {
- Node->DFSNumOut = DFSNum++;
- WorkStack.pop_back();
- } else {
- // Otherwise, recursively visit this child.
- DomTreeNodeBase<NodeT> *Child = *ChildIt;
- ++WorkStack.back().second;
-
- WorkStack.push_back(std::make_pair(Child, Child->begin()));
- Child->DFSNumIn = DFSNum++;
- }
+ DomTreeNodeBase<NodeT> *ThisRoot = getRootNode();
+
+ if (!ThisRoot)
+ return;
+
+ // Even in the case of multiple exits that form the post dominator root
+ // nodes, do not iterate over all exits, but start from the virtual root
+ // node. Otherwise bbs, that are not post dominated by any exit but by the
+ // virtual root node, will never be assigned a DFS number.
+ WorkStack.push_back(std::make_pair(ThisRoot, ThisRoot->begin()));
+ ThisRoot->DFSNumIn = DFSNum++;
+
+ while (!WorkStack.empty()) {
+ DomTreeNodeBase<NodeT> *Node = WorkStack.back().first;
+ typename DomTreeNodeBase<NodeT>::iterator ChildIt =
+ WorkStack.back().second;
+
+ // If we visited all of the children of this node, "recurse" back up the
+ // stack setting the DFOutNum.
+ if (ChildIt == Node->end()) {
+ Node->DFSNumOut = DFSNum++;
+ WorkStack.pop_back();
+ } else {
+ // Otherwise, recursively visit this child.
+ DomTreeNodeBase<NodeT> *Child = *ChildIt;
+ ++WorkStack.back().second;
+
+ WorkStack.push_back(std::make_pair(Child, Child->begin()));
+ Child->DFSNumIn = DFSNum++;
}
}
/// recalculate - compute a dominator tree for the given function
template<class FT>
void recalculate(FT& F) {
- if (!this->IsPostDominators) {
- reset();
+ reset();
+ this->Vertex.push_back(0);
- // Initialize roots
+ if (!this->IsPostDominators) {
+ // Initialize root
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...
-
// Initialize the roots list
for (typename FT::iterator I = F.begin(), E = F.end(); I != E; ++I) {
if (std::distance(GraphTraits<FT*>::child_begin(I),
this->DomTreeNodes[I] = 0;
}
- this->Vertex.push_back(0);
-
Calculate<FT, Inverse<NodeT*> >(*this, F);
}
}
DominatorTreeBase<BasicBlock>& getBase() { return *DT; }
- /// getRoots - Return the root blocks of the current CFG. This may include
+ /// 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).
///
virtual bool runOnFunction(Function &F);
+ virtual void verifyAnalysis() const;
+
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
// 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(const Instruction *A, const Instruction *B) const {
- const BasicBlock *BBA = A->getParent(), *BBB = B->getParent();
- if (BBA != BBB) return dominates(BBA, BBB);
-
- // It is not possible to determine dominance between two PHI nodes
- // based on their ordering.
- if (isa<PHINode>(A) && isa<PHINode>(B))
- return false;
+ bool dominates(const Instruction *A, const Instruction *B) const;
- // Loop through the basic block until we find A or B.
- BasicBlock::const_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,
- const 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);
}
}
/// 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
+ /// 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);
DT->changeImmediateDominator(N, NewIDom);
}
- /// eraseNode - Removes a node from the dominator tree. Block must not
+ /// 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) {
}
- virtual void releaseMemory() {
+ virtual void releaseMemory() {
DT->releaseMemory();
}
/// 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));
+ }
};
const bool IsPostDominators;
public:
- DominanceFrontierBase(void *ID, bool isPostDom)
+ DominanceFrontierBase(void *ID, bool isPostDom)
: FunctionPass(ID), IsPostDominators(isPostDom) {}
- /// getRoots - Return the root blocks of the current CFG. This may include
+ /// 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).
///
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.
bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const {
std::set<BasicBlock *> tmpSet;
for (DomSetType::const_iterator I = DS2.begin(),
- E = DS2.end(); I != E; ++I)
+ E = DS2.end(); I != E; ++I)
tmpSet.insert(*I);
for (DomSetType::const_iterator I = DS1.begin(),
bool compare(DominanceFrontierBase &Other) const {
DomSetMapType tmpFrontiers;
for (DomSetMapType::const_iterator I = Other.begin(),
- E = Other.end(); I != E; ++I)
+ E = Other.end(); I != E; ++I)
tmpFrontiers.insert(std::make_pair(I->first, I->second));
for (DomSetMapType::iterator I = tmpFrontiers.begin(),
E = tmpFrontiers.end(); I != E; ) {
BasicBlock *Node = I->first;
const_iterator DFI = find(Node);
- if (DFI == end())
+ if (DFI == end())
return true;
if (compareDomSet(I->second, DFI->second))
class DominanceFrontier : public DominanceFrontierBase {
public:
static char ID; // Pass ID, replacement for typeid
- DominanceFrontier() :
+ DominanceFrontier() :
DominanceFrontierBase(&ID, false) {}
BasicBlock *getRoot() const {
return false;
}
+ virtual void verifyAnalysis() const;
+
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<DominatorTree>();
/// to reflect this change.
void changeImmediateDominator(BasicBlock *BB, BasicBlock *NewBB,
DominatorTree *DT) {
- // NewBB is now dominating BB. Which means BB's dominance
+ // NewBB is now dominating BB. Which means BB's dominance
// frontier is now part of NewBB's dominance frontier. However, BB
// itself is not member of NewBB's dominance frontier.
DominanceFrontier::iterator NewDFI = find(NewBB);