[llvm-commits] [llvm] r131556 - in /llvm/trunk: include/llvm/DefaultPasses.h include/llvm/Support/StandardPasses.h lib/Support/StandardPasses.cpp

David Chisnall csdavec at swan.ac.uk
Wed May 18 12:00:41 PDT 2011


Author: theraven
Date: Wed May 18 14:00:41 2011
New Revision: 131556

URL: http://llvm.org/viewvc/llvm-project?rev=131556&view=rev
Log:
Second pass at allowing plugins to modify default passes.  This time without bonus inter-library dependencies.


Added:
    llvm/trunk/include/llvm/DefaultPasses.h
    llvm/trunk/lib/Support/StandardPasses.cpp
Modified:
    llvm/trunk/include/llvm/Support/StandardPasses.h

Added: llvm/trunk/include/llvm/DefaultPasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DefaultPasses.h?rev=131556&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DefaultPasses.h (added)
+++ llvm/trunk/include/llvm/DefaultPasses.h Wed May 18 14:00:41 2011
@@ -0,0 +1,162 @@
+//===- llvm/DefaultPasses.h - Default Pass Support code --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file defines the infrastructure for registering the standard pass list.
+// This defines sets of standard optimizations that plugins can modify and
+// front ends can use.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEFAULT_PASS_SUPPORT_H
+#define LLVM_DEFAULT_PASS_SUPPORT_H
+
+namespace llvm {
+
+class PassManagerBase;
+
+/// Unique identifiers for the default standard passes.  The addresses of
+/// these symbols are used to uniquely identify passes from the default list.
+namespace DefaultStandardPasses {
+extern unsigned char AggressiveDCEID;
+extern unsigned char ArgumentPromotionID;
+extern unsigned char BasicAliasAnalysisID;
+extern unsigned char CFGSimplificationID;
+extern unsigned char ConstantMergeID;
+extern unsigned char CorrelatedValuePropagationID;
+extern unsigned char DeadArgEliminationID;
+extern unsigned char DeadStoreEliminationID;
+extern unsigned char DeadTypeEliminationID;
+extern unsigned char EarlyCSEID;
+extern unsigned char FunctionAttrsID;
+extern unsigned char FunctionInliningID;
+extern unsigned char GVNID;
+extern unsigned char GlobalDCEID;
+extern unsigned char GlobalOptimizerID;
+extern unsigned char GlobalsModRefID;
+extern unsigned char IPSCCPID;
+extern unsigned char IndVarSimplifyID;
+extern unsigned char InlinerPlaceholderID;
+extern unsigned char InstructionCombiningID;
+extern unsigned char JumpThreadingID;
+extern unsigned char LICMID;
+extern unsigned char LoopDeletionID;
+extern unsigned char LoopIdiomID;
+extern unsigned char LoopRotateID;
+extern unsigned char LoopUnrollID;
+extern unsigned char LoopUnswitchID;
+extern unsigned char MemCpyOptID;
+extern unsigned char PruneEHID;
+extern unsigned char ReassociateID;
+extern unsigned char SCCPID;
+extern unsigned char ScalarReplAggregatesID;
+extern unsigned char SimplifyLibCallsID;
+extern unsigned char StripDeadPrototypesID;
+extern unsigned char TailCallEliminationID;
+extern unsigned char TypeBasedAliasAnalysisID;
+}
+
+/// StandardPass - The class responsible for maintaining the lists of standard 
+class StandardPass {
+  friend class RegisterStandardPassLists;
+  public:
+  /// Predefined standard sets of passes
+  enum StandardSet {
+    AliasAnalysis,
+    Function,
+    Module,
+    LTO
+  };
+  /// Flags to specify whether a pass should be enabled.  Passes registered
+  /// with the standard sets may specify a minimum optimization level and one
+  /// or more flags that must be set when constructing the set for the pass to
+  /// be used.
+  enum OptimizationFlags {
+    /// Optimize for size was requested.
+    OptimizeSize = 1<<0,
+    /// Allow passes which may make global module changes.
+    UnitAtATime = 1<<1,
+    /// UnrollLoops - Allow loop unrolling.
+    UnrollLoops = 1<<2,
+    /// Allow library calls to be simplified.
+    SimplifyLibCalls = 1<<3,
+    /// Whether the module may have code using exceptions.
+    HaveExceptions = 1<<4,
+    // Run an inliner pass as part of this set.
+    RunInliner = 1<<5
+  };
+  enum OptimizationFlagComponents {
+    /// The low bits are used to store the optimization level.  When requesting
+    /// passes, this should store the requested optimisation level.  When
+    /// setting passes, this should set the minimum optimization level at which
+    /// the pass will run.
+    OptimizationLevelMask=0xf,
+    /// The maximum optimisation level at which the pass is run.
+    MaxOptimizationLevelMask=0xf0,
+    // Flags that must be set
+    RequiredFlagMask=0xff00,
+    // Flags that may not be set.
+    DisallowedFlagMask=0xff0000,
+    MaxOptimizationLevelShift=4,
+    RequiredFlagShift=8,
+    DisallowedFlagShift=16
+  };
+  /// Returns the optimisation level from a set of flags.
+  static unsigned OptimizationLevel(unsigned flags) {
+      return flags & OptimizationLevelMask ; };
+  /// Returns the maximum optimization level for this set of flags
+  static unsigned MaxOptimizationLevel(unsigned flags) {
+      return (flags & MaxOptimizationLevelMask) >> 4; };
+  /// Constructs a set of flags from the specified minimum and maximum
+  /// optimisation level
+  static unsigned OptimzationFlags(unsigned minLevel=0, unsigned maxLevel=0xf,
+      unsigned requiredFlags=0, unsigned disallowedFlags=0) {
+    return ((minLevel & OptimizationLevelMask) |
+            ((maxLevel<<MaxOptimizationLevelShift) & MaxOptimizationLevelMask)
+            | ((requiredFlags<<RequiredFlagShift) & RequiredFlagMask)
+            | ((disallowedFlags<<DisallowedFlagShift) & DisallowedFlagMask)); }
+  /// Returns the flags that must be set for this to match
+  static unsigned RequiredFlags(unsigned flags) {
+      return (flags & RequiredFlagMask) >> RequiredFlagShift; };
+  /// Returns the flags that must not be set for this to match
+  static unsigned DisallowedFlags(unsigned flags) {
+      return (flags & DisallowedFlagMask) >> DisallowedFlagShift; };
+  /// Register a standard pass in the specified set.  If flags is non-zero,
+  /// then the pass will only be returned when the specified flags are set.
+  template<typename passName>
+  class RegisterStandardPass {
+    public:
+    RegisterStandardPass(StandardSet set, unsigned char *runBefore=0,
+        unsigned flags=0, unsigned char *ID=0) {
+      // Use the pass's ID if one is not specified
+      RegisterDefaultPass(PassInfo::NormalCtor_t(callDefaultCtor<passName>),
+               ID ? ID : (unsigned char*)&passName::ID, runBefore, set, flags);
+    };
+  };
+  /// Adds the passes from the specified set to the provided pass manager
+  static void AddPassesFromSet(PassManagerBase *PM,
+                               StandardSet set,
+                               unsigned flags=0,
+                               bool VerifyEach=false,
+                               Pass *inliner=0);
+  private:
+  /// Registers the default passes.  This is set by RegisterStandardPassLists
+  /// and is called lazily.
+  static void (*RegisterDefaultPasses)(void);
+  /// Creates the verifier pass that is inserted when a VerifyEach is passed to
+  /// AddPassesFromSet()
+  static Pass* (*CreateVerifierPass)(void);
+  /// Registers the pass
+  static void RegisterDefaultPass(PassInfo::NormalCtor_t constructor,
+                                  unsigned char *newPass,
+                                  unsigned char *oldPass,
+                                  StandardSet set,
+                                  unsigned flags=0);
+};
+
+} // namespace llvm
+
+#endif

