Skip to content

Commit

Permalink
Auto merge of #116352 - Kobzol:rustc-driver-bolt, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
Optimize `librustc_driver.so` with BOLT

This PR optimizes `librustc_driver.so` on 64-bit Linux CI with BOLT.

### Code
One thing that's not clear yet to me how to resolve is how to best pass a linker flag that we need for BOLT (the second commit). It is currently passed unconditionally, which is not a good idea. We somehow have to:
1) Only pass it when we actually plan to use BOLT. How to best do that? `config.toml` entry? Environment variable? CLI flag for bootstrap? BOLT optimization is done by `opt-dist`, therefore bootstrap doesn't know about it by default.
2) Only pass it to `librustc_driver.so` (see performance below).

Some discussion of this flag already happened on [Zulip](https://rust-lang.zulipchat.com/#narrow/stream/326414-t-infra.2Fbootstrap/topic/Adding.20a.20one-off.20linker.20flag).

### Performance
Latest perf. results can be found [here](#102487 (comment)). Note that instruction counts are not very interesting here, there are only regressions on hello world programs. Probably caused by a larger C   libstd (?).

Summary:
- ✔️ `-1.8%` mean improvement in cycle counts across many primary benchmarks.
- ✔️ `-1.8%` mean Max-RSS improvement.
- ✖️ 34 MiB ( 48%) artifact size regression of `librustc_driver.so`.
  - This is caused by building `librustc_driver.so` with relocations (which are required for BOLT). Hopefully, it will be [fixed](https://discourse.llvm.org/t/bolt-rfc-a-new-mode-to-rewrite-entire-binary/68674) in the future with BOLT improvements, but now trying to reduce this size increase is [tricky](#114649).
  - Note that the size of this file was recently reduced in #115554 by pretty much the same amount (33 MiB). So the size after this PR is basically the same as it was for the last ~year.
- ✖️ 1.4 MiB ( 53%) artifact size regression of `rustc`.
  - This is annoying and pretty much unnecessary. It is caused by the way relocations are currently applied in this PR, because they are applied both to `librustc_driver.so` (where they are needed) and for `rustc` (where they aren't needed), since both are built with a single cargo invocation. We might need e.g. some tricks in the bootstrap `rustc` shim to only apply the relocation flag for the shared library and not for `rustc`.

### CI time
CI (try build) got slower by ~5 minutes, which is fine, IMO. It can be further reduced by running LLVM and `librustc_driver` BOLT profile gathering at the same time (now they are gathered separately for LLVM and `librustc_driver`).

r? `@Mark-Simulacrum`

Also CC `@onur-ozkan,` primarily for the bootstrap linker flag issue.
  • Loading branch information
bors committed Oct 14, 2023
2 parents ee8c9d3 482a820 commit c543b6f
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 60 deletions.
6 changes: 6 additions & 0 deletions src/bootstrap/bin/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 193,12 @@ fn main() {
eprintln!("{prefix} libdir: {libdir:?}");
}

if env::var_os("RUSTC_BOLT_LINK_FLAGS").is_some() {
if let Some("rustc_driver") = crate_name {
cmd.arg("-Clink-args=-Wl,-q");
}
}

let start = Instant::now();
let (child, status) = {
let errmsg = format!("\nFailed to run:\n{cmd:?}\n-------------");
Expand Down
5 changes: 5 additions & 0 deletions src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 906,11 @@ impl Step for Rustc {
cargo.arg("-p").arg(krate);
}

if builder.build.config.enable_bolt_settings && compiler.stage == 1 {
// Relocations are required for BOLT to work.
cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
}

let _guard = builder.msg_sysroot_tool(
Kind::Build,
compiler.stage,
Expand Down
2 changes: 2 additions & 0 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 234,7 @@ pub struct Config {
pub llvm_profile_use: Option<String>,
pub llvm_profile_generate: bool,
pub llvm_libunwind_default: Option<LlvmLibunwind>,
pub enable_bolt_settings: bool,

pub reproducible_artifacts: Vec<String>,

Expand Down Expand Up @@ -1128,6 1129,7 @@ impl Config {
config.free_args = std::mem::take(&mut flags.free_args);
config.llvm_profile_use = flags.llvm_profile_use;
config.llvm_profile_generate = flags.llvm_profile_generate;
config.enable_bolt_settings = flags.enable_bolt_settings;

// Infer the rest of the configuration.

Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 152,9 @@ pub struct Flags {
/// generate PGO profile with llvm built for rustc
#[arg(global(true), long)]
pub llvm_profile_generate: bool,
/// Enable BOLT link flags
#[arg(global(true), long)]
pub enable_bolt_settings: bool,
/// Additional reproducible artifacts that should be added to the reproducible artifacts archive.
#[arg(global(true), long)]
pub reproducible_artifact: Vec<String>,
Expand Down
7 changes: 6 additions & 1 deletion src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 27,15 @@ sed -i'' 's|ftp://gcc\.gnu\.org/|https://gcc.gnu.org/|g' ./contrib/download_prer
./contrib/download_prerequisites
mkdir ../gcc-build
cd ../gcc-build

# '-fno-reorder-blocks-and-partition' is required to
# enable BOLT optimization of the C standard library,
# which is included in librustc_driver.so
hide_output ../gcc-$GCC/configure \
--prefix=/rustroot \
--enable-languages=c,c \
--disable-gnu-unique-object
--disable-gnu-unique-object \
--enable-cxx-flags='-fno-reorder-blocks-and-partition'
hide_output make -j$(nproc)
hide_output make install
ln -s gcc /rustroot/bin/cc
Expand Down
15 changes: 15 additions & 0 deletions src/etc/completions/x.py.fish
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 27,7 @@ complete -c x.py -n "__fish_use_subcommand" -l include-default-paths -d 'include
complete -c x.py -n "__fish_use_subcommand" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_use_subcommand" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_use_subcommand" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_use_subcommand" -s h -l help -d 'Print help'
complete -c x.py -n "__fish_use_subcommand" -f -a "build" -d 'Compile either the compiler or libraries'
complete -c x.py -n "__fish_use_subcommand" -f -a "check" -d 'Compile either the compiler or libraries, using cargo check'
Expand Down Expand Up @@ -71,6 72,7 @@ complete -c x.py -n "__fish_seen_subcommand_from build" -l include-default-paths
complete -c x.py -n "__fish_seen_subcommand_from build" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from build" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from build" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from build" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from check" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from check" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
Expand Down Expand Up @@ -102,6 104,7 @@ complete -c x.py -n "__fish_seen_subcommand_from check" -l include-default-paths
complete -c x.py -n "__fish_seen_subcommand_from check" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from check" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from check" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from check" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from clippy" -s A -d 'clippy lints to allow' -r
complete -c x.py -n "__fish_seen_subcommand_from clippy" -s D -d 'clippy lints to deny' -r
Expand Down Expand Up @@ -137,6 140,7 @@ complete -c x.py -n "__fish_seen_subcommand_from clippy" -l include-default-path
complete -c x.py -n "__fish_seen_subcommand_from clippy" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from clippy" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from clippy" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from clippy" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from fix" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from fix" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
Expand Down Expand Up @@ -167,6 171,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fix" -l include-default-paths -
complete -c x.py -n "__fish_seen_subcommand_from fix" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from fix" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from fix" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from fix" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
Expand Down Expand Up @@ -198,6 203,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fmt" -l include-default-paths -
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from fmt" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from fmt" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from doc" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from doc" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
Expand Down Expand Up @@ -230,6 236,7 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -l include-default-paths -
complete -c x.py -n "__fish_seen_subcommand_from doc" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from doc" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from doc" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from test" -l skip -d 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times' -r -F
complete -c x.py -n "__fish_seen_subcommand_from test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r
Expand Down Expand Up @@ -273,6 280,7 @@ complete -c x.py -n "__fish_seen_subcommand_from test" -l include-default-paths
complete -c x.py -n "__fish_seen_subcommand_from test" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from test" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from test" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from bench" -l test-args -r
complete -c x.py -n "__fish_seen_subcommand_from bench" -l config -d 'TOML configuration file for build' -r -F
Expand Down Expand Up @@ -304,6 312,7 @@ complete -c x.py -n "__fish_seen_subcommand_from bench" -l include-default-paths
complete -c x.py -n "__fish_seen_subcommand_from bench" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from bench" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from bench" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from bench" -s h -l help -d 'Print help'
complete -c x.py -n "__fish_seen_subcommand_from clean" -l stage -d 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used' -r
complete -c x.py -n "__fish_seen_subcommand_from clean" -l config -d 'TOML configuration file for build' -r -F
Expand Down Expand Up @@ -335,6 344,7 @@ complete -c x.py -n "__fish_seen_subcommand_from clean" -l include-default-paths
complete -c x.py -n "__fish_seen_subcommand_from clean" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from clean" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from clean" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from clean" -s h -l help -d 'Print help'
complete -c x.py -n "__fish_seen_subcommand_from dist" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from dist" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
Expand Down Expand Up @@ -365,6 375,7 @@ complete -c x.py -n "__fish_seen_subcommand_from dist" -l include-default-paths
complete -c x.py -n "__fish_seen_subcommand_from dist" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from dist" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from dist" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from dist" -s h -l help -d 'Print help'
complete -c x.py -n "__fish_seen_subcommand_from install" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from install" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
Expand Down Expand Up @@ -395,6 406,7 @@ complete -c x.py -n "__fish_seen_subcommand_from install" -l include-default-pat
complete -c x.py -n "__fish_seen_subcommand_from install" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from install" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from install" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from install" -s h -l help -d 'Print help'
complete -c x.py -n "__fish_seen_subcommand_from run" -l args -d 'arguments for the tool' -r
complete -c x.py -n "__fish_seen_subcommand_from run" -l config -d 'TOML configuration file for build' -r -F
Expand Down Expand Up @@ -426,6 438,7 @@ complete -c x.py -n "__fish_seen_subcommand_from run" -l include-default-paths -
complete -c x.py -n "__fish_seen_subcommand_from run" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from run" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from run" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from run" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from setup" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from setup" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
Expand Down Expand Up @@ -456,6 469,7 @@ complete -c x.py -n "__fish_seen_subcommand_from setup" -l include-default-paths
complete -c x.py -n "__fish_seen_subcommand_from setup" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from setup" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from setup" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from setup" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
Expand Down Expand Up @@ -487,4 501,5 @@ complete -c x.py -n "__fish_seen_subcommand_from suggest" -l include-default-pat
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from suggest" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from suggest" -s h -l help -d 'Print help (see more with \'--help\')'
Loading

0 comments on commit c543b6f

Please sign in to comment.