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.

`