Auto merge of #102487 - Kobzol:rustc-bolt, r= · rust-lang/rust@9928903 (original) (raw)
`@@ -12,7 +12,10 @@ use crate::environment::{Environment, EnvironmentBuilder};
`
12
12
`use crate::exec::{cmd, Bootstrap};
`
13
13
`use crate::tests::run_tests;
`
14
14
`use crate::timer::Timer;
`
15
``
`-
use crate::training::{gather_llvm_bolt_profiles, gather_llvm_profiles, gather_rustc_profiles};
`
``
15
`+
use crate::training::{
`
``
16
`+
gather_bolt_profiles, gather_llvm_profiles, gather_rustc_profiles, llvm_benchmarks,
`
``
17
`+
rustc_benchmarks,
`
``
18
`+
};
`
16
19
`use crate::utils::io::{copy_directory, move_directory, reset_directory};
`
17
20
`use crate::utils::{
`
18
21
` clear_llvm_files, format_env_variables, print_binary_sizes, print_free_disk_space,
`
`@@ -245,13 +248,13 @@ fn execute_pipeline(
`
245
248
`Ok(profile)
`
246
249
`})?;
`
247
250
``
248
``
`-
let llvm_bolt_profile = if env.use_bolt() {
`
``
251
`+
let bolt_profiles = if env.use_bolt() {
`
249
252
`// Stage 3: Build BOLT instrumented LLVM
`
250
253
`// We build a PGO optimized LLVM in this step, then instrument it with BOLT and gather BOLT profiles.
`
251
254
`// Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build.
`
252
255
`// BOLT instrumentation is performed "on-the-fly" when the LLVM library is copied to the sysroot of rustc,
`
253
256
`// therefore the LLVM artifacts on disk are not "tainted" with BOLT instrumentation and they can be reused.
`
254
``
`-
timer.section("Stage 3 (LLVM BOLT)", |stage| {
`
``
257
`+
timer.section("Stage 3 (BOLT)", |stage| {
`
255
258
` stage.section("Build PGO optimized LLVM", |stage| {
`
256
259
`Bootstrap::build(env)
`
257
260
`.with_llvm_bolt_ldflags()
`
`@@ -260,16 +263,17 @@ fn execute_pipeline(
`
260
263
`.run(stage)
`
261
264
`})?;
`
262
265
``
263
``
`` -
// Find the path to the libLLVM.so
file
``
264
``
`-
let llvm_lib = io::find_file_in_dir(
`
265
``
`-
&env.build_artifacts().join("stage2").join("lib"),
`
266
``
`-
"libLLVM",
`
267
``
`-
".so",
`
268
``
`-
)?;
`
``
266
`+
let libdir = env.build_artifacts().join("stage2").join("lib");
`
``
267
`+
let llvm_lib = io::find_file_in_dir(&libdir, "libLLVM", ".so")?;
`
269
268
``
270
``
`-
// Instrument it and gather profiles
`
271
``
`-
let profile = with_bolt_instrumented(&llvm_lib, || {
`
272
``
`-
stage.section("Gather profiles", |_| gather_llvm_bolt_profiles(env))
`
``
269
`+
log::info!("Optimizing {llvm_lib} with BOLT");
`
``
270
+
``
271
`+
// FIXME(kobzol: try gather profiles together, at once for LLVM and rustc
`
``
272
`+
// Instrument the libraries and gather profiles
`
``
273
`+
let llvm_profile = with_bolt_instrumented(&llvm_lib, |llvm_profile_dir| {
`
``
274
`+
stage.section("Gather profiles", |_| {
`
``
275
`+
gather_bolt_profiles(env, "LLVM", llvm_benchmarks(env), llvm_profile_dir)
`
``
276
`+
})
`
273
277
`})?;
`
274
278
`print_free_disk_space()?;
`
275
279
``
`@@ -278,27 +282,43 @@ fn execute_pipeline(
`
278
282
`// the final dist build. However, when BOLT optimizes an artifact, it does so in-place,
`
279
283
`// therefore it will actually optimize all the hard links, which means that the final
`
280
284
`` // packaged libLLVM.so
file will be BOLT optimized.
``
281
``
`-
bolt_optimize(&llvm_lib, &profile).context("Could not optimize LLVM with BOLT")?;
`
``
285
`+
bolt_optimize(&llvm_lib, &llvm_profile).context("Could not optimize LLVM with BOLT")?;
`
``
286
+
``
287
`+
let rustc_lib = io::find_file_in_dir(&libdir, "librustc_driver", ".so")?;
`
``
288
+
``
289
`+
log::info!("Optimizing {rustc_lib} with BOLT");
`
``
290
+
``
291
`+
// Instrument it and gather profiles
`
``
292
`+
let rustc_profile = with_bolt_instrumented(&rustc_lib, |rustc_profile_dir| {
`
``
293
`+
stage.section("Gather profiles", |_| {
`
``
294
`+
gather_bolt_profiles(env, "rustc", rustc_benchmarks(env), rustc_profile_dir)
`
``
295
`+
})
`
``
296
`+
})?;
`
``
297
`+
print_free_disk_space()?;
`
``
298
+
``
299
`+
// Now optimize the library with BOLT.
`
``
300
`+
bolt_optimize(&rustc_lib, &rustc_profile)
`
``
301
`+
.context("Could not optimize rustc with BOLT")?;
`
282
302
``
283
303
`// LLVM is not being cleared here, we want to use the BOLT-optimized LLVM
`
284
``
`-
Ok(Some(profile))
`
``
304
`+
Ok(vec![llvm_profile, rustc_profile])
`
285
305
`})?
`
286
306
`} else {
`
287
``
`-
None
`
``
307
`+
vec![]
`
288
308
`};
`
289
309
``
290
310
`let mut dist = Bootstrap::dist(env, &dist_args)
`
291
311
`.llvm_pgo_optimize(&llvm_pgo_profile)
`
292
312
`.rustc_pgo_optimize(&rustc_pgo_profile)
`
293
313
`.avoid_rustc_rebuild();
`
294
314
``
295
``
`-
if let Some(llvm_bolt_profile) = llvm_bolt_profile {
`
296
``
`-
dist = dist.with_bolt_profile(llvm_bolt_profile);
`
``
315
`+
for bolt_profile in bolt_profiles {
`
``
316
`+
dist = dist.with_bolt_profile(bolt_profile);
`
297
317
`}
`
298
318
``
299
319
`// Final stage: Assemble the dist artifacts
`
300
320
`// The previous PGO optimized rustc build and PGO optimized LLVM builds should be reused.
`
301
``
`-
timer.section("Stage 4 (final build)", |stage| dist.run(stage))?;
`
``
321
`+
timer.section("Stage 5 (final build)", |stage| dist.run(stage))?;
`
302
322
``
303
323
`// After dist has finished, run a subset of the test suite on the optimized artifacts to discover
`
304
324
`// possible regressions.
`