comparison 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
comparison
equal deleted inserted replaced
1169:2bff538fa3b9 1170:e40c65bd8c5d
1 #include "gen/optimizer.h"
2
1 #include "llvm/PassManager.h" 3 #include "llvm/PassManager.h"
2 #include "llvm/LinkAllPasses.h" 4 #include "llvm/LinkAllPasses.h"
3 #include "llvm/Analysis/LoopPass.h" 5 #include "llvm/Analysis/LoopPass.h"
4 #include "llvm/Target/TargetData.h" 6 #include "llvm/Target/TargetData.h"
7 #include "llvm/Support/CommandLine.h"
8 #include "llvm/Support/PassNameParser.h"
9
10 #include "root.h" // error() & fatal()
11 #include "mars.h" // global flags
5 12
6 using namespace llvm; 13 using namespace llvm;
7 14
8 ////////////////////////////////////////////////////////////////////////////////////////// 15 // Allow the user to specify specific optimizations to run.
16 static cl::list<const PassInfo*, bool, PassNameParser>
17 passList(
18 cl::desc("Running specific optimizations:"),
19 cl::Hidden // to clean up --help output
20 );
9 21
10 // this function runs some or all of the std-compile-opts passes depending on the 22 static cl::opt<char> optimizeLevel(
23 cl::desc("Setting the optimization level:"),
24 cl::ZeroOrMore,
25 cl::values(
26 clEnumValN(2, "O", "Equivalent to -O2"),
27 clEnumValN(0, "O0", "Trivial optimizations only"),
28 clEnumValN(1, "O1", "Simple optimizations"),
29 clEnumValN(2, "O2", "Good optimizations"),
30 clEnumValN(3, "O3", "Aggressive optimizations"),
31 clEnumValN(4, "O4", "Link-time optimization"), // not implemented?
32 clEnumValN(5, "O5", "Link-time optimization"), // not implemented?
33 clEnumValEnd),
34 cl::init(-1));
35
36 static cl::opt<bool> enableInlining("enable-inlining",
37 cl::desc("Enable function inlining (in -O<N>, if given)"),
38 cl::ZeroOrMore,
39 cl::init(false));
40
41 // Some accessors for the linker: (llvm-ld version only, currently unused?)
42 bool doInline() {
43 return enableInlining;
44 }
45
46 int optLevel() {
47 return optimizeLevel;
48 }
49
50 bool optimize() {
51 return (optimizeLevel != -1) || enableInlining || passList.empty();
52 }
53
54 // this function inserts some or all of the std-compile-opts passes depending on the
11 // optimization level given. 55 // optimization level given.
12 56 static void addPassesForOptLevel(PassManager& pm) {
13 void ldc_optimize_module(Module* m, char lvl, bool doinline)
14 {
15 if (!doinline && lvl < 0)
16 return;
17
18 PassManager pm;
19 pm.add(new TargetData(m));
20
21 // -O0 57 // -O0
22 if (lvl >= 0) 58 if (optimizeLevel >= 0)
23 { 59 {
24 //pm.add(createStripDeadPrototypesPass()); 60 //pm.add(createStripDeadPrototypesPass());
25 pm.add(createGlobalDCEPass()); 61 pm.add(createGlobalDCEPass());
26 } 62 }
27 63
28 // -O1 64 // -O1
29 if (lvl >= 1) 65 if (optimizeLevel >= 1)
30 { 66 {
31 pm.add(createRaiseAllocationsPass()); 67 pm.add(createRaiseAllocationsPass());
32 pm.add(createCFGSimplificationPass()); 68 pm.add(createCFGSimplificationPass());
33 pm.add(createPromoteMemoryToRegisterPass()); 69 pm.add(createPromoteMemoryToRegisterPass());
34 pm.add(createGlobalOptimizerPass()); 70 pm.add(createGlobalOptimizerPass());
35 pm.add(createGlobalDCEPass()); 71 pm.add(createGlobalDCEPass());
36 } 72 }
37 73
38 // -O2 74 // -O2
39 if (lvl >= 2) 75 if (optimizeLevel >= 2)
40 { 76 {
41 pm.add(createIPConstantPropagationPass()); 77 pm.add(createIPConstantPropagationPass());
42 pm.add(createDeadArgEliminationPass()); 78 pm.add(createDeadArgEliminationPass());
43 pm.add(createInstructionCombiningPass()); 79 pm.add(createInstructionCombiningPass());
44 pm.add(createCFGSimplificationPass()); 80 pm.add(createCFGSimplificationPass());
45 pm.add(createPruneEHPass()); 81 pm.add(createPruneEHPass());
46 } 82 }
47 83
48 // -inline 84 // -inline
49 if (doinline) { 85 if (enableInlining) {
50 pm.add(createFunctionInliningPass()); 86 pm.add(createFunctionInliningPass());
51 } 87 }
52 88
53 // -O3 89 // -O3
54 if (lvl >= 3) 90 if (optimizeLevel >= 3)
55 { 91 {
56 pm.add(createArgumentPromotionPass()); 92 pm.add(createArgumentPromotionPass());
57 pm.add(createTailDuplicationPass()); 93 pm.add(createTailDuplicationPass());
58 pm.add(createInstructionCombiningPass()); 94 pm.add(createInstructionCombiningPass());
59 pm.add(createCFGSimplificationPass()); 95 pm.add(createCFGSimplificationPass());
84 pm.add(createDeadTypeEliminationPass()); 120 pm.add(createDeadTypeEliminationPass());
85 pm.add(createConstantMergePass()); 121 pm.add(createConstantMergePass());
86 } 122 }
87 123
88 // level -O4 and -O5 are linktime optimizations 124 // level -O4 and -O5 are linktime optimizations
125 }
126
127 //////////////////////////////////////////////////////////////////////////////////////////
128 // This function runs optimization passes based on command line arguments.
129 // Returns true if any optimization passes were invoked.
130 bool ldc_optimize_module(llvm::Module* m)
131 {
132 if (!enableInlining && optimizeLevel == -1 && passList.empty())
133 return false;
134
135 PassManager pm;
136 pm.add(new TargetData(m));
137
138 bool optimize = (optimizeLevel != -1) || enableInlining;
139
140 unsigned optPos = optimizeLevel != -1
141 ? optimizeLevel.getPosition()
142 : enableInlining.getPosition();
143
144 for (size_t i = 0; i < passList.size(); i++) {
145 // insert -O<N> / -enable-inlining in right position
146 if (optimize && optPos < passList.getPosition(i)) {
147 addPassesForOptLevel(pm);
148 optimize = false;
149 }
150
151 const PassInfo* pass = passList[i];
152 if (PassInfo::NormalCtor_t ctor = pass->getNormalCtor()) {
153 pm.add(ctor());
154 } else {
155 const char* arg = pass->getPassArgument(); // may return null
156 if (arg)
157 error("Can't create pass '-%s' (%s)", arg, pass->getPassName());
158 else
159 error("Can't create pass (%s)", pass->getPassName());
160 fatal();
161 }
162 }
163 // insert -O<N> / -enable-inlining if specified at the end,
164 if (optimize)
165 addPassesForOptLevel(pm);
89 166
90 pm.run(*m); 167 pm.run(*m);
168 return true;
91 } 169 }