diff options
| author | bors <bors@rust-lang.org> | 2021-08-26 01:14:16 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-08-26 01:14:16 +0000 |
| commit | c4be230b4a30eb74e3a3908455731ebc2f731d3d (patch) | |
| tree | fc5037fc88bd8664b70ad71483c1637e0879f78e | |
| parent | 0afc20860eb98a29d9bbeea80f2acc5be38c6bf3 (diff) | |
| parent | 1ea8d93c0ca5168e7f434d87e19af337b83157e4 (diff) | |
| download | rust-c4be230b4a30eb74e3a3908455731ebc2f731d3d.tar.gz rust-c4be230b4a30eb74e3a3908455731ebc2f731d3d.zip | |
Auto merge of #88069 - Mark-Simulacrum:llvm-pgo, r=pietroalbini
PGO for LLVM builds on x86_64-unknown-linux-gnu in CI This shows up to 6% less instruction counts with larger - up to 18% - wins on cycles on multiple benchmarks, and up to 19% wins on the -j1 wall times for rustc self-compilation. We can afford to spend the extra cycles building LLVM essentially once more for the x86_64-unknown-linux-gnu CI build today. The builder finishes in around 50 minutes on average, and this adds just 10 more minutes. Given the sizeable improvements in compiler performance, this is definitely worth it.
| -rw-r--r-- | src/bootstrap/config.rs | 4 | ||||
| -rw-r--r-- | src/bootstrap/dist.rs | 14 | ||||
| -rw-r--r-- | src/bootstrap/download-ci-llvm-stamp | 2 | ||||
| -rw-r--r-- | src/bootstrap/flags.rs | 20 | ||||
| -rw-r--r-- | src/bootstrap/native.rs | 8 | ||||
| -rw-r--r-- | src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile | 6 | ||||
| -rwxr-xr-x | src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh | 6 | ||||
| -rw-r--r-- | src/ci/docker/scripts/sccache.sh | 7 | ||||
| -rwxr-xr-x | src/ci/pgo.sh | 96 | ||||
| -rwxr-xr-x | src/ci/scripts/install-sccache.sh | 2 |
10 files changed, 105 insertions, 60 deletions
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index dd536cb7b02..5706b8f9e7c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -143,6 +143,8 @@ pub struct Config { pub rust_new_symbol_mangling: bool, pub rust_profile_use: Option<String>, pub rust_profile_generate: Option<String>, + pub llvm_profile_use: Option<String>, + pub llvm_profile_generate: bool, pub build: TargetSelection, pub hosts: Vec<TargetSelection>, @@ -605,6 +607,8 @@ impl Config { if let Some(value) = flags.deny_warnings { config.deny_warnings = value; } + config.llvm_profile_use = flags.llvm_profile_use; + config.llvm_profile_generate = flags.llvm_profile_generate; if config.dry_run { let dir = config.out.join("tmp-dry-run"); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 64075e18366..d7d511c1c92 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2157,10 +2157,16 @@ impl Step for ReproducibleArtifacts { } fn run(self, builder: &Builder<'_>) -> Self::Output { - let path = builder.config.rust_profile_use.as_ref()?; - + let mut added_anything = false; let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple); - tarball.add_file(path, ".", 0o644); - Some(tarball.generate()) + if let Some(path) = builder.config.rust_profile_use.as_ref() { + tarball.add_file(path, ".", 0o644); + added_anything = true; + } + if let Some(path) = builder.config.llvm_profile_use.as_ref() { + tarball.add_file(path, ".", 0o644); + added_anything = true; + } + if added_anything { Some(tarball.generate()) } else { None } } } diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index fb5b058cb4d..19e5fffcc2d 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/80932 +Last change is for: https://github.com/rust-lang/rust/pull/88069 diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 80c33fa4d7c..2fddda74a28 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -71,6 +71,13 @@ pub struct Flags { pub rust_profile_use: Option<String>, pub rust_profile_generate: Option<String>, + + pub llvm_profile_use: Option<String>, + // LLVM doesn't support a custom location for generating profile + // information. + // + // llvm_out/build/profiles/ is the location this writes to. + pub llvm_profile_generate: bool, } pub enum Subcommand { @@ -222,8 +229,15 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`", VALUE overrides the skip-rebuild option in config.toml.", "VALUE", ); - opts.optopt("", "rust-profile-generate", "generate PGO profile with rustc build", "FORMAT"); - opts.optopt("", "rust-profile-use", "use PGO profile for rustc build", "FORMAT"); + opts.optopt( + "", + "rust-profile-generate", + "generate PGO profile with rustc build", + "PROFILE", + ); + opts.optopt("", "rust-profile-use", "use PGO profile for rustc build", "PROFILE"); + opts.optflag("", "llvm-profile-generate", "generate PGO profile with llvm built for rustc"); + opts.optopt("", "llvm-profile-use", "use PGO profile for llvm build", "PROFILE"); // We can't use getopt to parse the options until we have completed specifying which // options are valid, but under the current implementation, some options are conditional on @@ -687,6 +701,8 @@ Arguments: .expect("`color` should be `always`, `never`, or `auto`"), rust_profile_use: matches.opt_str("rust-profile-use"), rust_profile_generate: matches.opt_str("rust-profile-generate"), + llvm_profile_use: matches.opt_str("llvm-profile-use"), + llvm_profile_generate: matches.opt_present("llvm-profile-generate"), } } } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index d1397394be7..2172b01706d 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -189,6 +189,14 @@ impl Step for Llvm { .define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap()) .define("LLVM_DEFAULT_TARGET_TRIPLE", target_native); + if builder.config.llvm_profile_generate { + cfg.define("LLVM_BUILD_INSTRUMENTED", "IR"); + cfg.define("LLVM_BUILD_RUNTIME", "No"); + } + if let Some(path) = builder.config.llvm_profile_use.as_ref() { + cfg.define("LLVM_PROFDATA_FILE", &path); + } + if target != "aarch64-apple-darwin" && !target.contains("windows") { cfg.define("LLVM_ENABLE_ZLIB", "ON"); } else { diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 8242e091cd4..e29d990f0f9 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -82,6 +82,12 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ +ENV PERF_COMMIT 1e19fc4c6168d2f7596e512f42f358f245d8f09d +RUN curl -LS -o perf.zip https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \ + unzip perf.zip && \ + mv rustc-perf-$PERF_COMMIT rustc-perf && \ + rm perf.zip + COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh index 40a637616d3..ed5edfec4e1 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh @@ -20,14 +20,18 @@ cd clang-build # include path, /rustroot/include, to clang's default include path. INC="/rustroot/include:/usr/include" +# We need compiler-rt for the profile runtime (used later to PGO the LLVM build) +# but sanitizers aren't currently building. Since we don't need those, just +# disable them. hide_output \ cmake ../llvm \ -DCMAKE_C_COMPILER=/rustroot/bin/gcc \ -DCMAKE_CXX_COMPILER=/rustroot/bin/g++ \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/rustroot \ + -DCOMPILER_RT_BUILD_SANITIZERS=OFF \ -DLLVM_TARGETS_TO_BUILD=X86 \ - -DLLVM_ENABLE_PROJECTS="clang;lld" \ + -DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt" \ -DC_INCLUDE_DIRS="$INC" hide_output make -j$(nproc) diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index 292b3c1d562..6c713e1f861 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -1,12 +1,15 @@ #!/bin/sh + +# ignore-tidy-linelength + set -ex case "$(uname -m)" in x86_64) - url="https://ci-mirrors.rust-lang.org/rustc/2018-04-02-sccache-x86_64-unknown-linux-musl" + url="https://ci-mirrors.rust-lang.org/rustc/2021-08-24-sccache-v0.2.15-x86_64-unknown-linux-musl" ;; aarch64) - url="https://ci-mirrors.rust-lang.org/rustc/2019-12-17-sccache-aarch64-unknown-linux-gnu" + url="https://ci-mirrors.rust-lang.org/rustc/2021-08-25-sccache-v0.2.15-aarch64-unknown-linux-musl" ;; *) echo "unsupported architecture: $(uname -m)" diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh index aa009a4eac6..e35e3e670cc 100755 --- a/src/ci/pgo.sh +++ b/src/ci/pgo.sh @@ -5,61 +5,59 @@ set -euxo pipefail rm -rf /tmp/rustc-pgo python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \ - --stage 2 library/std --rust-profile-generate=/tmp/rustc-pgo + --stage 2 library/std \ + --rust-profile-generate=/tmp/rustc-pgo \ + --llvm-profile-generate +# Profile libcore compilation in opt-level=0 and opt-level=3 RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ --crate-type=lib ../library/core/src/lib.rs - -# Download and build a single-file stress test benchmark on perf.rust-lang.org. -function pgo_perf_benchmark { - local PERF=1e19fc4c6168d2f7596e512f42f358f245d8f09d - local github_prefix=https://raw.githubusercontent.com/rust-lang/rustc-perf/$PERF - local name=$1 - local edition=$2 - curl -o /tmp/$name.rs $github_prefix/collector/benchmarks/$name/src/lib.rs - - RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=$edition \ - --crate-type=lib /tmp/$name.rs -} - -pgo_perf_benchmark externs 2018 -pgo_perf_benchmark ctfe-stress-4 2018 -pgo_perf_benchmark inflate 2015 - -cp -pri ../src/tools/cargo /tmp/cargo - -# The Cargo repository does not have a Cargo.lock in it, as it relies on the -# lockfile already present in the rust-lang/rust monorepo. This decision breaks -# down when Cargo is built outside the monorepo though (like in this case), -# resulting in a build without any dependency locking. -# -# To ensure Cargo is built with locked dependencies even during PGO profiling -# the following command copies the monorepo's lockfile into the Cargo temporary -# directory. Cargo will *not* keep that lockfile intact, as it will remove all -# the dependencies Cargo itself doesn't rely on. Still, it will prevent -# building Cargo with arbitrary dependency versions. -# -# See #81378 for the bug that prompted adding this. -cp -p ../Cargo.lock /tmp/cargo - -# Build cargo (with some flags) -function pgo_cargo { - RUSTC=./build/$PGO_HOST/stage2/bin/rustc \ - ./build/$PGO_HOST/stage0/bin/cargo $@ \ - --manifest-path /tmp/cargo/Cargo.toml -} - -# Build a couple different variants of Cargo -CARGO_INCREMENTAL=1 pgo_cargo check -echo 'pub fn barbarbar() {}' >> /tmp/cargo/src/cargo/lib.rs -CARGO_INCREMENTAL=1 pgo_cargo check -touch /tmp/cargo/src/cargo/lib.rs -CARGO_INCREMENTAL=1 pgo_cargo check -pgo_cargo build --release +RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \ + --crate-type=lib -Copt-level=3 ../library/core/src/lib.rs + +cp -r /tmp/rustc-perf ./ +chown -R $(whoami): ./rustc-perf +cd rustc-perf + +# Build the collector ahead of time, which is needed to make sure the rustc-fake +# binary used by the collector is present. +RUSTC=/checkout/obj/build/$PGO_HOST/stage0/bin/rustc \ +RUSTC_BOOTSTRAP=1 \ +/checkout/obj/build/$PGO_HOST/stage0/bin/cargo build -p collector + +# benchmark using profile_local with eprintln, which essentially just means +# don't actually benchmark -- just make sure we run rustc a bunch of times. +RUST_LOG=collector=debug \ +RUSTC=/checkout/obj/build/$PGO_HOST/stage0/bin/rustc \ +RUSTC_BOOTSTRAP=1 \ +/checkout/obj/build/$PGO_HOST/stage0/bin/cargo run -p collector --bin collector -- \ + profile_local \ + eprintln \ + /checkout/obj/build/$PGO_HOST/stage2/bin/rustc \ + Test \ + --builds Check,Debug,Opt \ + --cargo /checkout/obj/build/$PGO_HOST/stage0/bin/cargo \ + --runs All \ + --include externs,ctfe-stress-4,inflate,cargo,token-stream-stress,match-stress-enum + +cd /checkout/obj # Merge the profile data we gathered ./build/$PGO_HOST/llvm/bin/llvm-profdata \ merge -o /tmp/rustc-pgo.profdata /tmp/rustc-pgo +# Merge the profile data we gathered for LLVM +# Note that this uses the profdata from the clang we used to build LLVM, +# which likely has a different version than our in-tree clang. +/rustroot/bin/llvm-profdata \ + merge -o /tmp/llvm-pgo.profdata ./build/$PGO_HOST/llvm/build/profiles + +# Rustbuild currently doesn't support rebuilding LLVM when PGO options +# change (or any other llvm-related options); so just clear out the relevant +# directories ourselves. +rm -r ./build/$PGO_HOST/llvm ./build/$PGO_HOST/lld + # This produces the actual final set of artifacts. -$@ --rust-profile-use=/tmp/rustc-pgo.profdata +$@ \ + --rust-profile-use=/tmp/rustc-pgo.profdata \ + --llvm-profile-use=/tmp/llvm-pgo.profdata diff --git a/src/ci/scripts/install-sccache.sh b/src/ci/scripts/install-sccache.sh index d3c29899225..e143152f330 100755 --- a/src/ci/scripts/install-sccache.sh +++ b/src/ci/scripts/install-sccache.sh @@ -8,7 +8,7 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" if isMacOS; then - curl -fo /usr/local/bin/sccache "${MIRRORS_BASE}/2018-04-02-sccache-x86_64-apple-darwin" + curl -fo /usr/local/bin/sccache "${MIRRORS_BASE}/2021-08-25-sccache-v0.2.15-x86_64-apple-darwin" chmod +x /usr/local/bin/sccache elif isWindows; then mkdir -p sccache |