Modified: llvm/trunk/include/llvm/Support/StandardPasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/StandardPasses.h?rev=131556&r1=131555&r2=131556&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/StandardPasses.h (original)
+++ llvm/trunk/include/llvm/Support/StandardPasses.h Wed May 18 14:00:41 2011
@@ -20,6 +20,7 @@
 #define LLVM_SUPPORT_STANDARDPASSES_H
 
 #include "llvm/PassManager.h"
+#include "llvm/DefaultPasses.h"
 #include "llvm/Analysis/Passes.h"
 #include "llvm/Analysis/Verifier.h"
 #include "llvm/Transforms/Scalar.h"
@@ -27,12 +28,273 @@
 
 namespace llvm {
 
+  /// RegisterStandardPassLists solves a circular dependency problem.  The
+  /// default list of passes has to live somewhere.  It can't live in the core
+  /// modules, because these don't link to the libraries that actually define
+  /// the passes.  It's in this header, so that a copy is created in every
+  /// library that requests the default set, while still allowing plugins to
+  /// register new passes without requiring them to link anything more than
+  /// VMCore.
+  class RegisterStandardPassLists {
+    public:
+    RegisterStandardPassLists() {
+      StandardPass::RegisterDefaultPasses = RegisterStandardPassList;
+      StandardPass::CreateVerifierPass = CreateVerifierPass;
+    }
+    private:
+    static llvm::Pass *CreateVerifierPass() { return createVerifierPass(); }
+    /// Passes must be registered with functions that take no arguments, so we have
+    /// to wrap their existing constructors.  
+    static Pass *createDefaultScalarReplAggregatesPass(void) {
+      return createScalarReplAggregatesPass(-1, false);
+    }
+    static Pass *createDefaultLoopUnswitchPass(void) {
+      return createLoopUnswitchPass(false);
+    }
+    static Pass *createDefaultLoopUnrollPass(void) {
+      return createLoopUnrollPass();
+    }
+    static Pass *createSizeOptimizingLoopUnswitchPass(void) {
+      return createLoopUnswitchPass(true);
+    }
+    static void RegisterStandardPassList(void) {
+      // Standard alias analysis passes
+
+      // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
+      // BasicAliasAnalysis wins if they disagree. This is intended to help
+      // support "obvious" type-punning idioms.
+#define DEFAULT_ALIAS_ANALYSIS_PASS(pass, flags)\
+  StandardPass::RegisterDefaultPass(\
+    PassInfo::NormalCtor_t(create ## pass ## Pass),\
+    &DefaultStandardPasses::pass ## ID, 0, StandardPass::AliasAnalysis, flags)
+      DEFAULT_ALIAS_ANALYSIS_PASS(TypeBasedAliasAnalysis, 0);
+      DEFAULT_ALIAS_ANALYSIS_PASS(BasicAliasAnalysis, 0);
+#undef DEFAULT_ALIAS_ANALYSIS_PASS
+
+#define DEFAULT_FUNCTION_PASS(pass, flags)\
+  StandardPass::RegisterDefaultPass(\
+      PassInfo::NormalCtor_t(create ## pass ## Pass),\
+      &DefaultStandardPasses::pass ## ID, 0, StandardPass::Function, flags)
+      DEFAULT_FUNCTION_PASS(CFGSimplification,
+          StandardPass::OptimzationFlags(1));
+      DEFAULT_FUNCTION_PASS(ScalarReplAggregates,
+          StandardPass::OptimzationFlags(1));
+      DEFAULT_FUNCTION_PASS(EarlyCSE, StandardPass::OptimzationFlags(1));
+#undef DEFAULT_FUNCTION_PASS
+
+#define DEFAULT_MODULE_PASS(pass, flags)\
+  StandardPass::RegisterDefaultPass(\
+      PassInfo::NormalCtor_t(create ## pass ## Pass),\
+      &DefaultStandardPasses::pass ## ID, 0, StandardPass::Module, flags)
+      // Optimize out global vars
+      DEFAULT_MODULE_PASS(GlobalOptimizer,
+          StandardPass::OptimzationFlags(0, 0, StandardPass::UnitAtATime));
+      // IP SCCP
+      DEFAULT_MODULE_PASS(IPSCCP,
+          StandardPass::OptimzationFlags(0, 0, StandardPass::UnitAtATime));
+      // Dead argument elimination
+      DEFAULT_MODULE_PASS(DeadArgElimination,
+          StandardPass::OptimzationFlags(0, 0, StandardPass::UnitAtATime));
+      // Clean up after IPCP & DAE
+      DEFAULT_MODULE_PASS(InstructionCombining,
+          StandardPass::OptimzationFlags(0, 0, StandardPass::UnitAtATime));
+      // Clean up after IPCP & DAE
+      DEFAULT_MODULE_PASS(CFGSimplification,
+          StandardPass::OptimzationFlags(0, 0, StandardPass::UnitAtATime));
+
+      // Remove dead EH info
+      DEFAULT_MODULE_PASS(PruneEH, StandardPass::OptimzationFlags(0, 0,
+            StandardPass::UnitAtATime | StandardPass::HaveExceptions));
+      // Placeholder that will be replaced by an inliner if one is specified
+      StandardPass::RegisterDefaultPass(0,
+        &DefaultStandardPasses::InlinerPlaceholderID, 0,
+        StandardPass::Module);
+      // Set readonly/readnone attrs
+      DEFAULT_MODULE_PASS(FunctionAttrs, StandardPass::OptimzationFlags(0, 0,
+            StandardPass::UnitAtATime));
+      // Scalarize uninlined fn args
+      DEFAULT_MODULE_PASS(ArgumentPromotion, StandardPass::OptimzationFlags(2));
+      // Start of function pass.
+      // Break up aggregate allocas, using SSAUpdater.
+      StandardPass::RegisterDefaultPass(
+          PassInfo::NormalCtor_t(createDefaultScalarReplAggregatesPass),
+          &DefaultStandardPasses::ScalarReplAggregatesID, 0,
+          StandardPass::Module);
+      // Catch trivial redundancies
+      DEFAULT_MODULE_PASS(EarlyCSE, 0);
+      // Library Call Optimizations
+      DEFAULT_MODULE_PASS(SimplifyLibCalls,
+          StandardPass::OptimzationFlags(0, 0, StandardPass::SimplifyLibCalls));
+      // Thread jumps
+      DEFAULT_MODULE_PASS(JumpThreading, 0);
+      // Propagate conditionals
+      DEFAULT_MODULE_PASS(CorrelatedValuePropagation, 0);
+      // Merge & remove BBs
+      DEFAULT_MODULE_PASS(CFGSimplification, 0);
+      // Combine silly seq's
+      DEFAULT_MODULE_PASS(InstructionCombining, 0);
+      // Eliminate tail calls
+      DEFAULT_MODULE_PASS(TailCallElimination, 0);
+      // Merge & remove BBs
+      DEFAULT_MODULE_PASS(CFGSimplification, 0);
+      // Reassociate expressions
+      DEFAULT_MODULE_PASS(Reassociate, 0);
+      // Rotate Loop
+      DEFAULT_MODULE_PASS(LoopRotate, 0);
+      // Hoist loop invariants
+      DEFAULT_MODULE_PASS(LICM, 0);
+      // Optimize for size if the optimzation level is 0-2
+      StandardPass::RegisterDefaultPass(
+          PassInfo::NormalCtor_t(createSizeOptimizingLoopUnswitchPass),
+          &DefaultStandardPasses::LoopUnswitchID, 0,
+          StandardPass::Module,
+          StandardPass::OptimzationFlags(0, 2));
+      // Optimize for size if the optimzation level is >2, and OptimizeSize is
+      // set
+      StandardPass::RegisterDefaultPass(
+          PassInfo::NormalCtor_t(createSizeOptimizingLoopUnswitchPass),
+          &DefaultStandardPasses::LoopUnswitchID, 0,
+          StandardPass::Module,
+          StandardPass::OptimzationFlags(3, 0, StandardPass::OptimizeSize));
+      // Don't optimize for size if optimisation level is >2 and OptimizeSize
+      // is not set
+      StandardPass::RegisterDefaultPass(
+          PassInfo::NormalCtor_t(createDefaultLoopUnswitchPass),
+          &DefaultStandardPasses::LoopUnswitchID, 0,
+          StandardPass::Module,
+          StandardPass::OptimzationFlags(3, 0, 0, StandardPass::OptimizeSize));
+      DEFAULT_MODULE_PASS(InstructionCombining, 0);
+      // Canonicalize indvars
+      DEFAULT_MODULE_PASS(IndVarSimplify, 0);
+      // Recognize idioms like memset.
+      DEFAULT_MODULE_PASS(LoopIdiom, 0);
+      // Delete dead loops
+      DEFAULT_MODULE_PASS(LoopDeletion, 0);
+      // Unroll small loops
+      StandardPass::RegisterDefaultPass(
+          PassInfo::NormalCtor_t(createDefaultLoopUnrollPass),
+          &DefaultStandardPasses::LoopUnrollID, 0,
+          StandardPass::Module,
+              StandardPass::OptimzationFlags(0, 0, StandardPass::UnrollLoops));
+      // Remove redundancies
+      DEFAULT_MODULE_PASS(GVN, StandardPass::OptimzationFlags(2));
+      // Remove memcpy / form memset
+      DEFAULT_MODULE_PASS(MemCpyOpt, 0);
+      // Constant prop with SCCP
+      DEFAULT_MODULE_PASS(SCCP, 0);
+
+      // Run instcombine after redundancy elimination to exploit opportunities
+      // opened up by them.
+      DEFAULT_MODULE_PASS(InstructionCombining, 0);
+      // Thread jumps
+      DEFAULT_MODULE_PASS(JumpThreading, 0);
+      DEFAULT_MODULE_PASS(CorrelatedValuePropagation, 0);
+      // Delete dead stores
+      DEFAULT_MODULE_PASS(DeadStoreElimination, 0);
+      // Delete dead instructions
+      DEFAULT_MODULE_PASS(AggressiveDCE, 0);
+      // Merge & remove BBs
+      DEFAULT_MODULE_PASS(CFGSimplification, 0);
+      // Clean up after everything.
+      DEFAULT_MODULE_PASS(InstructionCombining, 0);
+
+      // Get rid of dead prototypes
+      DEFAULT_MODULE_PASS(StripDeadPrototypes,
+              StandardPass::OptimzationFlags(0, 0, StandardPass::UnitAtATime));
+      // Eliminate dead types
+      DEFAULT_MODULE_PASS(DeadTypeElimination,
+              StandardPass::OptimzationFlags(0, 0, StandardPass::UnitAtATime));
+
+      // GlobalOpt already deletes dead functions and globals, at -O3 try a
+      // late pass of GlobalDCE.  It is capable of deleting dead cycles.
+      // Remove dead fns and globals.
+      DEFAULT_MODULE_PASS(GlobalDCE,
+              StandardPass::OptimzationFlags(3, 0, StandardPass::UnitAtATime));
+      // Merge dup global constants
+      DEFAULT_MODULE_PASS(ConstantMerge,
+              StandardPass::OptimzationFlags(2, 0, StandardPass::UnitAtATime));
+#undef DEFAULT_MODULE_PASS
+
+#define DEFAULT_LTO_PASS(pass, flags)\
+  StandardPass::RegisterDefaultPass(\
+      PassInfo::NormalCtor_t(create ## pass ## Pass), &DefaultStandardPasses::pass ## ID, 0, StandardPass::LTO, flags)
+
+      // LTO passes
+
+      // 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.  
+      DEFAULT_LTO_PASS(IPSCCP, 0);
+
+      // Now that we internalized some globals, see if we can hack on them!
+      DEFAULT_LTO_PASS(GlobalOptimizer, 0);
+      
+      // Linking modules together can lead to duplicated global constants, only
+      // keep one copy of each constant...
+      DEFAULT_LTO_PASS(ConstantMerge, 0);
+      
+      // Remove unused arguments from functions...
+      DEFAULT_LTO_PASS(DeadArgElimination, 0);
+
+      // 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.
+      DEFAULT_LTO_PASS(InstructionCombining, 0);
+
+      // Inline small functions
+      DEFAULT_LTO_PASS(FunctionInlining,
+          StandardPass::OptimzationFlags(0, 0xf, StandardPass::RunInliner));
+      // Remove dead EH info.
+      DEFAULT_LTO_PASS(PruneEH, 0);
+      // Optimize globals again if we ran the inliner.
+      DEFAULT_LTO_PASS(GlobalOptimizer,
+          StandardPass::OptimzationFlags(0, 0xf, StandardPass::RunInliner));
+      DEFAULT_LTO_PASS(GlobalDCE, 0);
+
+      // 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.
+      DEFAULT_LTO_PASS(ArgumentPromotion, 0);
+
+      // The IPO passes may leave cruft around.  Clean up after them.
+      DEFAULT_LTO_PASS(InstructionCombining, 0);
+      DEFAULT_LTO_PASS(JumpThreading, 0);
+      // Break up allocas
+      DEFAULT_LTO_PASS(ScalarReplAggregates, 0);
+
+      // Run a few AA driven optimizations here and now, to cleanup the code.
+      // Add nocapture.
+      DEFAULT_LTO_PASS(FunctionAttrs, 0);
+      // IP alias analysis.
+      DEFAULT_LTO_PASS(GlobalsModRef, 0);
+
+      // Hoist loop invariants.
+      DEFAULT_LTO_PASS(LICM, 0);
+      // Remove redundancies.
+      DEFAULT_LTO_PASS(GVN, 0);
+      // Remove dead memcpys.
+      DEFAULT_LTO_PASS(MemCpyOpt, 0);
+      // Nuke dead stores.
+      DEFAULT_LTO_PASS(DeadStoreElimination, 0);
+
+      // Cleanup and simplify the code after the scalar optimizations.
+      DEFAULT_LTO_PASS(InstructionCombining, 0);
+
+      DEFAULT_LTO_PASS(JumpThreading, 0);
+      
+      // Delete basic blocks, which optimization passes may have killed.
+      DEFAULT_LTO_PASS(CFGSimplification, 0);
+
+      // Now that we have optimized the program, discard unreachable functions.
+      DEFAULT_LTO_PASS(GlobalDCE, 0);
+#undef DEFAULT_LTO_PASS
+    }
+  };
+  static RegisterStandardPassLists AutoRegister;
+
+
   static inline void createStandardAliasAnalysisPasses(PassManagerBase *PM) {
-    // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
-    // BasicAliasAnalysis wins if they disagree. This is intended to help
-    // support "obvious" type-punning idioms.
-    PM->add(createTypeBasedAliasAnalysisPass());
-    PM->add(createBasicAliasAnalysisPass());
+    StandardPass::AddPassesFromSet(PM, StandardPass::AliasAnalysis);
   }
 
   /// createStandardFunctionPasses - Add the standard list of function passes to
@@ -42,12 +304,8 @@
   /// -O1, etc.
   static inline void createStandardFunctionPasses(PassManagerBase *PM,
                                                   unsigned OptimizationLevel) {
-    if (OptimizationLevel > 0) {
-      createStandardAliasAnalysisPasses(PM);
-      PM->add(createCFGSimplificationPass());
-      PM->add(createScalarReplAggregatesPass());
-      PM->add(createEarlyCSEPass());
-    }
+    StandardPass::AddPassesFromSet(PM, StandardPass::AliasAnalysis);
+    StandardPass::AddPassesFromSet(PM, StandardPass::Function, OptimizationLevel);
   }
 
   /// createStandardModulePasses - Add the standard list of module passes to the
@@ -78,84 +336,17 @@
         PM->add(InliningPass);
       return;
     }
-    
-    if (UnitAtATime) {
-      PM->add(createGlobalOptimizerPass());     // Optimize out global vars
-      
-      PM->add(createIPSCCPPass());              // IP SCCP
-      PM->add(createDeadArgEliminationPass());  // Dead argument elimination
-      
-      PM->add(createInstructionCombiningPass());// Clean up after IPCP & DAE
-      PM->add(createCFGSimplificationPass());   // Clean up after IPCP & DAE
-    }
-    
-    // Start of CallGraph SCC passes.
-    if (UnitAtATime && HaveExceptions)
-      PM->add(createPruneEHPass());             // Remove dead EH info
-    if (InliningPass)
-      PM->add(InliningPass);
-    if (UnitAtATime)
-      PM->add(createFunctionAttrsPass());       // Set readonly/readnone attrs
-    if (OptimizationLevel > 2)
-      PM->add(createArgumentPromotionPass());   // Scalarize uninlined fn args
-    
-    // Start of function pass.
-    // Break up aggregate allocas, using SSAUpdater.
-    PM->add(createScalarReplAggregatesPass(-1, false));
-    PM->add(createEarlyCSEPass());              // Catch trivial redundancies
-    if (SimplifyLibCalls)
-      PM->add(createSimplifyLibCallsPass());    // Library Call Optimizations
-    PM->add(createJumpThreadingPass());         // Thread jumps.
-    PM->add(createCorrelatedValuePropagationPass()); // Propagate conditionals
-    PM->add(createCFGSimplificationPass());     // Merge & remove BBs
-    PM->add(createInstructionCombiningPass());  // Combine silly seq's
-    
-    PM->add(createTailCallEliminationPass());   // Eliminate tail calls
-    PM->add(createCFGSimplificationPass());     // Merge & remove BBs
-    PM->add(createReassociatePass());           // Reassociate expressions
-    PM->add(createLoopRotatePass());            // Rotate Loop
-    PM->add(createLICMPass());                  // Hoist loop invariants
-    PM->add(createLoopUnswitchPass(OptimizeSize || OptimizationLevel < 3));
-    PM->add(createInstructionCombiningPass());  
-    PM->add(createIndVarSimplifyPass());        // Canonicalize indvars
-    PM->add(createLoopIdiomPass());             // Recognize idioms like memset.
-    PM->add(createLoopDeletionPass());          // Delete dead loops
-    if (UnrollLoops)
-      PM->add(createLoopUnrollPass());          // Unroll small loops
-    if (OptimizationLevel > 1)
-      PM->add(createGVNPass());                 // Remove redundancies
-    PM->add(createMemCpyOptPass());             // Remove memcpy / form memset
-    PM->add(createSCCPPass());                  // Constant prop with SCCP
-  
-    // Run instcombine after redundancy elimination to exploit opportunities
-    // opened up by them.
-    PM->add(createInstructionCombiningPass());
-    PM->add(createJumpThreadingPass());         // Thread jumps
-    PM->add(createCorrelatedValuePropagationPass());
-    PM->add(createDeadStoreEliminationPass());  // Delete dead stores
-    PM->add(createAggressiveDCEPass());         // Delete dead instructions
-    PM->add(createCFGSimplificationPass());     // Merge & remove BBs
-    PM->add(createInstructionCombiningPass());  // Clean up after everything.
-
-    if (UnitAtATime) {
-      PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes
-      PM->add(createDeadTypeEliminationPass()); // Eliminate dead types
 
-      // GlobalOpt already deletes dead functions and globals, at -O3 try a
-      // late pass of GlobalDCE.  It is capable of deleting dead cycles.
-      if (OptimizationLevel > 2)
-        PM->add(createGlobalDCEPass());         // Remove dead fns and globals.
+    StandardPass::AddPassesFromSet(PM, StandardPass::Module,
+      StandardPass::OptimzationFlags(OptimizationLevel, 0,
+        (OptimizeSize ? StandardPass::OptimizeSize : 0) |
+        (UnitAtATime ? StandardPass::UnitAtATime : 0) |
+        (UnrollLoops ? StandardPass::UnrollLoops : 0) |
+        (SimplifyLibCalls ? StandardPass::SimplifyLibCalls : 0) |
+        (HaveExceptions ? StandardPass::HaveExceptions : 0)),
+      false,
+      InliningPass);
     
-      if (OptimizationLevel > 1)
-        PM->add(createConstantMergePass());       // Merge dup global constants
-    }
-  }
-
-  static inline void addOnePass(PassManagerBase *PM, Pass *P, bool AndVerify) {
-    PM->add(P);
-
-    if (AndVerify)
-      PM->add(createVerifierPass());
   }
 
   /// createStandardLTOPasses - Add the standard list of module passes suitable
@@ -174,70 +365,15 @@
     // 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)
-      addOnePass(PM, createInternalizePass(true), VerifyEach);
-
-    // 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.  
-    addOnePass(PM, createIPSCCPPass(), VerifyEach);
-
-    // Now that we internalized some globals, see if we can hack on them!
-    addOnePass(PM, createGlobalOptimizerPass(), VerifyEach);
-    
-    // Linking modules together can lead to duplicated global constants, only
-    // keep one copy of each constant...
-    addOnePass(PM, createConstantMergePass(), VerifyEach);
-    
-    // Remove unused arguments from functions...
-    addOnePass(PM, createDeadArgEliminationPass(), VerifyEach);
-
-    // 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.
-    addOnePass(PM, createInstructionCombiningPass(), VerifyEach);
-
-    // Inline small functions
-    if (RunInliner)
-      addOnePass(PM, createFunctionInliningPass(), VerifyEach);
-
-    addOnePass(PM, createPruneEHPass(), VerifyEach);   // Remove dead EH info.
-    // Optimize globals again if we ran the inliner.
-    if (RunInliner)
-      addOnePass(PM, createGlobalOptimizerPass(), VerifyEach);
-    addOnePass(PM, createGlobalDCEPass(), VerifyEach); // 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.
-    addOnePass(PM, createArgumentPromotionPass(), VerifyEach);
-
-    // The IPO passes may leave cruft around.  Clean up after them.
-    addOnePass(PM, createInstructionCombiningPass(), VerifyEach);
-    addOnePass(PM, createJumpThreadingPass(), VerifyEach);
-    // Break up allocas
-    addOnePass(PM, createScalarReplAggregatesPass(), VerifyEach);
-
-    // Run a few AA driven optimizations here and now, to cleanup the code.
-    addOnePass(PM, createFunctionAttrsPass(), VerifyEach); // Add nocapture.
-    addOnePass(PM, createGlobalsModRefPass(), VerifyEach); // IP alias analysis.
-
-    addOnePass(PM, createLICMPass(), VerifyEach);      // Hoist loop invariants.
-    addOnePass(PM, createGVNPass(), VerifyEach);       // Remove redundancies.
-    addOnePass(PM, createMemCpyOptPass(), VerifyEach); // Remove dead memcpys.
-    // Nuke dead stores.
-    addOnePass(PM, createDeadStoreEliminationPass(), VerifyEach);
-
-    // Cleanup and simplify the code after the scalar optimizations.
-    addOnePass(PM, createInstructionCombiningPass(), VerifyEach);
-
-    addOnePass(PM, createJumpThreadingPass(), VerifyEach);
-    
-    // Delete basic blocks, which optimization passes may have killed.
-    addOnePass(PM, createCFGSimplificationPass(), VerifyEach);
+    if (Internalize) {
+      PM->add(createInternalizePass(true));
+      if (VerifyEach)
+        PM->add(createVerifierPass());
+    }
 
-    // Now that we have optimized the program, discard unreachable functions.
-    addOnePass(PM, createGlobalDCEPass(), VerifyEach);
+    StandardPass::AddPassesFromSet(PM, StandardPass::LTO,
+      StandardPass::OptimzationFlags(0, 0, RunInliner ?
+        StandardPass::RunInliner : 0), VerifyEach);
   }
 }
 

Added: llvm/trunk/lib/Support/StandardPasses.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/StandardPasses.cpp?rev=131556&view=auto
==============================================================================
--- llvm/trunk/lib/Support/StandardPasses.cpp (added)
+++ llvm/trunk/lib/Support/StandardPasses.cpp Wed May 18 14:00:41 2011
@@ -0,0 +1,247 @@
+//===-- lib/Support/StandardPasses.cpp - Standard pass lists -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines utility functions for creating a "standard" set of
+// optimization passes, so that compilers and tools which use optimization
+// passes use the same set of standard passes.
+//
+// This allows the creation of multiple standard sets, and their later
+// modification by plugins and front ends.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/PassManager.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/DefaultPasses.h"
+#include "llvm/Support/Mutex.h"
+
+using namespace llvm::DefaultStandardPasses;
+using namespace llvm;
+
+namespace {
+
+/// Entry in the standard passes list.
+struct StandardPassEntry {
+  /// Function called to create the pass
+  PassInfo::NormalCtor_t createPass;
+  /// Unique identifier for this pass
+  unsigned char *passID;
+  /// Flags specifying when this pass should be run
+  unsigned flags;
+
+  StandardPassEntry(PassInfo::NormalCtor_t constructor, unsigned char *ID,
+      unsigned f) : createPass(constructor), passID(ID), flags(f) {};
+};
+
+/// Standard alias analysis passes
+static llvm::SmallVector<StandardPassEntry, 4> AAPasses;
+/// Standard function passes
+static llvm::SmallVector<StandardPassEntry, 32> FunctionPasses;
+/// Standard module passes
+static llvm::SmallVector<StandardPassEntry, 32> ModulePasses;
+/// Standard link-time optimization passes
+static llvm::SmallVector<StandardPassEntry, 32> LTOPasses;
+
+/// Entry in the unresolved standard pass list.  IF a pass is inserted in front
+/// of a pass that is not yet registered in the standard pass list then it is
+/// stored in a separate list and resolved later.
+struct UnresolvedStandardPass : public StandardPassEntry {
+  /// The set into which this is stored
+  StandardPass::StandardSet set;
+  /// The unique ID of the pass that should follow this one in the sequence
+  unsigned char *next;
+  UnresolvedStandardPass(PassInfo::NormalCtor_t constructor,
+                         unsigned char *newPass,
+                         unsigned char *oldPass,
+                         StandardPass::StandardSet s,
+                         unsigned f) :
+    StandardPassEntry(constructor, newPass, f), set(s), next(oldPass) {}
+};
+
+/// The passes that can not be inserted into the correct lists yet because of
+/// their place in the sequence.
+static llvm::SmallVector<UnresolvedStandardPass, 16> UnresolvedPasses;
+
+/// Returns a reference to the pass list for the corresponding set of
+/// optimisations.
+llvm::SmallVectorImpl<StandardPassEntry>&
+PassList(StandardPass::StandardSet set) {
+  switch (set) {
+    case StandardPass::AliasAnalysis: return AAPasses;
+    case StandardPass::Function: return FunctionPasses;
+    case StandardPass::Module: return ModulePasses;
+    case StandardPass::LTO: return LTOPasses; 
+  }
+  // We could use a map of standard pass lists to allow definition of new
+  // default sets
+  llvm_unreachable("Invalid standard optimization set requested");
+}
+
+static ManagedStatic<sys::SmartMutex<true> > Lock;
+
+/// Registers the default set of standard passes.  This is called lazily when
+/// an attempt is made to read or modify the standard pass list
+void RegisterDefaultStandardPasses(void(*doRegister)(void)) {
+  // Only initialize the standard passes once
+  static volatile bool initialized = false;
+  if (initialized) return;
+
+  llvm::sys::SmartScopedLock<true> Guard(*Lock);
+  if (initialized) return;
+  if (doRegister) {
+    assert("No passes registered before setting default passes" &&
+            AAPasses.size() == 0 &&
+            FunctionPasses.size() == 0 &&
+            LTOPasses.size() == 0 &&
+            ModulePasses.size() == 0);
+
+    // We must set initialized to true before calling this function, because
+    // the doRegister() function will probably call RegisterDefaultPasses(),
+    // which will call this function, and we'd end up with infinite recursion
+    // and breakage if we didn't.
+    initialized = true;
+    doRegister();
+  }
+}
+
+} // Anonymous namespace
+
+void (*StandardPass::RegisterDefaultPasses)(void);
+Pass* (*StandardPass::CreateVerifierPass)(void);
+
+void StandardPass::RegisterDefaultPass(PassInfo::NormalCtor_t constructor,
+                                       unsigned char *newPass,
+                                       unsigned char *oldPass,
+                                       StandardPass::StandardSet set,
+                                       unsigned flags) {
+  // Make sure that the standard sets are already regstered
+  RegisterDefaultStandardPasses(RegisterDefaultPasses);
+  // Get the correct list to modify
+  llvm::SmallVectorImpl<StandardPassEntry>& passList = PassList(set);
+
+  // If there is no old pass specified, then we are adding a new final pass, so
+  // just push it onto the end.
+  if (!oldPass) {
+    StandardPassEntry pass(constructor, newPass, flags);
+    passList.push_back(pass);
+    return;
+  }
+
+  // Find the correct place to insert the pass.  This is a linear search, but
+  // this shouldn't be too slow since the SmallVector will store the values in
+  // a contiguous block of memory.  Each entry is just three words of memory, so
+  // in most cases we are only going to be looking in one or two cache lines.
+  // The extra memory accesses from a more complex search structure would
+  // offset any performance gain (unless someone decides to add an insanely
+  // large set of standard passes to a set)
+  for (SmallVectorImpl<StandardPassEntry>::iterator i=passList.begin(),
+       e=passList.end() ; i!=e ; ++i) {
+    if (i->passID == oldPass) {
+      StandardPassEntry pass(constructor, newPass, flags);
+      passList.insert(i, pass);
+      // If we've added a new pass, then there may have gained the ability to
+      // insert one of the previously unresolved ones.  If so, insert the new
+      // one.
+      for (SmallVectorImpl<UnresolvedStandardPass>::iterator
+          u=UnresolvedPasses.begin(), eu=UnresolvedPasses.end() ; u!=eu ; ++u){
+        if (u->next == newPass && u->set == set) {
+          UnresolvedStandardPass p = *u;
+          UnresolvedPasses.erase(u);
+          RegisterDefaultPass(p.createPass, p.passID, p.next, p.set, p.flags);
+        }
+      }
+      return;
+    }
+  }
+  // If we get to here, then we didn't find the correct place to insert the new
+  // pass
+  UnresolvedStandardPass pass(constructor, newPass, oldPass, set, flags);
+  UnresolvedPasses.push_back(pass);
+}
+
+void StandardPass::AddPassesFromSet(PassManagerBase *PM,
+                                    StandardSet set,
+                                    unsigned flags,
+                                    bool VerifyEach,
+                                    Pass *inliner) {
+  RegisterDefaultStandardPasses(RegisterDefaultPasses);
+  unsigned level = OptimizationLevel(flags);
+  flags = RequiredFlags(flags);
+  llvm::SmallVectorImpl<StandardPassEntry>& passList = PassList(set);
+
+  // Add all of the passes from this set
+  for (SmallVectorImpl<StandardPassEntry>::iterator i=passList.begin(),
+       e=passList.end() ; i!=e ; ++i) {
+    // Skip passes that don't have conditions that match the ones specified
+    // here.  For a pass to match:
+    // - Its minimum optimisation level must be less than or equal to the
+    //   specified level.
+    // - Its maximum optimisation level must be greater than or equal to the
+    //   specified level
+    // - All of its required flags must be set
+    // - None of its disallowed flags may be set
+    if ((level >= OptimizationLevel(i->flags)) &&
+        ((level <= MaxOptimizationLevel(i->flags))
+          || MaxOptimizationLevel(i->flags) == 0)  &&
+        ((RequiredFlags(i->flags) & flags) == RequiredFlags(i->flags)) &&
+        ((DisallowedFlags(i->flags) & flags) == 0)) {
+      // This is quite an ugly way of allowing us to specify an inliner pass to
+      // insert.  Ideally, we'd replace this with a general mechanism allowing
+      // callers to replace arbitrary passes in the list.
+      Pass *p = 0;
+      if (&InlinerPlaceholderID == i->passID) {
+          p = inliner;
+      } else if (i->createPass)
+        p = i->createPass();
+      if (p) {
+        PM->add(p);
+        if (VerifyEach)
+          PM->add(CreateVerifierPass());
+      }
+    }
+  }
+}
+
+unsigned char DefaultStandardPasses::AggressiveDCEID;
+unsigned char DefaultStandardPasses::ArgumentPromotionID;
+unsigned char DefaultStandardPasses::BasicAliasAnalysisID;
+unsigned char DefaultStandardPasses::CFGSimplificationID;
+unsigned char DefaultStandardPasses::ConstantMergeID;
+unsigned char DefaultStandardPasses::CorrelatedValuePropagationID;
+unsigned char DefaultStandardPasses::DeadArgEliminationID;
+unsigned char DefaultStandardPasses::DeadStoreEliminationID;
+unsigned char DefaultStandardPasses::DeadTypeEliminationID;
+unsigned char DefaultStandardPasses::EarlyCSEID;
+unsigned char DefaultStandardPasses::FunctionAttrsID;
+unsigned char DefaultStandardPasses::FunctionInliningID;
+unsigned char DefaultStandardPasses::GVNID;
+unsigned char DefaultStandardPasses::GlobalDCEID;
+unsigned char DefaultStandardPasses::GlobalOptimizerID;
+unsigned char DefaultStandardPasses::GlobalsModRefID;
+unsigned char DefaultStandardPasses::IPSCCPID;
+unsigned char DefaultStandardPasses::IndVarSimplifyID;
+unsigned char DefaultStandardPasses::InlinerPlaceholderID;
+unsigned char DefaultStandardPasses::InstructionCombiningID;
+unsigned char DefaultStandardPasses::JumpThreadingID;
+unsigned char DefaultStandardPasses::LICMID;
+unsigned char DefaultStandardPasses::LoopDeletionID;
+unsigned char DefaultStandardPasses::LoopIdiomID;
+unsigned char DefaultStandardPasses::LoopRotateID;
+unsigned char DefaultStandardPasses::LoopUnrollID;
+unsigned char DefaultStandardPasses::LoopUnswitchID;
+unsigned char DefaultStandardPasses::MemCpyOptID;
+unsigned char DefaultStandardPasses::PruneEHID;
+unsigned char DefaultStandardPasses::ReassociateID;
+unsigned char DefaultStandardPasses::SCCPID;
+unsigned char DefaultStandardPasses::ScalarReplAggregatesID;
+unsigned char DefaultStandardPasses::SimplifyLibCallsID;
+unsigned char DefaultStandardPasses::StripDeadPrototypesID;
+unsigned char DefaultStandardPasses::TailCallEliminationID;
+unsigned char DefaultStandardPasses::TypeBasedAliasAnalysisID;





More information about the llvm-commits mailing list