Skip to content

Commit 0e58964

Browse files
committed
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)]`. 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.
1 parent 44f415c commit 0e58964

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
@@ -801,6 +801,7 @@ fn test_unstable_options_tracking_hash() {
801801
tracked!(force_unstable_if_unmarked, true);
802802
tracked!(function_return, FunctionReturn::ThunkExtern);
803803
tracked!(function_sections, Some(false));
804+
tracked!(hint_mostly_unused, true);
804805
tracked!(human_readable_cgu_names, true);
805806
tracked!(incremental_ignore_spans, true);
806807
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
@@ -2233,6 +2233,8 @@ options! {
22332233
environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
22342234
has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
22352235
"explicitly enable the `cfg(target_thread_local)` directive"),
2236+
hint_mostly_unused: bool = (false, parse_bool, [TRACKED],
2237+
"hint that most of this crate will go unused, to minimize work for uncalled functions"),
22362238
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
22372239
"generate human-readable, predictable names for codegen units (default: no)"),
22382240
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)