X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FPassManagerT.h;h=123af346561b7d919b57f03edf941a8134136538;hb=27287de06b0a6d3c2713fc3a78281df8f5d1a0fa;hp=07bf738fcdc0dffeca09c3b13d39d8800fa020d6;hpb=05ad462d1b8e0486879ecd910c3ff4541bd8604c;p=oota-llvm.git diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h index 07bf738fcdc..123af346561 100644 --- a/lib/VMCore/PassManagerT.h +++ b/lib/VMCore/PassManagerT.h @@ -1,45 +1,115 @@ -//===- 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 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 +#include "Support/CommandLine.h" +#include "Support/LeakDetector.h" +#include "Support/Timer.h" +#include +#include +class Annotable; -// PassManager - Top level PassManagerT instantiation intended to be used. -typedef PassManagerT PassManager; +//===----------------------------------------------------------------------===// +// 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 +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"), + 0)); //===----------------------------------------------------------------------===// -// 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*, - 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 PrintAnalysisSetInfo(unsigned,const char*,const Pass::AnalysisSet&); -#endif + 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 *, Annotable *); + static void PrintAnalysisSetInfo(unsigned,const char*,Pass *P, + const std::vector &); }; +//===----------------------------------------------------------------------===// +// 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 TimingData; + TimerGroup TG; + + // Private ctor, must use 'create' member + TimingInfo() : TG("... Pass execution timing report ...") {} +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() { + // Delete all of the timers... + TimingData.clear(); + // TimerGroup is deleted next, printing the report. + } + + void passStarted(Pass *P) { + if (dynamic_cast(P)) return; + std::map::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(P)) return; + std::map::iterator I = TimingData.find(P); + assert (I != TimingData.end() && "passStarted/passEnded not nested right!"); + I->second.stopTimer(); + } +}; //===----------------------------------------------------------------------===// // Declare the PassManagerTraits which will be specialized... @@ -54,20 +124,22 @@ template class PassManagerTraits; // Do not define. // template class PassManagerT : public PassManagerTraits,public AnalysisResolver{ - typedef typename PassManagerTraits::PassClass PassClass; - typedef typename PassManagerTraits::SubPassClass SubPassClass; - typedef typename PassManagerTraits::BatcherClass BatcherClass; - typedef typename PassManagerTraits::ParentClass ParentClass; - typedef PassManagerTraits Traits; + typedef PassManagerTraits Traits; + typedef typename Traits::PassClass PassClass; + typedef typename Traits::SubPassClass SubPassClass; + typedef typename Traits::BatcherClass BatcherClass; + typedef typename Traits::ParentClass ParentClass; - friend typename PassManagerTraits::PassClass; - friend typename PassManagerTraits::SubPassClass; - friend class PassManagerTraits; + friend typename Traits::PassClass; + friend typename Traits::SubPassClass; + friend class Traits; + friend class ImmutablePass; - std::vector Passes; // List of pass's to run + std::vector Passes; // List of passes to run + std::vector ImmutablePasses; // List of immutable passes // The parent of this pass manager... - const ParentClass *Parent; + ParentClass * const Parent; // The current batcher if one is in use, or null BatcherClass *Batcher; @@ -78,12 +150,22 @@ class PassManagerT : public PassManagerTraits,public AnalysisResolver{ // std::map 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 LastUseOf; + public: PassManagerT(ParentClass *Par = 0) : Parent(Par), Batcher(0) {} ~PassManagerT() { // Delete all of the contained passes... - for (std::vector::iterator I = Passes.begin(), E = Passes.end(); - I != E; ++I) + for (typename std::vector::iterator + I = Passes.begin(), E = Passes.end(); I != E; ++I) + delete *I; + + for (std::vector::iterator + I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I) delete *I; } @@ -94,106 +176,257 @@ public: closeBatcher(); CurrentAnalyses.clear(); + // Add any immutable passes to the CurrentAnalyses set... + 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 &II = PI->getInterfacesImplemented(); + for (unsigned i = 0, e = II.size(); i != e; ++i) + CurrentAnalyses[II[i]] = IPass; + } + } + + // LastUserOf - This contains the inverted LastUseOfMap... + std::map > LastUserOf; + for (std::map::iterator I = LastUseOf.begin(), + E = LastUseOf.end(); I != E; ++I) + LastUserOf[I->second].push_back(I->first); + + // Output debug information... - if (Parent == 0) PMDebug::PrintPassStructure(this); + if (Parent == 0) PMDebug::PerformPassStartupStuff(this); // Run all of the passes 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 Required, Destroyed, Provided; - P->getAnalysisUsageInfo(Required, Destroyed, Provided); - - PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", Required); - -#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) { - assert(getAnalysisOrNullUp(*I) && "Analysis used but not available!"); + AnalysisUsage AnUsage; + P->getAnalysisUsage(AnUsage); + PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", P, + AnUsage.getRequiredSet()); + + // 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. + // + P->AnalysisImpls.clear(); + P->AnalysisImpls.reserve(AnUsage.getRequiredSet().size()); + for (std::vector::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)); } -#endif // Run the sub pass! - MadeChanges |= Traits::runPass(P, M); + startPass(P); + bool Changed = runPass(P, M); + endPass(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, + (Annotable*)M); + PMDebug::PrintAnalysisSetInfo(getDepth(), "Preserved", P, + AnUsage.getPreservedSet()); + + + // Erase all analyses not in the preserved set... + if (!AnUsage.getPreservesAll()) { + const std::vector &PreservedSet = AnUsage.getPreservedSet(); + for (std::map::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(I->second)) { + std::map::iterator J = I++; + CurrentAnalyses.erase(J); // Analysis not preserved! + } else { + ++I; + } + } + } - PMDebug::PrintAnalysisSetInfo(getDepth(), "Destroyed", Destroyed); - PMDebug::PrintAnalysisSetInfo(getDepth(), "Provided", Provided); + // 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 &II = PI->getInterfacesImplemented(); + for (unsigned i = 0, e = II.size(); i != e; ++i) + CurrentAnalyses[II[i]] = P; + } - // Erase all analyses in the destroyed set... - for (Pass::AnalysisSet::iterator I = Destroyed.begin(), - E = Destroyed.end(); I != E; ++I) - CurrentAnalyses.erase(*I); - - // Add all analyses in the provided set... - for (Pass::AnalysisSet::iterator I = Provided.begin(), - E = Provided.end(); I != E; ++I) - CurrentAnalyses[*I] = P; + // Free memory for any passes that we are the last use of... + std::vector &DeadPass = LastUserOf[P]; + for (std::vector::iterator I = DeadPass.begin(),E = DeadPass.end(); + I != E; ++I) { + PMDebug::PrintPassInformation(getDepth()+1, "Freeing Pass", *I, + (Annotable*)M); + (*I)->releaseMemory(); + } + + // Make sure to remove dead passes from the CurrentAnalyses list... + for (std::map::iterator I = CurrentAnalyses.begin(); + I != CurrentAnalyses.end(); ) { + std::vector::iterator DPI = std::find(DeadPass.begin(), + DeadPass.end(), I->second); + if (DPI != DeadPass.end()) { // This pass is dead now... remove it + std::map::iterator IDead = I++; + CurrentAnalyses.erase(IDead); + } else { + ++I; // Move on to the next element... + } + } } return MadeChanges; } - // add - Add a pass to the queue of passes to run. This passes ownership of + // dumpPassStructure - Implement the -debug-passes=PassStructure option + virtual 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, ' ') << Traits::getPMName() + << " Pass Manager\n"; + for (typename std::vector::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::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 *getAnalysisOrNullDown(const PassInfo *ID) const { + std::map::const_iterator I = CurrentAnalyses.find(ID); + + if (I != CurrentAnalyses.end()) + return I->second; // Found it. + + if (Batcher) + return ((AnalysisResolver*)Batcher)->getAnalysisOrNullDown(ID); + return 0; + } + + Pass *getAnalysisOrNullUp(const PassInfo *ID) const { + std::map::const_iterator I = CurrentAnalyses.find(ID); + if (I != CurrentAnalyses.end()) + return I->second; // Found it. + + if (Parent) // Try scanning... + return Parent->getAnalysisOrNullUp(ID); + return 0; + } + + // {start/end}Pass - Called when a pass is started, it just propagates + // 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 + // them... + // + void markPassUsed(const PassInfo *P, Pass *User) { + std::map::const_iterator I = CurrentAnalyses.find(P); + + if (I != CurrentAnalyses.end()) { + LastUseOf[I->second] = User; // Local pass, extend the lifetime + } 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) { + Parent->markPassUsed(P, this); + } else { + assert(0 && "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. Also, - // all passes MUST be new'd. + // 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... - std::vector Required, Destroyed, Provided; - P->getAnalysisUsageInfo(Required, Destroyed, Provided); + AnalysisUsage AnUsage; + P->getAnalysisUsage(AnUsage); + const std::vector &Required = AnUsage.getRequiredSet(); // Loop over all of the analyses used by this pass, - for (std::vector::iterator I = Required.begin(), - E = Required.end(); I != E; ++I) { + for (std::vector::const_iterator I = Required.begin(), + E = Required.end(); I != E; ++I) { if (getAnalysisOrNullDown(*I) == 0) - add(I->createPass()); + add((PassClass*)(*I)->createPass()); } // 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.. // - P->addToPassManager(this, Destroyed, Provided); - } - -#ifndef NDEBUG - // dumpPassStructure - Implement the -debug-passes=PassStructure option - virtual void dumpPassStructure(unsigned Offset = 0) { - std::cerr << std::string(Offset*2, ' ') << "Pass Manager\n"; - for (std::vector::iterator I = Passes.begin(), E = Passes.end(); - I != E; ++I) - (*I)->dumpPassStructure(Offset+1); - } -#endif - -public: - Pass *getAnalysisOrNullDown(AnalysisID ID) { - std::map::iterator I = CurrentAnalyses.find(ID); - if (I == CurrentAnalyses.end()) { - if (Batcher) - return ((AnalysisResolver*)Batcher)->getAnalysisOrNullDown(ID); - return 0; - } - return I->second; - } - - Pass *getAnalysisOrNullUp(AnalysisID ID) { - std::map::iterator I = CurrentAnalyses.find(ID); - if (I == CurrentAnalyses.end()) { - if (Parent) - return ((AnalysisResolver*)Parent)->getAnalysisOrNullUp(ID); - return 0; - } - return I->second; - } - - virtual unsigned getDepth() const { - if (Parent == 0) return 0; - return 1 + ((AnalysisResolver*)Parent)->getDepth(); + P->addToPassManager(this, AnUsage); } private: @@ -206,15 +439,17 @@ 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 &Destroyed, - Pass::AnalysisSet &Provided) { - // 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... + void addPass(PassClass *P, AnalysisUsage &AnUsage) { + const std::vector &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 to pass to execute before the batcher + // does, which will potentially allow us to batch more passes! // - if (Batcher && Provided.empty()) + //const std::vector &ProvidedSet = AnUsage.getProvidedSet(); + if (Batcher /*&& ProvidedSet.empty()*/) closeBatcher(); // This pass cannot be batched! // Set the Resolver instance variable in the Pass so that it knows where to @@ -223,27 +458,54 @@ private: setAnalysisResolver(P, this); Passes.push_back(P); - // Erase all analyses in the destroyed set... - for (std::vector::iterator I = Destroyed.begin(), - E = Destroyed.end(); I != E; ++I) - CurrentAnalyses.erase(*I); + // 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::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 &PreservedSet = AnUsage.getPreservedSet(); + for (std::map::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 all analyses in the provided set... - for (std::vector::iterator I = Provided.begin(), - E = Provided.end(); I != E; ++I) - CurrentAnalyses[*I] = P; + // 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 &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 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 &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, Destroyed, Provided); + // The Batcher will queue the passes up + MP->addToPassManager(Batcher, AnUsage); } // closeBatcher - Terminate the batcher that is being worked on. @@ -253,6 +515,60 @@ private: Batcher = 0; } } + +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_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(); + + // Add this pass to the currently available set... + if (const PassInfo *PI = IP->getPassInfo()) { + CurrentAnalyses[PI] = IP; + + // This pass is the current implementation of all of the interfaces it + // implements as well. + // + const std::vector &II = PI->getInterfacesImplemented(); + for (unsigned i = 0, e = II.size(); i != e; ++i) + CurrentAnalyses[II[i]] = IP; + } + } }; @@ -280,29 +596,49 @@ template<> struct PassManagerTraits : public BasicBlockPass { typedef PassClass BatcherClass; // ParentClass - The type of the parent PassManager... - typedef PassManagerT ParentClass; + typedef PassManagerT ParentClass; + + // PMType - The type of the passmanager that subclasses this class + typedef PassManagerT PMType; // runPass - Specify how the pass should be run on the UnitType static bool runPass(PassClass *P, BasicBlock *M) { // todo, init and finalize - return P->runOnBasicBlock(M); + return P->runOnBasicBlock(*M); } - // run - Implement the Pass interface... - virtual bool runOnBasicBlock(BasicBlock *BB); + // 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 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(); + } }; //===----------------------------------------------------------------------===// -// PassManagerTraits Specialization +// PassManagerTraits 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 : public MethodPass { +template<> struct PassManagerTraits : 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; @@ -314,17 +650,30 @@ template<> struct PassManagerTraits : public MethodPass { typedef PassManagerT ParentClass; // PMType - The type of the passmanager that subclasses this class - typedef PassManagerT PMType; + typedef PassManagerT PMType; // runPass - Specify how the pass should be run on the UnitType - static bool runPass(PassClass *P, Method *M) { - return P->runOnMethod(M); + static bool runPass(PassClass *P, Function *F) { + return P->runOnFunction(*F); } - // Implement the MethodPass interface... - virtual bool doInitialization(Module *M); - virtual bool runOnMethod(Method *M); - virtual bool doFinalization(Module *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 "Function"; } + virtual const char *getPassName() const { return "Function Pass Manager"; } + + // Implement the FunctionPass interface... + virtual bool doInitialization(Module &M); + virtual bool runOnFunction(Function &F); + virtual bool doFinalization(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } }; @@ -339,21 +688,53 @@ template<> struct PassManagerTraits : public Pass { 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 BatcherClass; + typedef PassManagerT BatcherClass; // ParentClass - The type of the parent PassManager... - typedef void ParentClass; + typedef AnalysisResolver ParentClass; // runPass - Specify how the pass should be run on the UnitType - static bool runPass(PassClass *P, Module *M) { return P->run(M); } + static bool runPass(PassClass *P, Module *M) { return P->run(*M); } + + // 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; - // run - Implement the Pass interface... - virtual bool run(Module *M) { - return ((PassManagerT*)this)->runOnUnit(M); + // 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 PassManager interface... + bool run(Module &M) { + TimeInfo = TimingInfo::create(); + bool Result = ((PassManagerT*)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) {} }; @@ -364,28 +745,53 @@ template<> struct PassManagerTraits : public Pass { // PassManagerTraits Implementations // -inline bool PassManagerTraits::runOnBasicBlock(BasicBlock *BB) { - return ((PassManagerT*)this)->runOnUnit(BB); +inline bool PassManagerTraits::doInitialization(Module &M) { + bool Changed = false; + for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i) + ((PMType*)this)->Passes[i]->doInitialization(M); + return Changed; } +inline bool PassManagerTraits::doInitialization(Function &F) { + bool Changed = false; + for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i) + ((PMType*)this)->Passes[i]->doInitialization(F); + return Changed; +} -// PassManagerTraits Implementations -// -inline bool PassManagerTraits::doInitialization(Module *M) { +inline bool PassManagerTraits::runOnBasicBlock(BasicBlock &BB) { + return ((PMType*)this)->runOnUnit(&BB); +} + +inline bool PassManagerTraits::doFinalization(Function &F) { bool Changed = false; for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i) - ((PMType*)this)->Passes[i]->doInitialization(M); + ((PMType*)this)->Passes[i]->doFinalization(F); return Changed; } -inline bool PassManagerTraits::runOnMethod(Method *M) { - return ((PMType*)this)->runOnUnit(M); +inline bool PassManagerTraits::doFinalization(Module &M) { + bool Changed = false; + for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i) + ((PMType*)this)->Passes[i]->doFinalization(M); + return Changed; } -// PassManagerTraits Implementations +// PassManagerTraits Implementations // -inline bool PassManagerTraits::doFinalization(Module *M) { +inline bool PassManagerTraits::doInitialization(Module &M) { + bool Changed = false; + for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i) + ((PMType*)this)->Passes[i]->doInitialization(M); + return Changed; +} + +inline bool PassManagerTraits::runOnFunction(Function &F) { + return ((PMType*)this)->runOnUnit(&F); +} + +inline bool PassManagerTraits::doFinalization(Module &M) { bool Changed = false; for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i) ((PMType*)this)->Passes[i]->doFinalization(M);