Skip to content

Tweak pass management and add some more options #8894

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 31, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 75 additions & 41 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ pub mod write {
use lib;

use std::c_str::ToCStr;
use std::libc::c_uint;
use std::libc::{c_uint, c_int};
use std::path::Path;
use std::run;
use std::str;
Expand Down Expand Up @@ -257,17 +257,7 @@ pub mod write {
}
}

// Copy what clan does by turning on loop vectorization at O2 and
// slp vectorization at O3
let vectorize_loop = !sess.no_vectorize_loops() &&
(sess.opts.optimize == session::Default ||
sess.opts.optimize == session::Aggressive);
let vectorize_slp = !sess.no_vectorize_slp() &&
sess.opts.optimize == session::Aggressive;
llvm::LLVMRustSetLLVMOptions(sess.print_llvm_passes(),
vectorize_loop,
vectorize_slp,
sess.time_llvm_passes());
configure_llvm(sess);

let OptLevel = match sess.opts.optimize {
session::No => lib::llvm::CodeGenLevelNone,
Expand All @@ -293,12 +283,9 @@ pub mod write {
// Create the two optimizing pass managers. These mirror what clang
// does, and are by populated by LLVM's default PassManagerBuilder.
// Each manager has a different set of passes, but they also share
// some common passes. Each one is initialized with the analyis
// passes the target requires, and then further passes are added.
// some common passes.
let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
let mpm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);

// If we're verifying or linting, add them to the function pass
// manager.
Expand All @@ -308,32 +295,11 @@ pub mod write {
if !sess.no_verify() { assert!(addpass("verify")); }
if sess.lint_llvm() { assert!(addpass("lint")); }

// Create the PassManagerBuilder for LLVM. We configure it with
// reasonable defaults and prepare it to actually populate the pass
// manager.
let builder = llvm::LLVMPassManagerBuilderCreate();
match sess.opts.optimize {
session::No => {
// Don't add lifetime intrinsics add O0
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
}
// numeric values copied from clang
session::Less => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
225);
}
session::Default | session::Aggressive => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
275);
}
if !sess.no_prepopulate_passes() {
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
populate_llvm_passess(fpm, mpm, llmod, OptLevel);
}
llvm::LLVMPassManagerBuilderSetOptLevel(builder, OptLevel as c_uint);
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod);

// Use the builder to populate the function/module pass managers.
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
llvm::LLVMPassManagerBuilderDispose(builder);

for pass in sess.opts.custom_passes.iter() {
do pass.with_c_str |s| {
Expand Down Expand Up @@ -424,6 +390,74 @@ pub mod write {
sess.abort_if_errors();
}
}

unsafe fn configure_llvm(sess: Session) {
// Copy what clan does by turning on loop vectorization at O2 and
// slp vectorization at O3
let vectorize_loop = !sess.no_vectorize_loops() &&
(sess.opts.optimize == session::Default ||
sess.opts.optimize == session::Aggressive);
let vectorize_slp = !sess.no_vectorize_slp() &&
sess.opts.optimize == session::Aggressive;

let mut llvm_c_strs = ~[];
let mut llvm_args = ~[];
let add = |arg: &str| {
let s = arg.to_c_str();
llvm_args.push(s.with_ref(|p| p));
llvm_c_strs.push(s);
};
add("rustc"); // fake program name
add("-arm-enable-ehabi");
add("-arm-enable-ehabi-descriptors");
if vectorize_loop { add("-vectorize-loops"); }
if vectorize_slp { add("-vectorize-slp"); }
if sess.time_llvm_passes() { add("-time-passes"); }
if sess.print_llvm_passes() { add("-debug-pass=Structure"); }

for arg in sess.opts.llvm_args.iter() {
add(*arg);
}

do llvm_args.as_imm_buf |p, len| {
llvm::LLVMRustSetLLVMOptions(len as c_int, p);
}
}

unsafe fn populate_llvm_passess(fpm: lib::llvm::PassManagerRef,
mpm: lib::llvm::PassManagerRef,
llmod: ModuleRef,
opt: lib::llvm::CodeGenOptLevel) {
// Create the PassManagerBuilder for LLVM. We configure it with
// reasonable defaults and prepare it to actually populate the pass
// manager.
let builder = llvm::LLVMPassManagerBuilderCreate();
match opt {
lib::llvm::CodeGenLevelNone => {
// Don't add lifetime intrinsics add O0
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
}
lib::llvm::CodeGenLevelLess => {
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
}
// numeric values copied from clang
lib::llvm::CodeGenLevelDefault => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
225);
}
lib::llvm::CodeGenLevelAggressive => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
275);
}
}
llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod);

// Use the builder to populate the function/module pass managers.
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
llvm::LLVMPassManagerBuilderDispose(builder);
}
}


