another typo
[oota-llvm.git] / include / llvm / Support / PassManagerBuilder.h
index c684f096111831a75869dba22bca563a87b34c90..0d690cfe29789a5fb28a5f88513fcf4a416bf850 100644 (file)
@@ -1,4 +1,4 @@
-//===-- llvm/Support/PasaMangerBuilder.h - Build Standard Pass --*- C++ -*-===//
+//===-- llvm/Support/PassManagerBuilder.h - Build Standard Pass -*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -37,53 +37,92 @@ namespace llvm {
 ///  Builder.populateFunctionPassManager(FPM);
 ///  Builder.populateModulePassManager(MPM);
 ///
+/// In addition to setting up the basic passes, PassManagerBuilder allows
+/// frontends to vend a plugin API, where plugins are allowed to add extensions
+/// to the default pass manager.  They do this by specifying where in the pass
+/// pipeline they want to be added, along with a callback function that adds
+/// the pass(es).  For example, a plugin that wanted to add a loop optimization
+/// could do something like this:
+///
+/// static void addMyLoopPass(const PMBuilder &Builder, PassManagerBase &PM) {
+///   if (Builder.getOptLevel() > 2 && Builder.getOptSizeLevel() == 0)
+///     PM.add(createMyAwesomePass());
+/// }
+///   ...
+///   Builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd,
+///                        addMyLoopPass);
+///   ...
 class PassManagerBuilder {
-  unsigned OptLevel;   // 0 = -O0, 1 = -O1, 2 = -O2, 3 = -O3
-  unsigned SizeLevel;  // 0 = none, 1 = -Os, 2 = -Oz
-  TargetLibraryInfo *TLI;
-  Pass *InlinerPass;
+public:
+  
+  /// Extensions are passed the builder itself (so they can see how it is
+  /// configured) as well as the pass manager to add stuff to.
+  typedef void (*ExtensionFn)(const PassManagerBuilder &Builder,
+                              PassManagerBase &PM);
+  enum ExtensionPointTy {
+    /// EP_EarlyAsPossible - This extension point allows adding passes before
+    /// any other transformations, allowing them to see the code as it is coming
+    /// out of the frontend.
+    EP_EarlyAsPossible,
+    
+    /// EP_LoopOptimizerEnd - This extension point allows adding loop passes to
+    /// the end of the loop optimizer.
+    EP_LoopOptimizerEnd
+  };
+  
+  /// The Optimization Level - Specify the basic optimization level.
+  ///    0 = -O0, 1 = -O1, 2 = -O2, 3 = -O3
+  unsigned OptLevel;
+  
+  /// SizeLevel - How much we're optimizing for size.
+  ///    0 = none, 1 = -Os, 2 = -Oz
+  unsigned SizeLevel;
+  
+  /// LibraryInfo - Specifies information about the runtime library for the
+  /// optimizer.  If this is non-null, it is added to both the function and
+  /// per-module pass pipeline.
+  TargetLibraryInfo *LibraryInfo;
+  
+  /// Inliner - Specifies the inliner to use.  If this is non-null, it is
+  /// added to the per-module passes.
+  Pass *Inliner;
   
   bool DisableSimplifyLibCalls;
   bool DisableUnitAtATime;
   bool DisableUnrollLoops;
+  
+private:
+  /// ExtensionList - This is list of all of the extensions that are registered.
+  std::vector<std::pair<ExtensionPointTy, ExtensionFn> > Extensions;
+  
 public:
   PassManagerBuilder() {
     OptLevel = 2;
     SizeLevel = 0;
-    TLI = 0;
-    InlinerPass = 0;
+    LibraryInfo = 0;
+    Inliner = 0;
     DisableSimplifyLibCalls = false;
     DisableUnitAtATime = false;
     DisableUnrollLoops = false;
   }
   
   ~PassManagerBuilder() {
-    delete TLI;
-    delete InlinerPass;
+    delete LibraryInfo;
+    delete Inliner;
   }
   
-  /// setOptimizationLevel - Specify the basic optimization level -O0 ... -O3.
-  void setOptimizationLevel(unsigned L) { OptLevel = L; }
-
-  /// setSizeLevel - Specify the size optimization level: none, -Os, -Oz.
-  void setSizeLevel(unsigned L) { SizeLevel = L; }
-
-  /// setLibraryInfo - Set information about the runtime library for the
-  /// optimizer.  If this is specified, it is added to both the function and
-  /// per-module pass pipeline.
-  void setLibraryInfo(TargetLibraryInfo *LI) { TLI = LI; }
-  
-  /// setInliner - Specify the inliner to use.  If this is specified, it is
-  /// added to the per-module passes.
-  void setInliner(Pass *P) { InlinerPass = P; }
-  
-  
-  void disableSimplifyLibCalls() { DisableSimplifyLibCalls = true; }
-  void disableUnitAtATime() { DisableUnitAtATime = true; }
-  void disableUnrollLoops() { DisableUnrollLoops = true; }
+  void addExtension(ExtensionPointTy Ty, ExtensionFn Fn) {
+    Extensions.push_back(std::make_pair(Ty, Fn));
+  }
   
 private:
-  void addInitialAliasAnalysisPasses(PassManagerBase &PM) {
+  void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const {
+    for (unsigned i = 0, e = Extensions.size(); i != e; ++i)
+      if (Extensions[i].first == ETy)
+        Extensions[i].second(*this, PM);
+  }
+  
+  void addInitialAliasAnalysisPasses(PassManagerBase &PM) const {
     // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
     // BasicAliasAnalysis wins if they disagree. This is intended to help
     // support "obvious" type-punning idioms.
@@ -96,11 +135,13 @@ public:
   /// which is expected to be run on each function immediately as it is
   /// generated.  The idea is to reduce the size of the IR in memory.
   void populateFunctionPassManager(FunctionPassManager &FPM) {
-    if (OptLevel == 0) return;
-    
-    // Add TLI if we have some.
-    if (TLI) FPM.add(new TargetLibraryInfo(*TLI));
+    addExtensionsToPM(EP_EarlyAsPossible, FPM);
     
+    // Add LibraryInfo if we have some.
+    if (LibraryInfo) FPM.add(new TargetLibraryInfo(*LibraryInfo));
+
+    if (OptLevel == 0) return;
+
     addInitialAliasAnalysisPasses(FPM);
     
     FPM.add(createCFGSimplificationPass());
@@ -112,15 +153,15 @@ public:
   void populateModulePassManager(PassManagerBase &MPM) {
     // If all optimizations are disabled, just run the always-inline pass.
     if (OptLevel == 0) {
-      if (InlinerPass) {
-        MPM.add(InlinerPass);
-        InlinerPass = 0;
+      if (Inliner) {
+        MPM.add(Inliner);
+        Inliner = 0;
       }
       return;
     }
       
-    // Add TLI if we have some.
-    if (TLI) MPM.add(new TargetLibraryInfo(*TLI));
+    // Add LibraryInfo if we have some.
+    if (LibraryInfo) MPM.add(new TargetLibraryInfo(*LibraryInfo));
 
     addInitialAliasAnalysisPasses(MPM);
     
@@ -137,9 +178,9 @@ public:
     // Start of CallGraph SCC passes.
     if (!DisableUnitAtATime)
       MPM.add(createPruneEHPass());             // Remove dead EH info
-    if (InlinerPass) {
-      MPM.add(InlinerPass);
-      InlinerPass = 0;
+    if (Inliner) {
+      MPM.add(Inliner);
+      Inliner = 0;
     }
     if (!DisableUnitAtATime)
       MPM.add(createFunctionAttrsPass());       // Set readonly/readnone attrs
@@ -169,6 +210,8 @@ public:
     MPM.add(createLoopDeletionPass());          // Delete dead loops
     if (!DisableUnrollLoops)
       MPM.add(createLoopUnrollPass());          // Unroll small loops
+    addExtensionsToPM(EP_LoopOptimizerEnd, MPM);
+
     if (OptLevel > 1)
       MPM.add(createGVNPass());                 // Remove redundancies
     MPM.add(createMemCpyOptPass());             // Remove memcpy / form memset
@@ -197,6 +240,81 @@ public:
         MPM.add(createConstantMergePass());     // Merge dup global constants
     }
   }
+  
+  void populateLTOPassManager(PassManagerBase &PM, bool Internalize,
+                              bool RunInliner) {
+    // Provide AliasAnalysis services for optimizations.
+    addInitialAliasAnalysisPasses(PM);
+    
+    // Now that composite has been compiled, scan through the module, looking
+    // for a main function.  If main is defined, mark all other functions
+    // internal.
+    if (Internalize)
+      PM.add(createInternalizePass(true));
+    
+    // Propagate constants at call sites into the functions they call.  This
+    // opens opportunities for globalopt (and inlining) by substituting function
+    // pointers passed as arguments to direct uses of functions.  
+    PM.add(createIPSCCPPass());
+    
+    // Now that we internalized some globals, see if we can hack on them!
+    PM.add(createGlobalOptimizerPass());
+    
+    // Linking modules together can lead to duplicated global constants, only
+    // keep one copy of each constant.
+    PM.add(createConstantMergePass());
+    
+    // Remove unused arguments from functions.
+    PM.add(createDeadArgEliminationPass());
+    
+    // Reduce the code after globalopt and ipsccp.  Both can open up significant
+    // simplification opportunities, and both can propagate functions through
+    // function pointers.  When this happens, we often have to resolve varargs
+    // calls, etc, so let instcombine do this.
+    PM.add(createInstructionCombiningPass());
+
+    // Inline small functions
+    if (RunInliner)
+      PM.add(createFunctionInliningPass());
+    
+    PM.add(createPruneEHPass());   // Remove dead EH info.
+    
+    // Optimize globals again if we ran the inliner.
+    if (RunInliner)
+      PM.add(createGlobalOptimizerPass());
+    PM.add(createGlobalDCEPass()); // Remove dead functions.
+    
+    // If we didn't decide to inline a function, check to see if we can
+    // transform it to pass arguments by value instead of by reference.
+    PM.add(createArgumentPromotionPass());
+    
+    // The IPO passes may leave cruft around.  Clean up after them.
+    PM.add(createInstructionCombiningPass());
+    PM.add(createJumpThreadingPass());
+    // Break up allocas
+    PM.add(createScalarReplAggregatesPass());
+    
+    // Run a few AA driven optimizations here and now, to cleanup the code.
+    PM.add(createFunctionAttrsPass()); // Add nocapture.
+    PM.add(createGlobalsModRefPass()); // IP alias analysis.
+    
+    PM.add(createLICMPass());      // Hoist loop invariants.
+    PM.add(createGVNPass());       // Remove redundancies.
+    PM.add(createMemCpyOptPass()); // Remove dead memcpys.
+    // Nuke dead stores.
+    PM.add(createDeadStoreEliminationPass());
+    
+    // Cleanup and simplify the code after the scalar optimizations.
+    PM.add(createInstructionCombiningPass());
+    
+    PM.add(createJumpThreadingPass());
+    
+    // Delete basic blocks, which optimization passes may have killed.
+    PM.add(createCFGSimplificationPass());
+   
+    // Now that we have optimized the program, discard unreachable functions.
+    PM.add(createGlobalDCEPass());
+  }
 };