Mercurial > projects > ldc
diff gen/optimizer.cpp @ 1170:e40c65bd8c5d
Allow specific optimization passes to be requested from the command line.
Now you can run "`ldc test.d -c -mem2reg -simplifycfg`" if you feel the urge.
The -O<N> options are still supported, and are inserted in the passes list in
the position where they appear on the command line.
(so -simplifycfg -O1 -instcombine does the "right thing")
One small change: -inline is renamed to -enable-inlining due to a naming
conflict with the option to add the -inline pass. -inline now inserts the
inlining pass in the position specified, not in the middle of -O<N>.
(ldmd has been updated to translate -inline to -enable-inlining)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Sun, 29 Mar 2009 15:46:55 +0200 |
parents | 6aaa3d3c1183 |
children | 461a85f0db31 |
line wrap: on
line diff
--- a/gen/optimizer.cpp Sun Mar 29 11:44:32 2009 +0200 +++ b/gen/optimizer.cpp Sun Mar 29 15:46:55 2009 +0200 @@ -1,32 +1,68 @@ +#include "gen/optimizer.h" + #include "llvm/PassManager.h" #include "llvm/LinkAllPasses.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Target/TargetData.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/PassNameParser.h" + +#include "root.h" // error() & fatal() +#include "mars.h" // global flags using namespace llvm; -////////////////////////////////////////////////////////////////////////////////////////// +// Allow the user to specify specific optimizations to run. +static cl::list<const PassInfo*, bool, PassNameParser> + passList( + cl::desc("Running specific optimizations:"), + cl::Hidden // to clean up --help output + ); -// this function runs some or all of the std-compile-opts passes depending on the -// optimization level given. +static cl::opt<char> optimizeLevel( + cl::desc("Setting the optimization level:"), + cl::ZeroOrMore, + cl::values( + clEnumValN(2, "O", "Equivalent to -O2"), + clEnumValN(0, "O0", "Trivial optimizations only"), + clEnumValN(1, "O1", "Simple optimizations"), + clEnumValN(2, "O2", "Good optimizations"), + clEnumValN(3, "O3", "Aggressive optimizations"), + clEnumValN(4, "O4", "Link-time optimization"), // not implemented? + clEnumValN(5, "O5", "Link-time optimization"), // not implemented? + clEnumValEnd), + cl::init(-1)); -void ldc_optimize_module(Module* m, char lvl, bool doinline) -{ - if (!doinline && lvl < 0) - return; +static cl::opt<bool> enableInlining("enable-inlining", + cl::desc("Enable function inlining (in -O<N>, if given)"), + cl::ZeroOrMore, + cl::init(false)); + +// Some accessors for the linker: (llvm-ld version only, currently unused?) +bool doInline() { + return enableInlining; +} - PassManager pm; - pm.add(new TargetData(m)); +int optLevel() { + return optimizeLevel; +} +bool optimize() { + return (optimizeLevel != -1) || enableInlining || passList.empty(); +} + +// this function inserts some or all of the std-compile-opts passes depending on the +// optimization level given. +static void addPassesForOptLevel(PassManager& pm) { // -O0 - if (lvl >= 0) + if (optimizeLevel >= 0) { //pm.add(createStripDeadPrototypesPass()); pm.add(createGlobalDCEPass()); } // -O1 - if (lvl >= 1) + if (optimizeLevel >= 1) { pm.add(createRaiseAllocationsPass()); pm.add(createCFGSimplificationPass()); @@ -36,7 +72,7 @@ } // -O2 - if (lvl >= 2) + if (optimizeLevel >= 2) { pm.add(createIPConstantPropagationPass()); pm.add(createDeadArgEliminationPass()); @@ -46,12 +82,12 @@ } // -inline - if (doinline) { + if (enableInlining) { pm.add(createFunctionInliningPass()); } // -O3 - if (lvl >= 3) + if (optimizeLevel >= 3) { pm.add(createArgumentPromotionPass()); pm.add(createTailDuplicationPass()); @@ -86,6 +122,48 @@ } // level -O4 and -O5 are linktime optimizations +} + +////////////////////////////////////////////////////////////////////////////////////////// +// This function runs optimization passes based on command line arguments. +// Returns true if any optimization passes were invoked. +bool ldc_optimize_module(llvm::Module* m) +{ + if (!enableInlining && optimizeLevel == -1 && passList.empty()) + return false; + + PassManager pm; + pm.add(new TargetData(m)); + + bool optimize = (optimizeLevel != -1) || enableInlining; + + unsigned optPos = optimizeLevel != -1 + ? optimizeLevel.getPosition() + : enableInlining.getPosition(); + + for (size_t i = 0; i < passList.size(); i++) { + // insert -O<N> / -enable-inlining in right position + if (optimize && optPos < passList.getPosition(i)) { + addPassesForOptLevel(pm); + optimize = false; + } + + const PassInfo* pass = passList[i]; + if (PassInfo::NormalCtor_t ctor = pass->getNormalCtor()) { + pm.add(ctor()); + } else { + const char* arg = pass->getPassArgument(); // may return null + if (arg) + error("Can't create pass '-%s' (%s)", arg, pass->getPassName()); + else + error("Can't create pass (%s)", pass->getPassName()); + fatal(); + } + } + // insert -O<N> / -enable-inlining if specified at the end, + if (optimize) + addPassesForOptLevel(pm); pm.run(*m); + return true; }