Skip to content

Commit 1ee57ce

Browse files
committed
Use PGO for libstd
1 parent 8c52a83 commit 1ee57ce

File tree

5 files changed

+79
-1
lines changed

5 files changed

+79
-1
lines changed

compiler/rustc_metadata/src/creader.rs

+5
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,11 @@ impl<'a> CrateLoader<'a> {
772772

773773
info!("loading profiler");
774774

775+
let local_crate_name = self.local_crate_name.as_str();
776+
if std::env::var("RUST_LIBSTD_PGO").is_ok() && local_crate_name != "std" {
777+
return;
778+
}
779+
775780
let name = Symbol::intern(&self.sess.opts.debugging_opts.profiler_runtime);
776781
if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
777782
self.sess.err(

src/bootstrap/compile.rs

+36
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,42 @@ impl Step for Std {
108108
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build");
109109
std_cargo(builder, target, compiler.stage, &mut cargo);
110110

111+
if builder.config.libstd_profile_use.is_some()
112+
&& builder.config.libstd_profile_generate.is_some()
113+
{
114+
panic!("Cannot use and generate PGO profiles for libstd at the same time");
115+
}
116+
117+
let is_collecting = if let Some(path) = &builder.config.libstd_profile_generate {
118+
if compiler.stage == 1 {
119+
cargo.env("RUST_LIBSTD_PGO", "1");
120+
cargo.rustflag(&format!("-Cprofile-generate={}", path));
121+
// Apparently necessary to avoid overflowing the counters during
122+
// a Cargo build profile
123+
cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
124+
true
125+
} else {
126+
false
127+
}
128+
} else if let Some(path) = &builder.config.libstd_profile_use {
129+
if compiler.stage == 1 {
130+
cargo.rustflag(&format!("-Cprofile-use={}", path));
131+
cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
132+
true
133+
} else {
134+
false
135+
}
136+
} else {
137+
false
138+
};
139+
if is_collecting {
140+
// Ensure paths to Rust sources are relative, not absolute.
141+
cargo.rustflag(&format!(
142+
"-Cllvm-args=-static-func-strip-dirname-prefix={}",
143+
builder.config.src.components().count()
144+
));
145+
}
146+
111147
builder.info(&format!(
112148
"Building stage{} std artifacts ({} -> {})",
113149
compiler.stage, &compiler.host, target

src/bootstrap/config.rs

+4
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ pub struct Config {
156156
pub rust_new_symbol_mangling: Option<bool>,
157157
pub rust_profile_use: Option<String>,
158158
pub rust_profile_generate: Option<String>,
159+
pub libstd_profile_use: Option<String>,
160+
pub libstd_profile_generate: Option<String>,
159161
pub llvm_profile_use: Option<String>,
160162
pub llvm_profile_generate: bool,
161163
pub llvm_libunwind_default: Option<LlvmLibunwind>,
@@ -797,6 +799,8 @@ impl Config {
797799
}
798800
config.llvm_profile_use = flags.llvm_profile_use;
799801
config.llvm_profile_generate = flags.llvm_profile_generate;
802+
config.libstd_profile_use = flags.libstd_profile_use;
803+
config.libstd_profile_generate = flags.libstd_profile_generate;
800804

801805
let stage0_json = t!(std::fs::read(&config.src.join("src").join("stage0.json")));
802806
config.stage0_metadata = t!(serde_json::from_slice::<Stage0Metadata>(&stage0_json));

src/bootstrap/flags.rs

+12
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ pub struct Flags {
7979
//
8080
// llvm_out/build/profiles/ is the location this writes to.
8181
pub llvm_profile_generate: bool,
82+
83+
pub libstd_profile_use: Option<String>,
84+
pub libstd_profile_generate: Option<String>,
8285
}
8386

8487
#[cfg_attr(test, derive(Clone))]
@@ -247,6 +250,13 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
247250
opts.optopt("", "rust-profile-use", "use PGO profile for rustc build", "PROFILE");
248251
opts.optflag("", "llvm-profile-generate", "generate PGO profile with llvm built for rustc");
249252
opts.optopt("", "llvm-profile-use", "use PGO profile for llvm build", "PROFILE");
253+
opts.optopt(
254+
"",
255+
"libstd-profile-generate",
256+
"generate PGO profile with libstd build",
257+
"PROFILE",
258+
);
259+
opts.optopt("", "libstd-profile-use", "use PGO profile for libstd build", "PROFILE");
250260

251261
// We can't use getopt to parse the options until we have completed specifying which
252262
// options are valid, but under the current implementation, some options are conditional on
@@ -676,6 +686,8 @@ Arguments:
676686
rust_profile_generate: matches.opt_str("rust-profile-generate"),
677687
llvm_profile_use: matches.opt_str("llvm-profile-use"),
678688
llvm_profile_generate: matches.opt_present("llvm-profile-generate"),
689+
libstd_profile_use: matches.opt_str("libstd-profile-use"),
690+
libstd_profile_generate: matches.opt_str("libstd-profile-generate"),
679691
}
680692
}
681693
}

src/ci/pgo.sh

+22-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,26 @@ du -sh ${RUSTC_PROFILE_DIRECTORY_ROOT}
120120
echo "Profile file count"
121121
find ${RUSTC_PROFILE_DIRECTORY_ROOT} -type f | wc -l
122122

123+
rm -r ./build/$PGO_HOST/llvm ./build/$PGO_HOST/lld
124+
125+
python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
126+
--stage 2 library/std \
127+
--rust-profile-use=/tmp/rustc-pgo.profdata \
128+
--libstd-profile-generate=/tmp/libstd-pgo
129+
130+
# Here we're profiling the `rustc` frontend, so we also include `Check`.
131+
# The benchmark set includes various stress tests that put the frontend under pressure.
132+
LLVM_PROFILE_FILE=/tmp/libstd-pgo/default_%m_%p.profraw gather_profiles "Check,Debug,Opt" "All" \
133+
"externs,ctfe-stress-5,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress"
134+
135+
# Merge the profile data we gathered
136+
./build/$PGO_HOST/llvm/bin/llvm-profdata \
137+
merge -o /tmp/libstd-pgo.profdata /tmp/libstd-pgo
138+
139+
echo "libstd PGO statistics"
140+
./build/$PGO_HOST/llvm/bin/llvm-profdata \
141+
show /tmp/libstd-pgo.profdata --all-functions
142+
123143
# Rustbuild currently doesn't support rebuilding LLVM when PGO options
124144
# change (or any other llvm-related options); so just clear out the relevant
125145
# directories ourselves.
@@ -129,4 +149,5 @@ rm -r ./build/$PGO_HOST/llvm ./build/$PGO_HOST/lld
129149
# collected profiling data.
130150
$@ \
131151
--rust-profile-use=${RUSTC_PROFILE_MERGED_FILE} \
132-
--llvm-profile-use=${LLVM_PROFILE_MERGED_FILE}
152+
--llvm-profile-use=${LLVM_PROFILE_MERGED_FILE} \
153+
--libstd-profile-use=/tmp/libstd-pgo.profdata

0 commit comments

Comments
 (0)