diff options
| author | Brandon Edens <brandonedens@gmail.com> | 2016-03-27 12:42:47 -0700 |
|---|---|---|
| committer | Brandon Edens <brandonedens@gmail.com> | 2016-04-28 23:08:30 -0700 |
| commit | b1337d309a67e34c1452b4a9a378a23dbd8b3573 (patch) | |
| tree | 69983bbeb4cc6ccfcd65f19f010f06ad8b8ba40d /src | |
| parent | 8da2bcac5db1e091b90cceb19d0496f0f7501c88 (diff) | |
| download | rust-b1337d309a67e34c1452b4a9a378a23dbd8b3573.tar.gz rust-b1337d309a67e34c1452b4a9a378a23dbd8b3573.zip | |
Add opt-level options for optimizing for size and minimum size. This attempts
to mimic the behavior of clang's options Os and Oz.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/session/config.rs | 22 | ||||
| -rw-r--r-- | src/librustc_llvm/lib.rs | 9 | ||||
| -rw-r--r-- | src/librustc_trans/back/write.rs | 46 | ||||
| -rw-r--r-- | src/librustc_trans/declare.rs | 11 |
4 files changed, 69 insertions, 19 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 9f29f9050e6..6ade74790a5 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -48,7 +48,9 @@ pub enum OptLevel { No, // -O0 Less, // -O1 Default, // -O2 - Aggressive // -O3 + Aggressive, // -O3 + Size, // -Os + SizeMin, // -Oz } #[derive(Clone, Copy, PartialEq)] @@ -567,8 +569,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, debuginfo: Option<usize> = (None, parse_opt_uint, "debug info emission level, 0 = no debug info, 1 = line tables only, \ 2 = full debug info with variable and type information"), - opt_level: Option<usize> = (None, parse_opt_uint, - "optimize with possible levels 0-3"), + opt_level: Option<String> = (None, parse_opt_string, + "optimize with possible levels 0-3, s, or z"), debug_assertions: Option<bool> = (None, parse_opt_bool, "explicitly enable the cfg(debug_assertions) directive"), inline_threshold: Option<usize> = (None, parse_opt_uint, @@ -1125,15 +1127,17 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } OptLevel::Default } else { - match cg.opt_level { + match cg.opt_level.as_ref().map(String::as_ref) { None => OptLevel::No, - Some(0) => OptLevel::No, - Some(1) => OptLevel::Less, - Some(2) => OptLevel::Default, - Some(3) => OptLevel::Aggressive, + Some("0") => OptLevel::No, + Some("1") => OptLevel::Less, + Some("2") => OptLevel::Default, + Some("3") => OptLevel::Aggressive, + Some("s") => OptLevel::Size, + Some("z") => OptLevel::SizeMin, Some(arg) => { early_error(error_format, &format!("optimization level needs to be \ - between 0-3 (instead was `{}`)", + between 0-3, s, or z (instead was `{}`)", arg)); } } diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 526b6bf68be..ea0d8eae75d 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -44,6 +44,7 @@ pub use self::FileType::*; pub use self::MetadataType::*; pub use self::AsmDialect::*; pub use self::CodeGenOptLevel::*; +pub use self::CodeGenOptSize::*; pub use self::RelocMode::*; pub use self::CodeGenModel::*; pub use self::DiagnosticKind::*; @@ -377,6 +378,14 @@ pub enum CodeGenOptLevel { #[derive(Copy, Clone, PartialEq)] #[repr(C)] +pub enum CodeGenOptSize { + CodeGenOptSizeNone = 0, + CodeGenOptSizeDefault = 1, + CodeGenOptSizeAggressive = 2, +} + +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] pub enum RelocMode { RelocDefault = 0, RelocStatic = 1, diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 8a915f04405..777245c4e0c 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -140,6 +140,15 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { config::OptLevel::Less => llvm::CodeGenLevelLess, config::OptLevel::Default => llvm::CodeGenLevelDefault, config::OptLevel::Aggressive => llvm::CodeGenLevelAggressive, + _ => llvm::CodeGenLevelDefault, + } +} + +fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize { + match optimize { + config::OptLevel::Size => llvm::CodeGenOptSizeDefault, + config::OptLevel::SizeMin => llvm::CodeGenOptSizeAggressive, + _ => llvm::CodeGenOptSizeNone, } } @@ -237,6 +246,9 @@ pub struct ModuleConfig { /// absolutely no optimizations (used for the metadata module). opt_level: Option<llvm::CodeGenOptLevel>, + /// Some(level) to optimize binary size, or None to not affect program size. + opt_size: Option<llvm::CodeGenOptSize>, + // Flags indicating which outputs to produce. emit_no_opt_bc: bool, emit_bc: bool, @@ -268,6 +280,7 @@ impl ModuleConfig { tm: tm, passes: passes, opt_level: None, + opt_size: None, emit_no_opt_bc: false, emit_bc: false, @@ -637,6 +650,7 @@ pub fn run_passes(sess: &Session, let mut metadata_config = ModuleConfig::new(tm, vec!()); modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize)); + modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize)); // Save all versions of the bytecode if we're saving our temporaries. if sess.opts.cg.save_temps { @@ -991,13 +1005,19 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef, // reasonable defaults and prepare it to actually populate the pass // manager. let builder = llvm::LLVMPassManagerBuilderCreate(); - let opt = config.opt_level.unwrap_or(llvm::CodeGenLevelNone); + let opt_level = config.opt_level.unwrap_or(llvm::CodeGenLevelNone); + let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone); let inline_threshold = config.inline_threshold; - llvm::LLVMRustConfigurePassManagerBuilder(builder, opt, + llvm::LLVMRustConfigurePassManagerBuilder(builder, opt_level, config.merge_functions, config.vectorize_slp, config.vectorize_loop); + llvm::LLVMPassManagerBuilderSetSizeLevel(builder, opt_size as u32); + + if opt_size != llvm::CodeGenOptSizeNone { + llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(builder, 1); + } llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins); @@ -1005,22 +1025,28 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef, // always-inline functions (but don't add lifetime intrinsics), at O1 we // inline with lifetime intrinsics, and O2+ we add an inliner with a // thresholds copied from clang. - match (opt, inline_threshold) { - (_, Some(t)) => { + match (opt_level, opt_size, inline_threshold) { + (_, _, Some(t)) => { llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32); } - (llvm::CodeGenLevelNone, _) => { + (llvm::CodeGenLevelAggressive, _, _) => { + llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275); + } + (_, llvm::CodeGenOptSizeDefault, _) => { + llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 75); + } + (_, llvm::CodeGenOptSizeAggressive, _) => { + llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25); + } + (llvm::CodeGenLevelNone, _, _) => { llvm::LLVMRustAddAlwaysInlinePass(builder, false); } - (llvm::CodeGenLevelLess, _) => { + (llvm::CodeGenLevelLess, _, _) => { llvm::LLVMRustAddAlwaysInlinePass(builder, true); } - (llvm::CodeGenLevelDefault, _) => { + (llvm::CodeGenLevelDefault, _, _) => { llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225); } - (llvm::CodeGenLevelAggressive, _) => { - llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275); - } } f(builder); diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index eb520fe744a..9a4d20ca301 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -69,6 +69,17 @@ fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoRedZone) } + match ccx.tcx().sess.opts.cg.opt_level.as_ref().map(String::as_ref) { + Some("s") => { + llvm::SetFunctionAttribute(llfn, llvm::Attribute::OptimizeForSize); + }, + Some("z") => { + llvm::SetFunctionAttribute(llfn, llvm::Attribute::MinSize); + llvm::SetFunctionAttribute(llfn, llvm::Attribute::OptimizeForSize); + }, + _ => {}, + } + llfn } |
