@@ -309,12 +309,13 @@ fn merge_codegen_units<'tcx>(
309
309
let mut cgu_contents: FxHashMap < Symbol , Vec < Symbol > > =
310
310
codegen_units. iter ( ) . map ( |cgu| ( cgu. name ( ) , vec ! [ cgu. name( ) ] ) ) . collect ( ) ;
311
311
312
+ let cgu_name_builder = & mut CodegenUnitNameBuilder :: new ( cx. tcx ) ;
312
313
// Having multiple CGUs can drastically speed up compilation. But for
313
314
// non-incremental builds, tiny CGUs slow down compilation *and* result in
314
315
// worse generated code. So we don't allow CGUs smaller than this (unless
315
316
// there is just one CGU, of course). Note that CGU sizes of 100,000+ are
316
317
// common in larger programs, so this isn't all that large.
317
- const NON_INCR_MIN_CGU_SIZE : usize = 1000 ;
318
+ // const NON_INCR_MIN_CGU_SIZE: usize = 1000;
318
319
319
320
// Repeatedly merge the two smallest codegen units as long as:
320
321
// - we have more CGUs than the upper limit, or
@@ -326,36 +327,39 @@ fn merge_codegen_units<'tcx>(
326
327
// the `compiler_builtins` crate sets `codegen-units = 10000` and it's
327
328
// critical they aren't merged. Also, some tests use explicit small values
328
329
// and likewise won't work if small CGUs are merged.
329
- while codegen_units. len ( ) > cx. tcx . sess . codegen_units ( ) . as_usize ( )
330
+
331
+ if codegen_units. len ( ) > cx. tcx . sess . codegen_units ( ) . as_usize ( )
330
332
|| ( cx. tcx . sess . opts . incremental . is_none ( )
331
333
&& matches ! ( cx. tcx. sess. codegen_units( ) , CodegenUnits :: Default ( _) )
332
- && codegen_units. len ( ) > 1
333
- && codegen_units. iter ( ) . any ( |cgu| cgu. size_estimate ( ) < NON_INCR_MIN_CGU_SIZE ) )
334
+ && codegen_units. len ( ) > 1 )
334
335
{
335
336
// Sort small cgus to the back.
336
337
codegen_units. sort_by_cached_key ( |cgu| cmp:: Reverse ( cgu. size_estimate ( ) ) ) ;
338
+ let fallback_cgu_name = fallback_cgu_name ( cgu_name_builder) ;
339
+ let mut merged_subsets: Vec < CodegenUnit < ' _ > > =
340
+ vec ! [ CodegenUnit :: new( fallback_cgu_name) ; cx. tcx. sess. codegen_units( ) . as_usize( ) ] ;
337
341
338
- let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
339
- let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
340
-
341
- // Move the mono-items from `smallest` to `second_smallest`
342
- second_smallest. modify_size_estimate ( smallest. size_estimate ( ) ) ;
343
- second_smallest. items_mut ( ) . extend ( smallest. items_mut ( ) . drain ( ) ) ;
344
-
345
- // Record that `second_smallest` now contains all the stuff that was
346
- // in `smallest` before.
347
- let mut consumed_cgu_names = cgu_contents. remove ( & smallest. name ( ) ) . unwrap ( ) ;
348
- cgu_contents. get_mut ( & second_smallest. name ( ) ) . unwrap ( ) . append ( & mut consumed_cgu_names) ;
349
-
350
- debug ! (
351
- "CodegenUnit {} merged into CodegenUnit {}" ,
352
- smallest. name( ) ,
353
- second_smallest. name( )
354
- ) ;
342
+ for cgu in codegen_units. iter_mut ( ) {
343
+ let min = merged_subsets
344
+ . iter ( )
345
+ . enumerate ( )
346
+ . min_by_key ( |( _, cgu) | cgu. size_estimate ( ) )
347
+ . map ( |( i, _) | i)
348
+ . unwrap_or ( 0 ) ;
349
+ let min_cgu = & mut merged_subsets[ min] ;
350
+ if min_cgu. name ( ) == fallback_cgu_name {
351
+ * min_cgu = std:: mem:: replace ( cgu, CodegenUnit :: new ( fallback_cgu_name) ) ;
352
+ } else {
353
+ min_cgu. modify_size_estimate ( cgu. size_estimate ( ) ) ;
354
+ min_cgu. items_mut ( ) . extend ( cgu. items_mut ( ) . drain ( ) ) ;
355
+ let mut consumed_cgu_names = cgu_contents. remove ( & cgu. name ( ) ) . unwrap ( ) ;
356
+ cgu_contents. get_mut ( & min_cgu. name ( ) ) . unwrap ( ) . append ( & mut consumed_cgu_names) ;
357
+ debug ! ( "CodegenUnit {} merged into CodegenUnit {}" , cgu. name( ) , min_cgu. name( ) ) ;
358
+ }
359
+ }
360
+ * codegen_units = merged_subsets;
355
361
}
356
362
357
- let cgu_name_builder = & mut CodegenUnitNameBuilder :: new ( cx. tcx ) ;
358
-
359
363
if cx. tcx . sess . opts . incremental . is_some ( ) {
360
364
// If we are doing incremental compilation, we want CGU names to
361
365
// reflect the path of the source level module they correspond to.
0 commit comments