X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FPassManagerT.h;h=123af346561b7d919b57f03edf941a8134136538;hb=27287de06b0a6d3c2713fc3a78281df8f5d1a0fa;hp=4e0d6b24bf30e72f1608122cdb40f973d4ec154d;hpb=789bc8426249c3427e7caa7ba7c3ace4400ab2b0;p=oota-llvm.git diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h index 4e0d6b24bf3..123af346561 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,25 +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; - - 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. @@ -100,27 +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(); + } }; -//===----------------------------------------------------------------------===// -// Forward declarations of global functions defined in Pass.cpp. These are -// defined to be static functions because this header is *ONLY* included by -// Pass.cpp. -// - -// findAnalysisGroupMember - Return an iterator pointing to one of the elements -// of Map if there is a pass in Map that is a member of the analysis group for -// the specified AnalysisGroupID. -// -static std::map::const_iterator -findAnalysisGroupMember(const PassInfo *AnalysisGroupID, - const std::map &Map); - - //===----------------------------------------------------------------------===// // Declare the PassManagerTraits which will be specialized... // @@ -143,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; @@ -171,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 @@ -180,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(), @@ -203,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); @@ -218,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); @@ -226,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; ) @@ -234,22 +260,29 @@ public: 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 + if (!dynamic_cast(I->second)) { + std::map::iterator J = I++; + CurrentAnalyses.erase(J); // Analysis not preserved! + } 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(); @@ -258,12 +291,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 @@ -283,13 +333,7 @@ public: } Pass *getAnalysisOrNullDown(const PassInfo *ID) const { - std::map::const_iterator I; - - if (ID->getPassType() == PassInfo::AnalysisGroup) { - I = findAnalysisGroupMember(ID, CurrentAnalyses); - } else { - I = CurrentAnalyses.find(ID); - } + std::map::const_iterator I = CurrentAnalyses.find(ID); if (I != CurrentAnalyses.end()) return I->second; // Found it. @@ -300,12 +344,7 @@ public: } Pass *getAnalysisOrNullUp(const PassInfo *ID) const { - std::map::const_iterator I; - if (ID->getPassType() == PassInfo::AnalysisGroup) { - I = findAnalysisGroupMember(ID, CurrentAnalyses); - } else { - I = CurrentAnalyses.find(ID); - } + std::map::const_iterator I = CurrentAnalyses.find(ID); if (I != CurrentAnalyses.end()) return I->second; // Found it. @@ -314,7 +353,7 @@ public: 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. @@ -334,27 +373,25 @@ public: // them... // void markPassUsed(const PassInfo *P, Pass *User) { - std::map::const_iterator I; - - if (P->getPassType() == PassInfo::AnalysisGroup) { - I = findAnalysisGroupMember(P, CurrentAnalyses); - } else { - I = CurrentAnalyses.find(P); - } + 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!"); - 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; @@ -430,27 +467,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; } @@ -473,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; + } + } }; @@ -522,7 +618,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 { @@ -654,10 +752,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)