Mercurial > projects > ldc
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 } |