@@ -318,31 +318,50 @@ fn merge_codegen_units<'tcx>(
318318 let mut cgu_contents: FxHashMap < Symbol , Vec < Symbol > > =
319319 codegen_units. iter ( ) . map ( |cgu| ( cgu. name ( ) , vec ! [ cgu. name( ) ] ) ) . collect ( ) ;
320320
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+
321342 // Having multiple CGUs can drastically speed up compilation. But for
322343 // non-incremental builds, tiny CGUs slow down compilation *and* result in
323344 // worse generated code. So we don't allow CGUs smaller than this (unless
324345 // there is just one CGU, of course). Note that CGU sizes of 100,000+ are
325346 // common in larger programs, so this isn't all that large.
326347 const NON_INCR_MIN_CGU_SIZE : usize = 1800 ;
327348
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.
332352 //
333353 // The "didn't specify a CGU count" condition is because when an explicit
334354 // count is requested we observe it as closely as possible. For example,
335355 // the `compiler_builtins` crate sets `codegen-units = 10000` and it's
336356 // critical they aren't merged. Also, some tests use explicit small values
337357 // 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 )
343362 {
344363 // 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 ( ) ) ) ;
346365
347366 let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
348367 let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
@@ -353,16 +372,7 @@ fn merge_codegen_units<'tcx>(
353372 second_smallest. items_mut ( ) . extend ( smallest. items_mut ( ) . drain ( ) ) ;
354373 second_smallest. compute_size_estimate ( ) ;
355374
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.
366376 }
367377
368378 let cgu_name_builder = & mut CodegenUnitNameBuilder :: new ( cx. tcx ) ;
0 commit comments