Skip to content

Commit c4be230

Browse files
committed
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.
2 parents 0afc208 + 1ea8d93 commit c4be230

File tree

10 files changed

+105
-60
lines changed

10 files changed

+105
-60
lines changed

src/bootstrap/config.rs

+4
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ pub struct Config {
143143
pub rust_new_symbol_mangling: bool,
144144
pub rust_profile_use: Option<String>,
145145
pub rust_profile_generate: Option<String>,
146+
pub llvm_profile_use: Option<String>,
147+
pub llvm_profile_generate: bool,
146148

147149
pub build: TargetSelection,
148150
pub hosts: Vec<TargetSelection>,
@@ -605,6 +607,8 @@ impl Config {
605607
if let Some(value) = flags.deny_warnings {
606608
config.deny_warnings = value;
607609
}
610+
config.llvm_profile_use = flags.llvm_profile_use;
611+
config.llvm_profile_generate = flags.llvm_profile_generate;
608612

609613
if config.dry_run {
610614
let dir = config.out.join("tmp-dry-run");

src/bootstrap/dist.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -2157,10 +2157,16 @@ impl Step for ReproducibleArtifacts {
21572157
}
21582158

21592159
fn run(self, builder: &Builder<'_>) -> Self::Output {
2160-
let path = builder.config.rust_profile_use.as_ref()?;
2161-
2160+
let mut added_anything = false;
21622161
let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2163-
tarball.add_file(path, ".", 0o644);
2164-
Some(tarball.generate())
2162+
if let Some(path) = builder.config.rust_profile_use.as_ref() {
2163+
tarball.add_file(path, ".", 0o644);
2164+
added_anything = true;
2165+
}
2166+
if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2167+
tarball.add_file(path, ".", 0o644);
2168+
added_anything = true;
2169+
}
2170+
if added_anything { Some(tarball.generate()) } else { None }
21652171
}
21662172
}

src/bootstrap/download-ci-llvm-stamp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
Change this file to make users of the `download-ci-llvm` configuration download
22
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
33

4-
Last change is for: https://github.com/rust-lang/rust/pull/80932
4+
Last change is for: https://github.com/rust-lang/rust/pull/88069

src/bootstrap/flags.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ pub struct Flags {
7171

7272
pub rust_profile_use: Option<String>,
7373
pub rust_profile_generate: Option<String>,
74+
75+
pub llvm_profile_use: Option<String>,
76+
// LLVM doesn't support a custom location for generating profile
77+
// information.
78+
//
79+
// llvm_out/build/profiles/ is the location this writes to.
80+
pub llvm_profile_generate: bool,
7481
}
7582

7683
pub enum Subcommand {
@@ -222,8 +229,15 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
222229
VALUE overrides the skip-rebuild option in config.toml.",
223230
"VALUE",
224231
);
225-
opts.optopt("", "rust-profile-generate", "generate PGO profile with rustc build", "FORMAT");
226-
opts.optopt("", "rust-profile-use", "use PGO profile for rustc build", "FORMAT");
232+
opts.optopt(
233+
"",
234+
"rust-profile-generate",
235+
"generate PGO profile with rustc build",
236+
"PROFILE",
237+
);
238+
opts.optopt("", "rust-profile-use", "use PGO profile for rustc build", "PROFILE");
239+
opts.optflag("", "llvm-profile-generate", "generate PGO profile with llvm built for rustc");
240+
opts.optopt("", "llvm-profile-use", "use PGO profile for llvm build", "PROFILE");
227241

228242
// We can't use getopt to parse the options until we have completed specifying which
229243
// options are valid, but under the current implementation, some options are conditional on
@@ -687,6 +701,8 @@ Arguments:
687701
.expect("`color` should be `always`, `never`, or `auto`"),
688702
rust_profile_use: matches.opt_str("rust-profile-use"),
689703
rust_profile_generate: matches.opt_str("rust-profile-generate"),
704+
llvm_profile_use: matches.opt_str("llvm-profile-use"),
705+
llvm_profile_generate: matches.opt_present("llvm-profile-generate"),
690706
}
691707
}
692708
}

src/bootstrap/native.rs

+8
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,14 @@ impl Step for Llvm {
189189
.define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap())
190190
.define("LLVM_DEFAULT_TARGET_TRIPLE", target_native);
191191

