@@ -318,31 +318,50 @@ fn merge_codegen_units<'tcx>(
318
318
let mut cgu_contents: FxHashMap < Symbol , Vec < Symbol > > =
319
319
codegen_units. iter ( ) . map ( |cgu| ( cgu. name ( ) , vec ! [ cgu. name( ) ] ) ) . collect ( ) ;
320
320
321
+ // Repeatedly merge the two smallest codegen units as long as we have more
322
+ // CGUs than the upper limit.
323
+ while codegen_units. len ( ) > cx. tcx . sess . codegen_units ( ) . as_usize ( ) {
324
+ // Sort small cgus to the back.
325
+ codegen_units. sort_by_key ( |cgu| cmp:: Reverse ( cgu. size_estimate ( ) ) ) ;
326
+
327
+ let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
328
+ let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
329
+
330
+ // Move the items from `smallest` to `second_smallest`. Some of them
331
+ // may be duplicate inlined items, in which case the destination CGU is
332
+ // unaffected. Recalculate size estimates afterwards.
333
+ second_smallest. items_mut ( ) . extend ( smallest. items_mut ( ) . drain ( ) ) ;
334
+ second_smallest. compute_size_estimate ( ) ;
335
+
336
+ // Record that `second_smallest` now contains all the stuff that was
337
+ // in `smallest` before.
338
+ let mut consumed_cgu_names = cgu_contents. remove ( & smallest. name ( ) ) . unwrap ( ) ;
339
+ cgu_contents. get_mut ( & second_smallest. name ( ) ) . unwrap ( ) . append ( & mut consumed_cgu_names) ;
340
+ }
341
+
321
342
// Having multiple CGUs can drastically speed up compilation. But for
322
343
// non-incremental builds, tiny CGUs slow down compilation *and* result in
323
344
// worse generated code. So we don't allow CGUs smaller than this (unless
324
345
// there is just one CGU, of course). Note that CGU sizes of 100,000+ are
325
346
// common in larger programs, so this isn't all that large.
326
347
const NON_INCR_MIN_CGU_SIZE : usize = 1800 ;
327
348
328
- // Repeatedly merge the two smallest codegen units as long as:
329
- // - we have more CGUs than the upper limit, or
330
- // - (Non-incremental builds only) the user didn't specify a CGU count, and
331
- // there are multiple CGUs, and some are below the minimum size.
349
+ // Repeatedly merge the two smallest codegen units as long as: it's a
350
+ // non-incremental build, and the user didn't specify a CGU count, and
351
+ // there are multiple CGUs, and some are below the minimum size.
332
352
//
333
353
// The "didn't specify a CGU count" condition is because when an explicit
334
354
// count is requested we observe it as closely as possible. For example,
335
355
// the `compiler_builtins` crate sets `codegen-units = 10000` and it's
336
356
// critical they aren't merged. Also, some tests use explicit small values
337
357
// and likewise won't work if small CGUs are merged.
338
- while codegen_units. len ( ) > cx. tcx . sess . codegen_units ( ) . as_usize ( )
339
- || ( cx. tcx . sess . opts . incremental . is_none ( )
340
- && matches ! ( cx. tcx. sess. codegen_units( ) , CodegenUnits :: Default ( _) )
341
- && codegen_units. len ( ) > 1
342
- && codegen_units. iter ( ) . any ( |cgu| cgu. size_estimate ( ) < NON_INCR_MIN_CGU_SIZE ) )
358
+ while cx. tcx . sess . opts . incremental . is_none ( )
359
+ && matches ! ( cx. tcx. sess. codegen_units( ) , CodegenUnits :: Default ( _) )
360
+ && codegen_units. len ( ) > 1
361
+ && codegen_units. iter ( ) . any ( |cgu| cgu. size_estimate ( ) < NON_INCR_MIN_CGU_SIZE )
343
362
{
344
363
// Sort small cgus to the back.
345
- codegen_units. sort_by_key ( |cgu| cmp:: Reverse ( cgu. size_estimate ( ) ) ) ;
364
+ codegen_units. sort_by_cached_key ( |cgu| cmp:: Reverse ( cgu. size_estimate ( ) ) ) ;
346
365
347
366
let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
348
367
let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
@@ -353,16 +372,7 @@ fn merge_codegen_units<'tcx>(
353
372
second_smallest. items_mut ( ) . extend ( smallest. items_mut ( ) . drain ( ) ) ;
354
373
second_smallest. compute_size_estimate ( ) ;
355
374
356
- // Record that `second_smallest` now contains all the stuff that was
357
- // in `smallest` before.
358
- let mut consumed_cgu_names = cgu_contents. remove ( & smallest. name ( ) ) . unwrap ( ) ;
359
- cgu_contents. get_mut ( & second_smallest. name ( ) ) . unwrap ( ) . append ( & mut consumed_cgu_names) ;
360
-
361
- debug ! (
362
- "CodegenUnit {} merged into CodegenUnit {}" ,
363
- smallest. name( ) ,
364
- second_smallest. name( )
365
- ) ;
375
+ // Don't update `cgu_contents`, that's only for incremental builds.
366
376
}
367
377
368
378
let cgu_name_builder = & mut CodegenUnitNameBuilder :: new ( cx. tcx ) ;
0 commit comments