-//===- llvm/PassManager.h - Container for Passes -----------------*- C++ -*--=//
+//===- PassManagerT.h - Container for Passes ---------------------*- C++ -*--=//
//
-// This file defines the PassManager class. This class is used to hold,
+// 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 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_H
-#define LLVM_PASSMANAGER_H
+#ifndef LLVM_PASSMANAGER_T_H
+#define LLVM_PASSMANAGER_T_H
#include "llvm/Pass.h"
#include <string>
+#include <algorithm>
+class Annotable;
//===----------------------------------------------------------------------===//
-// PMDebug class - a set of debugging functions that are enabled when compiling
-// with -g on. If compiling at -O, all functions are inlined noops.
+// PMDebug class - a set of debugging functions, that are not to be
+// instantiated by the template.
//
struct PMDebug {
-#ifdef NDEBUG
- inline static void PrintPassStructure(Pass *) {}
- inline static void PrintPassInformation(unsigned,const char*,Pass*,Value*) {}
- inline static void PrintAnalysisSetInfo(unsigned,const char*,Pass *P,
- const Pass::AnalysisSet &) {}
-#else
// If compiled in debug mode, these functions can be enabled by setting
// -debug-pass on the command line of the tool being used.
//
static void PrintPassStructure(Pass *P);
- static void PrintPassInformation(unsigned,const char*,Pass *, Value *);
+ static void PrintPassInformation(unsigned,const char*,Pass *, Annotable *);
static void PrintAnalysisSetInfo(unsigned,const char*,Pass *P,
- const Pass::AnalysisSet&);
-#endif
+ 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*, double> TimingData;
+ TimingInfo() {} // Private ctor, must use create member
+public:
+ // Create method. If Timing is enabled, this creates and returns a new timing
+ // object, otherwise it returns null.
+ //
+ static TimingInfo *create();
+
+ // TimingDtor - Print out information about timing information
+ ~TimingInfo();
+
+ void passStarted(Pass *P);
+ void passEnded(Pass *P);
};
//
template<typename UnitType>
class PassManagerT : public PassManagerTraits<UnitType>,public AnalysisResolver{
- typedef typename PassManagerTraits<UnitType>::PassClass PassClass;
- typedef typename PassManagerTraits<UnitType>::SubPassClass SubPassClass;
- typedef typename PassManagerTraits<UnitType>::BatcherClass BatcherClass;
- typedef typename PassManagerTraits<UnitType>::ParentClass ParentClass;
- typedef PassManagerTraits<UnitType> Traits;
+ typedef PassManagerTraits<UnitType> Traits;
+ typedef typename Traits::PassClass PassClass;
+ typedef typename Traits::SubPassClass SubPassClass;
+ typedef typename Traits::BatcherClass BatcherClass;
+ typedef typename Traits::ParentClass ParentClass;
- friend typename PassManagerTraits<UnitType>::PassClass;
- friend typename PassManagerTraits<UnitType>::SubPassClass;
- friend class PassManagerTraits<UnitType>;
+ friend typename Traits::PassClass;
+ friend typename Traits::SubPassClass;
+ friend class Traits;
std::vector<PassClass*> Passes; // List of pass's to run
for (unsigned i = 0, e = Passes.size(); i < e; ++i) {
PassClass *P = Passes[i];
- PMDebug::PrintPassInformation(getDepth(), "Executing Pass", P, (Value*)M);
+ PMDebug::PrintPassInformation(getDepth(), "Executing Pass", P,
+ (Annotable*)M);
// Get information about what analyses the pass uses...
- std::vector<AnalysisID> Required, Destroyed, Provided;
- P->getAnalysisUsageInfo(Required, Destroyed, Provided);
-
- PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", P, Required);
+ AnalysisUsage AnUsage;
+ P->getAnalysisUsage(AnUsage);
+ PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", P,
+ AnUsage.getRequiredSet());
#ifndef NDEBUG
// All Required analyses should be available to the pass as it runs!
- for (Pass::AnalysisSet::iterator I = Required.begin(),
- E = Required.end(); I != E; ++I) {
+ for (vector<AnalysisID>::const_iterator
+ I = AnUsage.getRequiredSet().begin(),
+ E = AnUsage.getRequiredSet().end(); I != E; ++I) {
assert(getAnalysisOrNullUp(*I) && "Analysis used but not available!");
}
#endif
// Run the sub pass!
- bool Changed = Traits::runPass(P, M);
+ startPass(P);
+ bool Changed = runPass(P, M);
+ endPass(P);
MadeChanges |= Changed;
if (Changed)
PMDebug::PrintPassInformation(getDepth()+1, "Made Modification", P,
- (Value*)M);
- PMDebug::PrintAnalysisSetInfo(getDepth(), "Destroyed", P, Destroyed);
- PMDebug::PrintAnalysisSetInfo(getDepth(), "Provided", P, Provided);
-
- // Erase all analyses in the destroyed set...
- for (Pass::AnalysisSet::iterator I = Destroyed.begin(),
- E = Destroyed.end(); I != E; ++I)
- CurrentAnalyses.erase(*I);
-
+ (Annotable*)M);
+ PMDebug::PrintAnalysisSetInfo(getDepth(), "Preserved", P,
+ AnUsage.getPreservedSet());
+ PMDebug::PrintAnalysisSetInfo(getDepth(), "Provided", P,
+ AnUsage.getProvidedSet());
+
+
+ // Erase all analyses not in the preserved set...
+ if (!AnUsage.preservesAll()) {
+ 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 MAP_DOESNT_HAVE_BROKEN_ERASE_MEMBER
+ I = CurrentAnalyses.erase(I); // Analysis not preserved!
+#else
+ // GCC 2.95.3 STL doesn't have correct erase member!
+ CurrentAnalyses.erase(I);
+ I = CurrentAnalyses.begin();
+#endif
+ }
+ }
+
// Add all analyses in the provided set...
- for (Pass::AnalysisSet::iterator I = Provided.begin(),
- E = Provided.end(); I != E; ++I)
+ for (std::vector<AnalysisID>::const_iterator
+ I = AnUsage.getProvidedSet().begin(),
+ E = AnUsage.getProvidedSet().end(); I != E; ++I)
CurrentAnalyses[*I] = P;
// Free memory for any passes that we are the last use of...
for (std::vector<Pass*>::iterator I = DeadPass.begin(),E = DeadPass.end();
I != E; ++I) {
PMDebug::PrintPassInformation(getDepth()+1, "Freeing Pass", *I,
- (Value*)M);
+ (Annotable*)M);
(*I)->releaseMemory();
}
}
return MadeChanges;
}
-#ifndef NDEBUG
// dumpPassStructure - Implement the -debug-passes=PassStructure option
virtual void dumpPassStructure(unsigned Offset = 0) {
std::cerr << std::string(Offset*2, ' ') << Traits::getPMName()
}
}
}
-#endif
Pass *getAnalysisOrNullDown(AnalysisID ID) const {
std::map<AnalysisID, Pass*>::const_iterator I = CurrentAnalyses.find(ID);
return I->second;
}
+ // {start/end}Pass - Called when a pass is started, it just propogates
+ // information up to the top level PassManagerT object to tell it that a pass
+ // has started or ended. This is used to gather timing information about
+ // passes.
+ //
+ void startPass(Pass *P) {
+ if (Parent) Parent->startPass(P);
+ else PassStarted(P);
+ }
+ void endPass(Pass *P) {
+ if (Parent) Parent->endPass(P);
+ else PassEnded(P);
+ }
+
// 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
//
void add(PassClass *P) {
// Get information about what analyses the pass uses...
- std::vector<AnalysisID> Required, Destroyed, Provided;
- P->getAnalysisUsageInfo(Required, Destroyed, Provided);
+ AnalysisUsage AnUsage;
+ P->getAnalysisUsage(AnUsage);
+ const std::vector<AnalysisID> &Required = AnUsage.getRequiredSet();
// Loop over all of the analyses used by this pass,
- for (std::vector<AnalysisID>::iterator I = Required.begin(),
- E = Required.end(); I != E; ++I) {
+ for (std::vector<AnalysisID>::const_iterator I = Required.begin(),
+ E = Required.end(); I != E; ++I) {
if (getAnalysisOrNullDown(*I) == 0)
add((PassClass*)I->createPass());
}
// depends on the class of the pass, and is critical to laying out passes in
// an optimal order..
//
- P->addToPassManager(this, Required, Destroyed, Provided);
+ P->addToPassManager(this, AnUsage);
}
private:
//
// 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
- // MethodPasses that are present.
+ // FunctionPass's that are present.
//
- void addPass(PassClass *P, Pass::AnalysisSet &Required,
- Pass::AnalysisSet &Destroyed, Pass::AnalysisSet &Provided) {
+ void addPass(PassClass *P, AnalysisUsage &AnUsage) {
+ const std::vector<AnalysisID> &RequiredSet = AnUsage.getRequiredSet();
+ const std::vector<AnalysisID> &ProvidedSet = AnUsage.getProvidedSet();
+
// Providers are analysis classes which are forbidden to modify the module
// they are operating on, so they are allowed to be reordered to before the
// batcher...
//
- if (Batcher && Provided.empty())
+ if (Batcher && ProvidedSet.empty())
closeBatcher(); // This pass cannot be batched!
// Set the Resolver instance variable in the Pass so that it knows where to
// 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>::iterator I = Required.begin(),
- E = Required.end(); I != E; ++I)
+ 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 in the destroyed set...
- for (std::vector<AnalysisID>::iterator I = Destroyed.begin(),
- E = Destroyed.end(); I != E; ++I)
- CurrentAnalyses.erase(*I);
+ // Erase all analyses not in the preserved set...
+ if (!AnUsage.preservesAll()) {
+ 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 MAP_DOESNT_HAVE_BROKEN_ERASE_MEMBER
+ I = CurrentAnalyses.erase(I); // Analysis not preserved!
+#else
+ CurrentAnalyses.erase(I);// GCC 2.95.3 STL doesn't have correct erase!
+ I = CurrentAnalyses.begin();
+#endif
+ }
+ }
// Add all analyses in the provided set...
- for (std::vector<AnalysisID>::iterator I = Provided.begin(),
- E = Provided.end(); I != E; ++I)
+ for (std::vector<AnalysisID>::const_iterator I = ProvidedSet.begin(),
+ E = ProvidedSet.end(); I != E; ++I)
CurrentAnalyses[*I] = P;
// For now assume that our results are never used...
LastUseOf[P] = P;
}
- // For MethodPass subclasses, we must be sure to batch the MethodPasses
- // together in a MethodPassBatcher object so that all of the analyses are run
- // together a method at a time.
+ // 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, Pass::AnalysisSet &Required,
- Pass::AnalysisSet &Destroyed, Pass::AnalysisSet &Provided) {
+ void addPass(SubPassClass *MP, AnalysisUsage &AnUsage) {
if (Batcher == 0) // If we don't have a batcher yet, make one now.
Batcher = new BatcherClass(this);
// The Batcher will queue them passes up
- MP->addToPassManager(Batcher, Required, Destroyed, Provided);
+ MP->addToPassManager(Batcher, AnUsage);
}
// closeBatcher - Terminate the batcher that is being worked on.
return P->runOnBasicBlock(M);
}
+ // Dummy implementation of PassStarted/PassEnded
+ static void PassStarted(Pass *P) {}
+ static void PassEnded(Pass *P) {}
+
// getPMName() - Return the name of the unit the PassManager operates on for
// debugging.
const char *getPMName() const { return "BasicBlock"; }
+ virtual const char *getPassName() const { return "BasicBlock Pass Manager"; }
// Implement the BasicBlockPass interface...
virtual bool doInitialization(Module *M);
virtual bool runOnBasicBlock(BasicBlock *BB);
virtual bool doFinalization(Module *M);
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
};
//===----------------------------------------------------------------------===//
// PassManagerTraits<Function> Specialization
//
-// This pass manager is used to group together all of the MethodPass's
+// This pass manager is used to group together all of the FunctionPass's
// into a single unit.
//
-template<> struct PassManagerTraits<Function> : public MethodPass {
+template<> struct PassManagerTraits<Function> : public FunctionPass {
// PassClass - The type of passes tracked by this PassManager
- typedef MethodPass PassClass;
+ typedef FunctionPass PassClass;
// SubPassClass - The types of classes that should be collated together
typedef BasicBlockPass SubPassClass;
typedef PassManagerT<Function> PMType;
// runPass - Specify how the pass should be run on the UnitType
- static bool runPass(PassClass *P, Function *M) {
- return P->runOnMethod(M);
+ static bool runPass(PassClass *P, Function *F) {
+ return P->runOnFunction(F);
}
+ // Dummy implementation of PassStarted/PassEnded
+ static void PassStarted(Pass *P) {}
+ static void PassEnded(Pass *P) {}
+
// getPMName() - Return the name of the unit the PassManager operates on for
// debugging.
const char *getPMName() const { return "Function"; }
+ virtual const char *getPassName() const { return "Function Pass Manager"; }
- // Implement the MethodPass interface...
+ // Implement the FunctionPass interface...
virtual bool doInitialization(Module *M);
- virtual bool runOnMethod(Function *M);
+ virtual bool runOnFunction(Function *F);
virtual bool doFinalization(Module *M);
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
};
typedef Pass PassClass;
// SubPassClass - The types of classes that should be collated together
- typedef MethodPass SubPassClass;
+ typedef FunctionPass SubPassClass;
// BatcherClass - The type to use for collation of subtypes...
typedef PassManagerT<Function> BatcherClass;
// getPMName() - Return the name of the unit the PassManager operates on for
// debugging.
const char *getPMName() const { return "Module"; }
+ virtual const char *getPassName() const { return "Module Pass Manager"; }
+
+ // TimingInformation - This data member maintains timing information for each
+ // of the passes that is executed.
+ //
+ TimingInfo *TimeInfo;
+
+ // PassStarted/Ended - This callback is notified any time a pass is started
+ // or stops. This is used to collect timing information about the different
+ // passes being executed.
+ //
+ void PassStarted(Pass *P) {
+ if (TimeInfo) TimeInfo->passStarted(P);
+ }
+ void PassEnded(Pass *P) {
+ if (TimeInfo) TimeInfo->passEnded(P);
+ }
- // run - Implement the Pass interface...
- virtual bool run(Module *M) {
- return ((PassManagerT<Module>*)this)->runOnUnit(M);
+ // run - Implement the PassManager interface...
+ bool run(Module *M) {
+ TimeInfo = TimingInfo::create();
+ bool Result = ((PassManagerT<Module>*)this)->runOnUnit(M);
+ if (TimeInfo) {
+ delete TimeInfo;
+ TimeInfo = 0;
+ }
+ return Result;
}
+
+ // PassManagerTraits constructor - Create a timing info object if the user
+ // specified timing info should be collected on the command line.
+ //
+ PassManagerTraits() : TimeInfo(0) {}
};
return Changed;
}
-inline bool PassManagerTraits<Function>::runOnMethod(Function *M) {
- return ((PMType*)this)->runOnUnit(M);
+inline bool PassManagerTraits<Function>::runOnFunction(Function *F) {
+ return ((PMType*)this)->runOnUnit(F);
}
inline bool PassManagerTraits<Function>::doFinalization(Module *M) {