Skip to content

Commit 257ec3b

Browse files
committed
Update PGO staging logic for static LLVM linkage
This commit updates the logic around PGO staging when linking LLVM statically to ensure that the necessary runtime libraries are included. In addition, several flags related to PGO can now be specified in the config.toml file.
1 parent 63c748e commit 257ec3b

File tree

5 files changed

+61
-41
lines changed

5 files changed

+61
-41
lines changed

src/bootstrap/compile.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -666,8 +666,10 @@ impl Step for Rustc {
666666
cargo.rustflag("-Clink-args=-Wl,--icf=all");
667667
}
668668

669-
let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
670-
if compiler.stage == 1 {
669+
let use_relative_paths = if let Some(path) = &builder.config.rust_profile_generate {
670+
if compiler.stage >= 1
671+
|| (builder.config.llvm_profile_generate.is_some() && !builder.llvm_link_shared())
672+
{
671673
cargo.rustflag(&format!("-Cprofile-generate={}", path));
672674
// Apparently necessary to avoid overflowing the counters during
673675
// a Cargo build profile
@@ -676,18 +678,28 @@ impl Step for Rustc {
676678
} else {
677679
false
678680
}
679-
} else if let Some(path) = &builder.config.rust_profile_use {
680-
if compiler.stage == 1 {
681-
cargo.rustflag(&format!("-Cprofile-use={}", path));
682-
cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
681+
} else if let Some(path) = &builder.config.llvm_profile_generate {
682+
// If libLLVM.a is instrumented it will need to be linked against
683+
// the profiler's runtime environment. The only way to ensure that
684+
// occurs is to tell rustc to profile the compilation unit.
685+
if !builder.llvm_link_shared() {
686+
cargo.rustflag(&format!("-Cprofile-generate={}", path));
687+
// Apparently necessary to avoid overflowing the counters during
688+
// a Cargo build profile
689+
cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
683690
true
684691
} else {
685692
false
686693
}
694+
} else if let Some(path) = &builder.config.rust_profile_use {
695+
cargo.rustflag(&format!("-Cprofile-use={}", path));
696+
cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
697+
true
687698
} else {
688699
false
689700
};
690-
if is_collecting {
701+
702+
if use_relative_paths {
691703
// Ensure paths to Rust sources are relative, not absolute.
692704
cargo.rustflag(&format!(
693705
"-Cllvm-args=-static-func-strip-dirname-prefix={}",
@@ -821,7 +833,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
821833
// found. This is to avoid the linker errors about undefined references to
822834
// `__llvm_profile_instrument_memop` when linking `rustc_driver`.
823835
let mut llvm_linker_flags = String::new();
824-
if builder.config.llvm_profile_generate && target.contains("msvc") {
836+
if builder.config.llvm_profile_generate.is_some() && target.contains("msvc") {
825837
if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
826838
// Add clang's runtime library directory to the search path
827839
let clang_rt_dir = get_clang_cl_resource_dir(clang_cl_path);

src/bootstrap/config.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ pub struct Config {
140140
pub llvm_ldflags: Option<String>,
141141
pub llvm_use_libcxx: bool,
142142

143+
pub llvm_profile_use: Option<String>,
144+
pub llvm_profile_generate: Option<String>,
145+
pub llvm_libunwind_default: Option<LlvmLibunwind>,
146+
pub llvm_bolt_profile_generate: bool,
147+
pub llvm_bolt_profile_use: Option<String>,
148+
143149
// rust codegen options
144150
pub rust_optimize: bool,
145151
pub rust_codegen_units: Option<u32>,
@@ -167,11 +173,6 @@ pub struct Config {
167173
pub rust_profile_use: Option<String>,
168174
pub rust_profile_generate: Option<String>,
169175
pub rust_lto: RustcLto,
170-
pub llvm_profile_use: Option<String>,
171-
pub llvm_profile_generate: bool,
172-
pub llvm_libunwind_default: Option<LlvmLibunwind>,
173-
pub llvm_bolt_profile_generate: bool,
174-
pub llvm_bolt_profile_use: Option<String>,
175176

176177
pub build: TargetSelection,
177178
pub hosts: Vec<TargetSelection>,
@@ -679,6 +680,10 @@ define_config! {
679680
clang: Option<bool> = "clang",
680681
download_ci_llvm: Option<StringOrBool> = "download-ci-llvm",
681682
build_config: Option<HashMap<String, String>> = "build-config",
683+
profile_generate: Option<String> = "profile-generate",
684+
profile_use: Option<String> = "profile-use",
685+
bolt_profile_generate: Option<bool> = "bolt-profile-generate",
686+
bolt_profile_use: Option<String> = "bolt-profile-use",
682687
}
683688
}
684689

@@ -838,17 +843,6 @@ impl Config {
838843
if let Some(value) = flags.deny_warnings {
839844
config.deny_warnings = value;
840845
}
841-
config.llvm_profile_use = flags.llvm_profile_use;
842-
config.llvm_profile_generate = flags.llvm_profile_generate;
843-
config.llvm_bolt_profile_generate = flags.llvm_bolt_profile_generate;
844-
config.llvm_bolt_profile_use = flags.llvm_bolt_profile_use;
845-
846-
if config.llvm_bolt_profile_generate && config.llvm_bolt_profile_use.is_some() {
847-
eprintln!(
848-
"Cannot use both `llvm_bolt_profile_generate` and `llvm_bolt_profile_use` at the same time"
849-
);
850-
crate::detail_exit(1);
851-
}
852846

853847
// Infer the rest of the configuration.
854848

@@ -1141,6 +1135,25 @@ impl Config {
11411135
// the link step) with each stage.
11421136
config.llvm_link_shared.set(Some(true));
11431137
}
1138+
1139+
config.llvm_profile_generate = flags.llvm_profile_generate.or(llvm.profile_generate);
1140+
config.llvm_profile_use = flags.llvm_profile_use.or(llvm.profile_use);
1141+
1142+
config.llvm_bolt_profile_generate = flags.llvm_bolt_profile_generate;
1143+
config.llvm_bolt_profile_use = flags.llvm_bolt_profile_use.or(llvm.bolt_profile_use);
1144+
} else {
1145+
config.llvm_profile_generate = flags.llvm_profile_generate;
1146+
config.llvm_profile_use = flags.llvm_profile_use;
1147+
1148+
config.llvm_bolt_profile_generate = flags.llvm_bolt_profile_generate;
1149+
config.llvm_bolt_profile_use = flags.llvm_bolt_profile_use;
1150+
}
1151+
1152+
if config.llvm_bolt_profile_generate && config.llvm_bolt_profile_use.is_some() {
1153+
eprintln!(
1154+
"Cannot use both `llvm_bolt_profile_generate` and `llvm_bolt_profile_use` at the same time"
1155+
);
1156+
crate::detail_exit(1);
11441157
}
11451158

11461159
if let Some(rust) = toml.rust {

src/bootstrap/flags.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,12 @@ pub struct Flags {
6969

7070
pub llvm_skip_rebuild: Option<bool>,
7171

72-
pub rust_profile_use: Option<String>,
7372
pub rust_profile_generate: Option<String>,
73+
pub rust_profile_use: Option<String>,
7474

75+
pub llvm_profile_generate: Option<String>,
7576
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,
77+
8178
pub llvm_bolt_profile_generate: bool,
8279
pub llvm_bolt_profile_use: Option<String>,
8380
}
@@ -698,7 +695,7 @@ Arguments:
698695
rust_profile_use: matches.opt_str("rust-profile-use"),
699696
rust_profile_generate: matches.opt_str("rust-profile-generate"),
700697
llvm_profile_use: matches.opt_str("llvm-profile-use"),
701-
llvm_profile_generate: matches.opt_present("llvm-profile-generate"),
698+
llvm_profile_generate: matches.opt_str("llvm-profile-generate"),
702699
llvm_bolt_profile_generate: matches.opt_present("llvm-bolt-profile-generate"),
703700
llvm_bolt_profile_use: matches.opt_str("llvm-bolt-profile-use"),
704701
}

src/bootstrap/native.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,9 @@ impl Step for Llvm {
320320
// This flag makes sure `FileCheck` is copied in the final binaries directory.
321321
cfg.define("LLVM_INSTALL_UTILS", "ON");
322322

323-
if builder.config.llvm_profile_generate {
323+
if let Some(path) = &builder.config.llvm_profile_generate {
324324
cfg.define("LLVM_BUILD_INSTRUMENTED", "IR");
325-
if let Ok(llvm_profile_dir) = std::env::var("LLVM_PROFILE_DIR") {
326-
cfg.define("LLVM_PROFILE_DATA_DIR", llvm_profile_dir);
327-
}
325+
cfg.define("LLVM_PROFILE_DATA_DIR", &path);
328326
cfg.define("LLVM_BUILD_RUNTIME", "No");
329327
}
330328
if let Some(path) = builder.config.llvm_profile_use.as_ref() {
@@ -822,7 +820,7 @@ impl Step for Lld {
822820
// when doing PGO on CI, cmake or clang-cl don't automatically link clang's
823821
// profiler runtime in. In that case, we need to manually ask cmake to do it, to avoid
824822
// linking errors, much like LLVM's cmake setup does in that situation.
825-
if builder.config.llvm_profile_generate && target.contains("msvc") {
823+
if builder.config.llvm_profile_generate.is_some() && target.contains("msvc") {
826824
if let Some(clang_cl_path) = builder.config.llvm_clang_cl.as_ref() {
827825
// Find clang's runtime library directory and push that as a search path to the
828826
// cmake linker flags.

src/ci/pgo.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ LLVM_PROFILE_DIRECTORY_ROOT=$PGO_TMP/llvm-pgo
8484
# separate phases. This increases build time -- though not by a huge amount --
8585
# but prevents any problems from arising due to different profiling runtimes
8686
# being simultaneously linked in.
87-
# LLVM IR PGO does not respect LLVM_PROFILE_FILE, so we have to set the profiling file
88-
# path through our custom environment variable. We include the PID in the directory path
89-
# to avoid updates to profile files being lost because of race conditions.
90-
LLVM_PROFILE_DIR=${LLVM_PROFILE_DIRECTORY_ROOT}/prof-%p python3 $CHECKOUT/x.py build \
87+
# LLVM IR PGO does not respect LLVM_PROFILE_FILE, so we have to set the profiling path
88+
# through the LLVM build system in src/bootstrap/native.rs. We include the PID in the
89+
# directory path to avoid updates to profile files being lost because of race conditions.
90+
python3 $CHECKOUT/x.py build \
9191
--target=$PGO_HOST \
9292
--host=$PGO_HOST \
9393
--stage 2 library/std \
94-
--llvm-profile-generate
94+
--llvm-profile-generate=${LLVM_PROFILE_DIRECTORY_ROOT}/prof-%p
9595

9696
# Compile rustc-perf:
9797
# - get the expected commit source code: on linux, the Dockerfile downloads a source archive before

0 commit comments

Comments
 (0)