192+
if builder.config.llvm_profile_generate {
193+
cfg.define("LLVM_BUILD_INSTRUMENTED", "IR");
194+
cfg.define("LLVM_BUILD_RUNTIME", "No");
195+
}
196+
if let Some(path) = builder.config.llvm_profile_use.as_ref() {
197+
cfg.define("LLVM_PROFDATA_FILE", &path);
198+
}
199+
192200
if target != "aarch64-apple-darwin" && !target.contains("windows") {
193201
cfg.define("LLVM_ENABLE_ZLIB", "ON");
194202
} else {

src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile

+6
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/
8282
RUN ./build-clang.sh
8383
ENV CC=clang CXX=clang++
8484

85+
ENV PERF_COMMIT 1e19fc4c6168d2f7596e512f42f358f245d8f09d
86+
RUN curl -LS -o perf.zip https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \
87+
unzip perf.zip && \
88+
mv rustc-perf-$PERF_COMMIT rustc-perf && \
89+
rm perf.zip
90+
8591
COPY scripts/sccache.sh /scripts/
8692
RUN sh /scripts/sccache.sh
8793

src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh

+5-1
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@ cd clang-build
2020
# include path, /rustroot/include, to clang's default include path.
2121
INC="/rustroot/include:/usr/include"
2222

23+
# We need compiler-rt for the profile runtime (used later to PGO the LLVM build)
24+
# but sanitizers aren't currently building. Since we don't need those, just
25+
# disable them.
2326
hide_output \
2427
cmake ../llvm \
2528
-DCMAKE_C_COMPILER=/rustroot/bin/gcc \
2629
-DCMAKE_CXX_COMPILER=/rustroot/bin/g++ \
2730
-DCMAKE_BUILD_TYPE=Release \
2831
-DCMAKE_INSTALL_PREFIX=/rustroot \
32+
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
2933
-DLLVM_TARGETS_TO_BUILD=X86 \
30-
-DLLVM_ENABLE_PROJECTS="clang;lld" \
34+
-DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt" \
3135
-DC_INCLUDE_DIRS="$INC"
3236

3337
hide_output make -j$(nproc)

src/ci/docker/scripts/sccache.sh

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
#!/bin/sh
2+
3+
# ignore-tidy-linelength
4+
25
set -ex
36

47
case "$(uname -m)" in
58
x86_64)
6-
url="https://ci-mirrors.rust-lang.org/rustc/2018-04-02-sccache-x86_64-unknown-linux-musl"
9+
url="https://ci-mirrors.rust-lang.org/rustc/2021-08-24-sccache-v0.2.15-x86_64-unknown-linux-musl"
710
;;
811
aarch64)
9-
url="https://ci-mirrors.rust-lang.org/rustc/2019-12-17-sccache-aarch64-unknown-linux-gnu"
12+
url="https://ci-mirrors.rust-lang.org/rustc/2021-08-25-sccache-v0.2.15-aarch64-unknown-linux-musl"
1013
;;
1114
*)
1215
echo "unsupported architecture: $(uname -m)"

src/ci/pgo.sh

+47-49
Original file line numberDiff line numberDiff line change
@@ -5,61 +5,59 @@ set -euxo pipefail
55
rm -rf /tmp/rustc-pgo
66

77
python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
8-
--stage 2 library/std --rust-profile-generate=/tmp/rustc-pgo
8+
--stage 2 library/std \
9+
--rust-profile-generate=/tmp/rustc-pgo \
10+
--llvm-profile-generate
911

