Skip to content
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

Refactor optimization pass handling. #6778

Merged
merged 6 commits into from
May 29, 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
2 changes: 1 addition & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ DRIVER_CRATE := $(S)src/driver/driver.rs

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

define DEF_LLVM_VARS
# The configure script defines these variables with the target triples
Expand Down
2 changes: 1 addition & 1 deletion mk/rustllvm.mk
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ LLVM_EXTRA_INCDIRS_$(1)= -iquote $(S)src/llvm/include \
-iquote llvm/$(1)/include
endif

RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp)
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp PassWrapper.cpp)

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

Expand Down
70 changes: 18 additions & 52 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,11 @@ pub mod write {
use driver::session::Session;
use driver::session;
use lib::llvm::llvm;
use lib::llvm::{False, ModuleRef, mk_pass_manager, mk_target_data};
use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data};
use lib;

use back::passes;

use core::libc::{c_int, c_uint};
use core::path::Path;
use core::run;
Expand All @@ -202,16 +204,12 @@ pub mod write {
unsafe {
let opts = sess.opts;
if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
let mut pm = mk_pass_manager();
let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
let pm = mk_pass_manager();
llvm::LLVMAddTargetData(td.lltd, pm.llpm);
// FIXME (#2812): run the linter here also, once there are llvm-c
// bindings for it.

// Generate a pre-optimization intermediate file if -save-temps
// was specified.


if opts.save_temps {
match output_type {
output_type_bitcode => {
Expand All @@ -230,50 +228,22 @@ pub mod write {
}
}
}
if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
// FIXME (#2396): This is mostly a copy of the bits of opt's -O2
// that are available in the C api.
// Also: We might want to add optimization levels like -O1, -O2,
// -Os, etc
// Also: Should we expose and use the pass lists used by the opt
// tool?

if opts.optimize != session::No {
let fpm = mk_pass_manager();
llvm::LLVMAddTargetData(td.lltd, fpm.llpm);

let FPMB = llvm::LLVMPassManagerBuilderCreate();
llvm::LLVMPassManagerBuilderSetOptLevel(FPMB, 2u as c_uint);
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(
FPMB, fpm.llpm);
llvm::LLVMPassManagerBuilderDispose(FPMB);

llvm::LLVMRunPassManager(fpm.llpm, llmod);
let mut threshold = 225;
if opts.optimize == session::Aggressive { threshold = 275; }

let MPMB = llvm::LLVMPassManagerBuilderCreate();
llvm::LLVMPassManagerBuilderSetOptLevel(MPMB,
opts.optimize as
c_uint);
llvm::LLVMPassManagerBuilderSetSizeLevel(MPMB, False);
llvm::LLVMPassManagerBuilderSetDisableUnitAtATime(MPMB,
False);
llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(MPMB,
False);
llvm::LLVMPassManagerBuilderSetDisableSimplifyLibCalls(MPMB,
False);

if threshold != 0u {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold
(MPMB, threshold as c_uint);
}
llvm::LLVMPassManagerBuilderPopulateModulePassManager(
MPMB, pm.llpm);

llvm::LLVMPassManagerBuilderDispose(MPMB);
let mut mpm = passes::PassManager::new(td.lltd);

if !sess.no_verify() {
mpm.addPass(llvm::LLVMCreateVerifierPass());
}
if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }

if sess.lint_llvm() {
mpm.addPass(llvm::LLVMCreateLintPass());
}

passes::populatePassManager(&mut mpm, opts.optimize);

debug!("Running Module Optimization Pass");
mpm.run(llmod);

if is_object_or_assembly_or_exe(output_type) || opts.jit {
let LLVMOptNone = 0 as c_int; // -O0
let LLVMOptLess = 1 as c_int; // -O1
Expand Down Expand Up @@ -312,12 +282,9 @@ pub mod write {
// Always output the bitcode file with --save-temps

let filename = output.with_filetype("opt.bc");
llvm::LLVMRunPassManager(pm.llpm, llmod);
str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf)
});
pm = mk_pass_manager();

// Save the assembly file if -S is used
if output_type == output_type_assembly {
WriteOutputFile(
Expand Down Expand Up @@ -377,7 +344,6 @@ pub mod write {
} else {
// If only a bitcode file is asked for by using the
// '--emit-llvm' flag, then output it here
llvm::LLVMRunPassManager(pm.llpm, llmod);
str::as_c_str(output.to_str(),
|buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) );
}
Expand Down
154 changes: 154 additions & 0 deletions src/librustc/back/passes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::prelude::*;

use driver::session;
use lib::llvm::{PassRef, ModuleRef,PassManagerRef,TargetDataRef};
use lib::llvm::llvm;
use lib;

pub struct PassManager {
priv llpm: PassManagerRef
}

impl Drop for PassManager {
fn finalize(&self) {
unsafe {
llvm::LLVMDisposePassManager(self.llpm);
}
}
}

impl PassManager {
pub fn new(td: TargetDataRef) -> PassManager {
unsafe {
let pm = PassManager {
llpm: llvm::LLVMCreatePassManager()
};
llvm::LLVMAddTargetData(td, pm.llpm);

return pm;
}
}

pub fn addPass(&mut self, pass:PassRef) {
unsafe {
llvm::LLVMAddPass(self.llpm, pass);
}
}

pub fn run(&self, md:ModuleRef) -> bool {
unsafe {
llvm::LLVMRunPassManager(self.llpm, md) == lib::llvm::True
}
}
}


pub fn populatePassManager(pm: &mut PassManager, level:session::OptLevel) {
unsafe {
// We add a lot of normally-unused prototypes, so always strip them
// straight away, later passes will get rid of any that are optimized
// away
pm.addPass(llvm::LLVMCreateStripDeadPrototypesPass());
if level == session::No {
pm.addPass(llvm::LLVMCreateAlwaysInlinerPass());

return;
}

//NOTE: Add library info

pm.addPass(llvm::LLVMCreateTypeBasedAliasAnalysisPass());
pm.addPass(llvm::LLVMCreateBasicAliasAnalysisPass());

pm.addPass(llvm::LLVMCreateSROAPass());
pm.addPass(llvm::LLVMCreateEarlyCSEPass());
pm.addPass(llvm::LLVMCreateLowerExpectIntrinsicPass());

pm.addPass(llvm::LLVMCreateGlobalOptimizerPass());
pm.addPass(llvm::LLVMCreateIPSCCPPass());
pm.addPass(llvm::LLVMCreateDeadArgEliminationPass());
pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
pm.addPass(llvm::LLVMCreateCFGSimplificationPass());

pm.addPass(llvm::LLVMCreatePruneEHPass());

if level == session::Aggressive {
// Do this before inlining, since inlining might
// make minor changes to functions that mean they
// can't be merged, despite being almost identical
pm.addPass(llvm::LLVMCreateMergeFunctionsPass());
}

match level {
session::Less => pm.addPass(llvm::LLVMCreateFunctionInliningPass(200)),
session::Default => pm.addPass(llvm::LLVMCreateFunctionInliningPass(225)),
session::Aggressive => pm.addPass(llvm::LLVMCreateFunctionInliningPass(275)),
session::No => ()
}

pm.addPass(llvm::LLVMCreateFunctionAttrsPass());

if level == session::Aggressive {
pm.addPass(llvm::LLVMCreateArgumentPromotionPass());
}

pm.addPass(llvm::LLVMCreateEarlyCSEPass());
pm.addPass(llvm::LLVMCreateSimplifyLibCallsPass());
pm.addPass(llvm::LLVMCreateJumpThreadingPass());
pm.addPass(llvm::LLVMCreateCorrelatedValuePropagationPass());
pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
pm.addPass(llvm::LLVMCreateInstructionCombiningPass());

pm.addPass(llvm::LLVMCreateTailCallEliminationPass());
pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
pm.addPass(llvm::LLVMCreateReassociatePass());
pm.addPass(llvm::LLVMCreateLoopRotatePass());
pm.addPass(llvm::LLVMCreateLICMPass());

pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
pm.addPass(llvm::LLVMCreateIndVarSimplifyPass());
pm.addPass(llvm::LLVMCreateLoopIdiomPass());
pm.addPass(llvm::LLVMCreateLoopDeletionPass());

if level == session::Aggressive {
pm.addPass(llvm::LLVMCreateLoopVectorizePass());
}
pm.addPass(llvm::LLVMCreateLoopUnrollPass());

if level != session::Less {
pm.addPass(llvm::LLVMCreateGVNPass());
}
pm.addPass(llvm::LLVMCreateMemCpyOptPass());
pm.addPass(llvm::LLVMCreateSCCPPass());

pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
pm.addPass(llvm::LLVMCreateJumpThreadingPass());
pm.addPass(llvm::LLVMCreateCorrelatedValuePropagationPass());
pm.addPass(llvm::LLVMCreateDeadStoreEliminationPass());

pm.addPass(llvm::LLVMCreateBBVectorizePass());
pm.addPass(llvm::LLVMCreateInstructionCombiningPass());
pm.addPass(llvm::LLVMCreateEarlyCSEPass());

pm.addPass(llvm::LLVMCreateLoopUnrollPass());

pm.addPass(llvm::LLVMCreateAggressiveDCEPass());
pm.addPass(llvm::LLVMCreateCFGSimplificationPass());
pm.addPass(llvm::LLVMCreateInstructionSimplifierPass());

if level != session::Less {
pm.addPass(llvm::LLVMCreateGlobalDCEPass());
pm.addPass(llvm::LLVMCreateConstantMergePass());
}
}
}
5 changes: 5 additions & 0 deletions src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub static extra_debug_info: uint = 1 << 21;
pub static statik: uint = 1 << 22;
pub static print_link_args: uint = 1 << 23;
pub static no_debug_borrows: uint = 1 << 24;
pub static lint_llvm : uint = 1 << 25;

pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
~[(~"verbose", ~"in general, enable more debug printouts", verbose),
Expand Down Expand Up @@ -107,6 +108,9 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
(~"no-debug-borrows",
~"do not show where borrow checks fail",
no_debug_borrows),
(~"lint-llvm",
~"Run the LLVM lint pass on the pre-optimization IR",
lint_llvm),
]
}

Expand Down Expand Up @@ -265,6 +269,7 @@ pub impl Session_ {
fn meta_stats(@self) -> bool { self.debugging_opt(meta_stats) }
fn asm_comments(@self) -> bool { self.debugging_opt(asm_comments) }
fn no_verify(@self) -> bool { self.debugging_opt(no_verify) }
fn lint_llvm(@self) -> bool { self.debugging_opt(lint_llvm) }
fn trace(@self) -> bool { self.debugging_opt(trace) }
fn coherence(@self) -> bool { self.debugging_opt(coherence) }
fn borrowck_stats(@self) -> bool { self.debugging_opt(borrowck_stats) }
Expand Down
Loading