Template DominatorTreeBase by node type. This is the next major step towards

having dominator information on MBB's.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43036 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2007-10-16 19:59:25 +00:00
parent dcd8f78f8a
commit 49b653aa6a
5 changed files with 291 additions and 290 deletions

View File

@ -35,8 +35,8 @@
namespace llvm {
template<class GraphT>
unsigned DFSPass(DominatorTreeBase& DT, typename GraphT::NodeType* V,
unsigned N) {
unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* V, unsigned N) {
// This is more understandable as a recursive algorithm, but we can't use the
// recursive algorithm due to stack depth issues. Keep it here for
// documentation purposes.
@ -67,7 +67,8 @@ unsigned DFSPass(DominatorTreeBase& DT, typename GraphT::NodeType* V,
// First time we visited this BB?
if (NextSucc == GraphT::child_begin(BB)) {
DominatorTree::InfoRec &BBInfo = DT.Info[BB];
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &BBInfo =
DT.Info[BB];
BBInfo.Semi = ++N;
BBInfo.Label = BB;
@ -89,7 +90,8 @@ unsigned DFSPass(DominatorTreeBase& DT, typename GraphT::NodeType* V,
// Visit the successor next, if it isn't already visited.
typename GraphT::NodeType* Succ = *NextSucc;
DominatorTree::InfoRec &SuccVInfo = DT.Info[Succ];
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &SuccVInfo =
DT.Info[Succ];
if (SuccVInfo.Semi == 0) {
SuccVInfo.Parent = BB;
Worklist.push_back(std::make_pair(Succ, GraphT::child_begin(Succ)));
@ -100,20 +102,24 @@ unsigned DFSPass(DominatorTreeBase& DT, typename GraphT::NodeType* V,
}
template<class GraphT>
void Compress(DominatorTreeBase& DT, typename GraphT::NodeType *VIn) {
void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType *VIn) {
std::vector<typename GraphT::NodeType*> Work;
SmallPtrSet<typename GraphT::NodeType*, 32> Visited;
typename GraphT::NodeType* VInAncestor = DT.Info[VIn].Ancestor;
DominatorTreeBase::InfoRec &VInVAInfo = DT.Info[VInAncestor];
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInVAInfo =
DT.Info[VInAncestor];
if (VInVAInfo.Ancestor != 0)
Work.push_back(VIn);
while (!Work.empty()) {
typename GraphT::NodeType* V = Work.back();
DominatorTree::InfoRec &VInfo = DT.Info[V];
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo =
DT.Info[V];
typename GraphT::NodeType* VAncestor = VInfo.Ancestor;
DominatorTreeBase::InfoRec &VAInfo = DT.Info[VAncestor];
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo =
DT.Info[VAncestor];
// Process Ancestor first
if (Visited.insert(VAncestor) &&
@ -135,9 +141,10 @@ void Compress(DominatorTreeBase& DT, typename GraphT::NodeType *VIn) {
}
template<class GraphT>
typename GraphT::NodeType* Eval(DominatorTreeBase& DT,
typename GraphT::NodeType* Eval(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType *V) {
DominatorTreeBase::InfoRec &VInfo = DT.Info[V];
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo =
DT.Info[V];
#if !BALANCE_IDOM_TREE
// Higher-complexity but faster implementation
if (VInfo.Ancestor == 0)
@ -160,8 +167,9 @@ typename GraphT::NodeType* Eval(DominatorTreeBase& DT,
}
template<class GraphT>
void Link(DominatorTreeBase& DT, typename GraphT::NodeType* V,
typename GraphT::NodeType* W, DominatorTreeBase::InfoRec &WInfo) {
void Link(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* V, typename GraphT::NodeType* W,
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo) {
#if !BALANCE_IDOM_TREE
// Higher-complexity but faster implementation
WInfo.Ancestor = V;
@ -208,49 +216,49 @@ void Link(DominatorTreeBase& DT, typename GraphT::NodeType* V,
#endif
}
template<class NodeT>
void Calculate(DominatorTreeBase& DT, Function& F) {
template<class NodeT, class GraphT>
void Calculate(DominatorTreeBase<typename GraphT::NodeType>& DT, Function& F) {
// Step #1: Number blocks in depth-first order and initialize variables used
// in later stages of the algorithm.
unsigned N = 0;
for (unsigned i = 0, e = DT.Roots.size(); i != e; ++i)
N = DFSPass<GraphTraits<NodeT> >(DT, DT.Roots[i], N);
N = DFSPass<GraphT>(DT, DT.Roots[i], N);
for (unsigned i = N; i >= 2; --i) {
typename GraphTraits<NodeT>::NodeType* W = DT.Vertex[i];
DominatorTree::InfoRec &WInfo = DT.Info[W];
typename GraphT::NodeType* W = DT.Vertex[i];
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo =
DT.Info[W];
// Step #2: Calculate the semidominators of all vertices
for (typename GraphTraits<Inverse<NodeT> >::ChildIteratorType CI =
GraphTraits<Inverse<NodeT> >::child_begin(W),
E = GraphTraits<Inverse<NodeT> >::child_end(W); CI != E; ++CI)
if (DT.Info.count(*CI)) { // Only if this predecessor is reachable!
unsigned SemiU = DT.Info[Eval<GraphTraits<NodeT> >(DT, *CI)].Semi;
unsigned SemiU = DT.Info[Eval<GraphT>(DT, *CI)].Semi;
if (SemiU < WInfo.Semi)
WInfo.Semi = SemiU;
}
DT.Info[DT.Vertex[WInfo.Semi]].Bucket.push_back(W);
typename GraphTraits<NodeT>::NodeType* WParent = WInfo.Parent;
Link<GraphTraits<NodeT> >(DT, WParent, W, WInfo);
typename GraphT::NodeType* WParent = WInfo.Parent;
Link<GraphT>(DT, WParent, W, WInfo);
// Step #3: Implicitly define the immediate dominator of vertices
std::vector<typename GraphTraits<NodeT>::NodeType*> &WParentBucket =
std::vector<typename GraphT::NodeType*> &WParentBucket =
DT.Info[WParent].Bucket;
while (!WParentBucket.empty()) {
typename GraphTraits<NodeT>::NodeType* V = WParentBucket.back();
typename GraphT::NodeType* V = WParentBucket.back();
WParentBucket.pop_back();
typename GraphTraits<NodeT>::NodeType* U =
Eval<GraphTraits<NodeT> >(DT, V);
typename GraphT::NodeType* U = Eval<GraphT>(DT, V);
DT.IDoms[V] = DT.Info[U].Semi < DT.Info[V].Semi ? U : WParent;
}
}
// Step #4: Explicitly define the immediate dominator of each vertex
for (unsigned i = 2; i <= N; ++i) {
typename GraphTraits<NodeT>::NodeType* W = DT.Vertex[i];
typename GraphTraits<NodeT>::NodeType*& WIDom = DT.IDoms[W];
typename GraphT::NodeType* W = DT.Vertex[i];
typename GraphT::NodeType*& WIDom = DT.IDoms[W];
if (WIDom != DT.Vertex[DT.Info[W].Semi])
WIDom = DT.IDoms[WIDom];
}
@ -260,13 +268,13 @@ void Calculate(DominatorTreeBase& DT, Function& F) {
// Add a node for the root. This node might be the actual root, if there is
// one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0)
// which postdominates all real exits if there are multiple exit blocks.
typename GraphTraits<NodeT>::NodeType* Root = DT.Roots.size() == 1 ? DT.Roots[0]
: 0;
typename GraphT::NodeType* Root = DT.Roots.size() == 1 ? DT.Roots[0]
: 0;
DT.DomTreeNodes[Root] = DT.RootNode = new DomTreeNode(Root, 0);
// Loop over all of the reachable blocks in the function...
for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
if (typename GraphTraits<NodeT>::NodeType* ImmDom = DT.getIDom(I)) {
if (typename GraphT::NodeType* ImmDom = DT.getIDom(I)) {
// Reachable block.
DomTreeNode *BBNode = DT.DomTreeNodes[I];
if (BBNode) continue; // Haven't calculated this node yet?
@ -283,7 +291,7 @@ void Calculate(DominatorTreeBase& DT, Function& F) {
// Free temporary memory used to construct idom's
DT.IDoms.clear();
DT.Info.clear();
std::vector<typename GraphTraits<NodeT>::NodeType*>().swap(DT.Vertex);
std::vector<typename GraphT::NodeType*>().swap(DT.Vertex);
// FIXME: This does not work on PostDomTrees. It seems likely that this is
// due to an error in the algorithm for post-dominators. This really should

View File

@ -22,23 +22,28 @@
#define LLVM_ANALYSIS_DOMINATORS_H
#include "llvm/Pass.h"
#include "llvm/Instruction.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
#include <set>
#include "llvm/ADT/DenseMap.h"
namespace llvm {
class Instruction;
template <typename GraphType> struct GraphTraits;
//===----------------------------------------------------------------------===//
/// DominatorBase - Base class that other, more interesting dominator analyses
/// inherit from.
///
template <class NodeT>
class DominatorBase : public FunctionPass {
protected:
std::vector<BasicBlock*> Roots;
std::vector<NodeT*> Roots;
const bool IsPostDominators;
inline DominatorBase(intptr_t ID, bool isPostDom) :
FunctionPass(ID), Roots(), IsPostDominators(isPostDom) {}
@ -48,7 +53,7 @@ public:
/// 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; }
inline const std::vector<NodeT*> &getRoots() const { return Roots; }
/// isPostDominator - Returns true if analysis based of postdoms
///
@ -58,7 +63,7 @@ public:
//===----------------------------------------------------------------------===//
// DomTreeNode - Dominator Tree Node
class DominatorTreeBase;
template<class NodeT> class DominatorTreeBase;
class PostDominatorTree;
class MachineBasicBlock;
@ -69,7 +74,7 @@ class DomTreeNodeBase {
std::vector<DomTreeNodeBase<NodeT> *> Children;
int DFSNumIn, DFSNumOut;
friend class DominatorTreeBase;
template<class N> friend class DominatorTreeBase;
friend class PostDominatorTree;
public:
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::iterator iterator;
@ -124,18 +129,43 @@ private:
}
};
EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>);
template<class NodeT>
static std::ostream &operator<<(std::ostream &o,
const DomTreeNodeBase<NodeT> *Node) {
if (Node->getBlock())
WriteAsOperand(o, Node->getBlock(), false);
else
o << " <<exit node>>";
o << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "}";
return o << "\n";
}
template<class NodeT>
static void PrintDomTree(const DomTreeNodeBase<NodeT> *N, std::ostream &o,
unsigned Lev) {
o << std::string(2*Lev, ' ') << "[" << Lev << "] " << N;
for (typename DomTreeNodeBase<NodeT>::const_iterator I = N->begin(),
E = N->end(); I != E; ++I)
PrintDomTree<NodeT>(*I, o, Lev+1);
}
typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
typedef DomTreeNodeBase<MachineBasicBlock> MachineDomTreeNode;
//===----------------------------------------------------------------------===//
/// DominatorTree - Calculate the immediate dominator tree for a function.
///
class DominatorTreeBase : public DominatorBase {
template<class NodeT>
class DominatorTreeBase : public DominatorBase<NodeT> {
protected:
void reset();
typedef DenseMap<BasicBlock*, DomTreeNode*> DomTreeNodeMapType;
typedef DenseMap<NodeT*, DomTreeNodeBase<NodeT>*> DomTreeNodeMapType;
DomTreeNodeMapType DomTreeNodes;
DomTreeNode *RootNode;
DomTreeNodeBase<NodeT> *RootNode;
bool DFSInfoValid;
unsigned int SlowQueries;
@ -143,24 +173,35 @@ protected:
struct InfoRec {
unsigned Semi;
unsigned Size;
BasicBlock *Label, *Parent, *Child, *Ancestor;
NodeT *Label, *Parent, *Child, *Ancestor;
std::vector<BasicBlock*> Bucket;
std::vector<NodeT*> Bucket;
InfoRec() : Semi(0), Size(0), Label(0), Parent(0), Child(0), Ancestor(0) {}
};
DenseMap<BasicBlock*, BasicBlock*> IDoms;
DenseMap<NodeT*, NodeT*> IDoms;
// Vertex - Map the DFS number to the BasicBlock*
std::vector<BasicBlock*> Vertex;
std::vector<NodeT*> Vertex;
// Info - Collection of information used during the computation of idoms.
DenseMap<BasicBlock*, InfoRec> Info;
DenseMap<NodeT*, InfoRec> Info;
void reset() {
for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(),
E = DomTreeNodes.end(); I != E; ++I)
delete I->second;
DomTreeNodes.clear();
IDoms.clear();
this->Roots.clear();
Vertex.clear();
RootNode = 0;
}
public:
DominatorTreeBase(intptr_t ID, bool isPostDom)
: DominatorBase(ID, isPostDom), DFSInfoValid(false), SlowQueries(0) {}
: DominatorBase<NodeT>(ID, isPostDom), DFSInfoValid(false), SlowQueries(0) {}
~DominatorTreeBase() { reset(); }
virtual void releaseMemory() { reset(); }
@ -168,12 +209,12 @@ public:
/// 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 {
DomTreeNodeMapType::const_iterator I = DomTreeNodes.find(BB);
inline DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
typename DomTreeNodeMapType::const_iterator I = DomTreeNodes.find(BB);
return I != DomTreeNodes.end() ? I->second : 0;
}
inline DomTreeNode *operator[](BasicBlock *BB) const {
inline DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const {
return getNode(BB);
}
@ -184,25 +225,25 @@ public:
/// post-dominance information must be capable of dealing with this
/// possibility.
///
DomTreeNode *getRootNode() { return RootNode; }
const DomTreeNode *getRootNode() const { return RootNode; }
DomTreeNodeBase<NodeT> *getRootNode() { return RootNode; }
const DomTreeNodeBase<NodeT> *getRootNode() const { return RootNode; }
/// properlyDominates - Returns true iff this dominates N and this != N.
/// Note that this is not a constant time operation!
///
bool properlyDominates(const DomTreeNode *A,
DomTreeNode *B) const {
bool properlyDominates(const DomTreeNodeBase<NodeT> *A,
DomTreeNodeBase<NodeT> *B) const {
if (A == 0 || B == 0) return false;
return dominatedBySlowTreeWalk(A, B);
}
inline bool properlyDominates(BasicBlock *A, BasicBlock *B) {
inline bool properlyDominates(NodeT *A, NodeT *B) {
return properlyDominates(getNode(A), getNode(B));
}
bool dominatedBySlowTreeWalk(const DomTreeNode *A,
const DomTreeNode *B) const {
const DomTreeNode *IDom;
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
const DomTreeNodeBase<NodeT> *B) const {
const DomTreeNodeBase<NodeT> *IDom;
if (A == 0 || B == 0) return false;
while ((IDom = B->getIDom()) != 0 && IDom != A && IDom != B)
B = IDom; // Walk up the tree
@ -212,13 +253,17 @@ public:
/// isReachableFromEntry - Return true if A is dominated by the entry
/// block of the function containing it.
const bool isReachableFromEntry(BasicBlock* A);
const bool isReachableFromEntry(NodeT* A) {
assert (!this->isPostDominator()
&& "This is not implemented for post dominators");
return dominates(&A->getParent()->getEntryBlock(), A);
}
/// dominates - Returns true iff A dominates B. Note that this is not a
/// constant time operation!
///
inline bool dominates(const DomTreeNode *A,
DomTreeNode *B) {
inline bool dominates(const DomTreeNodeBase<NodeT> *A,
DomTreeNodeBase<NodeT> *B) {
if (B == A)
return true; // A node trivially dominates itself.
@ -239,7 +284,7 @@ public:
return dominatedBySlowTreeWalk(A, B);
}
inline bool dominates(BasicBlock *A, BasicBlock *B) {
inline bool dominates(NodeT *A, NodeT *B) {
if (A == B)
return true;
@ -248,11 +293,73 @@ public:
/// findNearestCommonDominator - Find nearest common dominator basic block
/// for basic block A and B. If there is no such block then return NULL.
BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B);
NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) {
assert (!this->isPostDominator()
&& "This is not implemented for post dominators");
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.
NodeT &Entry = A->getParent()->getEntryBlock();
if (A == &Entry || B == &Entry)
return &Entry;
// If B dominates A then B is nearest common dominator.
if (dominates(B, A))
return B;
// If A dominates B then A is nearest common dominator.
if (dominates(A, B))
return A;
DomTreeNodeBase<NodeT> *NodeA = getNode(A);
DomTreeNodeBase<NodeT> *NodeB = getNode(B);
// Collect NodeA dominators set.
SmallPtrSet<DomTreeNodeBase<NodeT>*, 16> NodeADoms;
NodeADoms.insert(NodeA);
DomTreeNodeBase<NodeT> *IDomA = NodeA->getIDom();
while (IDomA) {
NodeADoms.insert(IDomA);
IDomA = IDomA->getIDom();
}
// Walk NodeB immediate dominators chain and find common dominator node.
DomTreeNodeBase<NodeT> *IDomB = NodeB->getIDom();
while(IDomB) {
if (NodeADoms.count(IDomB) != 0)
return IDomB->getBlock();
IDomB = IDomB->getIDom();
}
return NULL;
}
// 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);
bool dominates(Instruction *A, Instruction *B) {
NodeT *BBA = A->getParent(), *BBB = B->getParent();
if (BBA != BBB) return this->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;
// Loop through the basic block until we find A or B.
typename NodeT::iterator I = BBA->begin();
for (; &*I != A && &*I != B; ++I) /*empty*/;
if(!this->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;
}
}
//===--------------------------------------------------------------------===//
// API to update (Post)DominatorTree information based on modifications to
@ -261,9 +368,9 @@ public:
/// 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.
DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) {
DomTreeNodeBase<NodeT> *addNewBlock(NodeT *BB, NodeT *DomBB) {
assert(getNode(BB) == 0 && "Block already in dominator tree!");
DomTreeNode *IDomNode = getNode(DomBB);
DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
assert(IDomNode && "Not immediate dominator specified for block!");
DFSInfoValid = false;
return DomTreeNodes[BB] =
@ -273,76 +380,156 @@ public:
/// changeImmediateDominator - This method is used to update the dominator
/// tree information when a node's immediate dominator changes.
///
void changeImmediateDominator(DomTreeNode *N,
DomTreeNode *NewIDom) {
void changeImmediateDominator(DomTreeNodeBase<NodeT> *N,
DomTreeNodeBase<NodeT> *NewIDom) {
assert(N && NewIDom && "Cannot change null node pointers!");
DFSInfoValid = false;
N->setIDom(NewIDom);
}
void changeImmediateDominator(BasicBlock *BB, BasicBlock *NewBB) {
void changeImmediateDominator(NodeT *BB, NodeT *NewBB) {
changeImmediateDominator(getNode(BB), getNode(NewBB));
}
/// 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(BasicBlock *BB);
void eraseNode(NodeT *BB) {
DomTreeNodeBase<NodeT> *Node = getNode(BB);
assert (Node && "Removing node that isn't in dominator tree.");
assert (Node->getChildren().empty() && "Node is not a leaf node.");
// Remove node from immediate dominator's children list.
DomTreeNodeBase<NodeT> *IDom = Node->getIDom();
if (IDom) {
typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I =
std::find(IDom->Children.begin(), IDom->Children.end(), Node);
assert(I != IDom->Children.end() &&
"Not in immediate dominator children set!");
// I am no longer your child...
IDom->Children.erase(I);
}
DomTreeNodes.erase(BB);
delete Node;
}
/// removeNode - Removes a node from the dominator tree. Block must not
/// dominate any other blocks. Invalidates any node pointing to removed
/// block.
void removeNode(BasicBlock *BB) {
void removeNode(NodeT *BB) {
assert(getNode(BB) && "Removing node that isn't in dominator tree.");
DomTreeNodes.erase(BB);
}
/// print - Convert to human readable form
///
virtual void print(std::ostream &OS, const Module* = 0) const;
virtual void print(std::ostream &o, const Module* ) const {
o << "=============================--------------------------------\n";
o << "Inorder Dominator Tree: ";
if (this->DFSInfoValid)
o << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
o << "\n";
PrintDomTree<NodeT>(getRootNode(), o, 1);
}
void print(std::ostream *OS, const Module* M = 0) const {
if (OS) print(*OS, M);
}
virtual void dump();
virtual void dump() {
print(llvm::cerr);
}
protected:
template<class GraphT> friend void Compress(DominatorTreeBase& DT,
template<class GraphT> friend void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* VIn);
template<class GraphT> friend typename GraphT::NodeType* Eval(
DominatorTreeBase& DT,
DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* V);
template<class GraphT> friend void Link(DominatorTreeBase& DT,
template<class GraphT> friend void Link(DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* V,
typename GraphT::NodeType* W,
InfoRec &WInfo);
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo);
template<class GraphT> friend unsigned DFSPass(DominatorTreeBase& DT,
template<class GraphT> friend unsigned DFSPass(
DominatorTreeBase<typename GraphT::NodeType>& DT,
typename GraphT::NodeType* V,
unsigned N);
template<class NodeT> friend void Calculate(DominatorTreeBase& DT,
Function& F);
template<class N, class GraphT> friend void Calculate(DominatorTreeBase<typename GraphT::NodeType>& DT,
Function& F);
/// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
/// dominator tree in dfs order.
void updateDFSNumbers();
void updateDFSNumbers() {
unsigned DFSNum = 0;
SmallVector<std::pair<DomTreeNodeBase<NodeT>*,
typename DomTreeNodeBase<NodeT>::iterator>, 32> WorkStack;
for (unsigned i = 0, e = 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++;
}
}
}
SlowQueries = 0;
DFSInfoValid = true;
}
DomTreeNode *getNodeForBlock(BasicBlock *BB);
DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) {
if (DomTreeNodeBase<NodeT> *BBNode = this->DomTreeNodes[BB])
return BBNode;
// Haven't calculated this node yet? Get or calculate the node for the
// immediate dominator.
NodeT *IDom = getIDom(BB);
DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom);
// Add a new tree node for this BasicBlock, and link it as a child of
// IDomNode
DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode);
return this->DomTreeNodes[BB] = IDomNode->addChild(C);
}
inline BasicBlock *getIDom(BasicBlock *BB) const {
DenseMap<BasicBlock*, BasicBlock*>::const_iterator I = IDoms.find(BB);
inline NodeT *getIDom(NodeT *BB) const {
typename DenseMap<NodeT*, NodeT*>::const_iterator I = IDoms.find(BB);
return I != IDoms.end() ? I->second : 0;
}
};
EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>);
//===-------------------------------------
/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to
/// compute a normal dominator tree.
///
class DominatorTree : public DominatorTreeBase {
class DominatorTree : public DominatorTreeBase<BasicBlock> {
public:
static char ID; // Pass ID, replacement for typeid
DominatorTree() : DominatorTreeBase(intptr_t(&ID), false) {}
DominatorTree() : DominatorTreeBase<BasicBlock>(intptr_t(&ID), false) {}
BasicBlock *getRoot() const {
assert(Roots.size() == 1 && "Should always have entry node!");
@ -392,7 +579,7 @@ template <> struct GraphTraits<DominatorTree*>
/// DominanceFrontierBase - Common base class for computing forward and inverse
/// dominance frontiers for a function.
///
class DominanceFrontierBase : public DominatorBase {
class DominanceFrontierBase : public DominatorBase<BasicBlock> {
public:
typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb
typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map
@ -400,7 +587,7 @@ protected:
DomSetMapType Frontiers;
public:
DominanceFrontierBase(intptr_t ID, bool isPostDom)
: DominatorBase(ID, isPostDom) {}
: DominatorBase<BasicBlock>(ID, isPostDom) {}
virtual void releaseMemory() { Frontiers.clear(); }

View File

@ -21,11 +21,11 @@ namespace llvm {
/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to
/// compute the a post-dominator tree.
///
struct PostDominatorTree : public DominatorTreeBase {
struct PostDominatorTree : public DominatorTreeBase<BasicBlock> {
static char ID; // Pass identification, replacement for typeid
PostDominatorTree() :
DominatorTreeBase((intptr_t)&ID, true) {}
DominatorTreeBase<BasicBlock>((intptr_t)&ID, true) {}
virtual bool runOnFunction(Function &F);

View File

@ -47,7 +47,7 @@ bool PostDominatorTree::runOnFunction(Function &F) {
Vertex.push_back(0);
Calculate<Inverse<BasicBlock*> >(*this, F);
Calculate<Inverse<BasicBlock*>, GraphTraits<Inverse<BasicBlock*> > >(*this, F);
return false;
}

View File

@ -16,7 +16,7 @@
#include "llvm/Analysis/Dominators.h"
#include "llvm/Support/CFG.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallPtrSet.h"
@ -49,6 +49,9 @@ static std::ostream &operator<<(std::ostream &o,
//
//===----------------------------------------------------------------------===//
TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>);
TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>);
char DominatorTree::ID = 0;
static RegisterPass<DominatorTree>
E("domtree", "Dominator Tree Construction", true);
@ -135,203 +138,6 @@ void DominatorTree::splitBlock(BasicBlock *NewBB) {
}
}
void DominatorTreeBase::updateDFSNumbers() {
unsigned DFSNum = 0;
SmallVector<std::pair<DomTreeNode*, DomTreeNode::iterator>, 32> WorkStack;
for (unsigned i = 0, e = Roots.size(); i != e; ++i) {
DomTreeNode *ThisRoot = getNode(Roots[i]);
WorkStack.push_back(std::make_pair(ThisRoot, ThisRoot->begin()));
ThisRoot->DFSNumIn = DFSNum++;
while (!WorkStack.empty()) {
DomTreeNode *Node = WorkStack.back().first;
DomTreeNode::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.
DomTreeNode *Child = *ChildIt;
++WorkStack.back().second;
WorkStack.push_back(std::make_pair(Child, Child->begin()));
Child->DFSNumIn = DFSNum++;
}
}
}
SlowQueries = 0;
DFSInfoValid = true;
}
/// isReachableFromEntry - Return true if A is dominated by the entry
/// block of the function containing it.
const bool DominatorTreeBase::isReachableFromEntry(BasicBlock* A) {
assert (!isPostDominator()
&& "This is not implemented for post dominators");
return dominates(&A->getParent()->getEntryBlock(), A);
}
// dominates - Return true if A dominates B. THis performs the
// special checks necessary if A and B are in the same basic block.
bool DominatorTreeBase::dominates(Instruction *A, Instruction *B) {
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;
// Loop through the basic block until we find A or B.
BasicBlock::iterator I = BBA->begin();
for (; &*I != A && &*I != B; ++I) /*empty*/;
if(!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;
}
}
// DominatorTreeBase::reset - Free all of the tree node memory.
//
void DominatorTreeBase::reset() {
for (DomTreeNodeMapType::iterator I = DomTreeNodes.begin(),
E = DomTreeNodes.end(); I != E; ++I)
delete I->second;
DomTreeNodes.clear();
IDoms.clear();
Roots.clear();
Vertex.clear();
RootNode = 0;
}
DomTreeNode *DominatorTreeBase::getNodeForBlock(BasicBlock *BB) {
if (DomTreeNode *BBNode = DomTreeNodes[BB])
return BBNode;
// Haven't calculated this node yet? Get or calculate the node for the
// immediate dominator.
BasicBlock *IDom = getIDom(BB);
DomTreeNode *IDomNode = getNodeForBlock(IDom);
// Add a new tree node for this BasicBlock, and link it as a child of
// IDomNode
DomTreeNode *C = new DomTreeNode(BB, IDomNode);
return DomTreeNodes[BB] = IDomNode->addChild(C);
}
/// findNearestCommonDominator - Find nearest common dominator basic block
/// for basic block A and B. If there is no such block then return NULL.
BasicBlock *DominatorTreeBase::findNearestCommonDominator(BasicBlock *A,
BasicBlock *B) {
assert (!isPostDominator()
&& "This is not implemented for post dominators");
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.
BasicBlock &Entry = A->getParent()->getEntryBlock();
if (A == &Entry || B == &Entry)
return &Entry;
// If B dominates A then B is nearest common dominator.
if (dominates(B, A))
return B;
// If A dominates B then A is nearest common dominator.
if (dominates(A, B))
return A;
DomTreeNode *NodeA = getNode(A);
DomTreeNode *NodeB = getNode(B);
// Collect NodeA dominators set.
SmallPtrSet<DomTreeNode*, 16> NodeADoms;
NodeADoms.insert(NodeA);
DomTreeNode *IDomA = NodeA->getIDom();
while (IDomA) {
NodeADoms.insert(IDomA);
IDomA = IDomA->getIDom();
}
// Walk NodeB immediate dominators chain and find common dominator node.
DomTreeNode *IDomB = NodeB->getIDom();
while(IDomB) {
if (NodeADoms.count(IDomB) != 0)
return IDomB->getBlock();
IDomB = IDomB->getIDom();
}
return NULL;
}
static std::ostream &operator<<(std::ostream &o, const DomTreeNode *Node) {
if (Node->getBlock())
WriteAsOperand(o, Node->getBlock(), false);
else
o << " <<exit node>>";
o << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "}";
return o << "\n";
}
static void PrintDomTree(const DomTreeNode *N, std::ostream &o,
unsigned Lev) {
o << std::string(2*Lev, ' ') << "[" << Lev << "] " << N;
for (DomTreeNode::const_iterator I = N->begin(), E = N->end();
I != E; ++I)
PrintDomTree(*I, o, Lev+1);
}
/// eraseNode - Removes a node from the domiantor 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 DominatorTreeBase::eraseNode(BasicBlock *BB) {
DomTreeNode *Node = getNode(BB);
assert (Node && "Removing node that isn't in dominator tree.");
assert (Node->getChildren().empty() && "Node is not a leaf node.");
// Remove node from immediate dominator's children list.
DomTreeNode *IDom = Node->getIDom();
if (IDom) {
std::vector<DomTreeNode*>::iterator I =
std::find(IDom->Children.begin(), IDom->Children.end(), Node);
assert(I != IDom->Children.end() &&
"Not in immediate dominator children set!");
// I am no longer your child...
IDom->Children.erase(I);
}
DomTreeNodes.erase(BB);
delete Node;
}
void DominatorTreeBase::print(std::ostream &o, const Module* ) const {
o << "=============================--------------------------------\n";
o << "Inorder Dominator Tree: ";
if (DFSInfoValid)
o << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
o << "\n";
PrintDomTree(getRootNode(), o, 1);
}
void DominatorTreeBase::dump() {
print(llvm::cerr);
}
bool DominatorTree::runOnFunction(Function &F) {
reset(); // Reset from the last time we were run...
@ -341,7 +147,7 @@ bool DominatorTree::runOnFunction(Function &F) {
DomTreeNodes[&F.getEntryBlock()] = 0;
Vertex.push_back(0);
Calculate<BasicBlock*>(*this, F);
Calculate<BasicBlock*, GraphTraits<BasicBlock*> >(*this, F);
updateDFSNumbers();