diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index f43db85cbbd..78cc92a2397 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -29,6 +29,11 @@ class Pass; template class PassManagerT; struct AnalysisResolver; +// PassManager - Top level PassManagerT instantiation intended to be used. +// Implemented in PassManager.h +typedef PassManagerT PassManager; + + //===----------------------------------------------------------------------===// // Pass interface - Implemented by all 'passes'. Subclass this if you are an // interprocedural optimization or you do not fit into any of the more @@ -69,6 +74,19 @@ public: // By default, no analysis results are used or destroyed. } + // releaseMemory() - This member can be implemented by a pass if it wants to + // be able to release its memory when it is no longer needed. The default + // behavior of passes is to hold onto memory for the entire duration of their + // lifetime (which is the entire compile time). For pipelined passes, this + // is not a big deal because that memory gets recycled every time the pass is + // invoked on another program unit. For IP passes, it is more important to + // free memory when it is unused. + // + // Optionally implement this function to release pass memory when it is no + // longer used. + // + virtual void releaseMemory() {} + #ifndef NDEBUG // dumpPassStructure - Implement the -debug-passes=PassStructure option virtual void dumpPassStructure(unsigned Offset = 0); @@ -89,9 +107,8 @@ private: friend class PassManagerT; friend class PassManagerT; friend class PassManagerT; - virtual void addToPassManager(PassManagerT *PM, - AnalysisSet &Destroyed, - AnalysisSet &Provided); + virtual void addToPassManager(PassManagerT *PM, AnalysisSet &Req, + AnalysisSet &Destroyed, AnalysisSet &Provided); }; @@ -132,10 +149,10 @@ private: friend class PassManagerT; friend class PassManagerT; friend class PassManagerT; - virtual void addToPassManager(PassManagerT *PM,AnalysisSet &Destroyed, - AnalysisSet &Provided); - virtual void addToPassManager(PassManagerT *PM,AnalysisSet &Destroyed, - AnalysisSet &Provided); + virtual void addToPassManager(PassManagerT *PM, AnalysisSet &Req, + AnalysisSet &Dest, AnalysisSet &Prov); + virtual void addToPassManager(PassManagerT *PM,AnalysisSet &Req, + AnalysisSet &Dest, AnalysisSet &Prov); }; @@ -169,11 +186,10 @@ struct BasicBlockPass : public MethodPass { private: friend class PassManagerT; friend class PassManagerT; - virtual void addToPassManager(PassManagerT *PM,AnalysisSet &Destroyed, - AnalysisSet &Provided); - virtual void addToPassManager(PassManagerT *PM, - AnalysisSet &Destroyed, - AnalysisSet &Provided); + virtual void addToPassManager(PassManagerT *PM, AnalysisSet &, + AnalysisSet &, AnalysisSet &); + virtual void addToPassManager(PassManagerT *PM, AnalysisSet &, + AnalysisSet &, AnalysisSet &); }; @@ -228,14 +244,16 @@ public: // is used to pull analysis information out of them. // struct AnalysisResolver { - virtual Pass *getAnalysisOrNullUp(AnalysisID ID) = 0; - virtual Pass *getAnalysisOrNullDown(AnalysisID ID) = 0; + virtual Pass *getAnalysisOrNullUp(AnalysisID ID) const = 0; + virtual Pass *getAnalysisOrNullDown(AnalysisID ID) const = 0; Pass *getAnalysis(AnalysisID ID) { Pass *Result = getAnalysisOrNullUp(ID); assert(Result && "Pass has an incorrect analysis uses set!"); return Result; } virtual unsigned getDepth() const = 0; + + virtual void markPassUsed(AnalysisID P, Pass *User) = 0; protected: void setAnalysisResolver(Pass *P, AnalysisResolver *AR); }; diff --git a/lib/VMCore/Pass.cpp b/lib/VMCore/Pass.cpp index a139a25e4d6..c18ff0adcc5 100644 --- a/lib/VMCore/Pass.cpp +++ b/lib/VMCore/Pass.cpp @@ -51,7 +51,7 @@ void PMDebug::PrintPassStructure(Pass *P) { void PMDebug::PrintPassInformation(unsigned Depth, const char *Action, Pass *P, Value *V) { if (PassDebugging >= PassExecutions) { - std::cerr << std::string(Depth*2, ' ') << Action << " '" + std::cerr << (void*)P << std::string(Depth*2+1, ' ') << Action << " '" << typeid(*P).name(); if (V) { std::cerr << "' on "; @@ -71,9 +71,9 @@ void PMDebug::PrintPassInformation(unsigned Depth, const char *Action, } void PMDebug::PrintAnalysisSetInfo(unsigned Depth, const char *Msg, - const Pass::AnalysisSet &Set) { + Pass *P, const Pass::AnalysisSet &Set) { if (PassDebugging >= PassDetails && !Set.empty()) { - std::cerr << std::string(Depth*2+2, ' ') << Msg << " Analyses:"; + std::cerr << (void*)P << std::string(Depth*2+3, ' ') << Msg << " Analyses:"; for (unsigned i = 0; i < Set.size(); ++i) { Pass *P = Set[i].createPass(); // Good thing this is just debug code... std::cerr << " " << typeid(*P).name(); @@ -94,9 +94,9 @@ void Pass::dumpPassStructure(unsigned Offset = 0) { // Pass Implementation // -void Pass::addToPassManager(PassManagerT *PM, AnalysisSet &Destroyed, - AnalysisSet &Provided) { - PM->addPass(this, Destroyed, Provided); +void Pass::addToPassManager(PassManagerT *PM, AnalysisSet &Required, + AnalysisSet &Destroyed, AnalysisSet &Provided) { + PM->addPass(this, Required, Destroyed, Provided); } //===----------------------------------------------------------------------===// @@ -126,15 +126,15 @@ bool MethodPass::run(Method *M) { } void MethodPass::addToPassManager(PassManagerT *PM, - AnalysisSet &Destroyed, + AnalysisSet &Required, AnalysisSet &Destroyed, AnalysisSet &Provided) { - PM->addPass(this, Destroyed, Provided); + PM->addPass(this, Required, Destroyed, Provided); } void MethodPass::addToPassManager(PassManagerT *PM, - AnalysisSet &Destroyed, + AnalysisSet &Required, AnalysisSet &Destroyed, AnalysisSet &Provided) { - PM->addPass(this, Destroyed, Provided); + PM->addPass(this, Required, Destroyed, Provided); } //===----------------------------------------------------------------------===// @@ -160,14 +160,16 @@ bool BasicBlockPass::run(BasicBlock *BB) { } void BasicBlockPass::addToPassManager(PassManagerT *PM, + AnalysisSet &Required, AnalysisSet &Destroyed, AnalysisSet &Provided) { - PM->addPass(this, Destroyed, Provided); + PM->addPass(this, Required, Destroyed, Provided); } void BasicBlockPass::addToPassManager(PassManagerT *PM, + AnalysisSet &Required, AnalysisSet &Destroyed, AnalysisSet &Provided) { - PM->addPass(this, Destroyed, Provided); + PM->addPass(this, Required, Destroyed, Provided); } diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h index 70f2cde66ea..5583b9b9187 100644 --- a/lib/VMCore/PassManagerT.h +++ b/lib/VMCore/PassManagerT.h @@ -15,10 +15,6 @@ #include "llvm/Pass.h" #include -// PassManager - Top level PassManagerT instantiation intended to be used. -typedef PassManagerT PassManager; - - //===----------------------------------------------------------------------===// // PMDebug class - a set of debugging functions that are enabled when compiling // with -g on. If compiling at -O, all functions are inlined noops. @@ -27,7 +23,7 @@ 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*, + 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 @@ -35,7 +31,8 @@ struct PMDebug { // static void PrintPassStructure(Pass *P); static void PrintPassInformation(unsigned,const char*,Pass *, Value *); - static void PrintAnalysisSetInfo(unsigned,const char*,const Pass::AnalysisSet&); + static void PrintAnalysisSetInfo(unsigned,const char*,Pass *P, + const Pass::AnalysisSet&); #endif }; @@ -67,7 +64,7 @@ class PassManagerT : public PassManagerTraits,public AnalysisResolver{ std::vector Passes; // List of pass's to run // 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,6 +75,12 @@ 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() { @@ -94,6 +97,13 @@ public: closeBatcher(); CurrentAnalyses.clear(); + // 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); @@ -107,7 +117,7 @@ public: std::vector Required, Destroyed, Provided; P->getAnalysisUsageInfo(Required, Destroyed, Provided); - PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", Required); + PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", P, Required); #ifndef NDEBUG // All Required analyses should be available to the pass as it runs! @@ -120,8 +130,8 @@ public: // Run the sub pass! MadeChanges |= Traits::runPass(P, M); - PMDebug::PrintAnalysisSetInfo(getDepth(), "Destroyed", Destroyed); - PMDebug::PrintAnalysisSetInfo(getDepth(), "Provided", Provided); + 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(), @@ -132,14 +142,91 @@ public: 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, + (Value*)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() + << " Pass Manager\n"; + for (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 << "Fr" << std::string(Offset*2, ' '); + I->first->dumpPassStructure(0); + } + } + } + } +#endif + + Pass *getAnalysisOrNullDown(AnalysisID 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; + } + + Pass *getAnalysisOrNullUp(AnalysisID 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; + } + + // 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(AnalysisID P, Pass *User) { + std::map::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 + // 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); + } + } + + // Return the number of parent PassManagers that exist + virtual unsigned getDepth() const { + if (Parent == 0) return 0; + return 1 + Parent->getDepth(); + } + // add - Add a pass to the queue of passes to run. This passes 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... @@ -157,43 +244,7 @@ public: // 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, Required, Destroyed, Provided); } private: @@ -208,8 +259,8 @@ private: // add the pass to the end of the pass list and terminate any accumulation of // MethodPasses that are present. // - void addPass(PassClass *P, Pass::AnalysisSet &Destroyed, - Pass::AnalysisSet &Provided) { + void addPass(PassClass *P, Pass::AnalysisSet &Required, + 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... @@ -223,6 +274,14 @@ private: setAnalysisResolver(P, this); Passes.push_back(P); + // 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::iterator I = Required.begin(), + E = Required.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) @@ -232,18 +291,21 @@ private: for (std::vector::iterator I = Provided.begin(), E = Provided.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. // - void addPass(SubPassClass *MP, Pass::AnalysisSet &Destroyed, - Pass::AnalysisSet &Provided) { + void addPass(SubPassClass *MP, Pass::AnalysisSet &Required, + Pass::AnalysisSet &Destroyed, Pass::AnalysisSet &Provided) { 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); + MP->addToPassManager(Batcher, Required, Destroyed, Provided); } // closeBatcher - Terminate the batcher that is being worked on. @@ -291,6 +353,10 @@ template<> struct PassManagerTraits : public BasicBlockPass { return P->runOnBasicBlock(M); } + // getPMName() - Return the name of the unit the PassManager operates on for + // debugging. + const char *getPMName() const { return "BasicBlock"; } + // Implement the BasicBlockPass interface... virtual bool doInitialization(Module *M); virtual bool runOnBasicBlock(BasicBlock *BB); @@ -326,6 +392,10 @@ template<> struct PassManagerTraits : public MethodPass { return P->runOnMethod(M); } + // getPMName() - Return the name of the unit the PassManager operates on for + // debugging. + const char *getPMName() const { return "Method"; } + // Implement the MethodPass interface... virtual bool doInitialization(Module *M); virtual bool runOnMethod(Method *M); @@ -350,11 +420,15 @@ template<> struct PassManagerTraits : public Pass { 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); } + // getPMName() - Return the name of the unit the PassManager operates on for + // debugging. + const char *getPMName() const { return "Module"; } + // run - Implement the Pass interface... virtual bool run(Module *M) { return ((PassManagerT*)this)->runOnUnit(M);