Expand Down
11 changes: 11 additions & 0 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -737,13 +737,22 @@ pub fn build_session_options(binary: @str,
}).collect()
}
};
let llvm_args = match getopts::opt_maybe_str(matches, "llvm-args") {
None => ~[],
Some(s) => {
s.split_iter(|c: char| c == ' ' || c == ',').map(|s| {
s.trim().to_owned()
}).collect()
}
};

let sopts = @session::options {
crate_type: crate_type,
is_static: statik,
gc: gc,
optimize: opt_level,
custom_passes: custom_passes,
llvm_args: llvm_args,
debuginfo: debuginfo,
extra_debuginfo: extra_debuginfo,
lint_opts: lint_opts,
Expand Down Expand Up @@ -851,6 +860,8 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] {
Appends to the default list of passes to run for the \
specified current optimization level. A value of \
\"list\" will list all of the available passes", "NAMES"),
optopt("", "llvm-args", "A list of arguments to pass to llvm, comma \
separated", "ARGS"),
optopt( "", "out-dir",
"Write output to compiler-chosen filename
in <dir>", "DIR"),
Expand Down
10 changes: 10 additions & 0 deletions src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub static once_fns: uint = 1 << 26;
pub static print_llvm_passes: uint = 1 << 27;
pub static no_vectorize_loops: uint = 1 << 28;
pub static no_vectorize_slp: uint = 1 << 29;
pub static no_prepopulate_passes: uint = 1 << 30;

pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
~[(~"verbose", ~"in general, enable more debug printouts", verbose),
Expand Down Expand Up @@ -126,6 +127,10 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
(~"print-llvm-passes",
~"Prints the llvm optimization passes being run",
print_llvm_passes),
(~"no-prepopulate-passes",
~"Don't pre-populate the pass managers with a list of passes, only use \
the passes from --passes",
no_prepopulate_passes),
(~"no-vectorize-loops",
~"Don't run the loop vectorization optimization passes",
no_vectorize_loops),
Expand All @@ -152,6 +157,7 @@ pub struct options {
gc: bool,
optimize: OptLevel,
custom_passes: ~[~str],
llvm_args: ~[~str],
debuginfo: bool,
extra_debuginfo: bool,
lint_opts: ~[(lint::lint, lint::level)],
Expand Down Expand Up @@ -320,6 +326,9 @@ impl Session_ {
pub fn print_llvm_passes(@self) -> bool {
self.debugging_opt(print_llvm_passes)
}
pub fn no_prepopulate_passes(@self) -> bool {
self.debugging_opt(no_prepopulate_passes)
}
pub fn no_vectorize_loops(@self) -> bool {
self.debugging_opt(no_vectorize_loops)
}
Expand Down Expand Up @@ -351,6 +360,7 @@ pub fn basic_options() -> @options {
gc: false,
optimize: No,
custom_passes: ~[],
llvm_args: ~[],
debuginfo: false,
extra_debuginfo: false,
lint_opts: ~[],
Expand Down
6 changes: 2 additions & 4 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ pub enum AsmDialect {
AD_Intel = 1
}

#[deriving(Eq)]
pub enum CodeGenOptLevel {
CodeGenLevelNone = 0,
CodeGenLevelLess = 1,
Expand Down Expand Up @@ -2123,10 +2124,7 @@ pub mod llvm {
pub fn LLVMRustPrintModule(PM: PassManagerRef,
M: ModuleRef,
Output: *c_char);
pub fn LLVMRustSetLLVMOptions(PrintPasses: bool,
VectorizeLoops: bool,
VectorizeSLP: bool,
TimePasses: bool);
pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: **c_char);
pub fn LLVMRustPrintPasses();
pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *c_char);
pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef,
Expand Down
25 changes: 2 additions & 23 deletions src/rustllvm/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,36 +143,15 @@ LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) {
}

extern "C" void
LLVMRustSetLLVMOptions(bool PrintPasses,
bool VectorizeLoops,
bool VectorizeSLP,
bool TimePasses) {
LLVMRustSetLLVMOptions(int Argc, char **Argv) {
// Initializing the command-line options more than once is not allowed. So,
// check if they've already been initialized. (This could happen if we're
// being called from rustpkg, for example). If the arguments change, then
// that's just kinda unfortunate.
static bool initialized = false;
if (initialized) return;

int argc = 3;
const char *argv[20] = {"rustc",
"-arm-enable-ehabi",
"-arm-enable-ehabi-descriptors"};
if (PrintPasses) {
argv[argc++] = "-debug-pass";
argv[argc++] = "Structure";
}
if (VectorizeLoops) {
argv[argc++] = "-vectorize-loops";
}
if (VectorizeSLP) {
argv[argc++] = "-vectorize-slp";
}
if (TimePasses) {
argv[argc++] = "-time-passes";
}
cl::ParseCommandLineOptions(argc, argv);
initialized = true;
cl::ParseCommandLineOptions(Argc, Argv);
}

extern "C" bool
Expand Down