Call doInitialization(), releaseMemory(), and doFinalization() for on-the-fly passes as well.
Also don't call finalizers for LoopPass if initialization was not called.
Add a unittest that tests that these methods are called, in the proper
order, and the correct number of times.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74438 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/LoopPass.cpp b/lib/Analysis/LoopPass.cpp
index 08c25f4..ee03556 100644
--- a/lib/Analysis/LoopPass.cpp
+++ b/lib/Analysis/LoopPass.cpp
@@ -195,6 +195,9 @@
   for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I)
     addLoopIntoQueue(*I, LQ);
 
+  if (LQ.empty()) // No loops, skip calling finalizers
+    return false;
+
   // Initialization
   for (std::deque<Loop *>::const_iterator I = LQ.begin(), E = LQ.end();
        I != E; ++I) {
diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp
index 86cf10e..24fb35c 100644
--- a/lib/VMCore/PassManager.cpp
+++ b/lib/VMCore/PassManager.cpp
@@ -165,11 +165,13 @@
 class FunctionPassManagerImpl : public Pass,
                                 public PMDataManager,
                                 public PMTopLevelManager {
+private:
+  bool wasRun;
 public:
   static char ID;
   explicit FunctionPassManagerImpl(int Depth) : 
     Pass(&ID), PMDataManager(Depth), 
-    PMTopLevelManager(TLM_Function) { }
+    PMTopLevelManager(TLM_Function), wasRun(false) { }
 
   /// 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
@@ -179,6 +181,10 @@
     schedulePass(P);
   }
  
+  // Prepare for running an on the fly pass, freeing memory if needed
+  // from a previous run.
+  void releaseMemoryOnTheFly();
+
   /// run - Execute all of the passes scheduled for execution.  Keep track of
   /// whether any of the passes modifies the module, and if so, return true.
   bool run(Function &F);
@@ -1290,6 +1296,17 @@
  }
 }
 
+void FunctionPassManagerImpl::releaseMemoryOnTheFly() {
+  if (!wasRun)
+    return;
+  for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
+    FPPassManager *FPPM = getContainedManager(Index);
+    for (unsigned Index = 0; Index < FPPM->getNumContainedPasses(); ++Index) {
+      FPPM->getContainedPass(Index)->releaseMemory();
+    }
+  }
+}
+
 // Execute all the passes managed by this top level manager.
 // Return true if any function is modified by a pass.
 bool FunctionPassManagerImpl::run(Function &F) {
@@ -1306,6 +1323,7 @@
   for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
     getContainedManager(Index)->cleanup();
 
+  wasRun = true;
   return Changed;
 }
 
@@ -1404,6 +1422,14 @@
 MPPassManager::runOnModule(Module &M) {
   bool Changed = false;
 
+  // Initialize on-the-fly passes
+  for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
+       I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
+       I != E; ++I) {
+    FunctionPassManagerImpl *FPP = I->second;
+    Changed |= FPP->doInitialization(M);
+  }
+
   for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
     ModulePass *MP = getContainedPass(Index);
 
@@ -1430,6 +1456,17 @@
     recordAvailableAnalysis(MP);
     removeDeadPasses(MP, M.getModuleIdentifier().c_str(), ON_MODULE_MSG);
   }
+
+  // Finalize on-the-fly passes
+  for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
+       I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
+       I != E; ++I) {
+    FunctionPassManagerImpl *FPP = I->second;
+    // We don't know when is the last time an on-the-fly pass is run,
+    // so we need to releaseMemory / finalize here
+    FPP->releaseMemoryOnTheFly();
+    Changed |= FPP->doFinalization(M);
+  }
   return Changed;
 }
 
@@ -1466,6 +1503,7 @@
   FunctionPassManagerImpl *FPP = OnTheFlyManagers[MP];
   assert(FPP && "Unable to find on the fly pass");
   
+  FPP->releaseMemoryOnTheFly();
   FPP->run(F);
   return (dynamic_cast<PMTopLevelManager *>(FPP))->findAnalysisPass(PI);
 }