Skip to content

Commit 772dbeb

Browse files
authored
Rollup merge of rust-lang#135656 - joshtriplett:hint-mostly-unused, r=saethlin
Add `-Z hint-mostly-unused` to tell rustc that most of a crate will go unused This hint allows the compiler to optimize its operation based on this assumption, in order to compile faster. This is a hint, and does not guarantee any particular behavior. This option can substantially speed up compilation if applied to a large dependency where the majority of the dependency does not get used. This flag may slow down compilation in other cases. Currently, this option makes the compiler defer as much code generation as possible from functions in the crate, until later crates invoke those functions. Functions that never get invoked will never have code generated for them. For instance, if a crate provides thousands of functions, but only a few of them will get called, this flag will result in the compiler only doing code generation for the called functions. (This uses the same mechanisms as cross-crate inlining of functions.) This does not affect `extern` functions, or functions marked as `#[inline(never)]`. This option has already existed in nightly as `-Zcross-crate-inline-threshold=always` for some time, and has gotten testing in that form. However, this option is still unstable, to give an opportunity for wider testing in this form. Some performance numbers, based on a crate with many dependencies having just *one* large dependency set to `-Z hint-mostly-unused` (using Cargo's `profile-rustflags` option): A release build went from 4m07s to 2m04s. A non-release build went from 2m26s to 1m28s.
2 parents 77ec48f + 1b23b64 commit 772dbeb

File tree

4 files changed

+43
-0
lines changed

4 files changed

+43
-0
lines changed

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ fn test_unstable_options_tracking_hash() {
802802
tracked!(force_unstable_if_unmarked, true);
803803
tracked!(function_return, FunctionReturn::ThunkExtern);
804804
tracked!(function_sections, Some(false));
805+
tracked!(hint_mostly_unused, true);
805806
tracked!(human_readable_cgu_names, true);
806807
tracked!(incremental_ignore_spans, true);
807808
tracked!(inline_mir, Some(true));

compiler/rustc_mir_transform/src/cross_crate_inline.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
5050
_ => {}
5151
}
5252

53+
// If the crate is likely to be mostly unused, use cross-crate inlining to defer codegen until
54+
// the function is referenced, in order to skip codegen for unused functions. This is
55+
// intentionally after the check for `inline(never)`, so that `inline(never)` wins.
56+
if tcx.sess.opts.unstable_opts.hint_mostly_unused {
57+
return true;
58+
}
59+
5360
let sig = tcx.fn_sig(def_id).instantiate_identity();
5461
for ty in sig.inputs().skip_binder().iter().chain(std::iter::once(&sig.output().skip_binder()))
5562
{

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2235,6 +2235,8 @@ options! {
22352235
environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
22362236
has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
22372237
"explicitly enable the `cfg(target_thread_local)` directive"),
2238+
hint_mostly_unused: bool = (false, parse_bool, [TRACKED],
2239+
"hint that most of this crate will go unused, to minimize work for uncalled functions"),
22382240
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
22392241
"generate human-readable, predictable names for codegen units (default: no)"),
22402242
identify_regions: bool = (false, parse_bool, [UNTRACKED],
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# `hint-mostly-unused`
2+
3+
This flag hints to the compiler that most of the crate will probably go unused.
4+
The compiler can optimize its operation based on this assumption, in order to
5+
compile faster. This is a hint, and does not guarantee any particular behavior.
6+
7+
This option can substantially speed up compilation if applied to a large
8+
dependency where the majority of the dependency does not get used. This flag
9+
may slow down compilation in other cases.
10+
11+
Currently, this option makes the compiler defer as much code generation as
12+
possible from functions in the crate, until later crates invoke those
13+
functions. Functions that never get invoked will never have code generated for
14+
them. For instance, if a crate provides thousands of functions, but only a few
15+
of them will get called, this flag will result in the compiler only doing code
16+
generation for the called functions. (This uses the same mechanisms as
17+
cross-crate inlining of functions.) This does not affect `extern` functions, or
18+
functions marked as `#[inline(never)]`.
19+
20+
To try applying this flag to one dependency out of a dependency tree, use the
21+
[`profile-rustflags`](https://doc.rust-lang.org/cargo/reference/unstable.html#profile-rustflags-option)
22+
feature of nightly cargo:
23+
24+
```toml
25+
cargo-features = ["profile-rustflags"]
26+
27+
# ...
28+
[dependencies]
29+
mostly-unused-dependency = "1.2.3"
30+
31+
[profile.release.package.mostly-unused-dependency]
32+
rustflags = ["-Zhint-mostly-unused"]
33+
```

0 commit comments

Comments
 (0)