about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/config.rs6
-rw-r--r--src/bootstrap/dist.rs4
-rw-r--r--src/bootstrap/flags.rs7
-rw-r--r--src/tools/opt-dist/src/bolt.rs2
-rw-r--r--src/tools/opt-dist/src/exec.rs7
-rw-r--r--src/tools/opt-dist/src/main.rs18
-rw-r--r--src/tools/opt-dist/src/training.rs2
-rw-r--r--src/tools/opt-dist/src/utils/io.rs22
8 files changed, 36 insertions, 32 deletions
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 56e667d4d12..45bea9608fc 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -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);
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 16d25b9b814..32da4ac29a4 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -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 }
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 96c9daf2c2c..a1e0a440729 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -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>,
diff --git a/src/tools/opt-dist/src/bolt.rs b/src/tools/opt-dist/src/bolt.rs
index 161ba4f3291..e44b8a4db92 100644
--- a/src/tools/opt-dist/src/bolt.rs
+++ b/src/tools/opt-dist/src/bolt.rs
@@ -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.
diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs
index 100b3ada7f2..4765dceb5dd 100644
--- a/src/tools/opt-dist/src/exec.rs
+++ b/src/tools/opt-dist/src/exec.rs
@@ -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");
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index 256317a3bcc..f6edd008845 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -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))?;
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 951bc6f9264..a9e88bdbb60 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -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}");
 
diff --git a/src/tools/opt-dist/src/utils/io.rs b/src/tools/opt-dist/src/utils/io.rs
index f333ed481b0..8bd516fa349 100644
--- a/src/tools/opt-dist/src/utils/io.rs
+++ b/src/tools/opt-dist/src/utils/io.rs
@@ -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
+        )),
     }
 }