X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FPassManagerT.h;h=4a2ad8867146d875df239874481e2f44dfea4fda;hb=a98bde53a7eb13e02c1dc707dae58aa21fd7ea2c;hp=c72af14ce2fb1e51e67d8351b41019778dd3039b;hpb=96c466b06ab0c830b07329c1b16037f585ccbe40;p=oota-llvm.git diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h index c72af14ce2f..4a2ad886714 100644 --- a/lib/VMCore/PassManagerT.h +++ b/lib/VMCore/PassManagerT.h @@ -16,19 +16,54 @@ #define LLVM_PASSMANAGER_T_H #include "llvm/Pass.h" -#include +#include "Support/CommandLine.h" +#include "Support/LeakDetector.h" #include +#include class Annotable; +//===----------------------------------------------------------------------===// +// 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 not to be // instantiated by the template. // struct PMDebug { - // 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 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 &); @@ -40,8 +75,24 @@ struct PMDebug { // amount of time each pass takes to execute. This only happens when // -time-passes is enabled on the command line. // +struct TimeRecord { // TimeRecord - Data we collect and print for each pass + double Elapsed; // Wall clock time elapsed in seconds + double UserTime; // User time elapsed + double SystemTime; // System time elapsed + unsigned long MaxRSS; // Maximum resident set size (in bytes) + unsigned long RSSTemp; // Temp for calculating maxrss + + TimeRecord() : Elapsed(0), UserTime(0), SystemTime(0), MaxRSS(0) {} + void passStart(const TimeRecord &T); + void passEnd(const TimeRecord &T); + void sum(const TimeRecord &TR); + bool operator<(const TimeRecord &TR) const; + + void print(const char *PassName, const TimeRecord &TotalTime) const; +}; + class TimingInfo { - std::map TimingData; + std::map TimingData; TimingInfo() {} // Private ctor, must use create member public: // Create method. If Timing is enabled, this creates and returns a new timing @@ -56,8 +107,6 @@ public: void passEnded(Pass *P); }; - - //===----------------------------------------------------------------------===// // Declare the PassManagerTraits which will be specialized... // @@ -81,7 +130,7 @@ class PassManagerT : public PassManagerTraits,public AnalysisResolver{ friend typename Traits::SubPassClass; friend class Traits; - std::vector Passes; // List of pass's to run + std::vector Passes; // List of passes to run // The parent of this pass manager... ParentClass * const Parent; @@ -105,8 +154,8 @@ 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; } @@ -125,7 +174,7 @@ public: // 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) { @@ -140,14 +189,28 @@ public: PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", P, AnUsage.getRequiredSet()); -#ifndef NDEBUG - // All Required analyses should be available to the pass as it runs! - for (vector::const_iterator + // 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) { - assert(getAnalysisOrNullUp(*I) && "Analysis used but not available!"); + 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! startPass(P); @@ -155,13 +218,15 @@ public: 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()); - PMDebug::PrintAnalysisSetInfo(getDepth(), "Provided", P, - AnUsage.getProvidedSet()); // Erase all analyses not in the preserved set... @@ -183,11 +248,19 @@ public: } } - // Add all analyses in the provided set... - for (std::vector::const_iterator - I = AnUsage.getProvidedSet().begin(), - E = AnUsage.getProvidedSet().end(); I != E; ++I) - CurrentAnalyses[*I] = P; + // 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; + } // Free memory for any passes that we are the last use of... std::vector &DeadPass = LastUserOf[P]; @@ -205,8 +278,8 @@ public: virtual void dumpPassStructure(unsigned Offset = 0) { std::cerr << std::string(Offset*2, ' ') << Traits::getPMName() << " Pass Manager\n"; - 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) { PassClass *P = *I; P->dumpPassStructure(Offset+1); @@ -214,31 +287,32 @@ public: for (std::map::iterator I = LastUseOf.begin(), E = LastUseOf.end(); I != E; ++I) { if (P == I->second) { - std::cerr << "Fr" << std::string(Offset*2, ' '); + std::cerr << "--" << std::string(Offset*2, ' '); I->first->dumpPassStructure(0); } } } } - Pass *getAnalysisOrNullDown(AnalysisID ID) const { + Pass *getAnalysisOrNullDown(const PassInfo *ID) const { std::map::const_iterator I = CurrentAnalyses.find(ID); - if (I == CurrentAnalyses.end()) { - if (Batcher) - return ((AnalysisResolver*)Batcher)->getAnalysisOrNullDown(ID); - return 0; - } - return I->second; + + if (I != CurrentAnalyses.end()) + return I->second; // Found it. + + if (Batcher) + return ((AnalysisResolver*)Batcher)->getAnalysisOrNullDown(ID); + return 0; } - Pass *getAnalysisOrNullUp(AnalysisID ID) const { + Pass *getAnalysisOrNullUp(const PassInfo *ID) const { std::map::const_iterator I = CurrentAnalyses.find(ID); - if (I == CurrentAnalyses.end()) { - if (Parent) - return Parent->getAnalysisOrNullUp(ID); - return 0; - } - return I->second; + 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 propogates @@ -260,8 +334,9 @@ public: // make sure that analyses are not free'd before we have to use // them... // - void markPassUsed(AnalysisID P, Pass *User) { - std::map::iterator I = CurrentAnalyses.find(P); + 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 { @@ -270,8 +345,7 @@ public: // parent that we (the passmanager) are using the analysis so that it // frees the analysis AFTER this pass manager runs. // - assert(Parent != 0 && "Pass available but not found! " - "Did your analysis pass 'Provide' itself?"); + assert(Parent != 0 && "Pass available but not found!"); Parent->markPassUsed(P, this); } } @@ -282,7 +356,13 @@ public: return 1 + Parent->getDepth(); } - // add - Add a pass to the queue of passes to run. This passes ownership of + 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. @@ -297,7 +377,7 @@ public: for (std::vector::const_iterator I = Required.begin(), E = Required.end(); I != E; ++I) { if (getAnalysisOrNullDown(*I) == 0) - add((PassClass*)I->createPass()); + add((PassClass*)(*I)->createPass()); } // Tell the pass to add itself to this PassManager... the way it does so @@ -321,13 +401,13 @@ private: // 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... + // 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 && ProvidedSet.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 @@ -362,10 +442,17 @@ private: } } - // Add all analyses in the provided set... - for (std::vector::const_iterator I = ProvidedSet.begin(), - E = ProvidedSet.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; @@ -378,7 +465,7 @@ private: 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 + // The Batcher will queue the passes up MP->addToPassManager(Batcher, AnUsage); } @@ -424,7 +511,7 @@ template<> struct PassManagerTraits : public BasicBlockPass { // 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); } // Dummy implementation of PassStarted/PassEnded @@ -437,9 +524,13 @@ template<> struct PassManagerTraits : public BasicBlockPass { 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 bool doInitialization(Module &M); + virtual bool runOnBasicBlock(BasicBlock &BB); + virtual bool doFinalization(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } }; @@ -468,7 +559,7 @@ template<> struct PassManagerTraits : public FunctionPass { // runPass - Specify how the pass should be run on the UnitType static bool runPass(PassClass *P, Function *F) { - return P->runOnFunction(F); + return P->runOnFunction(*F); } // Dummy implementation of PassStarted/PassEnded @@ -481,9 +572,13 @@ template<> struct PassManagerTraits : public FunctionPass { 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 bool doInitialization(Module &M); + virtual bool runOnFunction(Function &F); + virtual bool doFinalization(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } }; @@ -507,7 +602,7 @@ template<> struct PassManagerTraits : public Pass { 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. @@ -531,9 +626,9 @@ template<> struct PassManagerTraits : public Pass { } // run - Implement the PassManager interface... - bool run(Module *M) { + bool run(Module &M) { TimeInfo = TimingInfo::create(); - bool Result = ((PassManagerT*)this)->runOnUnit(M); + bool Result = ((PassManagerT*)this)->runOnUnit(&M); if (TimeInfo) { delete TimeInfo; TimeInfo = 0; @@ -555,18 +650,18 @@ template<> struct PassManagerTraits : public Pass { // PassManagerTraits Implementations // -inline bool PassManagerTraits::doInitialization(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::runOnBasicBlock(BasicBlock *BB) { - return ((PMType*)this)->runOnUnit(BB); +inline bool PassManagerTraits::runOnBasicBlock(BasicBlock &BB) { + return ((PMType*)this)->runOnUnit(&BB); } -inline bool PassManagerTraits::doFinalization(Module *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); @@ -576,18 +671,18 @@ inline bool PassManagerTraits::doFinalization(Module *M) { // PassManagerTraits Implementations // -inline bool PassManagerTraits::doInitialization(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::runOnFunction(Function &F) { + return ((PMType*)this)->runOnUnit(&F); } -inline bool PassManagerTraits::doFinalization(Module *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);