Skip to content

Commit 07dc4b3

Browse files
committed
Rollup merge of #53950 - michaelwoerister:more-lto-cli, r=alexcrichton
Allow for opting out of ThinLTO and clean up LTO related cli flag handling. It turns out that there currently is no way to explicitly disable ThinLTO (except for the nightly-only `-Zthinlto` flag). This PR extends `-C lto` to take `yes` and `no` in addition to `thin` and `fat`. It should be backwards compatible. It also cleans up how LTO mode selection is handled. Note that merging the PR in the current state would make the new values for `-C lto` available on the stable channel. I think that would be fine but maybe some team should vote on it.
2 parents 5db68ba + 24093a6 commit 07dc4b3

File tree

8 files changed

+97
-32
lines changed

8 files changed

+97
-32
lines changed

src/librustc/session/config.rs

+44-16
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,13 @@ pub enum OptLevel {
6868
SizeMin, // -Oz
6969
}
7070

71+
/// This is what the `LtoCli` values get mapped to after resolving defaults and
72+
/// and taking other command line options into account.
7173
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
7274
pub enum Lto {
7375
/// Don't do any LTO whatsoever
7476
No,
7577

76-
/// Do a full crate graph LTO. The flavor is determined by the compiler
77-
/// (currently the default is "fat").
78-
Yes,
79-
8078
/// Do a full crate graph LTO with ThinLTO
8179
Thin,
8280

@@ -88,6 +86,23 @@ pub enum Lto {
8886
Fat,
8987
}
9088

89+
/// The different settings that the `-C lto` flag can have.
90+
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
91+
pub enum LtoCli {
92+
/// `-C lto=no`
93+
No,
94+
/// `-C lto=yes`
95+
Yes,
96+
/// `-C lto`
97+
NoParam,
98+
/// `-C lto=thin`
99+
Thin,
100+
/// `-C lto=fat`
101+
Fat,
102+
/// No `-C lto` flag passed
103+
Unspecified,
104+
}
105+
91106
#[derive(Clone, PartialEq, Hash)]
92107
pub enum CrossLangLto {
93108
LinkerPlugin(PathBuf),
@@ -801,15 +816,16 @@ macro_rules! options {
801816
pub const parse_unpretty: Option<&'static str> =
802817
Some("`string` or `string=string`");
803818
pub const parse_lto: Option<&'static str> =
804-
Some("one of `thin`, `fat`, or omitted");
819+
Some("either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \
820+
`fat`, or omitted");
805821
pub const parse_cross_lang_lto: Option<&'static str> =
806822
Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \
807823
or the path to the linker plugin");
808824
}
809825

810826
#[allow(dead_code)]
811827
mod $mod_set {
812-
use super::{$struct_name, Passes, Sanitizer, Lto, CrossLangLto};
828+
use super::{$struct_name, Passes, Sanitizer, LtoCli, CrossLangLto};
813829
use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
814830
use std::path::PathBuf;
815831

@@ -1002,11 +1018,23 @@ macro_rules! options {
10021018
}
10031019
}
10041020

1005-
fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
1021+
fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool {
1022+
if v.is_some() {
1023+
let mut bool_arg = None;
1024+
if parse_opt_bool(&mut bool_arg, v) {
1025+
*slot = if bool_arg.unwrap() {
1026+
LtoCli::Yes
1027+
} else {
1028+
LtoCli::No
1029+
};
1030+
return true
1031+
}
1032+
}
1033+
10061034
*slot = match v {
1007-
None => Lto::Yes,
1008-
Some("thin") => Lto::Thin,
1009-
Some("fat") => Lto::Fat,
1035+
None => LtoCli::NoParam,
1036+
Some("thin") => LtoCli::Thin,
1037+
Some("fat") => LtoCli::Fat,
10101038
Some(_) => return false,
10111039
};
10121040
true
@@ -1047,7 +1075,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
10471075
"extra arguments to append to the linker invocation (space separated)"),
10481076
link_dead_code: bool = (false, parse_bool, [UNTRACKED],
10491077
"don't let linker strip dead code (turning it on can be used for code coverage)"),
1050-
lto: Lto = (Lto::No, parse_lto, [TRACKED],
1078+
lto: LtoCli = (LtoCli::Unspecified, parse_lto, [TRACKED],
10511079
"perform LLVM link-time optimizations"),
10521080
target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
10531081
"select target processor (rustc --print target-cpus for details)"),
@@ -2384,8 +2412,8 @@ mod dep_tracking {
23842412
use std::hash::Hash;
23852413
use std::path::PathBuf;
23862414
use std::collections::hash_map::DefaultHasher;
2387-
use super::{CrateType, DebugInfo, ErrorOutputType, Lto, OptLevel, OutputTypes,
2388-
Passes, Sanitizer, CrossLangLto};
2415+
use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
2416+
Passes, Sanitizer, LtoCli, CrossLangLto};
23892417
use syntax::feature_gate::UnstableFeatures;
23902418
use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple};
23912419
use syntax::edition::Edition;
@@ -2440,7 +2468,7 @@ mod dep_tracking {
24402468
impl_dep_tracking_hash_via_hash!(RelroLevel);
24412469
impl_dep_tracking_hash_via_hash!(Passes);
24422470
impl_dep_tracking_hash_via_hash!(OptLevel);
2443-
impl_dep_tracking_hash_via_hash!(Lto);
2471+
impl_dep_tracking_hash_via_hash!(LtoCli);
24442472
impl_dep_tracking_hash_via_hash!(DebugInfo);
24452473
impl_dep_tracking_hash_via_hash!(UnstableFeatures);
24462474
impl_dep_tracking_hash_via_hash!(OutputTypes);
@@ -2514,7 +2542,7 @@ mod tests {
25142542
use lint;
25152543
use middle::cstore;
25162544
use session::config::{build_configuration, build_session_options_and_crate_config};
2517-
use session::config::{Lto, CrossLangLto};
2545+
use session::config::{LtoCli, CrossLangLto};
25182546
use session::build_session;
25192547
use std::collections::{BTreeMap, BTreeSet};
25202548
use std::iter::FromIterator;
@@ -2948,7 +2976,7 @@ mod tests {
29482976

29492977
// Make sure changing a [TRACKED] option changes the hash
29502978
opts = reference.clone();
2951-
opts.cg.lto = Lto::Fat;
2979+
opts.cg.lto = LtoCli::Fat;
29522980
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
29532981

29542982
opts = reference.clone();

src/librustc/session/mod.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -550,9 +550,27 @@ impl Session {
550550
// lto` and we've for whatever reason forced off ThinLTO via the CLI,
551551
// then ensure we can't use a ThinLTO.
552552
match self.opts.cg.lto {
553-
config::Lto::No => {}
554-
config::Lto::Yes if self.opts.cli_forced_thinlto_off => return config::Lto::Fat,
555-
other => return other,
553+
config::LtoCli::Unspecified => {
554+
// The compiler was invoked without the `-Clto` flag. Fall
555+
// through to the default handling
556+
}
557+
config::LtoCli::No => {
558+
// The user explicitly opted out of any kind of LTO
559+
return config::Lto::No;
560+
}
561+
config::LtoCli::Yes |
562+
config::LtoCli::Fat |
563+
config::LtoCli::NoParam => {
564+
// All of these mean fat LTO
565+
return config::Lto::Fat;
566+
}
567+
config::LtoCli::Thin => {
568+
return if self.opts.cli_forced_thinlto_off {
569+
config::Lto::Fat
570+
} else {
571+
config::Lto::Thin
572+
};
573+
}
556574
}
557575

558576
// Ok at this point the target doesn't require anything and the user
@@ -1178,7 +1196,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
11781196

11791197
if sess.opts.incremental.is_some() {
11801198
match sess.lto() {
1181-
Lto::Yes |
11821199
Lto::Thin |
11831200
Lto::Fat => {
11841201
sess.err("can't perform LTO when compiling incrementally");

src/librustc_codegen_llvm/back/link.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1666,7 +1666,6 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
16661666

16671667
fn are_upstream_rust_objects_already_included(sess: &Session) -> bool {
16681668
match sess.lto() {
1669-
Lto::Yes |
16701669
Lto::Fat => true,
16711670
Lto::Thin => {
16721671
// If we defer LTO to the linker, we haven't run LTO ourselves, so

src/librustc_codegen_llvm/back/linker.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,12 @@ impl<'a> GccLinker<'a> {
205205
self.linker_arg(&format!("-plugin-opt={}", opt_level));
206206
self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess)));
207207

208-
match self.sess.opts.cg.lto {
208+
match self.sess.lto() {
209209
config::Lto::Thin |
210210
config::Lto::ThinLocal => {
211211
self.linker_arg("-plugin-opt=thin");
212212
}
213213
config::Lto::Fat |
214-
config::Lto::Yes |
215214
config::Lto::No => {
216215
// default to regular LTO
217216
}

src/librustc_codegen_llvm/back/lto.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ pub(crate) fn run(cgcx: &CodegenContext,
118118
Lto::ThinLocal => SymbolExportLevel::Rust,
119119

120120
// We're doing LTO for the entire crate graph
121-
Lto::Yes | Lto::Fat | Lto::Thin => {
121+
Lto::Fat | Lto::Thin => {
122122
symbol_export::crates_export_threshold(&cgcx.crate_types)
123123
}
124124

@@ -201,7 +201,6 @@ pub(crate) fn run(cgcx: &CodegenContext,
201201
.map(|c| c.as_ptr())
202202
.collect::<Vec<_>>();
203203
match cgcx.lto {
204-
Lto::Yes | // `-C lto` == fat LTO by default
205204
Lto::Fat => {
206205
assert!(cached_modules.is_empty());
207206
let opt_jobs = fat_lto(cgcx,

src/librustc_codegen_llvm/back/write.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,6 @@ fn need_pre_thin_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
937937
}
938938

939939
match sess.lto() {
940-
Lto::Yes |
941940
Lto::Fat |
942941
Lto::No => false,
943942
Lto::Thin |
@@ -1372,7 +1371,7 @@ fn execute_optimize_work_item(cgcx: &CodegenContext,
13721371
// require LTO so the request for LTO is always unconditionally
13731372
// passed down to the backend, but we don't actually want to do
13741373
// anything about it yet until we've got a final product.
1375-
Lto::Yes | Lto::Fat | Lto::Thin => {
1374+
Lto::Fat | Lto::Thin => {
13761375
cgcx.crate_types.len() != 1 ||
13771376
cgcx.crate_types[0] != config::CrateType::Rlib
13781377
}
@@ -1552,7 +1551,7 @@ fn start_executing_work(tcx: TyCtxt,
15521551
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
15531552
Some(Arc::new(exported_symbols))
15541553
}
1555-
Lto::Yes | Lto::Fat | Lto::Thin => {
1554+
Lto::Fat | Lto::Thin => {
15561555
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
15571556
for &cnum in tcx.crates().iter() {
15581557
exported_symbols.insert(cnum, copy_symbols(cnum));

src/test/run-make-fulldeps/codegen-options-parsing/Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ all:
1616
$(RUSTC) -C extra-filename=foo dummy.rs 2>&1
1717
#Option taking no argument
1818
$(RUSTC) -C lto= dummy.rs 2>&1 | \
19-
$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
19+
$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
2020
$(RUSTC) -C lto=1 dummy.rs 2>&1 | \
21-
$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
21+
$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
2222
$(RUSTC) -C lto=foo dummy.rs 2>&1 | \
23-
$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
23+
$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
2424
$(RUSTC) -C lto dummy.rs
2525

2626
# Should not link dead code...
+25-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
11
-include ../tools.mk
22

3-
all:
3+
all: noparam bool_true bool_false thin fat
4+
5+
noparam:
46
$(RUSTC) lib.rs
57
$(RUSTC) main.rs -C lto
68
$(call RUN,main)
9+
10+
bool_true:
11+
$(RUSTC) lib.rs
12+
$(RUSTC) main.rs -C lto=yes
13+
$(call RUN,main)
14+
15+
16+
bool_false:
17+
$(RUSTC) lib.rs
18+
$(RUSTC) main.rs -C lto=off
19+
$(call RUN,main)
20+
21+
thin:
22+
$(RUSTC) lib.rs
23+
$(RUSTC) main.rs -C lto=thin
24+
$(call RUN,main)
25+
26+
fat:
27+
$(RUSTC) lib.rs
28+
$(RUSTC) main.rs -C lto=fat
29+
$(call RUN,main)
30+

0 commit comments

Comments
 (0)