* Make debugging output nicer
authorChris Lattner <sabre@nondot.org>
Thu, 31 Jan 2002 18:32:27 +0000 (18:32 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 31 Jan 2002 18:32:27 +0000 (18:32 +0000)
* 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

include/llvm/Pass.h
lib/VMCore/Pass.cpp
lib/VMCore/PassManagerT.h

index f43db85cbbd4dfd681e4f2dad34fad5f27f4789e..78cc92a2397cb9b4917bbfe7c58bc41d40e838f9 100644 (file)
@@ -29,6 +29,11 @@ class Pass;
 template<class UnitType> class PassManagerT;
 struct AnalysisResolver;
 
+// PassManager - Top level PassManagerT instantiation intended to be used.
+// Implemented in PassManager.h
+typedef PassManagerT<Module> 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<Module>;
   friend class PassManagerT<Method>;
   friend class PassManagerT<BasicBlock>;
-  virtual void addToPassManager(PassManagerT<Module> *PM,
-                                AnalysisSet &Destroyed,
-                                AnalysisSet &Provided);
+  virtual void addToPassManager(PassManagerT<Module> *PM, AnalysisSet &Req,
+                                AnalysisSet &Destroyed, AnalysisSet &Provided);
 };
 
 
@@ -132,10 +149,10 @@ private:
   friend class PassManagerT<Module>;
   friend class PassManagerT<Method>;
   friend class PassManagerT<BasicBlock>;
-  virtual void addToPassManager(PassManagerT<Module> *PM,AnalysisSet &Destroyed,
-                                AnalysisSet &Provided);
-  virtual void addToPassManager(PassManagerT<Method> *PM,AnalysisSet &Destroyed,
-                                AnalysisSet &Provided);
+  virtual void addToPassManager(PassManagerT<Module> *PM, AnalysisSet &Req,
+                                AnalysisSet &Dest, AnalysisSet &Prov);
+  virtual void addToPassManager(PassManagerT<Method> *PM,AnalysisSet &Req,
+                                AnalysisSet &Dest, AnalysisSet &Prov);
 };
 
 
@@ -169,11 +186,10 @@ struct BasicBlockPass : public MethodPass {
 private:
   friend class PassManagerT<Method>;
   friend class PassManagerT<BasicBlock>;
-  virtual void addToPassManager(PassManagerT<Method> *PM,AnalysisSet &Destroyed,
-                                AnalysisSet &Provided);
-  virtual void addToPassManager(PassManagerT<BasicBlock> *PM,
-                                AnalysisSet &Destroyed,
-                                AnalysisSet &Provided);
+  virtual void addToPassManager(PassManagerT<Method> *PM, AnalysisSet &,
+                                AnalysisSet &, AnalysisSet &);
+  virtual void addToPassManager(PassManagerT<BasicBlock> *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);
 };
index a139a25e4d6fa7ca1ef7ea2ee5d0e955eb9a8e4b..c18ff0adcc5a48fc760961fa175bd95e9cb663cc 100644 (file)
@@ -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<Module> *PM, AnalysisSet &Destroyed,
-                            AnalysisSet &Provided) {
-  PM->addPass(this, Destroyed, Provided);
+void Pass::addToPassManager(PassManagerT<Module> *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<Module> *PM,
-                                  AnalysisSet &Destroyed,
+                                  AnalysisSet &Required, AnalysisSet &Destroyed,
                                   AnalysisSet &Provided) {
-  PM->addPass(this, Destroyed, Provided);
+  PM->addPass(this, Required, Destroyed, Provided);
 }
 
 void MethodPass::addToPassManager(PassManagerT<Method> *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<Method> *PM,
+                                      AnalysisSet &Required,
                                       AnalysisSet &Destroyed,
                                       AnalysisSet &Provided) {
-  PM->addPass(this, Destroyed, Provided);
+  PM->addPass(this, Required, Destroyed, Provided);
 }
 
 void BasicBlockPass::addToPassManager(PassManagerT<BasicBlock> *PM,
+                                      AnalysisSet &Required,
                                       AnalysisSet &Destroyed,
                                       AnalysisSet &Provided) {
-  PM->addPass(this, Destroyed, Provided);
+  PM->addPass(this, Required, Destroyed, Provided);
 }
 
index 70f2cde66ea2707f394ed5438e01b9576ac48db6..5583b9b9187f27ca2176368982b95fbb714fe15f 100644 (file)
 #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);