From c32ca06ac7f4127d50deb43b4a34cc5a3cdb822d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 19 Jul 2026 10:16:52 +0200 Subject: [PATCH 1/2] Gather PGO profiles in parallel --- src/tools/opt-dist/src/training.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index a0bbd39382c87..67c799497835b 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -38,6 +38,8 @@ fn init_compiler_benchmarks( scenarios.join(",").as_str(), "--exact-match", crates.join(",").as_str(), + "--jobs", + "4", ]) .env("RUSTC", env.rustc_stage_0().as_str()) .env("RUSTC_BOOTSTRAP", "1") From c373810c916810ccd271dd591e4a26fff67b8ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 18 Jul 2026 17:08:38 +0200 Subject: [PATCH 2/2] Parallelize BOLT optimization --- src/tools/opt-dist/src/main.rs | 50 ++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index 9ea1604b9f09c..22c9605cf205c 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -327,7 +327,7 @@ fn execute_pipeline( // therefore the LLVM artifacts on disk are not "tainted" with BOLT instrumentation and they can be reused. let libdir = env.build_artifacts().join("stage2").join("lib"); timer.section("Stage 3 (BOLT)", |stage| { - let llvm_profile = if env.build_llvm() { + let llvm_data = if env.build_llvm() { stage.section("Build PGO optimized LLVM", |stage| { Bootstrap::build(env) .with_llvm_bolt_ldflags() @@ -356,17 +356,7 @@ fn execute_pipeline( }) })?; print_free_disk_space()?; - - // Now optimize the library with BOLT. The `libLLVM-XXX.so` library is actually hard-linked - // from several places, and this specific path (`llvm_lib`) will *not* be packaged into - // 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. - stage.section("Optimize", |_| { - bolt_optimize(&llvm_lib, &llvm_profile, env) - .context("Could not optimize LLVM with BOLT") - })?; - Some(llvm_profile) + Some((llvm_lib, llvm_profile)) } else { None }; @@ -385,14 +375,40 @@ fn execute_pipeline( })?; print_free_disk_space()?; - // Now optimize the library with BOLT. - stage.section("Optimize", |_| { - bolt_optimize(&rustc_lib, &rustc_profile, env) - .context("Could not optimize rustc with BOLT") + stage.section("Optimize LLVM and rustc with BOLT", |_| { + std::thread::scope(|scope| { + let mut handles = vec![]; + // Now optimize the libLLVM library with BOLT. The `libLLVM-XXX.so` library is actually hard-linked + // from several places, and this specific path (`llvm_lib`) will *not* be packaged into + // 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. + if let Some((llvm_lib, llvm_profile)) = &llvm_data { + handles.push(scope.spawn(move || { + bolt_optimize(&llvm_lib, &llvm_profile, env) + .context("Could not optimize LLVM with BOLT")?; + anyhow::Ok(()) + })); + } + + handles.push(scope.spawn(|| { + // Now optimize the librustc_driver library with BOLT. + bolt_optimize(&rustc_lib, &rustc_profile, env) + .context("Could not optimize rustc with BOLT")?; + Ok(()) + })); + + for handle in handles { + handle.join().unwrap()?; + } + + anyhow::Ok(()) + })?; + Ok(()) })?; // LLVM is not being cleared here. Either we built it and we want to use the BOLT-optimized LLVM, or we // didn't build it, so we don't want to remove it. - Ok(vec![llvm_profile, Some(rustc_profile)]) + Ok(vec![llvm_data.map(|(_, profile)| profile), Some(rustc_profile)]) })? } else { vec![]