X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FPassManagerT.h;h=53ce19f2e1f1fd15e402b68e6c29b7805a9617c2;hb=2fe6626eade0f21654b710023eec769f4dba6dc9;hp=83061deac16a2cc306b6153bfef3b06ea68760cd;hpb=ca0a1f7d49e8b9a517959a3211bfc79a0fca7acd;p=oota-llvm.git diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h index 83061deac16..53ce19f2e1f 100644 --- a/lib/VMCore/PassManagerT.h +++ b/lib/VMCore/PassManagerT.h @@ -17,6 +17,8 @@ #include "llvm/Pass.h" #include "Support/CommandLine.h" +#include "Support/LeakDetector.h" +#include "Support/Timer.h" #include #include class Annotable; @@ -74,27 +76,13 @@ 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 { - return UserTime+SystemTime < TR.UserTime+TR.SystemTime; - } - - void print(const char *PassName, const TimeRecord &TotalTime) const; -}; class TimingInfo { - std::map TimingData; - TimingInfo() {} // Private ctor, must use create member + 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. @@ -102,14 +90,27 @@ public: static TimingInfo *create(); // TimingDtor - Print out information about timing information - ~TimingInfo(); + ~TimingInfo() { + // Delete all of the timers... + TimingData.clear(); + // TimerGroup is deleted next, printing the report. + } - void passStarted(Pass *P); - void passEnded(Pass *P); + 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... // @@ -132,8 +133,10 @@ class PassManagerT : public PassManagerTraits,public AnalysisResolver{ friend typename Traits::PassClass; friend typename Traits::SubPassClass; friend class Traits; + friend class ImmutablePass; std::vector Passes; // List of passes to run + std::vector ImmutablePasses; // List of immutable passes // The parent of this pass manager... ParentClass * const Parent; @@ -160,6 +163,10 @@ public: 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; } // run - Run all of the queued passes on the specified module in an optimal @@ -169,6 +176,18 @@ 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(), @@ -192,14 +211,28 @@ public: PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", P, AnUsage.getRequiredSet()); -#ifndef NDEBUG - // All Required analyses should be available to the pass as it runs! - for (std::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); @@ -207,6 +240,10 @@ 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); @@ -215,7 +252,7 @@ public: // Erase all analyses not in the preserved set... - if (!AnUsage.preservesAll()) { + if (!AnUsage.getPreservesAll()) { const std::vector &PreservedSet = AnUsage.getPreservedSet(); for (std::map::iterator I = CurrentAnalyses.begin(), E = CurrentAnalyses.end(); I != E; ) @@ -223,22 +260,34 @@ public: PreservedSet.end()) ++I; // This analysis is preserved, leave it in the available set... else { + if (!dynamic_cast(I->second)) { #if MAP_DOESNT_HAVE_BROKEN_ERASE_MEMBER - I = CurrentAnalyses.erase(I); // Analysis not preserved! + 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(); + // GCC 2.95.3 STL doesn't have correct erase member! + CurrentAnalyses.erase(I); + I = CurrentAnalyses.begin(); #endif + } else { + ++I; + } } } // 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()) + 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]; for (std::vector::iterator I = DeadPass.begin(),E = DeadPass.end(); @@ -247,12 +296,29 @@ public: (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; } // 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 @@ -271,27 +337,28 @@ public: } } - 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 + // {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. @@ -310,22 +377,26 @@ 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 { // Pass not in current available set, must be a higher level pass - // available to us, propogate to parent pass manager... We tell the + // 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. // - assert(Parent != 0 && "Pass available but not found! " - "Did your analysis pass 'Provide' itself?"); - Parent->markPassUsed(P, this); + 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; @@ -338,7 +409,7 @@ public: return Passes[N]; } - // add - Add a pass to the queue of passes to run. This passes ownership of + // 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. @@ -401,27 +472,32 @@ private: markPassUsed(*I, P); // Mark *I as used by P // Erase all analyses not in the preserved set... - if (!AnUsage.preservesAll()) { + 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 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! + 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(); -#endif + } else { + ++I; } + } } // Add this pass to the currently available set... - if (const PassInfo *PI = P->getPassInfo()) + 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; } @@ -444,6 +520,34 @@ 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); + + // 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; + } + } }; @@ -493,7 +597,9 @@ template<> struct PassManagerTraits : public BasicBlockPass { // 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 { @@ -625,10 +731,24 @@ inline bool PassManagerTraits::doInitialization(Module &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; +} + 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]->doFinalization(F); + return Changed; +} + inline bool PassManagerTraits::doFinalization(Module &M) { bool Changed = false; for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i)