X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FPassManagerT.h;h=e61d994d9a339d61491e161c5c43045f04523b7e;hb=18961504fc2b299578dba817900a0696cf3ccc4d;hp=7999db11b69dffb1007d89fd5037425583e5d8d5;hpb=e7506a366e8bd56c97d10beb68e4db953aebaeca;p=oota-llvm.git diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h index 7999db11b69..e61d994d9a3 100644 --- a/lib/VMCore/PassManagerT.h +++ b/lib/VMCore/PassManagerT.h @@ -1,39 +1,59 @@ -//===- 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 +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 &); +}; + + +//===----------------------------------------------------------------------===// +// 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; + 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); }; @@ -51,15 +71,15 @@ 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; std::vector Passes; // List of pass's to run @@ -111,40 +131,62 @@ public: 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", 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::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 &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 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::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... @@ -152,14 +194,13 @@ public: for (std::vector::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() @@ -179,7 +220,6 @@ public: } } } -#endif Pass *getAnalysisOrNullDown(AnalysisID ID) const { std::map::const_iterator I = CurrentAnalyses.find(ID); @@ -201,6 +241,20 @@ public: 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 @@ -235,12 +289,13 @@ public: // 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((PassClass*)I->createPass()); } @@ -249,7 +304,7 @@ public: // 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: @@ -262,15 +317,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 &Required, - Pass::AnalysisSet &Destroyed, Pass::AnalysisSet &Provided) { + void addPass(PassClass *P, AnalysisUsage &AnUsage) { + const std::vector &RequiredSet = AnUsage.getRequiredSet(); + const std::vector &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 @@ -283,34 +340,46 @@ private: // 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::iterator I = Required.begin(), - E = Required.end(); I != E; ++I) + 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 in the destroyed set... - for (std::vector::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 &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 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::iterator I = Provided.begin(), - E = Provided.end(); I != E; ++I) + for (std::vector::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. @@ -358,14 +427,23 @@ template<> struct PassManagerTraits : public BasicBlockPass { 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(); + } }; @@ -373,12 +451,12 @@ template<> struct PassManagerTraits : public BasicBlockPass { //===----------------------------------------------------------------------===// // 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; @@ -393,18 +471,27 @@ template<> struct PassManagerTraits : public MethodPass { typedef PassManagerT 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(); + } }; @@ -419,7 +506,7 @@ 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; @@ -433,11 +520,39 @@ template<> struct PassManagerTraits : public Pass { // 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*)this)->runOnUnit(M); + // 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) {} }; @@ -476,8 +591,8 @@ inline bool PassManagerTraits::doInitialization(Module *M) { return Changed; } -inline bool PassManagerTraits::runOnMethod(Function *M) { - return ((PMType*)this)->runOnUnit(M); +inline bool PassManagerTraits::runOnFunction(Function *F) { + return ((PMType*)this)->runOnUnit(F); } inline bool PassManagerTraits::doFinalization(Module *M) {