2002-08-02 16:43:03 +00:00
|
|
|
//===- Dominators.cpp - Dominator Calculation -----------------------------===//
|
2003-10-20 19:43:21 +00:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by the LLVM research group and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2001-07-02 05:46:38 +00:00
|
|
|
//
|
2002-08-02 16:43:03 +00:00
|
|
|
// This file implements simple dominator construction algorithms for finding
|
|
|
|
// forward dominators. Postdominators are available in libanalysis, but are not
|
|
|
|
// included in libvmcore, because it's not needed. Forward dominators are
|
|
|
|
// needed to support the Verifier pass.
|
2001-07-02 05:46:38 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Analysis/Dominators.h"
|
2002-02-12 21:07:25 +00:00
|
|
|
#include "llvm/Support/CFG.h"
|
2002-07-27 01:12:17 +00:00
|
|
|
#include "llvm/Assembly/Writer.h"
|
2001-11-27 00:03:19 +00:00
|
|
|
#include "Support/DepthFirstIterator.h"
|
2002-02-05 03:35:31 +00:00
|
|
|
#include "Support/SetOperations.h"
|
2003-11-21 20:23:48 +00:00
|
|
|
using namespace llvm;
|
2003-11-11 22:41:34 +00:00
|
|
|
|
2003-12-07 00:38:08 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ImmediateDominators Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Immediate Dominators construction - This pass constructs immediate dominator
|
|
|
|
// information for a flow-graph based on the algorithm described in this
|
|
|
|
// document:
|
|
|
|
//
|
|
|
|
// A Fast Algorithm for Finding Dominators in a Flowgraph
|
|
|
|
// T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141.
|
|
|
|
//
|
|
|
|
// This implements both the O(n*ack(n)) and the O(n*log(n)) versions of EVAL and
|
|
|
|
// LINK, but it turns out that the theoretically slower O(n*log(n))
|
|
|
|
// implementation is actually faster than the "efficient" algorithm (even for
|
|
|
|
// large CFGs) because the constant overheads are substantially smaller. The
|
|
|
|
// lower-complexity version can be enabled with the following #define:
|
|
|
|
//
|
|
|
|
#define BALANCE_IDOM_TREE 0
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
static RegisterAnalysis<ImmediateDominators>
|
|
|
|
C("idom", "Immediate Dominators Construction", true);
|
|
|
|
|
|
|
|
unsigned ImmediateDominators::DFSPass(BasicBlock *V, InfoRec &VInfo,
|
|
|
|
unsigned N) {
|
|
|
|
VInfo.Semi = ++N;
|
|
|
|
VInfo.Label = V;
|
|
|
|
|
|
|
|
Vertex.push_back(V); // Vertex[n] = V;
|
|
|
|
//Info[V].Ancestor = 0; // Ancestor[n] = 0
|
|
|
|
//Child[V] = 0; // Child[v] = 0
|
|
|
|
VInfo.Size = 1; // Size[v] = 1
|
|
|
|
|
|
|
|
for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) {
|
|
|
|
InfoRec &SuccVInfo = Info[*SI];
|
|
|
|
if (SuccVInfo.Semi == 0) {
|
|
|
|
SuccVInfo.Parent = V;
|
|
|
|
N = DFSPass(*SI, SuccVInfo, N);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return N;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImmediateDominators::Compress(BasicBlock *V, InfoRec &VInfo) {
|
|
|
|
BasicBlock *VAncestor = VInfo.Ancestor;
|
|
|
|
InfoRec &VAInfo = Info[VAncestor];
|
|
|
|
if (VAInfo.Ancestor == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Compress(VAncestor, VAInfo);
|
|
|
|
|
|
|
|
BasicBlock *VAncestorLabel = VAInfo.Label;
|
|
|
|
BasicBlock *VLabel = VInfo.Label;
|
|
|
|
if (Info[VAncestorLabel].Semi < Info[VLabel].Semi)
|
|
|
|
VInfo.Label = VAncestorLabel;
|
|
|
|
|
|
|
|
VInfo.Ancestor = VAInfo.Ancestor;
|
|
|
|
}
|
|
|
|
|
|
|
|
BasicBlock *ImmediateDominators::Eval(BasicBlock *V) {
|
|
|
|
InfoRec &VInfo = Info[V];
|
|
|
|
#if !BALANCE_IDOM_TREE
|
|
|
|
// Higher-complexity but faster implementation
|
|
|
|
if (VInfo.Ancestor == 0)
|
|
|
|
return V;
|
|
|
|
Compress(V, VInfo);
|
|
|
|
return VInfo.Label;
|
|
|
|
#else
|
|
|
|
// Lower-complexity but slower implementation
|
|
|
|
if (VInfo.Ancestor == 0)
|
|
|
|
return VInfo.Label;
|
|
|
|
Compress(V, VInfo);
|
|
|
|
BasicBlock *VLabel = VInfo.Label;
|
|
|
|
|
|
|
|
BasicBlock *VAncestorLabel = Info[VInfo.Ancestor].Label;
|
|
|
|
if (Info[VAncestorLabel].Semi >= Info[VLabel].Semi)
|
|
|
|
return VLabel;
|
|
|
|
else
|
|
|
|
return VAncestorLabel;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImmediateDominators::Link(BasicBlock *V, BasicBlock *W, InfoRec &WInfo){
|
|
|
|
#if !BALANCE_IDOM_TREE
|
|
|
|
// Higher-complexity but faster implementation
|
|
|
|
WInfo.Ancestor = V;
|
|
|
|
#else
|
|
|
|
// Lower-complexity but slower implementation
|
|
|
|
BasicBlock *WLabel = WInfo.Label;
|
|
|
|
unsigned WLabelSemi = Info[WLabel].Semi;
|
|
|
|
BasicBlock *S = W;
|
|
|
|
InfoRec *SInfo = &Info[S];
|
|
|
|
|
|
|
|
BasicBlock *SChild = SInfo->Child;
|
|
|
|
InfoRec *SChildInfo = &Info[SChild];
|
|
|
|
|
|
|
|
while (WLabelSemi < Info[SChildInfo->Label].Semi) {
|
|
|
|
BasicBlock *SChildChild = SChildInfo->Child;
|
|
|
|
if (SInfo->Size+Info[SChildChild].Size >= 2*SChildInfo->Size) {
|
|
|
|
SChildInfo->Ancestor = S;
|
|
|
|
SInfo->Child = SChild = SChildChild;
|
|
|
|
SChildInfo = &Info[SChild];
|
|
|
|
} else {
|
|
|
|
SChildInfo->Size = SInfo->Size;
|
|
|
|
S = SInfo->Ancestor = SChild;
|
|
|
|
SInfo = SChildInfo;
|
|
|
|
SChild = SChildChild;
|
|
|
|
SChildInfo = &Info[SChild];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
InfoRec &VInfo = Info[V];
|
|
|
|
SInfo->Label = WLabel;
|
|
|
|
|
|
|
|
assert(V != W && "The optimization here will not work in this case!");
|
|
|
|
unsigned WSize = WInfo.Size;
|
|
|
|
unsigned VSize = (VInfo.Size += WSize);
|
|
|
|
|
|
|
|
if (VSize < 2*WSize)
|
|
|
|
std::swap(S, VInfo.Child);
|
|
|
|
|
|
|
|
while (S) {
|
|
|
|
SInfo = &Info[S];
|
|
|
|
SInfo->Ancestor = V;
|
|
|
|
S = SInfo->Child;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ImmediateDominators::runOnFunction(Function &F) {
|
|
|
|
IDoms.clear(); // Reset from the last time we were run...
|
|
|
|
BasicBlock *Root = &F.getEntryBlock();
|
|
|
|
Roots.clear();
|
|
|
|
Roots.push_back(Root);
|
|
|
|
|
|
|
|
Vertex.push_back(0);
|
|
|
|
|
|
|
|
// 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 = Roots.size(); i != e; ++i)
|
|
|
|
N = DFSPass(Roots[i], Info[Roots[i]], 0);
|
|
|
|
|
|
|
|
for (unsigned i = N; i >= 2; --i) {
|
|
|
|
BasicBlock *W = Vertex[i];
|
|
|
|
InfoRec &WInfo = Info[W];
|
|
|
|
|
|
|
|
// Step #2: Calculate the semidominators of all vertices
|
|
|
|
for (pred_iterator PI = pred_begin(W), E = pred_end(W); PI != E; ++PI)
|
|
|
|
if (Info.count(*PI)) { // Only if this predecessor is reachable!
|
|
|
|
unsigned SemiU = Info[Eval(*PI)].Semi;
|
|
|
|
if (SemiU < WInfo.Semi)
|
|
|
|
WInfo.Semi = SemiU;
|
|
|
|
}
|
|
|
|
|
|
|
|
Info[Vertex[WInfo.Semi]].Bucket.push_back(W);
|
|
|
|
|
|
|
|
BasicBlock *WParent = WInfo.Parent;
|
|
|
|
Link(WParent, W, WInfo);
|
|
|
|
|
|
|
|
// Step #3: Implicitly define the immediate dominator of vertices
|
|
|
|
std::vector<BasicBlock*> &WParentBucket = Info[WParent].Bucket;
|
|
|
|
while (!WParentBucket.empty()) {
|
|
|
|
BasicBlock *V = WParentBucket.back();
|
|
|
|
WParentBucket.pop_back();
|
|
|
|
BasicBlock *U = Eval(V);
|
|
|
|
IDoms[V] = Info[U].Semi < Info[V].Semi ? U : WParent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Step #4: Explicitly define the immediate dominator of each vertex
|
|
|
|
for (unsigned i = 2; i <= N; ++i) {
|
|
|
|
BasicBlock *W = Vertex[i];
|
|
|
|
BasicBlock *&WIDom = IDoms[W];
|
|
|
|
if (WIDom != Vertex[Info[W].Semi])
|
|
|
|
WIDom = IDoms[WIDom];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free temporary memory used to construct idom's
|
|
|
|
Info.clear();
|
|
|
|
std::vector<BasicBlock*>().swap(Vertex);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImmediateDominatorsBase::print(std::ostream &o) const {
|
|
|
|
for (const_iterator I = begin(), E = end(); I != E; ++I) {
|
|
|
|
o << " Immediate Dominator For Basic Block:";
|
|
|
|
if (I->first)
|
|
|
|
WriteAsOperand(o, I->first, false);
|
|
|
|
else
|
|
|
|
o << " <<exit node>>";
|
|
|
|
o << " is:";
|
|
|
|
if (I->second)
|
|
|
|
WriteAsOperand(o, I->second, false);
|
|
|
|
else
|
|
|
|
o << " <<exit node>>";
|
|
|
|
o << "\n";
|
|
|
|
}
|
|
|
|
o << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-07-06 16:58:22 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2002-01-31 00:42:27 +00:00
|
|
|
// DominatorSet Implementation
|
2001-07-06 16:58:22 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2002-07-26 21:12:44 +00:00
|
|
|
static RegisterAnalysis<DominatorSet>
|
2003-12-07 00:38:08 +00:00
|
|
|
B("domset", "Dominator Set Construction", true);
|
2001-07-06 16:58:22 +00:00
|
|
|
|
2002-05-13 22:03:16 +00:00
|
|
|
// dominates - Return true if A dominates B. This performs the special checks
|
2003-08-18 14:43:39 +00:00
|
|
|
// necessary if A and B are in the same basic block.
|
2002-05-13 22:03:16 +00:00
|
|
|
//
|
2002-07-26 18:40:14 +00:00
|
|
|
bool DominatorSetBase::dominates(Instruction *A, Instruction *B) const {
|
2002-05-13 22:03:16 +00:00
|
|
|
BasicBlock *BBA = A->getParent(), *BBB = B->getParent();
|
|
|
|
if (BBA != BBB) return dominates(BBA, BBB);
|
|
|
|
|
|
|
|
// Loop through the basic block until we find A or B.
|
|
|
|
BasicBlock::iterator I = BBA->begin();
|
2002-06-25 16:13:24 +00:00
|
|
|
for (; &*I != A && &*I != B; ++I) /*empty*/;
|
2002-05-13 22:03:16 +00:00
|
|
|
|
|
|
|
// A dominates B if it is found first in the basic block...
|
2002-06-25 16:13:24 +00:00
|
|
|
return &*I == A;
|
2002-05-13 22:03:16 +00:00
|
|
|
}
|
2002-01-31 00:42:27 +00:00
|
|
|
|
2001-11-26 18:52:02 +00:00
|
|
|
|
2003-12-07 00:55:32 +00:00
|
|
|
// runOnFunction - This method calculates the forward dominator sets for the
|
|
|
|
// specified function.
|
|
|
|
//
|
|
|
|
bool DominatorSet::runOnFunction(Function &F) {
|
|
|
|
BasicBlock *Root = &F.getEntryBlock();
|
|
|
|
Roots.clear();
|
|
|
|
Roots.push_back(Root);
|
|
|
|
assert(pred_begin(Root) == pred_end(Root) &&
|
|
|
|
"Root node has predecessors in function!");
|
|
|
|
|
2003-12-07 00:38:08 +00:00
|
|
|
ImmediateDominators &ID = getAnalysis<ImmediateDominators>();
|
|
|
|
Doms.clear();
|
2003-12-07 00:55:32 +00:00
|
|
|
if (Roots.empty()) return false;
|
2003-12-07 00:38:08 +00:00
|
|
|
|
|
|
|
// Root nodes only dominate themselves.
|
|
|
|
for (unsigned i = 0, e = Roots.size(); i != e; ++i)
|
|
|
|
Doms[Roots[i]].insert(Roots[i]);
|
|
|
|
|
|
|
|
// Loop over all of the blocks in the function, calculating dominator sets for
|
|
|
|
// each function.
|
2003-12-07 00:55:32 +00:00
|
|
|
for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
|
2003-12-07 00:38:08 +00:00
|
|
|
if (BasicBlock *IDom = ID[I]) { // Get idom if block is reachable
|
|
|
|
DomSetType &DS = Doms[I];
|
|
|
|
assert(DS.empty() && "Domset already filled in for this block?");
|
|
|
|
DS.insert(I); // Blocks always dominate themselves
|
|
|
|
|
|
|
|
// Insert all dominators into the set...
|
|
|
|
while (IDom) {
|
|
|
|
// If we have already computed the dominator sets for our immediate
|
|
|
|
// dominator, just use it instead of walking all the way up to the root.
|
|
|
|
DomSetType &IDS = Doms[IDom];
|
|
|
|
if (!IDS.empty()) {
|
|
|
|
DS.insert(IDS.begin(), IDS.end());
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
DS.insert(IDom);
|
|
|
|
IDom = ID[IDom];
|
2003-05-12 22:35:13 +00:00
|
|
|
}
|
2001-07-02 05:46:38 +00:00
|
|
|
}
|
2003-12-07 00:38:08 +00:00
|
|
|
} else {
|
|
|
|
// Ensure that every basic block has at least an empty set of nodes. This
|
|
|
|
// is important for the case when there is unreachable blocks.
|
|
|
|
Doms[I];
|
2001-07-02 05:46:38 +00:00
|
|
|
}
|
2002-08-22 20:39:29 +00:00
|
|
|
|
2002-10-08 19:12:08 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2003-11-21 20:23:48 +00:00
|
|
|
namespace llvm {
|
2003-05-22 21:47:17 +00:00
|
|
|
static std::ostream &operator<<(std::ostream &o,
|
|
|
|
const std::set<BasicBlock*> &BBs) {
|
|
|
|
for (std::set<BasicBlock*>::const_iterator I = BBs.begin(), E = BBs.end();
|
2003-09-10 20:37:51 +00:00
|
|
|
I != E; ++I)
|
|
|
|
if (*I)
|
|
|
|
WriteAsOperand(o, *I, false);
|
|
|
|
else
|
|
|
|
o << " <<exit node>>";
|
2002-07-27 01:12:17 +00:00
|
|
|
return o;
|
|
|
|
}
|
2003-11-21 20:23:48 +00:00
|
|
|
}
|
2002-07-27 01:12:17 +00:00
|
|
|
|
|
|
|
void DominatorSetBase::print(std::ostream &o) const {
|
2002-09-29 21:42:42 +00:00
|
|
|
for (const_iterator I = begin(), E = end(); I != E; ++I) {
|
2003-09-10 20:37:51 +00:00
|
|
|
o << " DomSet For BB: ";
|
|
|
|
if (I->first)
|
|
|
|
WriteAsOperand(o, I->first, false);
|
|
|
|
else
|
|
|
|
o << " <<exit node>>";
|
|
|
|
o << " is:\t" << I->second << "\n";
|
2002-09-29 21:42:42 +00:00
|
|
|
}
|
2002-07-27 01:12:17 +00:00
|
|
|
}
|
2001-07-02 05:46:38 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DominatorTree Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2002-07-26 21:12:44 +00:00
|
|
|
static RegisterAnalysis<DominatorTree>
|
2002-07-30 16:27:52 +00:00
|
|
|
E("domtree", "Dominator Tree Construction", true);
|
2002-01-31 00:42:27 +00:00
|
|
|
|
2002-07-26 18:40:14 +00:00
|
|
|
// DominatorTreeBase::reset - Free all of the tree node memory.
|
2001-07-02 05:46:38 +00:00
|
|
|
//
|
2002-07-26 18:40:14 +00:00
|
|
|
void DominatorTreeBase::reset() {
|
2001-07-02 05:46:38 +00:00
|
|
|
for (NodeMapType::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I)
|
|
|
|
delete I->second;
|
2002-01-31 00:42:27 +00:00
|
|
|
Nodes.clear();
|
2003-09-10 20:37:51 +00:00
|
|
|
RootNode = 0;
|
2001-07-02 05:46:38 +00:00
|
|
|
}
|
|
|
|
|
2003-09-11 16:26:13 +00:00
|
|
|
void DominatorTreeBase::Node::setIDom(Node *NewIDom) {
|
2002-09-26 16:14:41 +00:00
|
|
|
assert(IDom && "No immediate dominator?");
|
|
|
|
if (IDom != NewIDom) {
|
|
|
|
std::vector<Node*>::iterator I =
|
|
|
|
std::find(IDom->Children.begin(), IDom->Children.end(), this);
|
|
|
|
assert(I != IDom->Children.end() &&
|
|
|
|
"Not in immediate dominator children set!");
|
|
|
|
// I am no longer your child...
|
|
|
|
IDom->Children.erase(I);
|
|
|
|
|
|
|
|
// Switch to new dominator
|
|
|
|
IDom = NewIDom;
|
|
|
|
IDom->Children.push_back(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-12-07 00:38:08 +00:00
|
|
|
DominatorTreeBase::Node *DominatorTree::getNodeForBlock(BasicBlock *BB) {
|
|
|
|
Node *&BBNode = Nodes[BB];
|
|
|
|
if (BBNode) return BBNode;
|
|
|
|
|
|
|
|
// Haven't calculated this node yet? Get or calculate the node for the
|
|
|
|
// immediate dominator.
|
|
|
|
BasicBlock *IDom = getAnalysis<ImmediateDominators>()[BB];
|
|
|
|
Node *IDomNode = getNodeForBlock(IDom);
|
|
|
|
|
|
|
|
// Add a new tree node for this BasicBlock, and link it as a child of
|
|
|
|
// IDomNode
|
|
|
|
return BBNode = IDomNode->addChild(new Node(BB, IDomNode));
|
|
|
|
}
|
2002-09-26 16:14:41 +00:00
|
|
|
|
2003-12-07 00:38:08 +00:00
|
|
|
void DominatorTree::calculate(const ImmediateDominators &ID) {
|
2003-09-10 20:37:51 +00:00
|
|
|
assert(Roots.size() == 1 && "DominatorTree should have 1 root block!");
|
|
|
|
BasicBlock *Root = Roots[0];
|
|
|
|
Nodes[Root] = RootNode = new Node(Root, 0); // Add a node for the root...
|
2001-07-02 05:46:38 +00:00
|
|
|
|
2003-12-07 00:38:08 +00:00
|
|
|
// Loop over all of the reachable blocks in the function...
|
|
|
|
for (ImmediateDominators::const_iterator I = ID.begin(), E = ID.end();
|
2002-07-26 18:40:14 +00:00
|
|
|
I != E; ++I) {
|
2003-12-07 00:38:08 +00:00
|
|
|
Node *&BBNode = Nodes[I->first];
|
|
|
|
if (!BBNode) { // Haven't calculated this node yet?
|
|
|
|
// Get or calculate the node for the immediate dominator
|
|
|
|
Node *IDomNode = getNodeForBlock(I->second);
|
|
|
|
|
|
|
|
// Add a new tree node for this BasicBlock, and link it as a child of
|
|
|
|
// IDomNode
|
|
|
|
BBNode = IDomNode->addChild(new Node(I->first, IDomNode));
|
2001-07-02 05:46:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-07-31 19:32:01 +00:00
|
|
|
static std::ostream &operator<<(std::ostream &o,
|
|
|
|
const DominatorTreeBase::Node *Node) {
|
2003-09-11 16:26:13 +00:00
|
|
|
if (Node->getBlock())
|
|
|
|
WriteAsOperand(o, Node->getBlock(), false);
|
2003-09-10 20:37:51 +00:00
|
|
|
else
|
|
|
|
o << " <<exit node>>";
|
|
|
|
return o << "\n";
|
2002-07-27 01:12:17 +00:00
|
|
|
}
|
|
|
|
|
2002-07-31 19:32:01 +00:00
|
|
|
static void PrintDomTree(const DominatorTreeBase::Node *N, std::ostream &o,
|
2002-07-27 01:12:17 +00:00
|
|
|
unsigned Lev) {
|
2003-09-10 20:37:51 +00:00
|
|
|
o << std::string(2*Lev, ' ') << "[" << Lev << "] " << N;
|
2002-07-27 01:12:17 +00:00
|
|
|
for (DominatorTreeBase::Node::const_iterator I = N->begin(), E = N->end();
|
2003-09-10 20:37:51 +00:00
|
|
|
I != E; ++I)
|
2002-07-27 01:12:17 +00:00
|
|
|
PrintDomTree(*I, o, Lev+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DominatorTreeBase::print(std::ostream &o) const {
|
|
|
|
o << "=============================--------------------------------\n"
|
|
|
|
<< "Inorder Dominator Tree:\n";
|
2003-09-10 20:37:51 +00:00
|
|
|
PrintDomTree(getRootNode(), o, 1);
|
2002-07-27 01:12:17 +00:00
|
|
|
}
|
2001-07-02 05:46:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DominanceFrontier Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2002-07-26 21:12:44 +00:00
|
|
|
static RegisterAnalysis<DominanceFrontier>
|
2002-07-30 16:27:52 +00:00
|
|
|
G("domfrontier", "Dominance Frontier Construction", true);
|
2002-01-31 00:42:27 +00:00
|
|
|
|
2002-04-28 16:21:30 +00:00
|
|
|
const DominanceFrontier::DomSetType &
|
2002-07-26 18:40:14 +00:00
|
|
|
DominanceFrontier::calculate(const DominatorTree &DT,
|
|
|
|
const DominatorTree::Node *Node) {
|
2001-07-02 05:46:38 +00:00
|
|
|
// Loop over CFG successors to calculate DFlocal[Node]
|
2003-09-11 16:26:13 +00:00
|
|
|
BasicBlock *BB = Node->getBlock();
|
2001-07-02 05:46:38 +00:00
|
|
|
DomSetType &S = Frontiers[BB]; // The new set to fill in...
|
|
|
|
|
2002-04-28 00:15:57 +00:00
|
|
|
for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB);
|
2002-02-12 22:39:50 +00:00
|
|
|
SI != SE; ++SI) {
|
2001-07-02 05:46:38 +00:00
|
|
|
// Does Node immediately dominate this successor?
|
|
|
|
if (DT[*SI]->getIDom() != Node)
|
|
|
|
S.insert(*SI);
|
|
|
|
}
|
|
|
|
|
|
|
|
// At this point, S is DFlocal. Now we union in DFup's of our children...
|
|
|
|
// Loop through and visit the nodes that Node immediately dominates (Node's
|
|
|
|
// children in the IDomTree)
|
|
|
|
//
|
|
|
|
for (DominatorTree::Node::const_iterator NI = Node->begin(), NE = Node->end();
|
|
|
|
NI != NE; ++NI) {
|
|
|
|
DominatorTree::Node *IDominee = *NI;
|
2002-07-26 18:40:14 +00:00
|
|
|
const DomSetType &ChildDF = calculate(DT, IDominee);
|
2001-07-02 05:46:38 +00:00
|
|
|
|
|
|
|
DomSetType::const_iterator CDFI = ChildDF.begin(), CDFE = ChildDF.end();
|
|
|
|
for (; CDFI != CDFE; ++CDFI) {
|
|
|
|
if (!Node->dominates(DT[*CDFI]))
|
|
|
|
S.insert(*CDFI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return S;
|
|
|
|
}
|
2001-07-06 16:58:22 +00:00
|
|
|
|
2002-07-27 01:12:17 +00:00
|
|
|
void DominanceFrontierBase::print(std::ostream &o) const {
|
|
|
|
for (const_iterator I = begin(), E = end(); I != E; ++I) {
|
2003-09-10 20:37:51 +00:00
|
|
|
o << " DomFrontier for BB";
|
|
|
|
if (I->first)
|
|
|
|
WriteAsOperand(o, I->first, false);
|
|
|
|
else
|
|
|
|
o << " <<exit node>>";
|
|
|
|
o << " is:\t" << I->second << "\n";
|
2002-07-27 01:12:17 +00:00
|
|
|
}
|
|
|
|
}
|
2003-11-11 22:41:34 +00:00
|
|
|
|