Skip to content

Commit

Permalink
Pass BOLT profile to bootstrap to be included in the reproducible art…
Browse files Browse the repository at this point in the history
…ifacts archive
  • Loading branch information
Kobzol committed Jul 31, 2023
1 parent 78403f4 commit 142995f
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 32 deletions.
6 changes: 4 additions & 2 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions src/bootstrap/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
7 changes: 2 additions & 5 deletions src/bootstrap/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down
2 changes: 1 addition & 1 deletion src/tools/opt-dist/src/bolt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 6 additions & 1 deletion src/tools/opt-dist/src/exec.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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");
Expand Down
18 changes: 12 additions & 6 deletions src/tools/opt-dist/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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))?;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/opt-dist/src/training.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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}");

Expand Down
22 changes: 8 additions & 14 deletions src/tools/opt-dist/src/utils/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
)),
}
}

0 comments on commit 142995f

Please sign in to comment.