From 93193f806378e06092820c099e437886c7309b94 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 31 Jan 2002 00:42:27 +0000 Subject: [PATCH] Convert analyses to new pass structure git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1603 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/IPA/CallGraph.cpp | 12 ++- lib/Analysis/IPA/FindUnsafePointerTypes.cpp | 47 +++++++--- lib/Analysis/IPA/FindUsedTypes.cpp | 73 ++++++++------- lib/Analysis/IntervalPartition.cpp | 11 ++- lib/Analysis/LoopInfo.cpp | 26 +++++- lib/Analysis/PostDominators.cpp | 91 ++++++++++++------- .../Utils/UnifyFunctionExitNodes.cpp | 4 + lib/VMCore/Dominators.cpp | 91 ++++++++++++------- lib/VMCore/Verifier.cpp | 2 +- 9 files changed, 237 insertions(+), 120 deletions(-) diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp index e48cf7fa386..244c35ea46e 100644 --- a/lib/Analysis/IPA/CallGraph.cpp +++ b/lib/Analysis/IPA/CallGraph.cpp @@ -19,6 +19,9 @@ #include "Support/STLExtras.h" #include +AnalysisID cfg::CallGraph::ID(AnalysisID::create()); +//AnalysisID cfg::CallGraph::ID(AnalysisID::template AnalysisID()); + // getNodeFor - Return the node for the specified method or create one if it // does not already exist. // @@ -53,7 +56,9 @@ void cfg::CallGraph::addToCallGraph(Method *M) { } } -cfg::CallGraph::CallGraph(Module *TheModule) { +bool cfg::CallGraph::run(Module *TheModule) { + destroy(); + Mod = TheModule; // Create the root node of the module... @@ -61,13 +66,16 @@ cfg::CallGraph::CallGraph(Module *TheModule) { // Add every method to the call graph... for_each(Mod->begin(), Mod->end(), bind_obj(this,&CallGraph::addToCallGraph)); + + return false; } -cfg::CallGraph::~CallGraph() { +void cfg::CallGraph::destroy() { for (MethodMapTy::iterator I = MethodMap.begin(), E = MethodMap.end(); I != E; ++I) { delete I->second; } + MethodMap.clear(); } diff --git a/lib/Analysis/IPA/FindUnsafePointerTypes.cpp b/lib/Analysis/IPA/FindUnsafePointerTypes.cpp index 85b5da8ce2e..bc092920907 100644 --- a/lib/Analysis/IPA/FindUnsafePointerTypes.cpp +++ b/lib/Analysis/IPA/FindUnsafePointerTypes.cpp @@ -19,8 +19,13 @@ #include "llvm/Analysis/FindUnsafePointerTypes.h" #include "llvm/Assembly/CachedWriter.h" #include "llvm/Type.h" +#include "llvm/Instruction.h" +#include "llvm/Method.h" +#include "llvm/Module.h" #include "Support/CommandLine.h" +AnalysisID FindUnsafePointerTypes::ID(AnalysisID::create()); + // Provide a command line option to turn on printing of which instructions cause // a type to become invalid // @@ -49,22 +54,25 @@ static inline bool isSafeInstruction(const Instruction *I) { // values of various types. If they are deemed to be 'unsafe' note that the // type is not safe to transform. // -bool FindUnsafePointerTypes::runOnMethod(Method *Meth) { - const Method *M = Meth; // We don't need/want write access - for (Method::const_inst_iterator I = M->inst_begin(), E = M->inst_end(); - I != E; ++I) { - const Instruction *Inst = *I; - const Type *ITy = Inst->getType(); - if (ITy->isPointerType() && !UnsafeTypes.count((PointerType*)ITy)) - if (!isSafeInstruction(Inst)) { - UnsafeTypes.insert((PointerType*)ITy); +bool FindUnsafePointerTypes::run(Module *Mod) { + for (Module::iterator MI = Mod->begin(), ME = Mod->end(); + MI != ME; ++MI) { + const Method *M = *MI; // We don't need/want write access + for (Method::const_inst_iterator I = M->inst_begin(), E = M->inst_end(); + I != E; ++I) { + const Instruction *Inst = *I; + const Type *ITy = Inst->getType(); + if (ITy->isPointerType() && !UnsafeTypes.count((PointerType*)ITy)) + if (!isSafeInstruction(Inst)) { + UnsafeTypes.insert((PointerType*)ITy); - if (PrintFailures) { - CachedWriter CW(M->getParent(), std::cerr); - CW << "FindUnsafePointerTypes: Type '" << ITy - << "' marked unsafe in '" << Meth->getName() << "' by:\n" << Inst; + if (PrintFailures) { + CachedWriter CW(M->getParent(), std::cerr); + CW << "FindUnsafePointerTypes: Type '" << ITy + << "' marked unsafe in '" << M->getName() << "' by:\n" << Inst; + } } - } + } } return false; @@ -74,7 +82,8 @@ bool FindUnsafePointerTypes::runOnMethod(Method *Meth) { // printResults - Loop over the results of the analysis, printing out unsafe // types. // -void FindUnsafePointerTypes::printResults(const Module *M, std::ostream &o) { +void FindUnsafePointerTypes::printResults(const Module *M, + std::ostream &o) const { if (UnsafeTypes.empty()) { o << "SafePointerAccess Analysis: No unsafe types found!\n"; return; @@ -90,3 +99,11 @@ void FindUnsafePointerTypes::printResults(const Module *M, std::ostream &o) { CW << " #" << Counter << ". " << (Value*)*I << "\n"; } } + +// getAnalysisUsageInfo - Of course, we provide ourself... +// +void FindUnsafePointerTypes::getAnalysisUsageInfo(Pass::AnalysisSet &Required, + Pass::AnalysisSet &Destroyed, + Pass::AnalysisSet &Provided) { + Provided.push_back(FindUnsafePointerTypes::ID); +} diff --git a/lib/Analysis/IPA/FindUsedTypes.cpp b/lib/Analysis/IPA/FindUsedTypes.cpp index c439407cb13..b876e5e68d8 100644 --- a/lib/Analysis/IPA/FindUsedTypes.cpp +++ b/lib/Analysis/IPA/FindUsedTypes.cpp @@ -9,6 +9,11 @@ #include "llvm/SymbolTable.h" #include "llvm/GlobalVariable.h" #include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Method.h" + +AnalysisID FindUsedTypes::ID(AnalysisID::create()); +AnalysisID FindUsedTypes::IncludeSymbolTableID(AnalysisID::create()); // IncorporateType - Incorporate one type and all of its subtypes into the // collection of used types. @@ -34,43 +39,39 @@ void FindUsedTypes::IncorporateSymbolTable(const SymbolTable *ST) { assert(0 && "Unimp"); } - -// doInitialization - This loops over global constants defined in the -// module, converting them to their new type. -// -bool FindUsedTypes::doInitialization(Module *m) { - const Module *M = m; - if (IncludeSymbolTables && M->hasSymbolTable()) - IncorporateSymbolTable(M->getSymbolTable()); // Add symtab first... - - // Loop over global variables, incorporating their types - for (Module::const_giterator I = M->gbegin(), E = M->gend(); I != E; ++I) - IncorporateType((*I)->getType()); - return false; -} - // doPerMethodWork - This incorporates all types used by the specified method // -bool FindUsedTypes::runOnMethod(Method *m) { - const Method *M = m; - if (IncludeSymbolTables && M->hasSymbolTable()) - IncorporateSymbolTable(M->getSymbolTable()); // Add symtab first... +bool FindUsedTypes::run(Module *m) { + UsedTypes.clear(); // reset if run multiple times... + + if (IncludeSymbolTables && m->hasSymbolTable()) + IncorporateSymbolTable(m->getSymbolTable()); // Add symtab first... + + // Loop over global variables, incorporating their types + for (Module::const_giterator I = m->gbegin(), E = m->gend(); I != E; ++I) + IncorporateType((*I)->getType()); + + for (Module::iterator MI = m->begin(), ME = m->end(); MI != ME; ++MI) { + const Method *M = *MI; + if (IncludeSymbolTables && M->hasSymbolTable()) + IncorporateSymbolTable(M->getSymbolTable()); // Add symtab first... - // Loop over all of the instructions in the method, adding their return type - // as well as the types of their operands. - // - for (Method::const_inst_iterator II = M->inst_begin(), IE = M->inst_end(); - II != IE; ++II) { - const Instruction *I = *II; - const Type *Ty = I->getType(); + // Loop over all of the instructions in the method, adding their return type + // as well as the types of their operands. + // + for (Method::const_inst_iterator II = M->inst_begin(), IE = M->inst_end(); + II != IE; ++II) { + const Instruction *I = *II; + const Type *Ty = I->getType(); - IncorporateType(Ty); // Incorporate the type of the instruction - for (User::const_op_iterator OI = I->op_begin(), OE = I->op_end(); - OI != OE; ++OI) - if ((*OI)->getType() != Ty) // Avoid set lookup in common case - IncorporateType((*OI)->getType()); // Insert inst operand types as well + IncorporateType(Ty); // Incorporate the type of the instruction + for (User::const_op_iterator OI = I->op_begin(), OE = I->op_end(); + OI != OE; ++OI) + if ((*OI)->getType() != Ty) // Avoid set lookup in common case + IncorporateType((*OI)->getType());// Insert inst operand types as well + } } - + return false; } @@ -90,3 +91,11 @@ void FindUsedTypes::printTypes(std::ostream &o, const Module *M = 0) const { E = UsedTypes.end(); I != E; ++I) o << " " << *I << "\n"; } + +// getAnalysisUsageInfo - Of course, we provide ourself... +// +void FindUsedTypes::getAnalysisUsageInfo(Pass::AnalysisSet &Required, + Pass::AnalysisSet &Destroyed, + Pass::AnalysisSet &Provided) { + Provided.push_back(FindUsedTypes::ID); +} diff --git a/lib/Analysis/IntervalPartition.cpp b/lib/Analysis/IntervalPartition.cpp index fff8d224e21..f524d016f16 100644 --- a/lib/Analysis/IntervalPartition.cpp +++ b/lib/Analysis/IntervalPartition.cpp @@ -11,13 +11,17 @@ using namespace cfg; using std::make_pair; +AnalysisID IntervalPartition::ID(AnalysisID::create()); + //===----------------------------------------------------------------------===// // IntervalPartition Implementation //===----------------------------------------------------------------------===// -// Destructor - Free memory -IntervalPartition::~IntervalPartition() { +// destroy - Reset state back to before method was analyzed +void IntervalPartition::destroy() { for_each(begin(), end(), deleter); + IntervalMap.clear(); + RootInterval = 0; } // addIntervalToPartition - Add an interval to the internal list of intervals, @@ -48,7 +52,7 @@ void IntervalPartition::updatePredecessors(cfg::Interval *Int) { // IntervalPartition ctor - Build the first level interval partition for the // specified method... // -IntervalPartition::IntervalPartition(Method *M) { +bool IntervalPartition::runOnMethod(Method *M) { assert(M->front() && "Cannot operate on prototypes!"); // Pass false to intervals_begin because we take ownership of it's memory @@ -67,6 +71,7 @@ IntervalPartition::IntervalPartition(Method *M) { // predecessors for each block... for_each(begin(), end(), bind_obj(this, &IntervalPartition::updatePredecessors)); + return false; } diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp index ed91ca8bd5f..9b34095e4f2 100644 --- a/lib/Analysis/LoopInfo.cpp +++ b/lib/Analysis/LoopInfo.cpp @@ -13,11 +13,27 @@ #include "Support/DepthFirstIterator.h" #include +AnalysisID cfg::LoopInfo::ID(AnalysisID::create()); + +//===----------------------------------------------------------------------===// +// cfg::Loop implementation +// bool cfg::Loop::contains(const BasicBlock *BB) const { return find(Blocks.begin(), Blocks.end(), BB) != Blocks.end(); } -cfg::LoopInfo::LoopInfo(const DominatorSet &DS) { + +//===----------------------------------------------------------------------===// +// cfg::LoopInfo implementation +// +bool cfg::LoopInfo::runOnMethod(Method *M) { + BBMap.clear(); // Reset internal state of analysis + TopLevelLoops.clear(); + Calculate(getAnalysis()); // Update + return false; +} + +void cfg::LoopInfo::Calculate(const DominatorSet &DS) { const BasicBlock *RootNode = DS.getRoot(); for (df_iterator NI = df_begin(RootNode), @@ -29,6 +45,14 @@ cfg::LoopInfo::LoopInfo(const DominatorSet &DS) { TopLevelLoops[i]->setLoopDepth(1); } +void cfg::LoopInfo::getAnalysisUsageInfo(Pass::AnalysisSet &Required, + Pass::AnalysisSet &Destroyed, + Pass::AnalysisSet &Provided) { + Required.push_back(DominatorSet::ID); + Provided.push_back(ID); +} + + cfg::Loop *cfg::LoopInfo::ConsiderForLoop(const BasicBlock *BB, const DominatorSet &DS) { if (BBMap.find(BB) != BBMap.end()) return 0; // Havn't processed this node? diff --git a/lib/Analysis/PostDominators.cpp b/lib/Analysis/PostDominators.cpp index 2e4f6e4df1f..f3e66137771 100644 --- a/lib/Analysis/PostDominators.cpp +++ b/lib/Analysis/PostDominators.cpp @@ -5,7 +5,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/Dominators.h" -#include "llvm/Analysis/SimplifyCFG.h" // To get cfg::UnifyAllExitNodes +#include "llvm/Transforms/UnifyMethodExitNodes.h" #include "llvm/Method.h" #include "Support/DepthFirstIterator.h" #include "Support/STLExtras.h" @@ -30,32 +30,29 @@ void set_intersect(set &S1, const set &S2) { } } -//===----------------------------------------------------------------------===// -// DominatorBase Implementation -//===----------------------------------------------------------------------===// - -bool cfg::DominatorBase::isPostDominator() const { - // Root can be null if there is no exit node from the CFG and is postdom set - return Root == 0 || Root != Root->getParent()->front(); -} - - //===----------------------------------------------------------------------===// // DominatorSet Implementation //===----------------------------------------------------------------------===// -// DominatorSet ctor - Build either the dominator set or the post-dominator -// set for a method... -// -cfg::DominatorSet::DominatorSet(const Method *M) : DominatorBase(M->front()) { - calcForwardDominatorSet(M); +AnalysisID cfg::DominatorSet::ID(AnalysisID::create()); +AnalysisID cfg::DominatorSet::PostDomID(AnalysisID::create()); + +bool cfg::DominatorSet::runOnMethod(Method *M) { + Doms.clear(); // Reset from the last time we were run... + + if (isPostDominator()) + calcPostDominatorSet(M); + else + calcForwardDominatorSet(M); + return false; } + // calcForwardDominatorSet - This method calculates the forward dominator sets // for the specified method. // -void cfg::DominatorSet::calcForwardDominatorSet(const Method *M) { - assert(Root && M && "Can't build dominator set of null method!"); +void cfg::DominatorSet::calcForwardDominatorSet(Method *M) { + Root = M->getEntryNode(); assert(Root->pred_begin() == Root->pred_end() && "Root node has predecessors in method!"); @@ -64,7 +61,7 @@ void cfg::DominatorSet::calcForwardDominatorSet(const Method *M) { Changed = false; DomSetType WorkingSet; - df_iterator It = df_begin(M), End = df_end(M); + df_iterator It = df_begin(M), End = df_end(M); for ( ; It != End; ++It) { const BasicBlock *BB = *It; BasicBlock::pred_const_iterator PI = BB->pred_begin(), @@ -99,13 +96,15 @@ void cfg::DominatorSet::calcForwardDominatorSet(const Method *M) { // only have a single exit node (return stmt), then calculates the post // dominance sets for the method. // -cfg::DominatorSet::DominatorSet(Method *M, bool PostDomSet) - : DominatorBase(M->front()) { - if (!PostDomSet) { calcForwardDominatorSet(M); return; } +void cfg::DominatorSet::calcPostDominatorSet(Method *M) { + // Since we require that the unify all exit nodes pass has been run, we know + // that there can be at most one return instruction in the method left. + // Get it. + // + Root = getAnalysis().getExitNode(); - Root = cfg::UnifyAllExitNodes(M); if (Root == 0) { // No exit node for the method? Postdomsets are all empty - for (Method::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) + for (Method::const_iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) Doms[*MI] = DomSetType(); return; } @@ -116,7 +115,7 @@ cfg::DominatorSet::DominatorSet(Method *M, bool PostDomSet) set Visited; DomSetType WorkingSet; - idf_iterator It = idf_begin(Root), End = idf_end(Root); + idf_iterator It = idf_begin(Root), End = idf_end(Root); for ( ; It != End; ++It) { const BasicBlock *BB = *It; BasicBlock::succ_const_iterator PI = BB->succ_begin(), @@ -147,11 +146,26 @@ cfg::DominatorSet::DominatorSet(Method *M, bool PostDomSet) } while (Changed); } +// getAnalysisUsageInfo - This obviously provides a dominator set, but it also +// uses the UnifyMethodExitNodes pass if building post-dominators +// +void cfg::DominatorSet::getAnalysisUsageInfo(Pass::AnalysisSet &Requires, + Pass::AnalysisSet &Destroyed, + Pass::AnalysisSet &Provided) { + if (isPostDominator()) + Requires.push_back(UnifyMethodExitNodes::ID); + + Provided.push_back(ID); +} + //===----------------------------------------------------------------------===// // ImmediateDominators Implementation //===----------------------------------------------------------------------===// +AnalysisID cfg::ImmediateDominators::ID(AnalysisID::create()); +AnalysisID cfg::ImmediateDominators::PostDomID(AnalysisID::create()); + // calcIDoms - Calculate the immediate dominator mapping, given a set of // dominators for every basic block. void cfg::ImmediateDominators::calcIDoms(const DominatorSet &DS) { @@ -193,14 +207,20 @@ void cfg::ImmediateDominators::calcIDoms(const DominatorSet &DS) { // DominatorTree Implementation //===----------------------------------------------------------------------===// -// DominatorTree dtor - Free all of the tree node memory. +AnalysisID cfg::DominatorTree::ID(AnalysisID::create()); +AnalysisID cfg::DominatorTree::PostDomID(AnalysisID::create()); + +// DominatorTree::reset - Free all of the tree node memory. // -cfg::DominatorTree::~DominatorTree() { +void cfg::DominatorTree::reset() { for (NodeMapType::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) delete I->second; + Nodes.clear(); } +#if 0 +// Given immediate dominators, we can also calculate the dominator tree cfg::DominatorTree::DominatorTree(const ImmediateDominators &IDoms) : DominatorBase(IDoms.getRoot()) { const Method *M = Root->getParent(); @@ -224,13 +244,14 @@ cfg::DominatorTree::DominatorTree(const ImmediateDominators &IDoms) } } } +#endif void cfg::DominatorTree::calculate(const DominatorSet &DS) { Nodes[Root] = new Node(Root, 0); // Add a node for the root... if (!isPostDominator()) { // Iterate over all nodes in depth first order... - for (df_iterator I = df_begin(Root), E = df_end(Root); + for (df_iterator I = df_begin(Root), E = df_end(Root); I != E; ++I) { const BasicBlock *BB = *I; const DominatorSet::DomSetType &Dominators = DS.getDominators(BB); @@ -271,7 +292,7 @@ void cfg::DominatorTree::calculate(const DominatorSet &DS) { } } else if (Root) { // Iterate over all nodes in depth first order... - for (idf_iterator I = idf_begin(Root), E = idf_end(Root); + for (idf_iterator I = idf_begin(Root), E = idf_end(Root); I != E; ++I) { const BasicBlock *BB = *I; const DominatorSet::DomSetType &Dominators = DS.getDominators(BB); @@ -290,10 +311,11 @@ void cfg::DominatorTree::calculate(const DominatorSet &DS) { DominatorSet::DomSetType::const_iterator I = Dominators.begin(); DominatorSet::DomSetType::const_iterator End = Dominators.end(); for (; I != End; ++I) { // Iterate over dominators... - // All of our dominators should form a chain, where the number of elements - // in the dominator set indicates what level the node is at in the chain. - // We want the node immediately above us, so it will have an identical - // dominator set, except that BB will not dominate it... therefore it's + // All of our dominators should form a chain, where the number + // of elements in the dominator set indicates what level the + // node is at in the chain. We want the node immediately + // above us, so it will have an identical dominator set, + // except that BB will not dominate it... therefore it's // dominator set size will be one less than BB's... // if (DS.getDominators(*I).size() == DomSetSize - 1) { @@ -319,6 +341,9 @@ void cfg::DominatorTree::calculate(const DominatorSet &DS) { // DominanceFrontier Implementation //===----------------------------------------------------------------------===// +AnalysisID cfg::DominanceFrontier::ID(AnalysisID::create()); +AnalysisID cfg::DominanceFrontier::PostDomID(AnalysisID::create()); + const cfg::DominanceFrontier::DomSetType & cfg::DominanceFrontier::calcDomFrontier(const DominatorTree &DT, const DominatorTree::Node *Node) { diff --git a/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp index 56c4b204ca9..4716e7ebcd8 100644 --- a/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +++ b/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp @@ -6,6 +6,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/SimplifyCFG.h" +#include "llvm/Transforms/UnifyMethodExitNodes.h" #include "llvm/BasicBlock.h" #include "llvm/Method.h" #include "llvm/iTerminators.h" @@ -13,6 +14,9 @@ #include "llvm/Type.h" using std::vector; +AnalysisID UnifyMethodExitNodes::ID(AnalysisID::create()); + + // UnifyAllExitNodes - Unify all exit nodes of the CFG by creating a new // BasicBlock, and converting all returns to unconditional branches to this // new basic block. The singular exit node is returned. diff --git a/lib/VMCore/Dominators.cpp b/lib/VMCore/Dominators.cpp index 2e4f6e4df1f..f3e66137771 100644 --- a/lib/VMCore/Dominators.cpp +++ b/lib/VMCore/Dominators.cpp @@ -5,7 +5,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/Dominators.h" -#include "llvm/Analysis/SimplifyCFG.h" // To get cfg::UnifyAllExitNodes +#include "llvm/Transforms/UnifyMethodExitNodes.h" #include "llvm/Method.h" #include "Support/DepthFirstIterator.h" #include "Support/STLExtras.h" @@ -30,32 +30,29 @@ void set_intersect(set &S1, const set &S2) { } } -//===----------------------------------------------------------------------===// -// DominatorBase Implementation -//===----------------------------------------------------------------------===// - -bool cfg::DominatorBase::isPostDominator() const { - // Root can be null if there is no exit node from the CFG and is postdom set - return Root == 0 || Root != Root->getParent()->front(); -} - - //===----------------------------------------------------------------------===// // DominatorSet Implementation //===----------------------------------------------------------------------===// -// DominatorSet ctor - Build either the dominator set or the post-dominator -// set for a method... -// -cfg::DominatorSet::DominatorSet(const Method *M) : DominatorBase(M->front()) { - calcForwardDominatorSet(M); +AnalysisID cfg::DominatorSet::ID(AnalysisID::create()); +AnalysisID cfg::DominatorSet::PostDomID(AnalysisID::create()); + +bool cfg::DominatorSet::runOnMethod(Method *M) { + Doms.clear(); // Reset from the last time we were run... + + if (isPostDominator()) + calcPostDominatorSet(M); + else + calcForwardDominatorSet(M); + return false; } + // calcForwardDominatorSet - This method calculates the forward dominator sets // for the specified method. // -void cfg::DominatorSet::calcForwardDominatorSet(const Method *M) { - assert(Root && M && "Can't build dominator set of null method!"); +void cfg::DominatorSet::calcForwardDominatorSet(Method *M) { + Root = M->getEntryNode(); assert(Root->pred_begin() == Root->pred_end() && "Root node has predecessors in method!"); @@ -64,7 +61,7 @@ void cfg::DominatorSet::calcForwardDominatorSet(const Method *M) { Changed = false; DomSetType WorkingSet; - df_iterator It = df_begin(M), End = df_end(M); + df_iterator It = df_begin(M), End = df_end(M); for ( ; It != End; ++It) { const BasicBlock *BB = *It; BasicBlock::pred_const_iterator PI = BB->pred_begin(), @@ -99,13 +96,15 @@ void cfg::DominatorSet::calcForwardDominatorSet(const Method *M) { // only have a single exit node (return stmt), then calculates the post // dominance sets for the method. // -cfg::DominatorSet::DominatorSet(Method *M, bool PostDomSet) - : DominatorBase(M->front()) { - if (!PostDomSet) { calcForwardDominatorSet(M); return; } +void cfg::DominatorSet::calcPostDominatorSet(Method *M) { + // Since we require that the unify all exit nodes pass has been run, we know + // that there can be at most one return instruction in the method left. + // Get it. + // + Root = getAnalysis().getExitNode(); - Root = cfg::UnifyAllExitNodes(M); if (Root == 0) { // No exit node for the method? Postdomsets are all empty - for (Method::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) + for (Method::const_iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) Doms[*MI] = DomSetType(); return; } @@ -116,7 +115,7 @@ cfg::DominatorSet::DominatorSet(Method *M, bool PostDomSet) set Visited; DomSetType WorkingSet; - idf_iterator It = idf_begin(Root), End = idf_end(Root); + idf_iterator It = idf_begin(Root), End = idf_end(Root); for ( ; It != End; ++It) { const BasicBlock *BB = *It; BasicBlock::succ_const_iterator PI = BB->succ_begin(), @@ -147,11 +146,26 @@ cfg::DominatorSet::DominatorSet(Method *M, bool PostDomSet) } while (Changed); } +// getAnalysisUsageInfo - This obviously provides a dominator set, but it also +// uses the UnifyMethodExitNodes pass if building post-dominators +// +void cfg::DominatorSet::getAnalysisUsageInfo(Pass::AnalysisSet &Requires, + Pass::AnalysisSet &Destroyed, + Pass::AnalysisSet &Provided) { + if (isPostDominator()) + Requires.push_back(UnifyMethodExitNodes::ID); + + Provided.push_back(ID); +} + //===----------------------------------------------------------------------===// // ImmediateDominators Implementation //===----------------------------------------------------------------------===// +AnalysisID cfg::ImmediateDominators::ID(AnalysisID::create()); +AnalysisID cfg::ImmediateDominators::PostDomID(AnalysisID::create()); + // calcIDoms - Calculate the immediate dominator mapping, given a set of // dominators for every basic block. void cfg::ImmediateDominators::calcIDoms(const DominatorSet &DS) { @@ -193,14 +207,20 @@ void cfg::ImmediateDominators::calcIDoms(const DominatorSet &DS) { // DominatorTree Implementation //===----------------------------------------------------------------------===// -// DominatorTree dtor - Free all of the tree node memory. +AnalysisID cfg::DominatorTree::ID(AnalysisID::create()); +AnalysisID cfg::DominatorTree::PostDomID(AnalysisID::create()); + +// DominatorTree::reset - Free all of the tree node memory. // -cfg::DominatorTree::~DominatorTree() { +void cfg::DominatorTree::reset() { for (NodeMapType::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) delete I->second; + Nodes.clear(); } +#if 0 +// Given immediate dominators, we can also calculate the dominator tree cfg::DominatorTree::DominatorTree(const ImmediateDominators &IDoms) : DominatorBase(IDoms.getRoot()) { const Method *M = Root->getParent(); @@ -224,13 +244,14 @@ cfg::DominatorTree::DominatorTree(const ImmediateDominators &IDoms) } } } +#endif void cfg::DominatorTree::calculate(const DominatorSet &DS) { Nodes[Root] = new Node(Root, 0); // Add a node for the root... if (!isPostDominator()) { // Iterate over all nodes in depth first order... - for (df_iterator I = df_begin(Root), E = df_end(Root); + for (df_iterator I = df_begin(Root), E = df_end(Root); I != E; ++I) { const BasicBlock *BB = *I; const DominatorSet::DomSetType &Dominators = DS.getDominators(BB); @@ -271,7 +292,7 @@ void cfg::DominatorTree::calculate(const DominatorSet &DS) { } } else if (Root) { // Iterate over all nodes in depth first order... - for (idf_iterator I = idf_begin(Root), E = idf_end(Root); + for (idf_iterator I = idf_begin(Root), E = idf_end(Root); I != E; ++I) { const BasicBlock *BB = *I; const DominatorSet::DomSetType &Dominators = DS.getDominators(BB); @@ -290,10 +311,11 @@ void cfg::DominatorTree::calculate(const DominatorSet &DS) { DominatorSet::DomSetType::const_iterator I = Dominators.begin(); DominatorSet::DomSetType::const_iterator End = Dominators.end(); for (; I != End; ++I) { // Iterate over dominators... - // All of our dominators should form a chain, where the number of elements - // in the dominator set indicates what level the node is at in the chain. - // We want the node immediately above us, so it will have an identical - // dominator set, except that BB will not dominate it... therefore it's + // All of our dominators should form a chain, where the number + // of elements in the dominator set indicates what level the + // node is at in the chain. We want the node immediately + // above us, so it will have an identical dominator set, + // except that BB will not dominate it... therefore it's // dominator set size will be one less than BB's... // if (DS.getDominators(*I).size() == DomSetSize - 1) { @@ -319,6 +341,9 @@ void cfg::DominatorTree::calculate(const DominatorSet &DS) { // DominanceFrontier Implementation //===----------------------------------------------------------------------===// +AnalysisID cfg::DominanceFrontier::ID(AnalysisID::create()); +AnalysisID cfg::DominanceFrontier::PostDomID(AnalysisID::create()); + const cfg::DominanceFrontier::DomSetType & cfg::DominanceFrontier::calcDomFrontier(const DominatorTree &DT, const DominatorTree::Node *Node) { diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 0702e85f0e0..02c24aa799c 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -21,7 +21,7 @@ // . PHI nodes must have an entry for each predecessor, with no extras. // . All other things that are tested by asserts spread about the code... // . All basic blocks should only end with terminator insts, not contain them -// . All methods must have >= 1 basic block +// . The entry node to a method must not have predecessors! // . Verify that none of the Value getType()'s are null. // . Method's cannot take a void typed parameter // . Verify that a method's argument list agrees with it's declared type.