12+
# Profile libcore compilation in opt-level=0 and opt-level=3
1013
RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \
1114
--crate-type=lib ../library/core/src/lib.rs
12-
13-
# Download and build a single-file stress test benchmark on perf.rust-lang.org.
14-
function pgo_perf_benchmark {
15-
local PERF=1e19fc4c6168d2f7596e512f42f358f245d8f09d
16-
local github_prefix=https://raw.githubusercontent.com/rust-lang/rustc-perf/$PERF
17-
local name=$1
18-
local edition=$2
19-
curl -o /tmp/$name.rs $github_prefix/collector/benchmarks/$name/src/lib.rs
20-
21-
RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=$edition \
22-
--crate-type=lib /tmp/$name.rs
23-
}
24-
25-
pgo_perf_benchmark externs 2018
26-
pgo_perf_benchmark ctfe-stress-4 2018
27-
pgo_perf_benchmark inflate 2015
28-
29-
cp -pri ../src/tools/cargo /tmp/cargo
30-
31-
# The Cargo repository does not have a Cargo.lock in it, as it relies on the
32-
# lockfile already present in the rust-lang/rust monorepo. This decision breaks
33-
# down when Cargo is built outside the monorepo though (like in this case),
34-
# resulting in a build without any dependency locking.
35-
#
36-
# To ensure Cargo is built with locked dependencies even during PGO profiling
37-
# the following command copies the monorepo's lockfile into the Cargo temporary
38-
# directory. Cargo will *not* keep that lockfile intact, as it will remove all
39-
# the dependencies Cargo itself doesn't rely on. Still, it will prevent
40-
# building Cargo with arbitrary dependency versions.
41-
#
42-
# See #81378 for the bug that prompted adding this.
43-
cp -p ../Cargo.lock /tmp/cargo
44-
45-
# Build cargo (with some flags)
46-
function pgo_cargo {
47-
RUSTC=./build/$PGO_HOST/stage2/bin/rustc \
48-
./build/$PGO_HOST/stage0/bin/cargo $@ \
49-
--manifest-path /tmp/cargo/Cargo.toml
50-
}
51-
52-
# Build a couple different variants of Cargo
53-
CARGO_INCREMENTAL=1 pgo_cargo check
54-
echo 'pub fn barbarbar() {}' >> /tmp/cargo/src/cargo/lib.rs
55-
CARGO_INCREMENTAL=1 pgo_cargo check
56-
touch /tmp/cargo/src/cargo/lib.rs
57-
CARGO_INCREMENTAL=1 pgo_cargo check
58-
pgo_cargo build --release
15+
RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \
16+
--crate-type=lib -Copt-level=3 ../library/core/src/lib.rs
17+
18+
cp -r /tmp/rustc-perf ./
19+
chown -R $(whoami): ./rustc-perf
20+
cd rustc-perf
21+
22+
# Build the collector ahead of time, which is needed to make sure the rustc-fake
23+
# binary used by the collector is present.
24+
RUSTC=/checkout/obj/build/$PGO_HOST/stage0/bin/rustc \
25+
RUSTC_BOOTSTRAP=1 \
26+
/checkout/obj/build/$PGO_HOST/stage0/bin/cargo build -p collector
27+
28+
# benchmark using profile_local with eprintln, which essentially just means
29+
# don't actually benchmark -- just make sure we run rustc a bunch of times.
30+
RUST_LOG=collector=debug \
31+
RUSTC=/checkout/obj/build/$PGO_HOST/stage0/bin/rustc \
32+
RUSTC_BOOTSTRAP=1 \
33+
/checkout/obj/build/$PGO_HOST/stage0/bin/cargo run -p collector --bin collector -- \
34+
profile_local \
35+
eprintln \
36+
/checkout/obj/build/$PGO_HOST/stage2/bin/rustc \
37+
Test \
38+
--builds Check,Debug,Opt \
39+
--cargo /checkout/obj/build/$PGO_HOST/stage0/bin/cargo \
40+
--runs All \
41+
--include externs,ctfe-stress-4,inflate,cargo,token-stream-stress,match-stress-enum
42+
43+
cd /checkout/obj
5944

6045
# Merge the profile data we gathered
6146
./build/$PGO_HOST/llvm/bin/llvm-profdata \
6247
merge -o /tmp/rustc-pgo.profdata /tmp/rustc-pgo
6348

49+
# Merge the profile data we gathered for LLVM
50+
# Note that this uses the profdata from the clang we used to build LLVM,
51+
# which likely has a different version than our in-tree clang.
52+
/rustroot/bin/llvm-profdata \
53+
merge -o /tmp/llvm-pgo.profdata ./build/$PGO_HOST/llvm/build/profiles
54+
55+
# Rustbuild currently doesn't support rebuilding LLVM when PGO options
56+
# change (or any other llvm-related options); so just clear out the relevant
57+
# directories ourselves.
58+
rm -r ./build/$PGO_HOST/llvm ./build/$PGO_HOST/lld
59+
6460
# This produces the actual final set of artifacts.
65-
$@ --rust-profile-use=/tmp/rustc-pgo.profdata
61+
$@ \
62+
--rust-profile-use=/tmp/rustc-pgo.profdata \
63+
--llvm-profile-use=/tmp/llvm-pgo.profdata

src/ci/scripts/install-sccache.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ IFS=$'\n\t'
88
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
99

1010
if isMacOS; then
11-
curl -fo /usr/local/bin/sccache "${MIRRORS_BASE}/2018-04-02-sccache-x86_64-apple-darwin"
11+
curl -fo /usr/local/bin/sccache "${MIRRORS_BASE}/2021-08-25-sccache-v0.2.15-x86_64-apple-darwin"
1212
chmod +x /usr/local/bin/sccache
1313
elif isWindows; then
1414
mkdir -p sccache

0 commit comments

Comments
 (0)