mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 20:59:51 +00:00
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:
parent
d673057c96
commit
0fa92e55c3
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
240
lib/VMCore/StandardPasses.cpp
Normal file
240
lib/VMCore/StandardPasses.cpp
Normal 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;
|
Loading…
Reference in New Issue
Block a user