@@ -107,19 +107,11 @@ use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
107107use rustc_middle:: ty:: print:: characteristic_def_id_of_type;
108108use rustc_middle:: ty:: query:: Providers ;
109109use rustc_middle:: ty:: { self , DefIdTree , InstanceDef , TyCtxt } ;
110- use rustc_span:: symbol:: Symbol ;
110+ use rustc_span:: symbol:: { Symbol , SymbolStr } ;
111111
112112use crate :: monomorphize:: collector:: InliningMap ;
113113use crate :: monomorphize:: collector:: { self , MonoItemCollectionMode } ;
114114
115- pub enum PartitioningStrategy {
116- /// Generates one codegen unit per source-level module.
117- PerModule ,
118-
119- /// Partition the whole crate into a fixed number of codegen units.
120- FixedUnitCount ( usize ) ,
121- }
122-
123115// Anything we can't find a proper codegen unit for goes into this.
124116fn fallback_cgu_name ( name_builder : & mut CodegenUnitNameBuilder < ' _ > ) -> Symbol {
125117 name_builder. build_cgu_name ( LOCAL_CRATE , & [ "fallback" ] , Some ( "cgu" ) )
@@ -128,7 +120,7 @@ fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol {
128120pub fn partition < ' tcx , I > (
129121 tcx : TyCtxt < ' tcx > ,
130122 mono_items : I ,
131- strategy : PartitioningStrategy ,
123+ max_cgu_count : usize ,
132124 inlining_map : & InliningMap < ' tcx > ,
133125) -> Vec < CodegenUnit < ' tcx > >
134126where
@@ -148,11 +140,10 @@ where
148140
149141 debug_dump ( tcx, "INITIAL PARTITIONING:" , initial_partitioning. codegen_units . iter ( ) ) ;
150142
151- // If the partitioning should produce a fixed count of codegen units, merge
152- // until that count is reached.
153- if let PartitioningStrategy :: FixedUnitCount ( count) = strategy {
143+ // Merge until we have at most `max_cgu_count` codegen units.
144+ {
154145 let _prof_timer = tcx. prof . generic_activity ( "cgu_partitioning_merge_cgus" ) ;
155- merge_codegen_units ( tcx, & mut initial_partitioning, count ) ;
146+ merge_codegen_units ( tcx, & mut initial_partitioning, max_cgu_count ) ;
156147 debug_dump ( tcx, "POST MERGING:" , initial_partitioning. codegen_units . iter ( ) ) ;
157148 }
158149
@@ -480,27 +471,78 @@ fn merge_codegen_units<'tcx>(
480471 // the stable sort below will keep everything nice and deterministic.
481472 codegen_units. sort_by_cached_key ( |cgu| cgu. name ( ) . as_str ( ) ) ;
482473
474+ // This map keeps track of what got merged into what.
475+ let mut cgu_contents: FxHashMap < Symbol , Vec < SymbolStr > > =
476+ codegen_units. iter ( ) . map ( |cgu| ( cgu. name ( ) , vec ! [ cgu. name( ) . as_str( ) ] ) ) . collect ( ) ;
477+
483478 // Merge the two smallest codegen units until the target size is reached.
484479 while codegen_units. len ( ) > target_cgu_count {
485480 // Sort small cgus to the back
486481 codegen_units. sort_by_cached_key ( |cgu| cmp:: Reverse ( cgu. size_estimate ( ) ) ) ;
487482 let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
488483 let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
489484
485+ // Move the mono-items from `smallest` to `second_smallest`
490486 second_smallest. modify_size_estimate ( smallest. size_estimate ( ) ) ;
491487 for ( k, v) in smallest. items_mut ( ) . drain ( ) {
492488 second_smallest. items_mut ( ) . insert ( k, v) ;
493489 }
490+
491+ // Record that `second_smallest` now contains all the stuff that was in
492+ // `smallest` before.
493+ let mut consumed_cgu_names = cgu_contents. remove ( & smallest. name ( ) ) . unwrap ( ) ;
494+ cgu_contents. get_mut ( & second_smallest. name ( ) ) . unwrap ( ) . extend ( consumed_cgu_names. drain ( ..) ) ;
495+
494496 debug ! (
495- "CodegenUnit {} merged in to CodegenUnit {}" ,
497+ "CodegenUnit {} merged into CodegenUnit {}" ,
496498 smallest. name( ) ,
497499 second_smallest. name( )
498500 ) ;
499501 }
500502
501503 let cgu_name_builder = & mut CodegenUnitNameBuilder :: new ( tcx) ;
502- for ( index, cgu) in codegen_units. iter_mut ( ) . enumerate ( ) {
503- cgu. set_name ( numbered_codegen_unit_name ( cgu_name_builder, index) ) ;
504+
505+ if tcx. sess . opts . incremental . is_some ( ) {
506+ // If we are doing incremental compilation, we want CGU names to
507+ // reflect the path of the source level module they correspond to.
508+ // For CGUs that contain the code of multiple modules because of the
509+ // merging done above, we use a concatenation of the names of
510+ // all contained CGUs.
511+ let new_cgu_names: FxHashMap < Symbol , String > = cgu_contents
512+ . into_iter ( )
513+ // This `filter` makes sure we only update the name of CGUs that
514+ // were actually modified by merging.
515+ . filter ( |( _, cgu_contents) | cgu_contents. len ( ) > 1 )
516+ . map ( |( current_cgu_name, cgu_contents) | {
517+ let mut cgu_contents: Vec < & str > = cgu_contents. iter ( ) . map ( |s| & s[ ..] ) . collect ( ) ;
518+
519+ // Sort the names, so things are deterministic and easy to
520+ // predict.
521+ cgu_contents. sort ( ) ;
522+
523+ ( current_cgu_name, cgu_contents. join ( "--" ) )
524+ } )
525+ . collect ( ) ;
526+
527+ for cgu in codegen_units. iter_mut ( ) {
528+ if let Some ( new_cgu_name) = new_cgu_names. get ( & cgu. name ( ) ) {
529+ if tcx. sess . opts . debugging_opts . human_readable_cgu_names {
530+ cgu. set_name ( Symbol :: intern ( & new_cgu_name) ) ;
531+ } else {
532+ // If we don't require CGU names to be human-readable, we
533+ // use a fixed length hash of the composite CGU name
534+ // instead.
535+ let new_cgu_name = CodegenUnit :: mangle_name ( & new_cgu_name) ;
536+ cgu. set_name ( Symbol :: intern ( & new_cgu_name) ) ;
537+ }
538+ }
539+ }
540+ } else {
541+ // If we are compiling non-incrementally we just generate simple CGU
542+ // names containing an index.
543+ for ( index, cgu) in codegen_units. iter_mut ( ) . enumerate ( ) {
544+ cgu. set_name ( numbered_codegen_unit_name ( cgu_name_builder, index) ) ;
545+ }
504546 }
505547}
506548
@@ -879,13 +921,7 @@ fn collect_and_partition_mono_items(
879921 let ( codegen_units, _) = tcx. sess . time ( "partition_and_assert_distinct_symbols" , || {
880922 sync:: join (
881923 || {
882- let strategy = if tcx. sess . opts . incremental . is_some ( ) {
883- PartitioningStrategy :: PerModule
884- } else {
885- PartitioningStrategy :: FixedUnitCount ( tcx. sess . codegen_units ( ) )
886- } ;
887-
888- partition ( tcx, items. iter ( ) . cloned ( ) , strategy, & inlining_map)
924+ partition ( tcx, items. iter ( ) . cloned ( ) , tcx. sess . codegen_units ( ) , & inlining_map)
889925 . into_iter ( )
890926 . map ( Arc :: new)
891927 . collect :: < Vec < _ > > ( )
0 commit comments