aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Chisnall <csdavec@swan.ac.uk>2011-05-18 19:00:41 +0000
committerDavid Chisnall <csdavec@swan.ac.uk>2011-05-18 19:00:41 +0000
commitb2a00dca1b03cea98ebb557dba56802109c11c19 (patch)
tree256130257dc936431a02f1f9796f7f565523b1fa
parentb936e3006f04f60aca4c4de4a3604ec141ab0a45 (diff)
downloadexternal_llvm-b2a00dca1b03cea98ebb557dba56802109c11c19.zip
external_llvm-b2a00dca1b03cea98ebb557dba56802109c11c19.tar.gz
external_llvm-b2a00dca1b03cea98ebb557dba56802109c11c19.tar.bz2
Second pass at allowing plugins to modify default passes. This time without bonus inter-library dependencies.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131556 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/DefaultPasses.h162
-rw-r--r--include/llvm/Support/StandardPasses.h436
-rw-r--r--lib/Support/StandardPasses.cpp247
3 files changed, 695 insertions, 150 deletions
diff --git a/include/llvm/DefaultPasses.h b/include/llvm/DefaultPasses.h
new file mode 100644
index 0000000..8a87bc5
--- /dev/null
+++ b/include/llvm/DefaultPasses.h
@@ -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
diff --git a/include/llvm/Support/StandardPasses.h b/include/llvm/Support/StandardPasses.h
index e13e9fa..c13ade2 100644
--- a/include/llvm/Support/StandardPasses.h
+++ b/include/llvm/Support/StandardPasses.h
@@ -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 @@ namespace llvm {
/// -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 @@ namespace llvm {
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 @@ namespace llvm {
// 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);
}
}
diff --git a/lib/Support/StandardPasses.cpp b/lib/Support/StandardPasses.cpp
new file mode 100644
index 0000000..5a98fd6
--- /dev/null
+++ b/lib/Support/StandardPasses.cpp
@@ -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;