llvm-6502/lib/VMCore/PassManagerT.h
Chris Lattner 3159048c00 Patch #9 from Saem:
"Cut up the runPasses method into smaller pieces.  The small private
helpers should  be easier to deal with when code shuffling arising
from creating the new specialised batchers, not to mention, they're
much easier to understand.

I inlined them, in case function call overhead would be noticeable --
doubtful."


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25213 91177308-0d34-0410-b5e6-96231b3b80d8
2006-01-11 16:14:49 +00:00

931 lines
32 KiB
C++

//===- PassManagerT.h - Container for Passes --------------------*- C++ -*-===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PassManagerT class. This class is used to hold,
// maintain, and optimize execution of Pass's. The PassManager class ensures
// that analysis results are available before a pass runs, and that Pass's are
// destroyed when the PassManager is destroyed.
//
// The PassManagerT template is instantiated three times to do its job. The
// public PassManager class is a Pimpl around the PassManagerT<Module> interface
// to avoid having all of the PassManager clients being exposed to the
// implementation details herein.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_PASSMANAGER_T_H
#define LLVM_PASSMANAGER_T_H
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/Timer.h"
#include <algorithm>
#include <iostream>
namespace llvm {
//===----------------------------------------------------------------------===//
// Pass debugging information. Often it is useful to find out what pass is
// running when a crash occurs in a utility. When this library is compiled with
// debugging on, a command line option (--debug-pass) is enabled that causes the
// pass name to be printed before it executes.
//
// Different debug levels that can be enabled...
enum PassDebugLevel {
None, Arguments, Structure, Executions, Details
};
static cl::opt<enum PassDebugLevel>
PassDebugging("debug-pass", cl::Hidden,
cl::desc("Print PassManager debugging information"),
cl::values(
clEnumVal(None , "disable debug output"),
clEnumVal(Arguments , "print pass arguments to pass to 'opt'"),
clEnumVal(Structure , "print pass structure before run()"),
clEnumVal(Executions, "print pass name before it is executed"),
clEnumVal(Details , "print pass details when it is executed"),
clEnumValEnd));
//===----------------------------------------------------------------------===//
// PMDebug class - a set of debugging functions, that are not to be
// instantiated by the template.
//
struct PMDebug {
static void PerformPassStartupStuff(Pass *P) {
// If debugging is enabled, print out argument information...
if (PassDebugging >= Arguments) {
std::cerr << "Pass Arguments: ";
PrintArgumentInformation(P);
std::cerr << "\n";
// Print the pass execution structure
if (PassDebugging >= Structure)
P->dumpPassStructure();
}
}
static void PrintArgumentInformation(const Pass *P);
static void PrintPassInformation(unsigned,const char*,Pass *, Module *);
static void PrintPassInformation(unsigned,const char*,Pass *, Function *);
static void PrintPassInformation(unsigned,const char*,Pass *, BasicBlock *);
static void PrintAnalysisSetInfo(unsigned,const char*,Pass *P,
const std::vector<AnalysisID> &);
};
//===----------------------------------------------------------------------===//
// TimingInfo Class - This class is used to calculate information about the
// amount of time each pass takes to execute. This only happens when
// -time-passes is enabled on the command line.
//
class TimingInfo {
std::map<Pass*, Timer> TimingData;
TimerGroup TG;
// Private ctor, must use 'create' member
TimingInfo() : TG("... Pass execution timing report ...") {}
public:
// TimingDtor - Print out information about timing information
~TimingInfo() {
// Delete all of the timers...
TimingData.clear();
// TimerGroup is deleted next, printing the report.
}
// createTheTimeInfo - This method either initializes the TheTimeInfo pointer
// to a non null value (if the -time-passes option is enabled) or it leaves it
// null. It may be called multiple times.
static void createTheTimeInfo();
void passStarted(Pass *P) {
if (dynamic_cast<AnalysisResolver*>(P)) return;
std::map<Pass*, Timer>::iterator I = TimingData.find(P);
if (I == TimingData.end())
I=TimingData.insert(std::make_pair(P, Timer(P->getPassName(), TG))).first;
I->second.startTimer();
}
void passEnded(Pass *P) {
if (dynamic_cast<AnalysisResolver*>(P)) return;
std::map<Pass*, Timer>::iterator I = TimingData.find(P);
assert (I != TimingData.end() && "passStarted/passEnded not nested right!");
I->second.stopTimer();
}
};
static TimingInfo *TheTimeInfo;
struct BBTraits {
typedef BasicBlock UnitType;
// PassClass - The type of passes tracked by this PassManager
typedef BasicBlockPass PassClass;
// SubPassClass - The types of classes that should be collated together
// This is impossible to match, so BasicBlock instantiations of PassManagerT
// do not collate.
//
typedef BasicBlockPassManager SubPassClass;
// BatcherClass - The type to use for collation of subtypes... This class is
// never instantiated for the BasicBlockPassManager, but it must be an
// instance of PassClass to typecheck.
//
typedef PassClass BatcherClass;
// ParentClass - The type of the parent PassManager...
typedef FunctionPassManagerT ParentClass;
// PMType - The type of this passmanager
typedef BasicBlockPassManager PMType;
};
struct FTraits {
typedef Function UnitType;
// PassClass - The type of passes tracked by this PassManager
typedef FunctionPass PassClass;
// SubPassClass - The types of classes that should be collated together
typedef BasicBlockPass SubPassClass;
// BatcherClass - The type to use for collation of subtypes...
typedef BasicBlockPassManager BatcherClass;
// ParentClass - The type of the parent PassManager...
typedef ModulePassManager ParentClass;
// PMType - The type of this passmanager
typedef FunctionPassManagerT PMType;
};
struct MTraits {
typedef Module UnitType;
// PassClass - The type of passes tracked by this PassManager
typedef ModulePass PassClass;
// SubPassClass - The types of classes that should be collated together
typedef FunctionPass SubPassClass;
// BatcherClass - The type to use for collation of subtypes...
typedef FunctionPassManagerT BatcherClass;
// ParentClass - The type of the parent PassManager...
typedef AnalysisResolver ParentClass;
// PMType - The type of this passmanager
typedef ModulePassManager PMType;
};
//===----------------------------------------------------------------------===//
// PassManagerT - Container object for passes. The PassManagerT destructor
// deletes all passes contained inside of the PassManagerT, so you shouldn't
// delete passes manually, and all passes should be dynamically allocated.
//
template<typename Trait> class PassManagerT : public AnalysisResolver {
typedef typename Trait::PassClass PassClass;
typedef typename Trait::UnitType UnitType;
typedef typename Trait::ParentClass ParentClass;
typedef typename Trait::SubPassClass SubPassClass;
typedef typename Trait::BatcherClass BatcherClass;
typedef typename Trait::PMType PMType;
friend class ModulePass;
friend class FunctionPass;
friend class BasicBlockPass;
friend class ImmutablePass;
friend class BasicBlockPassManager;
friend class FunctionPassManagerT;
friend class ModulePassManager;
std::vector<PassClass*> Passes; // List of passes to run
std::vector<ImmutablePass*> ImmutablePasses; // List of immutable passes
// The parent of this pass manager...
ParentClass * const Parent;
// The current batcher if one is in use, or null
BatcherClass *Batcher;
// CurrentAnalyses - As the passes are being run, this map contains the
// analyses that are available to the current pass for use. This is accessed
// through the getAnalysis() function in this class and in Pass.
//
std::map<AnalysisID, Pass*> CurrentAnalyses;
// LastUseOf - This map keeps track of the last usage in our pipeline of a
// particular pass. When executing passes, the memory for .first is free'd
// after .second is run.
//
std::map<Pass*, Pass*> LastUseOf;
public:
// getPMName() - Return the name of the unit the PassManager operates on for
// debugging.
virtual const char *getPMName() const =0;
virtual const char *getPassName() const =0;
virtual bool runPass(PassClass *P, UnitType *M) =0;
// TODO:Figure out what pure virtuals remain.
PassManagerT(ParentClass *Par = 0) : Parent(Par), Batcher(0) {}
virtual ~PassManagerT() {
// Delete all of the contained passes...
for (typename std::vector<PassClass*>::iterator
I = Passes.begin(), E = Passes.end(); I != E; ++I)
delete *I;
for (std::vector<ImmutablePass*>::iterator
I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
delete *I;
}
// run - Run all of the queued passes on the specified module in an optimal
// way.
virtual bool runOnUnit(UnitType *M) {
closeBatcher();
CurrentAnalyses.clear();
TimingInfo::createTheTimeInfo();
addImmutablePasses();
// LastUserOf - This contains the inverted LastUseOfMap...
std::map<Pass *, std::vector<Pass*> > LastUserOf;
for (std::map<Pass*, Pass*>::iterator I = LastUseOf.begin(),
E = LastUseOf.end(); I != E; ++I)
LastUserOf[I->second].push_back(I->first);
// Output debug information...
assert(dynamic_cast<PassClass*>(this) &&
"It wasn't the PassClass I thought it was");
if (Parent == 0)
PMDebug::PerformPassStartupStuff((dynamic_cast<PMType*>(this)));
return runPasses(M, LastUserOf);
}
// dumpPassStructure - Implement the -debug-passes=PassStructure option
inline void dumpPassStructure(unsigned Offset = 0) {
// Print out the immutable passes...
for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i)
ImmutablePasses[i]->dumpPassStructure(0);
std::cerr << std::string(Offset*2, ' ') << this->getPMName()
<< " Pass Manager\n";
for (typename std::vector<PassClass*>::iterator
I = Passes.begin(), E = Passes.end(); I != E; ++I) {
PassClass *P = *I;
P->dumpPassStructure(Offset+1);
// Loop through and see which classes are destroyed after this one...
for (std::map<Pass*, Pass*>::iterator I = LastUseOf.begin(),
E = LastUseOf.end(); I != E; ++I) {
if (P == I->second) {
std::cerr << "--" << std::string(Offset*2, ' ');
I->first->dumpPassStructure(0);
}
}
}
}
Pass *getImmutablePassOrNull(const PassInfo *ID) const {
for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i) {
const PassInfo *IPID = ImmutablePasses[i]->getPassInfo();
if (IPID == ID)
return ImmutablePasses[i];
// This pass is the current implementation of all of the interfaces it
// implements as well.
//
const std::vector<const PassInfo*> &II =
IPID->getInterfacesImplemented();
for (unsigned j = 0, e = II.size(); j != e; ++j)
if (II[j] == ID) return ImmutablePasses[i];
}
return 0;
}
Pass *getAnalysisOrNullDown(const PassInfo *ID) const {
std::map<AnalysisID, Pass*>::const_iterator I = CurrentAnalyses.find(ID);
if (I != CurrentAnalyses.end())
return I->second; // Found it.
if (Pass *P = getImmutablePassOrNull(ID))
return P;
if (Batcher)
return ((AnalysisResolver*)Batcher)->getAnalysisOrNullDown(ID);
return 0;
}
Pass *getAnalysisOrNullUp(const PassInfo *ID) const {
std::map<AnalysisID, Pass*>::const_iterator I = CurrentAnalyses.find(ID);
if (I != CurrentAnalyses.end())
return I->second; // Found it.
if (Parent) // Try scanning...
return Parent->getAnalysisOrNullUp(ID);
else if (!ImmutablePasses.empty())
return getImmutablePassOrNull(ID);
return 0;
}
// markPassUsed - Inform higher level pass managers (and ourselves)
// that these analyses are being used by this pass. This is used to
// make sure that analyses are not free'd before we have to use
// them...
//
void markPassUsed(const PassInfo *P, Pass *User) {
std::map<AnalysisID, Pass*>::const_iterator I = CurrentAnalyses.find(P);
if (I != CurrentAnalyses.end()) {
LastUseOf[I->second] = User; // Local pass, extend the lifetime
// Prolong live range of analyses that are needed after an analysis pass
// is destroyed, for querying by subsequent passes
AnalysisUsage AnUsage;
I->second->getAnalysisUsage(AnUsage);
const std::vector<AnalysisID> &IDs = AnUsage.getRequiredTransitiveSet();
for (std::vector<AnalysisID>::const_iterator i = IDs.begin(),
e = IDs.end(); i != e; ++i)
markPassUsed(*i, User);
} else {
// Pass not in current available set, must be a higher level pass
// available to us, propagate to parent pass manager... We tell the
// parent that we (the passmanager) are using the analysis so that it
// frees the analysis AFTER this pass manager runs.
//
if (Parent) {
assert(dynamic_cast<Pass*>(this) &&
"It wasn't the Pass type I thought it was.");
Parent->markPassUsed(P, dynamic_cast<Pass*>(this));
} else {
assert(getAnalysisOrNullUp(P) &&
dynamic_cast<ImmutablePass*>(getAnalysisOrNullUp(P)) &&
"Pass available but not found! "
"Perhaps this is a module pass requiring a function pass?");
}
}
}
// Return the number of parent PassManagers that exist
virtual unsigned getDepth() const {
if (Parent == 0) return 0;
return 1 + Parent->getDepth();
}
virtual unsigned getNumContainedPasses() const { return Passes.size(); }
virtual const Pass *getContainedPass(unsigned N) const {
assert(N < Passes.size() && "Pass number out of range!");
return Passes[N];
}
// add - Add a pass to the queue of passes to run. This gives ownership of
// the Pass to the PassManager. When the PassManager is destroyed, the pass
// will be destroyed as well, so there is no need to delete the pass. This
// implies that all passes MUST be new'd.
//
void add(PassClass *P) {
// Get information about what analyses the pass uses...
AnalysisUsage AnUsage;
P->getAnalysisUsage(AnUsage);
addRequiredPasses(AnUsage.getRequiredSet());
// Tell the pass to add itself to this PassManager... the way it does so
// depends on the class of the pass, and is critical to laying out passes in
// an optimal order..
//
assert(dynamic_cast<PMType*>(this) &&
"It wasn't the right passmanager type.");
P->addToPassManager(static_cast<PMType*>(this), AnUsage);
}
// add - H4x0r an ImmutablePass into a PassManager that might not be
// expecting one.
//
void add(ImmutablePass *P) {
// Get information about what analyses the pass uses...
AnalysisUsage AnUsage;
P->getAnalysisUsage(AnUsage);
addRequiredPasses(AnUsage.getRequiredSet());
// Add the ImmutablePass to this PassManager.
addPass(P, AnUsage);
}
private:
// addPass - These functions are used to implement the subclass specific
// behaviors present in PassManager. Basically the add(Pass*) method ends up
// reflecting its behavior into a Pass::addToPassManager call. Subclasses of
// Pass override it specifically so that they can reflect the type
// information inherent in "this" back to the PassManager.
//
// For generic Pass subclasses (which are interprocedural passes), we simply
// add the pass to the end of the pass list and terminate any accumulation of
// FunctionPass's that are present.
//
void addPass(PassClass *P, AnalysisUsage &AnUsage) {
const std::vector<AnalysisID> &RequiredSet = AnUsage.getRequiredSet();
// FIXME: If this pass being added isn't killed by any of the passes in the
// batcher class then we can reorder the pass to execute before the batcher
// does, which will potentially allow us to batch more passes!
//
if (Batcher)
closeBatcher(); // This pass cannot be batched!
// Set the Resolver instance variable in the Pass so that it knows where to
// find this object...
//
setAnalysisResolver(P, this);
Passes.push_back(P);
// Inform higher level pass managers (and ourselves) that these analyses are
// being used by this pass. This is used to make sure that analyses are not
// free'd before we have to use them...
//
for (std::vector<AnalysisID>::const_iterator I = RequiredSet.begin(),
E = RequiredSet.end(); I != E; ++I)
markPassUsed(*I, P); // Mark *I as used by P
// Erase all analyses not in the preserved set...
if (!AnUsage.getPreservesAll()) {
const std::vector<AnalysisID> &PreservedSet = AnUsage.getPreservedSet();
for (std::map<AnalysisID, Pass*>::iterator I = CurrentAnalyses.begin(),
E = CurrentAnalyses.end(); I != E; ) {
if (std::find(PreservedSet.begin(), PreservedSet.end(), I->first) ==
PreservedSet.end()) { // Analysis not preserved!
CurrentAnalyses.erase(I); // Remove from available analyses
I = CurrentAnalyses.begin();
} else {
++I;
}
}
}
// Add this pass to the currently available set...
if (const PassInfo *PI = P->getPassInfo()) {
CurrentAnalyses[PI] = P;
// This pass is the current implementation of all of the interfaces it
// implements as well.
//
const std::vector<const PassInfo*> &II = PI->getInterfacesImplemented();
for (unsigned i = 0, e = II.size(); i != e; ++i)
CurrentAnalyses[II[i]] = P;
}
// For now assume that our results are never used...
LastUseOf[P] = P;
}
// For FunctionPass subclasses, we must be sure to batch the FunctionPass's
// together in a BatcherClass object so that all of the analyses are run
// together a function at a time.
//
void addPass(SubPassClass *MP, AnalysisUsage &AnUsage) {
if (Batcher == 0) { // If we don't have a batcher yet, make one now.
assert(dynamic_cast<PMType*>(this) &&
"It wasn't the PassManager type I thought it was");
Batcher = new BatcherClass((static_cast<PMType*>(this)));
}
// The Batcher will queue the passes up
MP->addToPassManager(Batcher, AnUsage);
}
// closeBatcher - Terminate the batcher that is being worked on.
void closeBatcher() {
if (Batcher) {
Passes.push_back(Batcher);
Batcher = 0;
}
}
void addRequiredPasses(const std::vector<AnalysisID> &Required) {
for (std::vector<AnalysisID>::const_iterator I = Required.begin(),
E = Required.end(); I != E; ++I) {
if (getAnalysisOrNullDown(*I) == 0) {
Pass *AP = (*I)->createPass();
if (ImmutablePass *IP = dynamic_cast<ImmutablePass *> (AP)) add(IP);
else if (PassClass *RP = dynamic_cast<PassClass *> (AP)) add(RP);
else assert (0 && "Wrong kind of pass for this PassManager");
}
}
}
public:
// When an ImmutablePass is added, it gets added to the top level pass
// manager.
void addPass(ImmutablePass *IP, AnalysisUsage &AU) {
if (Parent) { // Make sure this request goes to the top level passmanager...
Parent->addPass(IP, AU);
return;
}
// Set the Resolver instance variable in the Pass so that it knows where to
// find this object...
//
setAnalysisResolver(IP, this);
ImmutablePasses.push_back(IP);
// All Required analyses should be available to the pass as it initializes!
// Here we fill in the AnalysisImpls member of the pass so that it can
// successfully use the getAnalysis() method to retrieve the implementations
// it needs.
//
IP->AnalysisImpls.clear();
IP->AnalysisImpls.reserve(AU.getRequiredSet().size());
for (std::vector<const PassInfo *>::const_iterator
I = AU.getRequiredSet().begin(),
E = AU.getRequiredSet().end(); I != E; ++I) {
Pass *Impl = getAnalysisOrNullUp(*I);
if (Impl == 0) {
std::cerr << "Analysis '" << (*I)->getPassName()
<< "' used but not available!";
assert(0 && "Analysis used but not available!");
} else if (PassDebugging == Details) {
if ((*I)->getPassName() != std::string(Impl->getPassName()))
std::cerr << " Interface '" << (*I)->getPassName()
<< "' implemented by '" << Impl->getPassName() << "'\n";
}
IP->AnalysisImpls.push_back(std::make_pair(*I, Impl));
}
// Initialize the immutable pass...
IP->initializePass();
}
private:
// Add any immutable passes to the CurrentAnalyses set...
inline void addImmutablePasses() {
for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i) {
ImmutablePass *IPass = ImmutablePasses[i];
if (const PassInfo *PI = IPass->getPassInfo()) {
CurrentAnalyses[PI] = IPass;
const std::vector<const PassInfo*> &II = PI->getInterfacesImplemented();
for (unsigned i = 0, e = II.size(); i != e; ++i)
CurrentAnalyses[II[i]] = IPass;
}
}
}
// Run all of the passes
inline bool runPasses(UnitType *M,
std::map<Pass *, std::vector<Pass*> > &LastUserOf) {
bool MadeChanges = false;
for (unsigned i = 0, e = Passes.size(); i < e; ++i) {
PassClass *P = Passes[i];
PMDebug::PrintPassInformation(getDepth(), "Executing Pass", P, M);
// Get information about what analyses the pass uses...
AnalysisUsage AnUsage;
P->getAnalysisUsage(AnUsage);
PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", P,
AnUsage.getRequiredSet());
initialiseAnalysisImpl(P, AnUsage);
// Run the sub pass!
if (TheTimeInfo) TheTimeInfo->passStarted(P);
bool Changed = runPass(P, M);
if (TheTimeInfo) TheTimeInfo->passEnded(P);
MadeChanges |= Changed;
// Check for memory leaks by the pass...
LeakDetector::checkForGarbage(std::string("after running pass '") +
P->getPassName() + "'");
if (Changed)
PMDebug::PrintPassInformation(getDepth()+1, "Made Modification", P, M);
PMDebug::PrintAnalysisSetInfo(getDepth(), "Preserved", P,
AnUsage.getPreservedSet());
// Erase all analyses not in the preserved set
removeNonPreservedAnalyses(AnUsage);
// Add the current pass to the set of passes that have been run, and are
// thus available to users.
//
if (const PassInfo *PI = P->getPassInfo()) {
CurrentAnalyses[PI] = P;
// This pass is the current implementation of all of the interfaces it
// implements as well.
//
const std::vector<const PassInfo*> &II = PI->getInterfacesImplemented();
for (unsigned i = 0, e = II.size(); i != e; ++i)
CurrentAnalyses[II[i]] = P;
}
// Free memory for any passes that we are the last use of...
std::vector<Pass*> &DeadPass = LastUserOf[P];
for (std::vector<Pass*>::iterator I = DeadPass.begin(),E = DeadPass.end();
I != E; ++I) {
PMDebug::PrintPassInformation(getDepth()+1, "Freeing Pass", *I, M);
(*I)->releaseMemory();
}
// remove dead passes from the CurrentAnalyses list...
removeDeadPasses(DeadPass);
}
return MadeChanges;
}
// All Required analyses should be available to the pass as it runs! Here
// we fill in the AnalysisImpls member of the pass so that it can
// successfully use the getAnalysis() method to retrieve the
// implementations it needs.
//
inline void initialiseAnalysisImpl(PassClass *P, AnalysisUsage &AnUsage) {
P->AnalysisImpls.clear();
P->AnalysisImpls.reserve(AnUsage.getRequiredSet().size());
for (std::vector<const PassInfo *>::const_iterator
I = AnUsage.getRequiredSet().begin(),
E = AnUsage.getRequiredSet().end(); I != E; ++I) {
Pass *Impl = getAnalysisOrNullUp(*I);
if (Impl == 0) {
std::cerr << "Analysis '" << (*I)->getPassName()
<< "' used but not available!";
assert(0 && "Analysis used but not available!");
} else if (PassDebugging == Details) {
if ((*I)->getPassName() != std::string(Impl->getPassName()))
std::cerr << " Interface '" << (*I)->getPassName()
<< "' implemented by '" << Impl->getPassName() << "'\n";
}
P->AnalysisImpls.push_back(std::make_pair(*I, Impl));
}
}
inline void removeNonPreservedAnalyses(AnalysisUsage &AnUsage) {
if (!AnUsage.getPreservesAll()) {
const std::vector<AnalysisID> &PreservedSet = AnUsage.getPreservedSet();
for (std::map<AnalysisID, Pass*>::iterator I = CurrentAnalyses.begin(),
E = CurrentAnalyses.end(); I != E; )
if (std::find(PreservedSet.begin(), PreservedSet.end(), I->first) !=
PreservedSet.end())
++I; // This analysis is preserved, leave it in the available set...
else {
if (!dynamic_cast<ImmutablePass*>(I->second)) {
std::map<AnalysisID, Pass*>::iterator J = I++;
CurrentAnalyses.erase(J); // Analysis not preserved!
} else {
++I;
}
}
}
}
inline void removeDeadPasses(std::vector<Pass*> &DeadPass) {
for (std::map<AnalysisID, Pass*>::iterator I = CurrentAnalyses.begin();
I != CurrentAnalyses.end(); ) {
std::vector<Pass*>::iterator DPI = std::find(DeadPass.begin(),
DeadPass.end(), I->second);
if (DPI != DeadPass.end()) { // This pass is dead now... remove it
std::map<AnalysisID, Pass*>::iterator IDead = I++;
CurrentAnalyses.erase(IDead);
} else {
++I; // Move on to the next element...
}
}
}
};
//===----------------------------------------------------------------------===//
// BasicBlockPassManager
//
// This pass manager is used to group together all of the BasicBlockPass's
// into a single unit.
//
class BasicBlockPassManager : public BasicBlockPass,
public BBTraits,
public PassManagerT<BBTraits> {
public:
BasicBlockPassManager(BBTraits::ParentClass* PC) :
PassManagerT<BBTraits>(PC) {
}
BasicBlockPassManager(BasicBlockPassManager* BBPM) :
PassManagerT<BBTraits>(BBPM->Parent) {
}
// runPass - Specify how the pass should be run on the UnitType
virtual bool runPass(BBTraits::PassClass *P, BasicBlock *M) {
// TODO: init and finalize
return P->runOnBasicBlock(*M);
}
virtual ~BasicBlockPassManager() {}
virtual void dumpPassStructure(unsigned Offset = 0) {
PassManagerT<BBTraits>::dumpPassStructure(Offset);
}
// getPMName() - Return the name of the unit the PassManager operates on for
// debugging.
virtual const char *getPMName() const { return "BasicBlock"; }
virtual const char *getPassName() const { return "BasicBlock Pass Manager"; }
virtual bool doInitialization(Module &M);
virtual bool doInitialization(Function &F);
virtual bool runOnBasicBlock(BasicBlock &BB);
virtual bool doFinalization(Function &F);
virtual bool doFinalization(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
};
//===----------------------------------------------------------------------===//
// FunctionPassManager
//
// This pass manager is used to group together all of the FunctionPass's
// into a single unit.
//
class FunctionPassManagerT : public FunctionPass,
public FTraits,
public PassManagerT<FTraits> {
public:
FunctionPassManagerT() : PassManagerT<FTraits>(0) {}
// Parent constructor
FunctionPassManagerT(FTraits::ParentClass* PC) : PassManagerT<FTraits>(PC) {}
FunctionPassManagerT(FunctionPassManagerT* FPM) :
PassManagerT<FTraits>(FPM->Parent) {
}
virtual ~FunctionPassManagerT() {}
virtual void dumpPassStructure(unsigned Offset = 0) {
PassManagerT<FTraits>::dumpPassStructure(Offset);
}
// getPMName() - Return the name of the unit the PassManager operates on for
// debugging.
virtual const char *getPMName() const { return "Function"; }
virtual const char *getPassName() const { return "Function Pass Manager"; }
virtual bool runOnFunction(Function &F);
virtual bool doInitialization(Module &M);
virtual bool doFinalization(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
// runPass - Specify how the pass should be run on the UnitType
virtual bool runPass(FTraits::PassClass *P, Function *F) {
return P->runOnFunction(*F);
}
};
//===----------------------------------------------------------------------===//
// ModulePassManager
//
// This is the top level PassManager implementation that holds generic passes.
//
class ModulePassManager : public ModulePass,
public MTraits,
public PassManagerT<MTraits> {
public:
ModulePassManager() : PassManagerT<MTraits>(0) {}
// Batcher Constructor
ModulePassManager(MTraits::ParentClass* PC) : PassManagerT<MTraits>(PC) {}
ModulePassManager(ModulePassManager* MPM) :
PassManagerT<MTraits>((MPM->Parent)) {
}
virtual ~ModulePassManager() {}
virtual void dumpPassStructure(unsigned Offset = 0) {
PassManagerT<MTraits>::dumpPassStructure(Offset);
}
// getPMName() - Return the name of the unit the PassManager operates on for
// debugging.
virtual const char *getPassName() const { return "Module Pass Manager"; }
// getPMName() - Return the name of the unit the PassManager operates on for
// debugging.
virtual const char *getPMName() const { return "Module"; }
// runOnModule - Implement the PassManager interface.
virtual bool runOnModule(Module &M);
// runPass - Specify how the pass should be run on the UnitType
virtual bool runPass(MTraits::PassClass *P, Module *M) {
return P->runOnModule(*M);
}
};
//===----------------------------------------------------------------------===//
// PassManagerTraits Method Implementations
//
// BasicBlockPassManager Implementations
//
inline bool BasicBlockPassManager::runOnBasicBlock(BasicBlock &BB) {
return ((BBTraits::PMType*)this)->runOnUnit(&BB);
}
inline bool BasicBlockPassManager::doInitialization(Module &M) {
bool Changed = false;
for (unsigned i = 0, e =((BBTraits::PMType*)this)->Passes.size(); i != e; ++i)
((BBTraits::PMType*)this)->Passes[i]->doInitialization(M);
return Changed;
}
inline bool BasicBlockPassManager::doInitialization(Function &F) {
bool Changed = false;
for (unsigned i = 0, e =((BBTraits::PMType*)this)->Passes.size(); i != e; ++i)
((BBTraits::PMType*)this)->Passes[i]->doInitialization(F);
return Changed;
}
inline bool BasicBlockPassManager::doFinalization(Function &F) {
bool Changed = false;
for (unsigned i = 0, e =((BBTraits::PMType*)this)->Passes.size(); i != e; ++i)
((BBTraits::PMType*)this)->Passes[i]->doFinalization(F);
return Changed;
}
inline bool BasicBlockPassManager::doFinalization(Module &M) {
bool Changed = false;
for (unsigned i=0, e = ((BBTraits::PMType*)this)->Passes.size(); i != e; ++i)
((BBTraits::PMType*)this)->Passes[i]->doFinalization(M);
return Changed;
}
// FunctionPassManagerT Implementations
//
inline bool FunctionPassManagerT::runOnFunction(Function &F) {
return ((FTraits::PMType*)this)->runOnUnit(&F);
}
inline bool FunctionPassManagerT::doInitialization(Module &M) {
bool Changed = false;
for (unsigned i=0, e = ((FTraits::PMType*)this)->Passes.size(); i != e; ++i)
((FTraits::PMType*)this)->Passes[i]->doInitialization(M);
return Changed;
}
inline bool FunctionPassManagerT::doFinalization(Module &M) {
bool Changed = false;
for (unsigned i=0, e = ((FTraits::PMType*)this)->Passes.size(); i != e; ++i)
((FTraits::PMType*)this)->Passes[i]->doFinalization(M);
return Changed;
}
// ModulePassManager Implementations
//
bool ModulePassManager::runOnModule(Module &M) {
return ((PassManagerT<MTraits>*)this)->runOnUnit(&M);
}
} // End llvm namespace
#endif