1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use driver::session::{OptLevel, No, Less, Aggressive};
15 use driver::session::{Session};
16 use lib::llvm::{PassRef, ModuleRef,PassManagerRef,TargetDataRef};
20 pub struct PassManager {
21 priv llpm: PassManagerRef
24 impl Drop for PassManager {
27 llvm::LLVMDisposePassManager(self.llpm);
33 pub fn new(td: TargetDataRef) -> PassManager {
35 let pm = PassManager {
36 llpm: llvm::LLVMCreatePassManager()
38 llvm::LLVMAddTargetData(td, pm.llpm);
44 pub fn add_pass(&mut self, pass:PassRef) {
46 llvm::LLVMAddPass(self.llpm, pass);
50 pub fn add_pass_from_name(&mut self, name:&str) {
51 let pass = create_pass(name).unwrap();
55 pub fn run(&self, md:ModuleRef) -> bool {
57 llvm::LLVMRunPassManager(self.llpm, md) == lib::llvm::True
62 pub fn create_standard_passes(level: OptLevel) -> ~[~str] {
65 // mostly identical to clang 3.3, all differences are documented with comments
68 passes.push(~"targetlibinfo");
69 passes.push(~"no-aa");
70 // "tbaa" omitted, we don't emit clang-style type-based alias analysis information
71 passes.push(~"basicaa");
72 passes.push(~"globalopt");
73 passes.push(~"ipsccp");
74 passes.push(~"deadargelim");
75 passes.push(~"instcombine");
76 passes.push(~"simplifycfg");
79 passes.push(~"basiccg");
82 passes.push(~"prune-eh");
85 passes.push(~"inline-cost");
87 if level == No || level == Less {
88 passes.push(~"always-inline");
90 passes.push(~"inline");
94 passes.push(~"functionattrs");
95 if level == Aggressive {
96 passes.push(~"argpromotion");
99 passes.push(~"domtree");
100 passes.push(~"early-cse");
101 passes.push(~"simplify-libcalls");
102 passes.push(~"lazy-value-info");
103 passes.push(~"jump-threading");
104 passes.push(~"correlated-propagation");
105 passes.push(~"simplifycfg");
106 passes.push(~"instcombine");
107 passes.push(~"tailcallelim");
108 passes.push(~"simplifycfg");
109 passes.push(~"reassociate");
110 passes.push(~"domtree");
111 passes.push(~"loops");
112 passes.push(~"loop-simplify");
113 passes.push(~"lcssa");
114 passes.push(~"loop-rotate");
115 passes.push(~"licm");
116 passes.push(~"lcssa");
117 passes.push(~"loop-unswitch");
118 passes.push(~"instcombine");
119 passes.push(~"scalar-evolution");
120 passes.push(~"loop-simplify");
121 passes.push(~"lcssa");
122 passes.push(~"indvars");
123 passes.push(~"loop-idiom");
124 passes.push(~"loop-deletion");
125 if level == Aggressive {
126 passes.push(~"loop-simplify");
127 passes.push(~"lcssa");
128 passes.push(~"loop-vectorize");
129 passes.push(~"loop-simplify");
130 passes.push(~"lcssa");
131 passes.push(~"scalar-evolution");
132 passes.push(~"loop-simplify");
133 passes.push(~"lcssa");
136 passes.push(~"loop-unroll");
137 passes.push(~"memdep");
140 passes.push(~"memdep");
141 passes.push(~"memcpyopt");
142 passes.push(~"sccp");
143 passes.push(~"instcombine");
144 passes.push(~"lazy-value-info");
145 passes.push(~"jump-threading");
146 passes.push(~"correlated-propagation");
147 passes.push(~"domtree");
148 passes.push(~"memdep");
150 passes.push(~"adce");
151 passes.push(~"simplifycfg");
152 passes.push(~"instcombine");
153 // clang does `strip-dead-prototypes` here, since it does not emit them
156 // rustc emits dead prototypes, so always ask LLVM to strip them
157 passes.push(~"strip-dead-prototypes");
160 passes.push(~"globaldce");
161 passes.push(~"constmerge");
167 pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~str]) {
168 for pass_list.iter().advance |nm| {
169 match create_pass(*nm) {
170 Some(p) => pm.add_pass(p),
171 None => sess.warn(fmt!("Unknown pass %s", *nm))
176 pub fn create_pass(name:&str) -> Option<PassRef> {
177 do str::as_c_str(name) |s| {
179 let p = llvm::LLVMCreatePass(s);
189 pub fn list_passes() {
190 io::println("\nAvailable Passes:");
192 io::println("\nAnalysis Passes:");
193 for analysis_passes.iter().advance |&(name, desc)| {
194 printfln!(" %-30s -- %s", name, desc);
196 io::println("\nTransformation Passes:");
197 for transform_passes.iter().advance |&(name, desc)| {
198 printfln!(" %-30s -- %s", name, desc);
200 io::println("\nUtility Passes:");
201 for utility_passes.iter().advance |&(name, desc)| {
202 printfln!(" %-30s -- %s", name, desc);
206 /** Analysis Passes */
207 pub static analysis_passes : &'static [(&'static str, &'static str)] = &'static [
208 ("aa-eval", "Exhausive Alias Analysis Precision Evaluator"),
209 ("asan", "AddressSanitizer"),
210 ("basicaa", "Basic Alias Analysis"),
211 ("basiccg", "Basic CallGraph Construction"),
212 ("block-freq", "Block Frequency Analysis"),
213 ("cost-model", "Cost Model Analysis"),
214 ("count-aa", "Count Alias Analysis Query Responses"),
215 ("da", "Dependence Analysis"),
216 ("debug-aa", "AA Use Debugger"),
217 ("domfrontier", "Dominance Frontier Construction"),
218 ("domtree", "Dominator Tree Construction"),
219 ("globalsmodref-aa", "Simple mod/ref analysis for globals"),
220 ("instcount", "Count the various types of Instructions"),
221 ("intervals", "Interval Partition Construction"),
222 ("iv-users", "Induction Variable Users"),
223 ("lazy-value-info", "Lazy Value Information Analysis"),
224 ("libcall-aa", "LibCall Alias Analysis"),
225 ("lint", "Statically lint-check LLVM IR"),
226 ("loops", "Natural Loop Information"),
227 ("memdep", "Memory Dependence Analysis"),
228 ("module-debuginfo", "Decodes module-level debug info"),
229 ("profile-estimator", "Estimate profiling information"),
230 ("profile-loader", "Load profile information from llvmprof.out"),
231 ("profile-verifier", "Verify profiling information"),
232 ("regions", "Detect single entry single exit regions"),
233 ("scalar-evolution", "Scalar Evolution Analysis"),
234 ("scev-aa", "Scalar Evolution-based Alias Analysis"),
235 ("tbaa", "Type-Based Alias Analysis"),
236 ("tsan", "ThreadSanitizer"),
239 /** Transformation Passes */
240 pub static transform_passes : &'static [(&'static str, &'static str)] = &'static [
241 ("adce", "Aggressive Dead Code Elimination"),
242 ("always-inline", "Inliner for #[inline] functions"),
243 ("argpromotion", "Promote 'by reference' arguments to scalars"),
244 ("bb-vectorize", "Basic-Block Vectorization"),
245 ("block-placement", "Profile Guided Basic Block Placement"),
246 ("bounds-checking", "Run-time bounds checking"),
247 ("break-crit-edges", "Break critical edges in CFG"),
248 ("codegenprepare", "Optimize for code generation"),
249 ("constmerge", "Merge Duplicate Global Constants"),
250 ("constprop", "Simple constant propagation"),
251 ("correlated-propagation", "Value Propagation"),
252 ("da", "Data Layout"),
253 ("dce", "Dead Code Elimination"),
254 ("deadargelim", "Dead Argument Elimination"),
255 ("die", "Dead Instruction Elimination"),
256 ("dse", "Dead Store Elimination"),
257 ("early-cse", "Early CSE"),
258 ("functionattrs", "Deduce function attributes"),
259 ("globaldce", "Dead Global Elimination"),
260 ("globalopt", "Global Variable Optimizer"),
261 ("gvn", "Global Value Numbering"),
262 ("indvars", "Canonicalize Induction Variables"),
263 ("inline", "Function Integration/Inlining"),
264 ("insert-edge-profiling", "Insert instrumentation for edge profiling"),
265 ("insert-gcov-profiling", "Insert instrumentation for GCOV profiling"),
266 ("insert-optimal-edge-profiling", "Insert optimal instrumentation for edge profiling"),
267 ("instcombine", "Combine redundant instructions"),
268 ("instsimplify", "Remove redundant instructions"),
269 ("ipconstprop", "Interprocedural constant propagation"),
270 ("ipsccp", "Interprocedural Sparse Conditional Constant Propagation"),
271 ("jump-threading", "Jump Threading"),
272 ("lcssa", "Loop-Closed SSA Form Pass"),
273 ("licm", "Loop Invariant Code Motion"),
274 ("loop-deletion", "Delete dead loops"),
275 ("loop-extract", "Extract loops into new functions"),
276 ("loop-extract-single", "Extract at most one loop into a new function"),
277 ("loop-idiom", "Recognise loop idioms"),
278 ("loop-instsimplify", "Simplify instructions in loops"),
279 ("loop-reduce", "Loop Strength Reduction"),
280 ("loop-rotate", "Rotate Loops"),
281 ("loop-simplify", "Canonicalize natural loops"),
282 ("loop-unroll", "Unroll loops"),
283 ("loop-unswitch", "Unswitch loops"),
284 ("loop-vectorize", "Loop Vectorization"),
285 ("lower-expect", "Lower 'expect' Intrinsics"),
286 ("mem2reg", "Promote Memory to Register"),
287 ("memcpyopt", "MemCpy Optimization"),
288 ("mergefunc", "Merge Functions"),
289 ("mergereturn", "Unify function exit nodes"),
290 ("partial-inliner", "Partial Inliner"),
291 ("prune-eh", "Remove unused exception handling info"),
292 ("reassociate", "Reassociate expressions"),
293 ("reg2mem", "Demote all values to stack slots"),
294 ("scalarrepl", "Scalar Replacement of Aggregates (DT)"),
295 ("scalarrepl-ssa", "Scalar Replacement of Aggregates (SSAUp)"),
296 ("sccp", "Sparse Conditional Constant Propagation"),
297 ("simplify-libcalls", "Simplify well-known library calls"),
298 ("simplifycfg", "Simplify the CFG"),
299 ("sink", "Code sinking"),
300 ("strip", "Strip all symbols from a module"),
301 ("strip-dead-debug-info", "Strip debug info for unused symbols"),
302 ("strip-dead-prototypes", "Strip Unused Function Prototypes"),
303 ("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics"),
304 ("strip-nondebug", "Strip all symbols, except dbg symbols, from a module"),
305 ("sroa", "Scalar Replacement of Aggregates"),
306 ("tailcallelim", "Tail Call Elimination"),
309 /** Utility Passes */
310 static utility_passes : &'static [(&'static str, &'static str)] = &'static [
311 ("instnamer", "Assign names to anonymous instructions"),
312 ("verify", "Module Verifier"),
317 let mut failed = ~[];
318 unsafe { llvm::LLVMInitializePasses(); }
319 for analysis_passes.iter().advance |&(name,_)| {
320 let pass = create_pass(name);
324 unsafe { llvm::LLVMDestroyPass(pass.get()) }
327 for transform_passes.iter().advance |&(name,_)| {
328 let pass = create_pass(name);
332 unsafe { llvm::LLVMDestroyPass(pass.get()) }
335 for utility_passes.iter().advance |&(name,_)| {
336 let pass = create_pass(name);
340 unsafe { llvm::LLVMDestroyPass(pass.get()) }
344 if failed.len() > 0 {
345 io::println("Some passes don't exist:");
346 for failed.iter().advance |&n| {