mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 14:57:14 +00:00
Merge branch 'configure-lto' of https://github.com/alexcrichton/rust into rollup
This commit is contained in:
commit
e61c609320
@ -72,6 +72,26 @@ pub enum OptLevel {
|
||||
SizeMin, // -Oz
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Hash)]
|
||||
pub enum Lto {
|
||||
/// Don't do any LTO whatsoever
|
||||
No,
|
||||
|
||||
/// Do a full crate graph LTO. The flavor is determined by the compiler
|
||||
/// (currently the default is "fat").
|
||||
Yes,
|
||||
|
||||
/// Do a full crate graph LTO with ThinLTO
|
||||
Thin,
|
||||
|
||||
/// Do a local graph LTO with ThinLTO (only relevant for multiple codegen
|
||||
/// units).
|
||||
ThinLocal,
|
||||
|
||||
/// Do a full crate graph LTO with "fat" LTO
|
||||
Fat,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Hash)]
|
||||
pub enum DebugInfoLevel {
|
||||
NoDebugInfo,
|
||||
@ -389,7 +409,7 @@ top_level_options!(
|
||||
// commands like `--emit llvm-ir` which they're often incompatible with
|
||||
// if we otherwise use the defaults of rustc.
|
||||
cli_forced_codegen_units: Option<usize> [UNTRACKED],
|
||||
cli_forced_thinlto: Option<bool> [UNTRACKED],
|
||||
cli_forced_thinlto_off: bool [UNTRACKED],
|
||||
}
|
||||
);
|
||||
|
||||
@ -590,7 +610,7 @@ pub fn basic_options() -> Options {
|
||||
debug_assertions: true,
|
||||
actually_rustdoc: false,
|
||||
cli_forced_codegen_units: None,
|
||||
cli_forced_thinlto: None,
|
||||
cli_forced_thinlto_off: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -780,11 +800,13 @@ macro_rules! options {
|
||||
Some("crate=integer");
|
||||
pub const parse_unpretty: Option<&'static str> =
|
||||
Some("`string` or `string=string`");
|
||||
pub const parse_lto: Option<&'static str> =
|
||||
Some("one of `thin`, `fat`, or omitted");
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod $mod_set {
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer};
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
|
||||
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -978,6 +1000,16 @@ macro_rules! options {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
|
||||
*slot = match v {
|
||||
None => Lto::Yes,
|
||||
Some("thin") => Lto::Thin,
|
||||
Some("fat") => Lto::Fat,
|
||||
Some(_) => return false,
|
||||
};
|
||||
true
|
||||
}
|
||||
}
|
||||
) }
|
||||
|
||||
@ -994,7 +1026,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
|
||||
"extra arguments to append to the linker invocation (space separated)"),
|
||||
link_dead_code: bool = (false, parse_bool, [UNTRACKED],
|
||||
"don't let linker strip dead code (turning it on can be used for code coverage)"),
|
||||
lto: bool = (false, parse_bool, [TRACKED],
|
||||
lto: Lto = (Lto::No, parse_lto, [TRACKED],
|
||||
"perform LLVM link-time optimizations"),
|
||||
target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
|
||||
"select target processor (rustc --print target-cpus for details)"),
|
||||
@ -1677,7 +1709,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
|
||||
|
||||
let mut cg = build_codegen_options(matches, error_format);
|
||||
let mut codegen_units = cg.codegen_units;
|
||||
let mut thinlto = None;
|
||||
let mut disable_thinlto = false;
|
||||
|
||||
// Issue #30063: if user requests llvm-related output to one
|
||||
// particular path, disable codegen-units.
|
||||
@ -1699,12 +1731,12 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
|
||||
}
|
||||
early_warn(error_format, "resetting to default -C codegen-units=1");
|
||||
codegen_units = Some(1);
|
||||
thinlto = Some(false);
|
||||
disable_thinlto = true;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
codegen_units = Some(1);
|
||||
thinlto = Some(false);
|
||||
disable_thinlto = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1734,7 +1766,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
|
||||
(&None, &None) => None,
|
||||
}.map(|m| PathBuf::from(m));
|
||||
|
||||
if cg.lto && incremental.is_some() {
|
||||
if cg.lto != Lto::No && incremental.is_some() {
|
||||
early_error(error_format, "can't perform LTO when compiling incrementally");
|
||||
}
|
||||
|
||||
@ -1934,7 +1966,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
|
||||
debug_assertions,
|
||||
actually_rustdoc: false,
|
||||
cli_forced_codegen_units: codegen_units,
|
||||
cli_forced_thinlto: thinlto,
|
||||
cli_forced_thinlto_off: disable_thinlto,
|
||||
},
|
||||
cfg)
|
||||
}
|
||||
@ -2052,7 +2084,7 @@ mod dep_tracking {
|
||||
use std::hash::Hash;
|
||||
use std::path::PathBuf;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use super::{Passes, CrateType, OptLevel, DebugInfoLevel,
|
||||
use super::{Passes, CrateType, OptLevel, DebugInfoLevel, Lto,
|
||||
OutputTypes, Externs, ErrorOutputType, Sanitizer};
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use rustc_back::{PanicStrategy, RelroLevel};
|
||||
@ -2107,6 +2139,7 @@ mod dep_tracking {
|
||||
impl_dep_tracking_hash_via_hash!(RelroLevel);
|
||||
impl_dep_tracking_hash_via_hash!(Passes);
|
||||
impl_dep_tracking_hash_via_hash!(OptLevel);
|
||||
impl_dep_tracking_hash_via_hash!(Lto);
|
||||
impl_dep_tracking_hash_via_hash!(DebugInfoLevel);
|
||||
impl_dep_tracking_hash_via_hash!(UnstableFeatures);
|
||||
impl_dep_tracking_hash_via_hash!(Externs);
|
||||
@ -2180,6 +2213,7 @@ mod tests {
|
||||
use lint;
|
||||
use middle::cstore;
|
||||
use session::config::{build_configuration, build_session_options_and_crate_config};
|
||||
use session::config::Lto;
|
||||
use session::build_session;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::iter::FromIterator;
|
||||
@ -2656,7 +2690,7 @@ mod tests {
|
||||
|
||||
// Make sure changing a [TRACKED] option changes the hash
|
||||
opts = reference.clone();
|
||||
opts.cg.lto = true;
|
||||
opts.cg.lto = Lto::Fat;
|
||||
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
||||
|
||||
opts = reference.clone();
|
||||
|
@ -498,9 +498,65 @@ impl Session {
|
||||
self.use_mir()
|
||||
}
|
||||
|
||||
pub fn lto(&self) -> bool {
|
||||
self.opts.cg.lto || self.target.target.options.requires_lto
|
||||
/// Calculates the flavor of LTO to use for this compilation.
|
||||
pub fn lto(&self) -> config::Lto {
|
||||
// If our target has codegen requirements ignore the command line
|
||||
if self.target.target.options.requires_lto {
|
||||
return config::Lto::Fat
|
||||
}
|
||||
|
||||
// If the user specified something, return that. If they only said `-C
|
||||
// lto` and we've for whatever reason forced off ThinLTO via the CLI,
|
||||
// then ensure we can't use a ThinLTO.
|
||||
match self.opts.cg.lto {
|
||||
config::Lto::No => {}
|
||||
config::Lto::Yes if self.opts.cli_forced_thinlto_off => {
|
||||
return config::Lto::Fat
|
||||
}
|
||||
other => return other,
|
||||
}
|
||||
|
||||
// Ok at this point the target doesn't require anything and the user
|
||||
// hasn't asked for anything. Our next decision is whether or not
|
||||
// we enable "auto" ThinLTO where we use multiple codegen units and
|
||||
// then do ThinLTO over those codegen units. The logic below will
|
||||
// either return `No` or `ThinLocal`.
|
||||
|
||||
// If processing command line options determined that we're incompatible
|
||||
// with ThinLTO (e.g. `-C lto --emit llvm-ir`) then return that option.
|
||||
if self.opts.cli_forced_thinlto_off {
|
||||
return config::Lto::No
|
||||
}
|
||||
|
||||
// If `-Z thinlto` specified process that, but note that this is mostly
|
||||
// a deprecated option now that `-C lto=thin` exists.
|
||||
if let Some(enabled) = self.opts.debugging_opts.thinlto {
|
||||
if enabled {
|
||||
return config::Lto::ThinLocal
|
||||
} else {
|
||||
return config::Lto::No
|
||||
}
|
||||
}
|
||||
|
||||
// If there's only one codegen unit and LTO isn't enabled then there's
|
||||
// no need for ThinLTO so just return false.
|
||||
if self.codegen_units() == 1 {
|
||||
return config::Lto::No
|
||||
}
|
||||
|
||||
// Right now ThinLTO isn't compatible with incremental compilation.
|
||||
if self.opts.incremental.is_some() {
|
||||
return config::Lto::No
|
||||
}
|
||||
|
||||
// Now we're in "defaults" territory. By default we enable ThinLTO for
|
||||
// optimized compiles (anything greater than O0).
|
||||
match self.opts.optimize {
|
||||
config::OptLevel::No => config::Lto::No,
|
||||
_ => config::Lto::ThinLocal,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the panic strategy for this compile session. If the user explicitly selected one
|
||||
/// using '-C panic', use that, otherwise use the panic strategy defined by the target.
|
||||
pub fn panic_strategy(&self) -> PanicStrategy {
|
||||
@ -804,38 +860,6 @@ impl Session {
|
||||
// scientific.
|
||||
16
|
||||
}
|
||||
|
||||
/// Returns whether ThinLTO is enabled for this compilation
|
||||
pub fn thinlto(&self) -> bool {
|
||||
// If processing command line options determined that we're incompatible
|
||||
// with ThinLTO (e.g. `-C lto --emit llvm-ir`) then return that option.
|
||||
if let Some(enabled) = self.opts.cli_forced_thinlto {
|
||||
return enabled
|
||||
}
|
||||
|
||||
// If explicitly specified, use that with the next highest priority
|
||||
if let Some(enabled) = self.opts.debugging_opts.thinlto {
|
||||
return enabled
|
||||
}
|
||||
|
||||
// If there's only one codegen unit and LTO isn't enabled then there's
|
||||
// no need for ThinLTO so just return false.
|
||||
if self.codegen_units() == 1 && !self.lto() {
|
||||
return false
|
||||
}
|
||||
|
||||
// Right now ThinLTO isn't compatible with incremental compilation.
|
||||
if self.opts.incremental.is_some() {
|
||||
return false
|
||||
}
|
||||
|
||||
// Now we're in "defaults" territory. By default we enable ThinLTO for
|
||||
// optimized compiles (anything greater than O0).
|
||||
match self.opts.optimize {
|
||||
config::OptLevel::No => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_session(sopts: config::Options,
|
||||
|
@ -16,7 +16,7 @@ use super::rpath::RPathConfig;
|
||||
use super::rpath;
|
||||
use metadata::METADATA_FILENAME;
|
||||
use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, PrintRequest};
|
||||
use rustc::session::config::RUST_CGU_EXT;
|
||||
use rustc::session::config::{RUST_CGU_EXT, Lto};
|
||||
use rustc::session::filesearch;
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::session::Session;
|
||||
@ -503,7 +503,8 @@ fn link_staticlib(sess: &Session,
|
||||
});
|
||||
ab.add_rlib(path,
|
||||
&name.as_str(),
|
||||
sess.lto() && !ignored_for_lto(sess, &trans.crate_info, cnum),
|
||||
is_full_lto_enabled(sess) &&
|
||||
!ignored_for_lto(sess, &trans.crate_info, cnum),
|
||||
skip_object_files).unwrap();
|
||||
|
||||
all_native_libs.extend(trans.crate_info.native_libraries[&cnum].iter().cloned());
|
||||
@ -1211,7 +1212,8 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||
lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib)
|
||||
});
|
||||
|
||||
if (!sess.lto() || ignored_for_lto(sess, &trans.crate_info, cnum)) &&
|
||||
if (!is_full_lto_enabled(sess) ||
|
||||
ignored_for_lto(sess, &trans.crate_info, cnum)) &&
|
||||
crate_type != config::CrateTypeDylib &&
|
||||
!skip_native {
|
||||
cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
|
||||
@ -1264,7 +1266,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||
// file, then we don't need the object file as it's part of the
|
||||
// LTO module. Note that `#![no_builtins]` is excluded from LTO,
|
||||
// though, so we let that object file slide.
|
||||
let skip_because_lto = sess.lto() &&
|
||||
let skip_because_lto = is_full_lto_enabled(sess) &&
|
||||
is_rust_object &&
|
||||
(sess.target.target.options.no_builtins ||
|
||||
!trans.crate_info.is_no_builtins.contains(&cnum));
|
||||
@ -1301,7 +1303,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||
fn add_dynamic_crate(cmd: &mut Linker, sess: &Session, cratepath: &Path) {
|
||||
// If we're performing LTO, then it should have been previously required
|
||||
// that all upstream rust dependencies were available in an rlib format.
|
||||
assert!(!sess.lto());
|
||||
assert!(!is_full_lto_enabled(sess));
|
||||
|
||||
// Just need to tell the linker about where the library lives and
|
||||
// what its name is
|
||||
@ -1409,3 +1411,13 @@ fn link_binaryen(sess: &Session,
|
||||
e));
|
||||
}
|
||||
}
|
||||
|
||||
fn is_full_lto_enabled(sess: &Session) -> bool {
|
||||
match sess.lto() {
|
||||
Lto::Yes |
|
||||
Lto::Thin |
|
||||
Lto::Fat => true,
|
||||
Lto::No |
|
||||
Lto::ThinLocal => false,
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ use llvm::{ModuleRef, TargetMachineRef, True, False};
|
||||
use llvm;
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use rustc::middle::exported_symbols::SymbolExportLevel;
|
||||
use rustc::session::config;
|
||||
use rustc::session::config::{self, Lto};
|
||||
use rustc::util::common::time;
|
||||
use time_graph::Timeline;
|
||||
use {ModuleTranslation, ModuleLlvm, ModuleKind, ModuleSource};
|
||||
@ -95,25 +95,22 @@ impl LtoModuleTranslation {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum LTOMode {
|
||||
WholeCrateGraph,
|
||||
JustThisCrate,
|
||||
}
|
||||
|
||||
pub(crate) fn run(cgcx: &CodegenContext,
|
||||
modules: Vec<ModuleTranslation>,
|
||||
mode: LTOMode,
|
||||
timeline: &mut Timeline)
|
||||
modules: Vec<ModuleTranslation>,
|
||||
timeline: &mut Timeline)
|
||||
-> Result<Vec<LtoModuleTranslation>, FatalError>
|
||||
{
|
||||
let diag_handler = cgcx.create_diag_handler();
|
||||
let export_threshold = match mode {
|
||||
LTOMode::WholeCrateGraph => {
|
||||
let export_threshold = match cgcx.lto {
|
||||
// We're just doing LTO for our one crate
|
||||
Lto::ThinLocal => SymbolExportLevel::Rust,
|
||||
|
||||
// We're doing LTO for the entire crate graph
|
||||
Lto::Yes | Lto::Fat | Lto::Thin => {
|
||||
symbol_export::crates_export_threshold(&cgcx.crate_types)
|
||||
}
|
||||
LTOMode::JustThisCrate => {
|
||||
SymbolExportLevel::Rust
|
||||
}
|
||||
|
||||
Lto::No => panic!("didn't request LTO but we're doing LTO"),
|
||||
};
|
||||
|
||||
let symbol_filter = &|&(ref name, _, level): &(String, _, SymbolExportLevel)| {
|
||||
@ -140,7 +137,7 @@ pub(crate) fn run(cgcx: &CodegenContext,
|
||||
// We save off all the bytecode and LLVM module ids for later processing
|
||||
// with either fat or thin LTO
|
||||
let mut upstream_modules = Vec::new();
|
||||
if let LTOMode::WholeCrateGraph = mode {
|
||||
if cgcx.lto != Lto::ThinLocal {
|
||||
if cgcx.opts.cg.prefer_dynamic {
|
||||
diag_handler.struct_err("cannot prefer dynamic linking when performing LTO")
|
||||
.note("only 'staticlib', 'bin', and 'cdylib' outputs are \
|
||||
@ -186,13 +183,16 @@ pub(crate) fn run(cgcx: &CodegenContext,
|
||||
}
|
||||
|
||||
let arr = symbol_white_list.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
|
||||
match mode {
|
||||
LTOMode::WholeCrateGraph if !cgcx.thinlto => {
|
||||
match cgcx.lto {
|
||||
Lto::Yes | // `-C lto` == fat LTO by default
|
||||
Lto::Fat => {
|
||||
fat_lto(cgcx, &diag_handler, modules, upstream_modules, &arr, timeline)
|
||||
}
|
||||
_ => {
|
||||
Lto::Thin |
|
||||
Lto::ThinLocal => {
|
||||
thin_lto(&diag_handler, modules, upstream_modules, &arr, timeline)
|
||||
}
|
||||
Lto::No => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
|
||||
use rustc::dep_graph::{DepGraph, WorkProductFileKind};
|
||||
use rustc::middle::cstore::{LinkMeta, EncodedMetadata};
|
||||
use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePasses,
|
||||
AllPasses, Sanitizer};
|
||||
AllPasses, Sanitizer, Lto};
|
||||
use rustc::session::Session;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_back::LinkerFlavor;
|
||||
@ -329,8 +329,7 @@ struct AssemblerCommand {
|
||||
pub struct CodegenContext {
|
||||
// Resouces needed when running LTO
|
||||
pub time_passes: bool,
|
||||
pub lto: bool,
|
||||
pub thinlto: bool,
|
||||
pub lto: Lto,
|
||||
pub no_landing_pads: bool,
|
||||
pub save_temps: bool,
|
||||
pub fewer_names: bool,
|
||||
@ -589,12 +588,7 @@ fn generate_lto_work(cgcx: &CodegenContext,
|
||||
TRANS_WORK_PACKAGE_KIND,
|
||||
"generate lto")
|
||||
}).unwrap_or(Timeline::noop());
|
||||
let mode = if cgcx.lto {
|
||||
lto::LTOMode::WholeCrateGraph
|
||||
} else {
|
||||
lto::LTOMode::JustThisCrate
|
||||
};
|
||||
let lto_modules = lto::run(cgcx, modules, mode, &mut timeline)
|
||||
let lto_modules = lto::run(cgcx, modules, &mut timeline)
|
||||
.unwrap_or_else(|e| panic!(e));
|
||||
|
||||
lto_modules.into_iter().map(|module| {
|
||||
@ -1296,28 +1290,51 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||
unsafe {
|
||||
optimize(cgcx, &diag_handler, &mtrans, config, timeline)?;
|
||||
|
||||
let lto = cgcx.lto;
|
||||
|
||||
let auto_thin_lto =
|
||||
cgcx.thinlto &&
|
||||
cgcx.total_cgus > 1 &&
|
||||
mtrans.kind != ModuleKind::Allocator;
|
||||
|
||||
// If we're a metadata module we never participate in LTO.
|
||||
// After we've done the initial round of optimizations we need to
|
||||
// decide whether to synchronously codegen this module or ship it
|
||||
// back to the coordinator thread for further LTO processing (which
|
||||
// has to wait for all the initial modules to be optimized).
|
||||
//
|
||||
// If LTO was explicitly requested on the command line, we always
|
||||
// LTO everything else.
|
||||
//
|
||||
// If LTO *wasn't* explicitly requested and we're not a metdata
|
||||
// module, then we may automatically do ThinLTO if we've got
|
||||
// multiple codegen units. Note, however, that the allocator module
|
||||
// doesn't participate here automatically because of linker
|
||||
// shenanigans later on.
|
||||
if mtrans.kind == ModuleKind::Metadata || (!lto && !auto_thin_lto) {
|
||||
// Here we dispatch based on the `cgcx.lto` and kind of module we're
|
||||
// translating...
|
||||
let needs_lto = match cgcx.lto {
|
||||
Lto::No => false,
|
||||
|
||||
// Here we've got a full crate graph LTO requested. We ignore
|
||||
// this, however, if the crate type is only an rlib as there's
|
||||
// no full crate graph to process, that'll happen later.
|
||||
//
|
||||
// This use case currently comes up primarily for targets that
|
||||
// require LTO so the request for LTO is always unconditionally
|
||||
// passed down to the backend, but we don't actually want to do
|
||||
// anything about it yet until we've got a final product.
|
||||
Lto::Yes | Lto::Fat | Lto::Thin => {
|
||||
cgcx.crate_types.len() != 1 ||
|
||||
cgcx.crate_types[0] != config::CrateTypeRlib
|
||||
}
|
||||
|
||||
// When we're automatically doing ThinLTO for multi-codegen-unit
|
||||
// builds we don't actually want to LTO the allocator modules if
|
||||
// it shows up. This is due to various linker shenanigans that
|
||||
// we'll encounter later.
|
||||
//
|
||||
// Additionally here's where we also factor in the current LLVM
|
||||
// version. If it doesn't support ThinLTO we skip this.
|
||||
Lto::ThinLocal => {
|
||||
mtrans.kind != ModuleKind::Allocator &&
|
||||
llvm::LLVMRustThinLTOAvailable()
|
||||
}
|
||||
};
|
||||
|
||||
// Metadata modules never participate in LTO regardless of the lto
|
||||
// settings.
|
||||
let needs_lto = needs_lto && mtrans.kind != ModuleKind::Metadata;
|
||||
|
||||
if needs_lto {
|
||||
Ok(WorkItemResult::NeedsLTO(mtrans))
|
||||
} else {
|
||||
let module = codegen(cgcx, &diag_handler, mtrans, config, timeline)?;
|
||||
Ok(WorkItemResult::Compiled(module))
|
||||
} else {
|
||||
Ok(WorkItemResult::NeedsLTO(mtrans))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1393,10 +1410,6 @@ fn start_executing_work(tcx: TyCtxt,
|
||||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||
}));
|
||||
|
||||
let crate_types = sess.crate_types.borrow();
|
||||
let only_rlib = crate_types.len() == 1 &&
|
||||
crate_types[0] == config::CrateTypeRlib;
|
||||
|
||||
let wasm_import_memory =
|
||||
attr::contains_name(&tcx.hir.krate().attrs, "wasm_import_memory");
|
||||
|
||||
@ -1415,18 +1428,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||
let cgcx = CodegenContext {
|
||||
crate_types: sess.crate_types.borrow().clone(),
|
||||
each_linked_rlib_for_lto,
|
||||
// If we're only building an rlibc then allow the LTO flag to be passed
|
||||
// but don't actually do anything, the full LTO will happen later
|
||||
lto: sess.lto() && !only_rlib,
|
||||
|
||||
// Enable ThinLTO if requested, but only if the target we're compiling
|
||||
// for doesn't require full LTO. Some targets require one LLVM module
|
||||
// (they effectively don't have a linker) so it's up to us to use LTO to
|
||||
// link everything together.
|
||||
thinlto: sess.thinlto() &&
|
||||
!sess.target.target.options.requires_lto &&
|
||||
unsafe { llvm::LLVMRustThinLTOAvailable() },
|
||||
|
||||
lto: sess.lto(),
|
||||
no_landing_pads: sess.no_landing_pads(),
|
||||
fewer_names: sess.fewer_names(),
|
||||
save_temps: sess.opts.cg.save_temps,
|
||||
|
@ -16,11 +16,11 @@ all:
|
||||
$(RUSTC) -C extra-filename=foo dummy.rs 2>&1
|
||||
#Option taking no argument
|
||||
$(RUSTC) -C lto= dummy.rs 2>&1 | \
|
||||
$(CGREP) 'codegen option `lto` takes no value'
|
||||
$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
|
||||
$(RUSTC) -C lto=1 dummy.rs 2>&1 | \
|
||||
$(CGREP) 'codegen option `lto` takes no value'
|
||||
$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
|
||||
$(RUSTC) -C lto=foo dummy.rs 2>&1 | \
|
||||
$(CGREP) 'codegen option `lto` takes no value'
|
||||
$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
|
||||
$(RUSTC) -C lto dummy.rs
|
||||
|
||||
# Should not link dead code...
|
||||
|
17
src/test/run-pass/fat-lto.rs
Normal file
17
src/test/run-pass/fat-lto.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// compile-flags: -Clto=fat
|
||||
// no-prefer-dynamic
|
||||
|
||||
fn main() {
|
||||
println!("hello!");
|
||||
}
|
||||
|
17
src/test/run-pass/thinlto/all-crates.rs
Normal file
17
src/test/run-pass/thinlto/all-crates.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// compile-flags: -Clto=thin
|
||||
// no-prefer-dynamic
|
||||
// min-llvm-version 4.0
|
||||
|
||||
fn main() {
|
||||
println!("hello!");
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z thinlto -C codegen-units=8 -O -C lto
|
||||
// compile-flags: -C codegen-units=8 -O -C lto=thin
|
||||
// aux-build:thin-lto-inlines-aux.rs
|
||||
// min-llvm-version 4.0
|
||||
// no-prefer-dynamic
|
||||
|
Loading…
Reference in New Issue
Block a user