Add support for plugins add passes to the default set of passes. The standard set of passes used by front ends can now be modified by LLVM plugins, without needing to modify any front ends.

Still to do:

- Allow replacing / removing passes (infrastructure there, just needs an infrastructure exposed)
- Defining sets of passes to be added or removed as a group
- Extending the support to allow user-defined groups of optimisations
- Allow plugins to be specified for loading automatically (e.g. from plugins.conf or some similar mechanism)

Reviewed by Nick Lewycky.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131155 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Chisnall 2011-05-10 21:36:48 +00:00
parent d673057c96
commit 0fa92e55c3
3 changed files with 655 additions and 150 deletions

View File

@ -29,6 +29,8 @@
namespace llvm {
class PassManagerBase;
//===---------------------------------------------------------------------------
/// PassInfo class - An instance of this class exists for every pass known by
/// the system, and can be obtained from a live Pass by calling its
@ -207,6 +209,149 @@ struct RegisterPass : public PassInfo {
}
};
/// 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;
}
class RegisterStandardPass;
/// RegisterStandardPass - Registers a pass as a member of a standard set.
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 OptimizationFlags(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) >> RequiredFlagShift;
}
/// 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 {
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 : &passName::ID, runBefore, set, flags);
};
};
/// Adds the passes from the specified set to a 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);
/// Registers the pass
static void RegisterDefaultPass(PassInfo::NormalCtor_t constructor,
unsigned char *newPass,
unsigned char *oldPass,
StandardSet set,
unsigned flags=0);
};
/// RegisterAnalysisGroup - Register a Pass as a member of an analysis _group_.
/// Analysis groups are used to define an interface (which need not derive from

View File

@ -20,6 +20,7 @@
#define LLVM_SUPPORT_STANDARDPASSES_H
#include "llvm/PassManager.h"
#include "llvm/PassSupport.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Transforms/Scalar.h"
@ -27,12 +28,259 @@
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;
}
private:
/// 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 *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(BasicAliasAnalysis, 0);
DEFAULT_ALIAS_ANALYSIS_PASS(TypeBasedAliasAnalysis, 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::OptimizationFlags(1));
DEFAULT_FUNCTION_PASS(ScalarReplAggregates,
StandardPass::OptimizationFlags(1));
DEFAULT_FUNCTION_PASS(EarlyCSE, StandardPass::OptimizationFlags(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::UnitAtATime);
// IP SCCP
DEFAULT_MODULE_PASS(IPSCCP,
StandardPass::OptimizationFlags(0, 0, StandardPass::UnitAtATime));
// Dead argument elimination
DEFAULT_MODULE_PASS(DeadArgElimination,
StandardPass::OptimizationFlags(0, 0, StandardPass::UnitAtATime));
// Clean up after IPCP & DAE
DEFAULT_MODULE_PASS(InstructionCombining,
StandardPass::OptimizationFlags(0, 0, StandardPass::UnitAtATime));
// Clean up after IPCP & DAE
DEFAULT_MODULE_PASS(CFGSimplification,
StandardPass::OptimizationFlags(0, 0, StandardPass::UnitAtATime));
// Placeholder that will be replaced by an inliner if one is specified
StandardPass::RegisterDefaultPass(0,
&DefaultStandardPasses::InlinerPlaceholderID , 0,
StandardPass::Module);
// Remove dead EH info
DEFAULT_MODULE_PASS(PruneEH, StandardPass::OptimizationFlags(0, 0,
StandardPass::UnitAtATime | StandardPass::HaveExceptions));
// Set readonly/readnone attrs
DEFAULT_MODULE_PASS(FunctionAttrs, StandardPass::OptimizationFlags(0, 0,
StandardPass::UnitAtATime));
// Scalarize uninlined fn args
DEFAULT_MODULE_PASS(ArgumentPromotion, 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::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::OptimizationFlags(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::OptimizationFlags(0, 3, StandardPass::OptimizeSize));
// Don't optimize for size if optimisation level is >2 and OptimizeSize
// is not set
StandardPass::RegisterDefaultPass(
PassInfo::NormalCtor_t(createSizeOptimizingLoopUnswitchPass),
&DefaultStandardPasses::LoopUnswitchID, 0,
StandardPass::Module,
StandardPass::OptimizationFlags(0, 3, 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
DEFAULT_MODULE_PASS(LoopUnroll, StandardPass::UnrollLoops);
// Remove redundancies
DEFAULT_MODULE_PASS(GVN, 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::UnitAtATime);
// Eliminate dead types
DEFAULT_MODULE_PASS(DeadTypeElimination, 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, 3 | StandardPass::UnitAtATime);
// Merge dup global constants
DEFAULT_MODULE_PASS(ConstantMerge, 2 | 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::OptimizationFlags(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::OptimizationFlags(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 +290,7 @@ 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::Function, OptimizationLevel);
}
/// createStandardModulePasses - Add the standard list of module passes to the
@ -78,84 +321,16 @@ 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::OptimizationFlags(OptimizationLevel,
(OptimizeSize ? StandardPass::OptimizeSize : 0) |
(UnitAtATime ? StandardPass::UnitAtATime : 0) |
(UnrollLoops ? StandardPass::UnrollLoops : 0) |
(SimplifyLibCalls ? StandardPass::SimplifyLibCalls : 0) |
(HaveExceptions ? StandardPass::HaveExceptions : 0)),
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 +349,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);
if (Internalize) {
PM->add(createInternalizePass(true));
if (VerifyEach)
PM->add(createVerifierPass());
}
// 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);
// Now that we have optimized the program, discard unreachable functions.
addOnePass(PM, createGlobalDCEPass(), VerifyEach);
StandardPass::AddPassesFromSet(PM, StandardPass::LTO,
StandardPass::OptimizationFlags(0, 0, RunInliner ?
StandardPass::RunInliner : 0), VerifyEach);
}
}

View File

@ -0,0 +1,240 @@
//=========-- 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.
//
//===----------------------------------------------------------------------===//
#include "llvm/PassManager.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.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 bool initialized = false;
if (initialized) return;
llvm::sys::SmartScopedLock<true> Guard(*Lock);
if (initialized) return;
if (doRegister) {
// 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);
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
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 = inliner;
if ((&InlinerPlaceholderID != i->passID) && 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;