mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 22:50:47 +00:00
Convert analyses to new pass structure
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1603 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0f0fc3253d
commit
93193f8063
@ -19,6 +19,9 @@
|
||||
#include "Support/STLExtras.h"
|
||||
#include <algorithm>
|
||||
|
||||
AnalysisID cfg::CallGraph::ID(AnalysisID::create<cfg::CallGraph>());
|
||||
//AnalysisID cfg::CallGraph::ID(AnalysisID::template AnalysisID<cfg::CallGraph>());
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<FindUnsafePointerTypes>());
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -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<FindUsedTypes>());
|
||||
AnalysisID FindUsedTypes::IncludeSymbolTableID(AnalysisID::create<FindUsedTypes>());
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -11,13 +11,17 @@
|
||||
using namespace cfg;
|
||||
using std::make_pair;
|
||||
|
||||
AnalysisID IntervalPartition::ID(AnalysisID::create<IntervalPartition>());
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// IntervalPartition Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Destructor - Free memory
|
||||
IntervalPartition::~IntervalPartition() {
|
||||
// destroy - Reset state back to before method was analyzed
|
||||
void IntervalPartition::destroy() {
|
||||
for_each(begin(), end(), deleter<cfg::Interval>);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,11 +13,27 @@
|
||||
#include "Support/DepthFirstIterator.h"
|
||||
#include <algorithm>
|
||||
|
||||
AnalysisID cfg::LoopInfo::ID(AnalysisID::create<cfg::LoopInfo>());
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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<DominatorSet>()); // Update
|
||||
return false;
|
||||
}
|
||||
|
||||
void cfg::LoopInfo::Calculate(const DominatorSet &DS) {
|
||||
const BasicBlock *RootNode = DS.getRoot();
|
||||
|
||||
for (df_iterator<const BasicBlock*> 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?
|
||||
|
@ -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<Ty> &S1, const set<Ty2> &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<cfg::DominatorSet>());
|
||||
AnalysisID cfg::DominatorSet::PostDomID(AnalysisID::create<cfg::DominatorSet>());
|
||||
|
||||
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<const Method*> It = df_begin(M), End = df_end(M);
|
||||
df_iterator<Method*> 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<UnifyMethodExitNodes>().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<const BasicBlock*> Visited;
|
||||
DomSetType WorkingSet;
|
||||
idf_iterator<const BasicBlock*> It = idf_begin(Root), End = idf_end(Root);
|
||||
idf_iterator<BasicBlock*> 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<cfg::ImmediateDominators>());
|
||||
AnalysisID cfg::ImmediateDominators::PostDomID(AnalysisID::create<cfg::ImmediateDominators>());
|
||||
|
||||
// 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<cfg::DominatorTree>());
|
||||
AnalysisID cfg::DominatorTree::PostDomID(AnalysisID::create<cfg::DominatorTree>());
|
||||
|
||||
// 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<const BasicBlock*> I = df_begin(Root), E = df_end(Root);
|
||||
for (df_iterator<BasicBlock*> 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<const BasicBlock*> I = idf_begin(Root), E = idf_end(Root);
|
||||
for (idf_iterator<BasicBlock*> 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<cfg::DominanceFrontier>());
|
||||
AnalysisID cfg::DominanceFrontier::PostDomID(AnalysisID::create<cfg::DominanceFrontier>());
|
||||
|
||||
const cfg::DominanceFrontier::DomSetType &
|
||||
cfg::DominanceFrontier::calcDomFrontier(const DominatorTree &DT,
|
||||
const DominatorTree::Node *Node) {
|
||||
|
@ -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<UnifyMethodExitNodes>());
|
||||
|
||||
|
||||
// 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.
|
||||
|
@ -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<Ty> &S1, const set<Ty2> &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<cfg::DominatorSet>());
|
||||
AnalysisID cfg::DominatorSet::PostDomID(AnalysisID::create<cfg::DominatorSet>());
|
||||
|
||||
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<const Method*> It = df_begin(M), End = df_end(M);
|
||||
df_iterator<Method*> 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<UnifyMethodExitNodes>().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<const BasicBlock*> Visited;
|
||||
DomSetType WorkingSet;
|
||||
idf_iterator<const BasicBlock*> It = idf_begin(Root), End = idf_end(Root);
|
||||
idf_iterator<BasicBlock*> 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<cfg::ImmediateDominators>());
|
||||
AnalysisID cfg::ImmediateDominators::PostDomID(AnalysisID::create<cfg::ImmediateDominators>());
|
||||
|
||||
// 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<cfg::DominatorTree>());
|
||||
AnalysisID cfg::DominatorTree::PostDomID(AnalysisID::create<cfg::DominatorTree>());
|
||||
|
||||
// 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<const BasicBlock*> I = df_begin(Root), E = df_end(Root);
|
||||
for (df_iterator<BasicBlock*> 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<const BasicBlock*> I = idf_begin(Root), E = idf_end(Root);
|
||||
for (idf_iterator<BasicBlock*> 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<cfg::DominanceFrontier>());
|
||||
AnalysisID cfg::DominanceFrontier::PostDomID(AnalysisID::create<cfg::DominanceFrontier>());
|
||||
|
||||
const cfg::DominanceFrontier::DomSetType &
|
||||
cfg::DominanceFrontier::calcDomFrontier(const DominatorTree &DT,
|
||||
const DominatorTree::Node *Node) {
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user