diff options
author | Chris Lattner <sabre@nondot.org> | 2002-01-31 18:32:27 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2002-01-31 18:32:27 +0000 |
commit | ce885e9f9d03fa1d9dd5e2abba5e95953473288f (patch) | |
tree | 23f71ede10e58de91bfd5cdbe46ade545aef86cd /lib/VMCore/PassManagerT.h | |
parent | 65b97090710df5c3fc70752eeff23de5cf4d1532 (diff) | |
download | external_llvm-ce885e9f9d03fa1d9dd5e2abba5e95953473288f.zip external_llvm-ce885e9f9d03fa1d9dd5e2abba5e95953473288f.tar.gz external_llvm-ce885e9f9d03fa1d9dd5e2abba5e95953473288f.tar.bz2 |
* Make debugging output nicer
* Implement pass memory freeing after the pass is unused
* Expose PassManager typedef in Pass.h instead of PassManager.h
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1617 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore/PassManagerT.h')
-rw-r--r-- | lib/VMCore/PassManagerT.h | 174 |
1 files changed, 124 insertions, 50 deletions
diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h index 70f2cde..5583b9b 100644 --- a/lib/VMCore/PassManagerT.h +++ b/lib/VMCore/PassManagerT.h @@ -15,10 +15,6 @@ #include "llvm/Pass.h" #include <string> -// PassManager - Top level PassManagerT instantiation intended to be used. -typedef PassManagerT<Module> 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<UnitType>,public AnalysisResolver{ std::vector<PassClass*> 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<UnitType>,public AnalysisResolver{ // std::map<AnalysisID, Pass*> 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<Pass*, Pass*> 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<Pass *, std::vector<Pass*> > LastUserOf; + for (std::map<Pass*, Pass*>::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<AnalysisID> 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,47 +142,43 @@ public: for (Pass::AnalysisSet::iterator I = Provided.begin(), E = Provided.end(); I != E; ++I) CurrentAnalyses[*I] = P; - } - return MadeChanges; - } - - // 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. - // - void add(PassClass *P) { - // Get information about what analyses the pass uses... - std::vector<AnalysisID> Required, Destroyed, Provided; - P->getAnalysisUsageInfo(Required, Destroyed, Provided); - // Loop over all of the analyses used by this pass, - for (std::vector<AnalysisID>::iterator I = Required.begin(), - E = Required.end(); I != E; ++I) { - if (getAnalysisOrNullDown(*I) == 0) - add((PassClass*)I->createPass()); + // Free memory for any passes that we are the last use of... + std::vector<Pass*> &DeadPass = LastUserOf[P]; + for (std::vector<Pass*>::iterator I = DeadPass.begin(),E = DeadPass.end(); + I != E; ++I) { + PMDebug::PrintPassInformation(getDepth()+1, "Freeing Pass", *I, + (Value*)M); + (*I)->releaseMemory(); + } } - - // Tell the pass to add itself to this PassManager... the way it does so - // depends on the class of the pass, and is critical to laying out passes in - // an optimal order.. - // - P->addToPassManager(this, Destroyed, Provided); + return MadeChanges; } #ifndef NDEBUG // dumpPassStructure - Implement the -debug-passes=PassStructure option virtual void dumpPassStructure(unsigned Offset = 0) { - std::cerr << std::string(Offset*2, ' ') << "Pass Manager\n"; + std::cerr << std::string(Offset*2, ' ') << Traits::getPMName() + << " Pass Manager\n"; for (std::vector<PassClass*>::iterator I = Passes.begin(), E = Passes.end(); - I != E; ++I) - (*I)->dumpPassStructure(Offset+1); + I != E; ++I) { + PassClass *P = *I; + P->dumpPassStructure(Offset+1); + + // Loop through and see which classes are destroyed after this one... + for (std::map<Pass*, Pass*>::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 -public: - Pass *getAnalysisOrNullDown(AnalysisID ID) { - std::map<AnalysisID, Pass*>::iterator I = CurrentAnalyses.find(ID); + Pass *getAnalysisOrNullDown(AnalysisID ID) const { + std::map<AnalysisID, Pass*>::const_iterator I = CurrentAnalyses.find(ID); if (I == CurrentAnalyses.end()) { if (Batcher) return ((AnalysisResolver*)Batcher)->getAnalysisOrNullDown(ID); @@ -181,19 +187,64 @@ public: return I->second; } - Pass *getAnalysisOrNullUp(AnalysisID ID) { - std::map<AnalysisID, Pass*>::iterator I = CurrentAnalyses.find(ID); + Pass *getAnalysisOrNullUp(AnalysisID ID) const { + std::map<AnalysisID, Pass*>::const_iterator I = CurrentAnalyses.find(ID); if (I == CurrentAnalyses.end()) { if (Parent) - return ((AnalysisResolver*)Parent)->getAnalysisOrNullUp(ID); + 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<AnalysisID, Pass*>::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 + ((AnalysisResolver*)Parent)->getDepth(); + 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. This + // implies that all passes MUST be new'd. + // + void add(PassClass *P) { + // Get information about what analyses the pass uses... + std::vector<AnalysisID> Required, Destroyed, Provided; + P->getAnalysisUsageInfo(Required, Destroyed, Provided); + + // Loop over all of the analyses used by this pass, + for (std::vector<AnalysisID>::iterator I = Required.begin(), + E = Required.end(); I != E; ++I) { + if (getAnalysisOrNullDown(*I) == 0) + add((PassClass*)I->createPass()); + } + + // Tell the pass to add itself to this PassManager... the way it does so + // depends on the class of the pass, and is critical to laying out passes in + // an optimal order.. + // + 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<AnalysisID>::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<AnalysisID>::iterator I = Destroyed.begin(), E = Destroyed.end(); I != E; ++I) @@ -232,18 +291,21 @@ private: for (std::vector<AnalysisID>::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<BasicBlock> : 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<Method> : 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<Module> : public Pass { typedef PassManagerT<Method> 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<Module>*)this)->runOnUnit(M); |