mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Pass BOLT profile to bootstrap to be included in the reproducible artifacts archive
This commit is contained in:
parent
78403f4e13
commit
142995f15f
@ -232,8 +232,8 @@ pub struct Config {
|
||||
pub llvm_profile_use: Option<String>,
|
||||
pub llvm_profile_generate: bool,
|
||||
pub llvm_libunwind_default: Option<LlvmLibunwind>,
|
||||
pub llvm_bolt_profile_generate: bool,
|
||||
pub llvm_bolt_profile_use: Option<String>,
|
||||
|
||||
pub reproducible_artifacts: Vec<String>,
|
||||
|
||||
pub build: TargetSelection,
|
||||
pub hosts: Vec<TargetSelection>,
|
||||
@ -1462,6 +1462,8 @@ impl Config {
|
||||
config.rust_profile_generate = flags.rust_profile_generate;
|
||||
}
|
||||
|
||||
config.reproducible_artifacts = flags.reproducible_artifact;
|
||||
|
||||
// rust_info must be set before is_ci_llvm_available() is called.
|
||||
let default = config.channel == "dev";
|
||||
config.omit_git_hash = omit_git_hash.unwrap_or(default);
|
||||
|
@ -2265,8 +2265,8 @@ impl Step for ReproducibleArtifacts {
|
||||
tarball.add_file(path, ".", 0o644);
|
||||
added_anything = true;
|
||||
}
|
||||
if let Some(path) = builder.config.llvm_bolt_profile_use.as_ref() {
|
||||
tarball.add_file(path, ".", 0o644);
|
||||
for profile in &builder.config.reproducible_artifacts {
|
||||
tarball.add_file(profile, ".", 0o644);
|
||||
added_anything = true;
|
||||
}
|
||||
if added_anything { Some(tarball.generate()) } else { None }
|
||||
|
@ -149,12 +149,9 @@ pub struct Flags {
|
||||
/// generate PGO profile with llvm built for rustc
|
||||
#[arg(global(true), long)]
|
||||
pub llvm_profile_generate: bool,
|
||||
/// generate BOLT profile for LLVM build
|
||||
/// Additional reproducible artifacts that should be added to the reproducible artifacts archive.
|
||||
#[arg(global(true), long)]
|
||||
pub llvm_bolt_profile_generate: bool,
|
||||
/// use BOLT profile for LLVM build
|
||||
#[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
|
||||
pub llvm_bolt_profile_use: Option<String>,
|
||||
pub reproducible_artifact: Vec<String>,
|
||||
#[arg(global(true))]
|
||||
/// paths for the subcommand
|
||||
pub paths: Vec<PathBuf>,
|
||||
|
@ -40,7 +40,7 @@ pub fn with_bolt_instrumented<F: FnOnce() -> anyhow::Result<R>, R>(
|
||||
}
|
||||
|
||||
/// Optimizes the file at `path` with BOLT in-place using the given `profile`.
|
||||
pub fn bolt_optimize(path: &Utf8Path, profile: LlvmBoltProfile) -> anyhow::Result<()> {
|
||||
pub fn bolt_optimize(path: &Utf8Path, profile: &LlvmBoltProfile) -> anyhow::Result<()> {
|
||||
// Copy the artifact to a new location, so that we do not use the same input and output file.
|
||||
// BOLT cannot handle optimizing when the input and output is the same file, because it performs
|
||||
// in-place patching.
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::environment::Environment;
|
||||
use crate::metrics::{load_metrics, record_metrics};
|
||||
use crate::timer::TimerSection;
|
||||
use crate::training::{LlvmPGOProfile, RustcPGOProfile};
|
||||
use crate::training::{LlvmBoltProfile, LlvmPGOProfile, RustcPGOProfile};
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::File;
|
||||
@ -159,6 +159,11 @@ impl Bootstrap {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_bolt_profile(mut self, profile: LlvmBoltProfile) -> Self {
|
||||
self.cmd = self.cmd.arg("--reproducible-artifact").arg(profile.0.as_str());
|
||||
self
|
||||
}
|
||||
|
||||
/// Do not rebuild rustc, and use a previously built rustc sysroot instead.
|
||||
pub fn avoid_rustc_rebuild(mut self) -> Self {
|
||||
self.cmd = self.cmd.arg("--keep-stage").arg("0").arg("--keep-stage").arg("1");
|
||||
|
@ -95,7 +95,7 @@ fn execute_pipeline(
|
||||
Ok(profile)
|
||||
})?;
|
||||
|
||||
if env.supports_bolt() {
|
||||
let llvm_bolt_profile = if env.supports_bolt() {
|
||||
// Stage 3: Build BOLT instrumented LLVM
|
||||
// We build a PGO optimized LLVM in this step, then instrument it with BOLT and gather BOLT profiles.
|
||||
// Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build.
|
||||
@ -128,18 +128,24 @@ fn execute_pipeline(
|
||||
// the final dist build. However, when BOLT optimizes an artifact, it does so *in-place*,
|
||||
// therefore it will actually optimize all the hard links, which means that the final
|
||||
// packaged `libLLVM.so` file *will* be BOLT optimized.
|
||||
bolt_optimize(&llvm_lib, profile).context("Could not optimize LLVM with BOLT")?;
|
||||
bolt_optimize(&llvm_lib, &profile).context("Could not optimize LLVM with BOLT")?;
|
||||
|
||||
// LLVM is not being cleared here, we want to use the BOLT-optimized LLVM
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
Ok(Some(profile))
|
||||
})?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let dist = Bootstrap::dist(env, &dist_args)
|
||||
let mut dist = Bootstrap::dist(env, &dist_args)
|
||||
.llvm_pgo_optimize(&llvm_pgo_profile)
|
||||
.rustc_pgo_optimize(&rustc_pgo_profile)
|
||||
.avoid_rustc_rebuild();
|
||||
|
||||
if let Some(llvm_bolt_profile) = llvm_bolt_profile {
|
||||
dist = dist.with_bolt_profile(llvm_bolt_profile);
|
||||
}
|
||||
|
||||
// Final stage: Assemble the dist artifacts
|
||||
// The previous PGO optimized rustc build and PGO optimized LLVM builds should be reused.
|
||||
timer.section("Stage 4 (final build)", |stage| dist.run(stage))?;
|
||||
|
@ -175,7 +175,7 @@ pub fn gather_llvm_bolt_profiles(env: &dyn Environment) -> anyhow::Result<LlvmBo
|
||||
.context("Cannot gather LLVM BOLT profiles")
|
||||
})?;
|
||||
|
||||
let merged_profile = env.opt_artifacts().join("bolt.profdata");
|
||||
let merged_profile = env.opt_artifacts().join("llvm-bolt.profdata");
|
||||
let profile_root = Utf8PathBuf::from("/tmp/prof.fdata");
|
||||
log::info!("Merging LLVM BOLT profiles to {merged_profile}");
|
||||
|
||||
|
@ -74,21 +74,15 @@ pub fn find_file_in_dir(
|
||||
prefix: &str,
|
||||
suffix: &str,
|
||||
) -> anyhow::Result<Utf8PathBuf> {
|
||||
let mut files = glob::glob(&format!("{directory}/{prefix}*{suffix}"))?
|
||||
let files = glob::glob(&format!("{directory}/{prefix}*{suffix}"))?
|
||||
.into_iter()
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
match files.pop() {
|
||||
Some(file) => {
|
||||
if !files.is_empty() {
|
||||
files.push(file);
|
||||
Err(anyhow::anyhow!(
|
||||
"More than one file with prefix {prefix} found in {directory}: {:?}",
|
||||
files
|
||||
))
|
||||
} else {
|
||||
Ok(Utf8PathBuf::from_path_buf(file).unwrap())
|
||||
}
|
||||
}
|
||||
None => Err(anyhow::anyhow!("No file with prefix {prefix} found in {directory}")),
|
||||
match files.len() {
|
||||
0 => Err(anyhow::anyhow!("No file with prefix {prefix} found in {directory}")),
|
||||
1 => Ok(Utf8PathBuf::from_path_buf(files[0].clone()).unwrap()),
|
||||
_ => Err(anyhow::anyhow!(
|
||||
"More than one file with prefix {prefix} found in {directory}: {:?}",
|
||||
files
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user