Skip to content

Commit d694e28

Browse files
committed
Refactor optimization pass handling.
Refactor the optimization passes to explicitly use the passes. This commit just re-implements the same passes as were already being run. It also adds an option (behind `-Z`) to run the LLVM lint pass on the unoptimized IR.
1 parent e3d0c1e commit d694e28

File tree

11 files changed

+717
-99
lines changed

11 files changed

+717
-99
lines changed

Makefile.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ DRIVER_CRATE := $(S)src/driver/driver.rs
275275

276276
# FIXME: x86-ism
277277
LLVM_COMPONENTS=x86 arm mips ipo bitreader bitwriter linker asmparser jit mcjit \
278-
interpreter
278+
interpreter instrumentation
279279

280280
define DEF_LLVM_VARS
281281
# The configure script defines these variables with the target triples

mk/rustllvm.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ LLVM_EXTRA_INCDIRS_$(1)= -iquote $(S)src/llvm/include \
2222
-iquote llvm/$(1)/include
2323
endif
2424

25-
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp)
25+
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp PassWrapper.cpp)
2626

2727
RUSTLLVM_DEF_$(1) := rustllvm/rustllvm$(CFG_DEF_SUFFIX_$(1))
2828

src/librustc/back/link.rs

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ pub mod write {
183183
use lib::llvm::{False, ModuleRef, mk_pass_manager, mk_target_data};
184184
use lib;
185185

186+
use back::passes;
187+
186188
use core::libc::{c_int, c_uint};
187189
use core::path::Path;
188190
use core::run;
@@ -202,16 +204,12 @@ pub mod write {
202204
unsafe {
203205
let opts = sess.opts;
204206
if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
205-
let mut pm = mk_pass_manager();
206207
let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
208+
let pm = mk_pass_manager();
207209
llvm::LLVMAddTargetData(td.lltd, pm.llpm);
208-
// FIXME (#2812): run the linter here also, once there are llvm-c
209-
// bindings for it.
210210

211211
// Generate a pre-optimization intermediate file if -save-temps
212212
// was specified.
213-
214-
215213
if opts.save_temps {
216214
match output_type {
217215
output_type_bitcode => {
@@ -230,50 +228,22 @@ pub mod write {
230228
}
231229
}
232230
}
233-
if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
234-
// FIXME (#2396): This is mostly a copy of the bits of opt's -O2
235-
// that are available in the C api.
236-
// Also: We might want to add optimization levels like -O1, -O2,
237-
// -Os, etc
238-
// Also: Should we expose and use the pass lists used by the opt
239-
// tool?
240-
241-
if opts.optimize != session::No {
242-
let fpm = mk_pass_manager();
243-
llvm::LLVMAddTargetData(td.lltd, fpm.llpm);
244-
245-
let FPMB = llvm::LLVMPassManagerBuilderCreate();
246-
llvm::LLVMPassManagerBuilderSetOptLevel(FPMB, 2u as c_uint);
247-
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(
248-
FPMB, fpm.llpm);
249-
llvm::LLVMPassManagerBuilderDispose(FPMB);
250-
251-
llvm::LLVMRunPassManager(fpm.llpm, llmod);
252-
let mut threshold = 225;
253-
if opts.optimize == session::Aggressive { threshold = 275; }
254-
255-
let MPMB = llvm::LLVMPassManagerBuilderCreate();
256-
llvm::LLVMPassManagerBuilderSetOptLevel(MPMB,
257-
opts.optimize as
258-
c_uint);
259-
llvm::LLVMPassManagerBuilderSetSizeLevel(MPMB, False);
260-
llvm::LLVMPassManagerBuilderSetDisableUnitAtATime(MPMB,
261-
False);
262-
llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(MPMB,
263-
False);
264-
llvm::LLVMPassManagerBuilderSetDisableSimplifyLibCalls(MPMB,
265-
False);
266-
267-
if threshold != 0u {
268-
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold
269-
(MPMB, threshold as c_uint);
270-
}
271-
llvm::LLVMPassManagerBuilderPopulateModulePassManager(
272-
MPMB, pm.llpm);
273231

274-
llvm::LLVMPassManagerBuilderDispose(MPMB);
232+
let mut mpm = passes::PassManager::new(td.lltd);
233+
234+
if !sess.no_verify() {
235+
mpm.addPass(llvm::LLVMCreateVerifierPass());
275236
}
276-
if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
237+
238+
if sess.lint_llvm() {
239+
mpm.addPass(llvm::LLVMCreateLintPass());
240+
}
241+
242+
passes::populatePassManager(&mut mpm, opts.optimize);
243+
244+
debug!("Running Module Optimization Pass");
245+
mpm.run(llmod);
246+
277247
if is_object_or_assembly_or_exe(output_type) || opts.jit {
278248
let LLVMOptNone = 0 as c_int; // -O0
279249
let LLVMOptLess = 1 as c_int; // -O1
@@ -312,12 +282,9 @@ pub mod write {
312282
// Always output the bitcode file with --save-temps
313283

314284
let filename = output.with_filetype("opt.bc");
315-
llvm::LLVMRunPassManager(pm.llpm, llmod);
316285
str::as_c_str(filename.to_str(), |buf| {
317286
llvm::LLVMWriteBitcodeToFile(llmod, buf)
318287
});
319-
pm = mk_pass_manager();
320-
321288
// Save the assembly file if -S is used
322289
if output_type == output_type_assembly {
323290
WriteOutputFile(
@@ -377,7 +344,6 @@ pub mod write {
377344
} else {
378345
// If only a bitcode file is asked for by using the
379346
// '--emit-llvm' flag, then output it here
380-
llvm::LLVMRunPassManager(pm.llpm, llmod);
381347
str::as_c_str(output.to_str(),
382348
|buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) );
383349
}

src/librustc/back/passes.rs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright 2012 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.
4+
//
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.
10+
11+
use core::prelude::*;
12+
13+
use driver::session::{Session, Session_, No, Less, Default};
14+
use driver::session;
15+
use lib::llvm::{PassRef, ModuleRef,PassManagerRef,ValueRef,TargetDataRef};
16+
use lib::llvm::llvm;
17+
use lib;
18+
19+
pub struct PassManager {
20+
priv llpm: PassManagerRef
21+
}
22+
23+
impl Drop for PassManager {
24+
fn finalize(&self) {
25+
unsafe {
26+
llvm::LLVMDisposePassManager(self.llpm);
27+
}
28+
}
29+
}
30+
31+
impl PassManager {
32+
pub fn new(td: TargetDataRef) -> PassManager {
33+
unsafe {
34+
let pm = PassManager {
35+
llpm: llvm::LLVMCreatePassManager()
36+
};
37+
llvm::LLVMAddTargetData(td, pm.llpm);
38+
39+
return pm;
40+
}
41+
}
42+
43+
pub fn addPass(&mut self, pass:PassRef) {
44+
unsafe {
45+
llvm::LLVMAddPass(self.llpm, pass);
46+
}
47+
}
48+
49+
pub fn run(&self, md:ModuleRef) -> bool {
50+
unsafe {
51+
llvm::LLVMRunPassManager(self.llpm, md) == lib::llvm::True
52+
}
53+
}
54+
}
55+
56+
57+
pub fn populatePassManager(pm: &mut PassManager, level:session::OptLevel) {
58+
unsafe {
59+
// We add a lot of potentially-unused prototypes, so strip them right at the
60+
// start. We do it again later when we know for certain which ones are used
61+
pm.addPass(llvm::LLVMCreateStripDeadPrototypesPass());
62+
63+
if level == session::No {
64+
pm.addPass(llvm::LLVMCreateAlwaysInlinerPass());
65+
return;
66+
}
67+
68+
//NOTE: Add library info
69+
70+
pm.addPass(llvm::LLVMCreateTypeBasedAliasAnalysisPass());
71+
pm.addPass(llvm::LLVMCreateBasicAliasAnalysisPass());
72+
73+
pm.addPass(llvm::LLVMCreateSROAPass());
74+
pm.addPass(llvm::LLVMCreateEarlyCSEPass());
75+
pm.addPass(llvm::LLVMCreateLowerExpectIntrinsicPass());
76+
77+
pm.addPass(llvm::LLVMCreateGlobalOptimizerPass());
78+
pm.addPass(llvm::LLVMCreateIPSCCPPass());
79+
pm.addPass(llvm::LLVMCreateDeadArgEliminationPass());
80+
pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
81+
pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
82+
83+
pm.addPass(llvm::LLVMCreatePruneEHPass());
84+
85+
match level {
86+
session::Less => pm.addPass(llvm::LLVMCreateFunctionInliningPass(200)),
87+
session::Default => pm.addPass(llvm::LLVMCreateFunctionInliningPass(225)),
88+
session::Aggressive => pm.addPass(llvm::LLVMCreateFunctionInliningPass(275)),
89+
session::No => ()
90+
}
91+
92+
pm.addPass(llvm::LLVMCreateFunctionAttrsPass());
93+
94+
if level == session::Aggressive {
95+
pm.addPass(llvm::LLVMCreateArgumentPromotionPass());
96+
}
97+
98+
pm.addPass(llvm::LLVMCreateSROAPass());
99+
100+
pm.addPass(llvm::LLVMCreateEarlyCSEPass());
101+
pm.addPass(llvm::LLVMCreateSimplifyLibCallsPass());
102+
pm.addPass(llvm::LLVMCreateJumpThreadingPass());
103+
pm.addPass(llvm::LLVMCreateCorrelatedValuePropagationPass());
104+
pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
105+
pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
106+
107+
pm.addPass(llvm::LLVMCreateTailCallEliminationPass());
108+
pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
109+
pm.addPass(llvm::LLVMCreateReassociatePass());
110+
pm.addPass(llvm::LLVMCreateLoopRotatePass());
111+
pm.addPass(llvm::LLVMCreateLICMPass());
112+
113+
pm.addPass(llvm::LLVMCreateLoopUnswitchPass());
114+
115+
pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
116+
pm.addPass(llvm::LLVMCreateIndVarSimplifyPass());
117+
pm.addPass(llvm::LLVMCreateLoopIdiomPass());
118+
pm.addPass(llvm::LLVMCreateLoopDeletionPass());
119+
120+
if level == session::Aggressive {
121+
pm.addPass(llvm::LLVMCreateLoopUnrollPass());
122+
}
123+
pm.addPass(llvm::LLVMCreateLoopUnrollPass());
124+
125+
if level != session::Less {
126+
pm.addPass(llvm::LLVMCreateGVNPass());
127+
}
128+
pm.addPass(llvm::LLVMCreateMemCpyOptPass());
129+
pm.addPass(llvm::LLVMCreateSCCPPass());
130+
131+
pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
132+
pm.addPass(llvm::LLVMCreateJumpThreadingPass());
133+
pm.addPass(llvm::LLVMCreateCorrelatedValuePropagationPass());
134+
pm.addPass(llvm::LLVMCreateDeadStoreEliminationPass());
135+
136+
pm.addPass(llvm::LLVMCreateBBVectorizePass());
137+
pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
138+
if level != session::Less {
139+
pm.addPass(llvm::LLVMCreateGlobalDCEPass());
140+
pm.addPass(llvm::LLVMCreateConstantMergePass());
141+
}
142+
143+
if level == session::Aggressive {
144+
pm.addPass(llvm::LLVMCreateMergeFunctionsPass());
145+
}
146+
147+
pm.addPass(llvm::LLVMCreateStripDeadPrototypesPass());
148+
149+
}
150+
}

src/librustc/driver/session.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ pub static extra_debug_info: uint = 1 << 21;
6969
pub static statik: uint = 1 << 22;
7070
pub static print_link_args: uint = 1 << 23;
7171
pub static no_debug_borrows: uint = 1 << 24;
72+
pub static lint_llvm : uint = 1 << 25;
7273

7374
pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
7475
~[(~"verbose", ~"in general, enable more debug printouts", verbose),
@@ -107,6 +108,9 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
107108
(~"no-debug-borrows",
108109
~"do not show where borrow checks fail",
109110
no_debug_borrows),
111+
(~"lint-llvm",
112+
~"Run the LLVM lint pass on the pre-optimization IR",
113+
lint_llvm),
110114
]
111115
}
112116

@@ -265,6 +269,7 @@ pub impl Session_ {
265269
fn meta_stats(@self) -> bool { self.debugging_opt(meta_stats) }
266270
fn asm_comments(@self) -> bool { self.debugging_opt(asm_comments) }
267271
fn no_verify(@self) -> bool { self.debugging_opt(no_verify) }
272+
fn lint_llvm(@self) -> bool { self.debugging_opt(lint_llvm) }
268273
fn trace(@self) -> bool { self.debugging_opt(trace) }
269274
fn coherence(@self) -> bool { self.debugging_opt(coherence) }
270275
fn borrowck_stats(@self) -> bool { self.debugging_opt(borrowck_stats) }

0 commit comments

Comments
 (0)