@@ -107,19 +107,11 @@ use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
107
107
use rustc_middle:: ty:: print:: characteristic_def_id_of_type;
108
108
use rustc_middle:: ty:: query:: Providers ;
109
109
use rustc_middle:: ty:: { self , DefIdTree , InstanceDef , TyCtxt } ;
110
- use rustc_span:: symbol:: Symbol ;
110
+ use rustc_span:: symbol:: { Symbol , SymbolStr } ;
111
111
112
112
use crate :: monomorphize:: collector:: InliningMap ;
113
113
use crate :: monomorphize:: collector:: { self , MonoItemCollectionMode } ;
114
114
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
-
123
115
// Anything we can't find a proper codegen unit for goes into this.
124
116
fn fallback_cgu_name ( name_builder : & mut CodegenUnitNameBuilder < ' _ > ) -> Symbol {
125
117
name_builder. build_cgu_name ( LOCAL_CRATE , & [ "fallback" ] , Some ( "cgu" ) )
@@ -128,7 +120,7 @@ fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol {
128
120
pub fn partition < ' tcx , I > (
129
121
tcx : TyCtxt < ' tcx > ,
130
122
mono_items : I ,
131
- strategy : PartitioningStrategy ,
123
+ max_cgu_count : usize ,
132
124
inlining_map : & InliningMap < ' tcx > ,
133
125
) -> Vec < CodegenUnit < ' tcx > >
134
126
where
@@ -148,11 +140,10 @@ where
148
140
149
141
debug_dump ( tcx, "INITIAL PARTITIONING:" , initial_partitioning. codegen_units . iter ( ) ) ;
150
142
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
+ {
154
145
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 ) ;
156
147
debug_dump ( tcx, "POST MERGING:" , initial_partitioning. codegen_units . iter ( ) ) ;
157
148
}
158
149
@@ -480,27 +471,78 @@ fn merge_codegen_units<'tcx>(
480
471
// the stable sort below will keep everything nice and deterministic.
481
472
codegen_units. sort_by_cached_key ( |cgu| cgu. name ( ) . as_str ( ) ) ;
482
473
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
+
483
478
// Merge the two smallest codegen units until the target size is reached.
484
479
while codegen_units. len ( ) > target_cgu_count {
485
480
// Sort small cgus to the back
486
481
codegen_units. sort_by_cached_key ( |cgu| cmp:: Reverse ( cgu. size_estimate ( ) ) ) ;
487
482
let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
488
483
let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
489
484
485
+ // Move the mono-items from `smallest` to `second_smallest`
490
486
second_smallest. modify_size_estimate ( smallest. size_estimate ( ) ) ;
491
487
for ( k, v) in smallest. items_mut ( ) . drain ( ) {
492
488
second_smallest. items_mut ( ) . insert ( k, v) ;
493
489
}
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
+
494
496
debug ! (
495
- "CodegenUnit {} merged in to CodegenUnit {}" ,
497
+ "CodegenUnit {} merged into CodegenUnit {}" ,
496
498
smallest. name( ) ,
497
499
second_smallest. name( )
498
500
) ;
499
501
}
500
502
501
503
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
+ }
504
546
}
505
547
}
506
548
@@ -879,13 +921,7 @@ fn collect_and_partition_mono_items(
879
921
let ( codegen_units, _) = tcx. sess . time ( "partition_and_assert_distinct_symbols" , || {
880
922
sync:: join (
881
923
|| {
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)
889
925
. into_iter ( )
890
926
. map ( Arc :: new)
891
927
. collect :: < Vec < _ > > ( )
0 commit comments