@@ -98,6 +98,10 @@ enum EnvironmentCmd {
9898 /// Perform tests after final build if it's not a fast try build
9999 #[ arg( long) ]
100100 run_tests : bool ,
101+
102+ /// Will be LLVM built during the run?
103+ #[ arg( long, default_value_t = true , action( clap:: ArgAction :: Set ) ) ]
104+ build_llvm : bool ,
101105 } ,
102106 /// Perform an optimized build on Linux CI, from inside Docker.
103107 LinuxCi {
@@ -133,6 +137,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
133137 benchmark_cargo_config,
134138 shared,
135139 run_tests,
140+ build_llvm,
136141 } => {
137142 let env = EnvironmentBuilder :: default ( )
138143 . host_tuple ( target_triple)
@@ -148,6 +153,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
148153 . benchmark_cargo_config ( benchmark_cargo_config)
149154 . run_tests ( run_tests)
150155 . fast_try_build ( is_fast_try_build)
156+ . build_llvm ( build_llvm)
151157 . build ( ) ?;
152158
153159 ( env, shared. build_args )
@@ -172,6 +178,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
172178 . skipped_tests ( vec ! [ ] )
173179 . run_tests ( true )
174180 . fast_try_build ( is_fast_try_build)
181+ . build_llvm ( true )
175182 . build ( ) ?;
176183
177184 ( env, shared. build_args )
@@ -193,6 +200,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
193200 . skipped_tests ( vec ! [ ] )
194201 . run_tests ( true )
195202 . fast_try_build ( is_fast_try_build)
203+ . build_llvm ( true )
196204 . build ( ) ?;
197205
198206 ( env, shared. build_args )
@@ -255,68 +263,79 @@ fn execute_pipeline(
255263 // Stage 2: Gather LLVM PGO profiles
256264 // Here we build a PGO instrumented LLVM, reusing the previously PGO optimized rustc.
257265 // Then we use the instrumented LLVM to gather LLVM PGO profiles.
258- let llvm_pgo_profile = timer. section ( "Stage 2 (LLVM PGO)" , |stage| {
259- // Remove the previous, uninstrumented build of LLVM.
260- clear_llvm_files ( env) ?;
266+ let llvm_pgo_profile = if env. build_llvm ( ) {
267+ timer. section ( "Stage 2 (LLVM PGO)" , |stage| {
268+ // Remove the previous, uninstrumented build of LLVM.
269+ clear_llvm_files ( env) ?;
261270
262- let llvm_profile_dir_root = env. artifact_dir ( ) . join ( "llvm-pgo" ) ;
271+ let llvm_profile_dir_root = env. artifact_dir ( ) . join ( "llvm-pgo" ) ;
263272
264- stage. section ( "Build PGO instrumented LLVM" , |section| {
265- Bootstrap :: build ( env)
266- . llvm_pgo_instrument ( & llvm_profile_dir_root)
267- . avoid_rustc_rebuild ( )
268- . run ( section)
269- } ) ?;
273+ stage. section ( "Build PGO instrumented LLVM" , |section| {
274+ Bootstrap :: build ( env)
275+ . llvm_pgo_instrument ( & llvm_profile_dir_root)
276+ . avoid_rustc_rebuild ( )
277+ . run ( section)
278+ } ) ?;
270279
271- let profile = stage
272- . section ( "Gather profiles" , |_| gather_llvm_profiles ( env, & llvm_profile_dir_root) ) ?;
280+ let profile = stage. section ( "Gather profiles" , |_| {
281+ gather_llvm_profiles ( env, & llvm_profile_dir_root)
282+ } ) ?;
273283
274- print_free_disk_space ( ) ?;
284+ print_free_disk_space ( ) ?;
275285
276- // Proactively delete the instrumented artifacts, to avoid using them by accident in
277- // follow-up stages.
278- clear_llvm_files ( env) ?;
286+ // Proactively delete the instrumented artifacts, to avoid using them by accident in
287+ // follow-up stages.
288+ clear_llvm_files ( env) ?;
279289
280- Ok ( profile)
281- } ) ?;
290+ Ok ( Some ( profile) )
291+ } ) ?
292+ } else {
293+ None
294+ } ;
282295
283296 let bolt_profiles = if env. use_bolt ( ) {
284297 // Stage 3: Build BOLT instrumented LLVM
285298 // We build a PGO optimized LLVM in this step, then instrument it with BOLT and gather BOLT profiles.
286299 // Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build.
287300 // BOLT instrumentation is performed "on-the-fly" when the LLVM library is copied to the sysroot of rustc,
288301 // therefore the LLVM artifacts on disk are not "tainted" with BOLT instrumentation and they can be reused.
302+ let libdir = env. build_artifacts ( ) . join ( "stage2" ) . join ( "lib" ) ;
289303 timer. section ( "Stage 3 (BOLT)" , |stage| {
290- stage. section ( "Build PGO optimized LLVM" , |stage| {
291- Bootstrap :: build ( env)
292- . with_llvm_bolt_ldflags ( )
293- . llvm_pgo_optimize ( & llvm_pgo_profile)
294- . avoid_rustc_rebuild ( )
295- . run ( stage)
296- } ) ?;
297-
298- let libdir = env. build_artifacts ( ) . join ( "stage2" ) . join ( "lib" ) ;
299- // The actual name will be something like libLLVM.so.18.1-rust-dev.
300- let llvm_lib = io:: find_file_in_dir ( & libdir, "libLLVM.so" , "" ) ?;
301-
302- log:: info!( "Optimizing {llvm_lib} with BOLT" ) ;
303-
304- // FIXME(kobzol): try gather profiles together, at once for LLVM and rustc
305- // Instrument the libraries and gather profiles
306- let llvm_profile = with_bolt_instrumented ( & llvm_lib, |llvm_profile_dir| {
307- stage. section ( "Gather profiles" , |_| {
308- gather_bolt_profiles ( env, "LLVM" , llvm_benchmarks ( env) , llvm_profile_dir)
309- } )
310- } ) ?;
311- print_free_disk_space ( ) ?;
312-
313- // Now optimize the library with BOLT. The `libLLVM-XXX.so` library is actually hard-linked
314- // from several places, and this specific path (`llvm_lib`) will *not* be packaged into
315- // the final dist build. However, when BOLT optimizes an artifact, it does so *in-place*,
316- // therefore it will actually optimize all the hard links, which means that the final
317- // packaged `libLLVM.so` file *will* be BOLT optimized.
318- bolt_optimize ( & llvm_lib, & llvm_profile, env)
319- . context ( "Could not optimize LLVM with BOLT" ) ?;
304+ let llvm_profile = if env. build_llvm ( ) {
305+ stage. section ( "Build PGO optimized LLVM" , |stage| {
306+ Bootstrap :: build ( env)
307+ . with_llvm_bolt_ldflags ( )
308+ . llvm_pgo_optimize ( llvm_pgo_profile. as_ref ( ) )
309+ . avoid_rustc_rebuild ( )
310+ . run ( stage)
311+ } ) ?;
312+
313+ // The actual name will be something like libLLVM.so.18.1-rust-dev.
314+ let llvm_lib = io:: find_file_in_dir ( & libdir, "libLLVM.so" , "" ) ?;
315+
316+ log:: info!( "Optimizing {llvm_lib} with BOLT" ) ;
317+
318+ // FIXME(kobzol): try gather profiles together, at once for LLVM and rustc
319+ // Instrument the libraries and gather profiles
320+ let llvm_profile = with_bolt_instrumented ( & llvm_lib, |llvm_profile_dir| {
321+ stage. section ( "Gather profiles" , |_| {
322+ gather_bolt_profiles ( env, "LLVM" , llvm_benchmarks ( env) , llvm_profile_dir)
323+ } )
324+ } ) ?;
325+ print_free_disk_space ( ) ?;
326+
327+ // Now optimize the library with BOLT. The `libLLVM-XXX.so` library is actually hard-linked
328+ // from several places, and this specific path (`llvm_lib`) will *not* be packaged into
329+ // the final dist build. However, when BOLT optimizes an artifact, it does so *in-place*,
330+ // therefore it will actually optimize all the hard links, which means that the final
331+ // packaged `libLLVM.so` file *will* be BOLT optimized.
332+ bolt_optimize ( & llvm_lib, & llvm_profile, env)
333+ . context ( "Could not optimize LLVM with BOLT" ) ?;
334+
335+ Some ( llvm_profile)
336+ } else {
337+ None
338+ } ;
320339
321340 let rustc_lib = io:: find_file_in_dir ( & libdir, "librustc_driver" , ".so" ) ?;
322341
@@ -334,15 +353,16 @@ fn execute_pipeline(
334353 bolt_optimize ( & rustc_lib, & rustc_profile, env)
335354 . context ( "Could not optimize rustc with BOLT" ) ?;
336355
337- // LLVM is not being cleared here, we want to use the BOLT-optimized LLVM
338- Ok ( vec ! [ llvm_profile, rustc_profile] )
356+ // LLVM is not being cleared here. Either we built it and we want to use the BOLT-optimized LLVM, or we
357+ // didn't build it, so we don't want to remove it.
358+ Ok ( vec ! [ llvm_profile, Some ( rustc_profile) ] )
339359 } ) ?
340360 } else {
341361 vec ! [ ]
342362 } ;
343363
344364 let mut dist = Bootstrap :: dist ( env, & dist_args)
345- . llvm_pgo_optimize ( & llvm_pgo_profile)
365+ . llvm_pgo_optimize ( llvm_pgo_profile. as_ref ( ) )
346366 . rustc_pgo_optimize ( & rustc_pgo_profile)
347367 . avoid_rustc_rebuild ( ) ;
348368
0 commit comments