@@ -129,14 +129,13 @@ struct PlacedRootMonoItems<'tcx> {
129
129
/// The codegen units, sorted by name to make things deterministic.
130
130
codegen_units : Vec < CodegenUnit < ' tcx > > ,
131
131
132
- roots : FxHashSet < MonoItem < ' tcx > > ,
133
132
internalization_candidates : FxHashSet < MonoItem < ' tcx > > ,
134
133
}
135
134
136
135
// The output CGUs are sorted by name.
137
136
fn partition < ' tcx , I > (
138
137
tcx : TyCtxt < ' tcx > ,
139
- mono_items : & mut I ,
138
+ mono_items : I ,
140
139
max_cgu_count : usize ,
141
140
usage_map : & UsageMap < ' tcx > ,
142
141
) -> Vec < CodegenUnit < ' tcx > >
@@ -150,7 +149,7 @@ where
150
149
// In the first step, we place all regular monomorphizations into their
151
150
// respective 'home' codegen unit. Regular monomorphizations are all
152
151
// functions and statics defined in the local crate.
153
- let PlacedRootMonoItems { mut codegen_units, roots , internalization_candidates } = {
152
+ let PlacedRootMonoItems { mut codegen_units, internalization_candidates } = {
154
153
let _prof_timer = tcx. prof . generic_activity ( "cgu_partitioning_place_roots" ) ;
155
154
place_root_mono_items ( cx, mono_items)
156
155
} ;
@@ -174,9 +173,9 @@ where
174
173
// monomorphizations have to go into each codegen unit. These additional
175
174
// monomorphizations can be drop-glue, functions from external crates, and
176
175
// local functions the definition of which is marked with `#[inline]`.
177
- let mono_item_placements = {
176
+ {
178
177
let _prof_timer = tcx. prof . generic_activity ( "cgu_partitioning_place_inline_items" ) ;
179
- place_inlined_mono_items ( cx, & mut codegen_units, roots )
178
+ place_inlined_mono_items ( cx, & mut codegen_units)
180
179
} ;
181
180
182
181
for cgu in & mut codegen_units {
@@ -189,12 +188,7 @@ where
189
188
// more freedom to optimize.
190
189
if !tcx. sess . link_dead_code ( ) {
191
190
let _prof_timer = tcx. prof . generic_activity ( "cgu_partitioning_internalize_symbols" ) ;
192
- internalize_symbols (
193
- cx,
194
- & mut codegen_units,
195
- mono_item_placements,
196
- internalization_candidates,
197
- ) ;
191
+ internalize_symbols ( cx, & mut codegen_units, internalization_candidates) ;
198
192
}
199
193
200
194
let instrument_dead_code =
@@ -239,12 +233,11 @@ where
239
233
240
234
fn place_root_mono_items < ' tcx , I > (
241
235
cx : & PartitioningCx < ' _ , ' tcx > ,
242
- mono_items : & mut I ,
236
+ mono_items : I ,
243
237
) -> PlacedRootMonoItems < ' tcx >
244
238
where
245
239
I : Iterator < Item = MonoItem < ' tcx > > ,
246
240
{
247
- let mut roots = FxHashSet :: default ( ) ;
248
241
let mut codegen_units = FxHashMap :: default ( ) ;
249
242
let is_incremental_build = cx. tcx . sess . opts . incremental . is_some ( ) ;
250
243
let mut internalization_candidates = FxHashSet :: default ( ) ;
@@ -295,7 +288,6 @@ where
295
288
}
296
289
297
290
codegen_unit. items_mut ( ) . insert ( mono_item, ( linkage, visibility) ) ;
298
- roots. insert ( mono_item) ;
299
291
}
300
292
301
293
// Always ensure we have at least one CGU; otherwise, if we have a
@@ -308,7 +300,7 @@ where
308
300
let mut codegen_units: Vec < _ > = codegen_units. into_values ( ) . collect ( ) ;
309
301
codegen_units. sort_by ( |a, b| a. name ( ) . as_str ( ) . cmp ( b. name ( ) . as_str ( ) ) ) ;
310
302
311
- PlacedRootMonoItems { codegen_units, roots , internalization_candidates }
303
+ PlacedRootMonoItems { codegen_units, internalization_candidates }
312
304
}
313
305
314
306
// This function requires the CGUs to be sorted by name on input, and ensures
@@ -404,67 +396,28 @@ fn merge_codegen_units<'tcx>(
404
396
codegen_units. sort_by ( |a, b| a. name ( ) . as_str ( ) . cmp ( b. name ( ) . as_str ( ) ) ) ;
405
397
}
406
398
407
- /// For symbol internalization, we need to know whether a symbol/mono-item is
408
- /// used from outside the codegen unit it is defined in. This type is used
409
- /// to keep track of that.
410
- #[ derive( Clone , PartialEq , Eq , Debug ) ]
411
- enum MonoItemPlacement {
412
- SingleCgu { cgu_name : Symbol } ,
413
- MultipleCgus ,
414
- }
415
-
416
399
fn place_inlined_mono_items < ' tcx > (
417
400
cx : & PartitioningCx < ' _ , ' tcx > ,
418
401
codegen_units : & mut [ CodegenUnit < ' tcx > ] ,
419
- roots : FxHashSet < MonoItem < ' tcx > > ,
420
- ) -> FxHashMap < MonoItem < ' tcx > , MonoItemPlacement > {
421
- let mut mono_item_placements = FxHashMap :: default ( ) ;
422
-
423
- let single_codegen_unit = codegen_units. len ( ) == 1 ;
424
-
402
+ ) {
425
403
for cgu in codegen_units. iter_mut ( ) {
426
- // Collect all items that need to be available in this codegen unit.
427
- let mut reachable = FxHashSet :: default ( ) ;
404
+ // Collect all inlined items that need to be available in this codegen unit.
405
+ let mut reachable_inlined_items = FxHashSet :: default ( ) ;
428
406
for root in cgu. items ( ) . keys ( ) {
429
- // Insert the root item itself, plus all inlined items that are
430
- // reachable from it without going via another root item.
431
- reachable. insert ( * root) ;
432
- get_reachable_inlined_items ( cx. tcx , * root, cx. usage_map , & mut reachable) ;
407
+ // Get all inlined items that are reachable from it without going
408
+ // via another root item.
409
+ get_reachable_inlined_items ( cx. tcx , * root, cx. usage_map , & mut reachable_inlined_items) ;
433
410
}
434
411
435
412
// Add all monomorphizations that are not already there.
436
- for mono_item in reachable {
437
- if !cgu. items ( ) . contains_key ( & mono_item) {
438
- if roots. contains ( & mono_item) {
439
- bug ! ( "GloballyShared mono-item inlined into other CGU: {:?}" , mono_item) ;
440
- }
441
-
442
- // This is a CGU-private copy.
443
- cgu. items_mut ( ) . insert ( mono_item, ( Linkage :: Internal , Visibility :: Default ) ) ;
444
- }
413
+ for inlined_item in reachable_inlined_items {
414
+ assert ! ( !cgu. items( ) . contains_key( & inlined_item) ) ;
445
415
446
- if !single_codegen_unit {
447
- // If there is more than one codegen unit, we need to keep track
448
- // in which codegen units each monomorphization is placed.
449
- match mono_item_placements. entry ( mono_item) {
450
- Entry :: Occupied ( e) => {
451
- let placement = e. into_mut ( ) ;
452
- debug_assert ! ( match * placement {
453
- MonoItemPlacement :: SingleCgu { cgu_name } => cgu_name != cgu. name( ) ,
454
- MonoItemPlacement :: MultipleCgus => true ,
455
- } ) ;
456
- * placement = MonoItemPlacement :: MultipleCgus ;
457
- }
458
- Entry :: Vacant ( e) => {
459
- e. insert ( MonoItemPlacement :: SingleCgu { cgu_name : cgu. name ( ) } ) ;
460
- }
461
- }
462
- }
416
+ // This is a CGU-private copy.
417
+ cgu. items_mut ( ) . insert ( inlined_item, ( Linkage :: Internal , Visibility :: Default ) ) ;
463
418
}
464
419
}
465
420
466
- return mono_item_placements;
467
-
468
421
fn get_reachable_inlined_items < ' tcx > (
469
422
tcx : TyCtxt < ' tcx > ,
470
423
item : MonoItem < ' tcx > ,
@@ -483,20 +436,40 @@ fn place_inlined_mono_items<'tcx>(
483
436
fn internalize_symbols < ' tcx > (
484
437
cx : & PartitioningCx < ' _ , ' tcx > ,
485
438
codegen_units : & mut [ CodegenUnit < ' tcx > ] ,
486
- mono_item_placements : FxHashMap < MonoItem < ' tcx > , MonoItemPlacement > ,
487
439
internalization_candidates : FxHashSet < MonoItem < ' tcx > > ,
488
440
) {
489
- if codegen_units. len ( ) == 1 {
490
- // Fast path for when there is only one codegen unit. In this case we
491
- // can internalize all candidates, since there is nowhere else they
492
- // could be used from.
493
- for cgu in codegen_units {
494
- for candidate in & internalization_candidates {
495
- cgu. items_mut ( ) . insert ( * candidate, ( Linkage :: Internal , Visibility :: Default ) ) ;
441
+ /// For symbol internalization, we need to know whether a symbol/mono-item
442
+ /// is used from outside the codegen unit it is defined in. This type is
443
+ /// used to keep track of that.
444
+ #[ derive( Clone , PartialEq , Eq , Debug ) ]
445
+ enum MonoItemPlacement {
446
+ SingleCgu { cgu_name : Symbol } ,
447
+ MultipleCgus ,
448
+ }
449
+
450
+ let mut mono_item_placements = FxHashMap :: default ( ) ;
451
+ let single_codegen_unit = codegen_units. len ( ) == 1 ;
452
+
453
+ if !single_codegen_unit {
454
+ for cgu in codegen_units. iter_mut ( ) {
455
+ for item in cgu. items ( ) . keys ( ) {
456
+ // If there is more than one codegen unit, we need to keep track
457
+ // in which codegen units each monomorphization is placed.
458
+ match mono_item_placements. entry ( * item) {
459
+ Entry :: Occupied ( e) => {
460
+ let placement = e. into_mut ( ) ;
461
+ debug_assert ! ( match * placement {
462
+ MonoItemPlacement :: SingleCgu { cgu_name } => cgu_name != cgu. name( ) ,
463
+ MonoItemPlacement :: MultipleCgus => true ,
464
+ } ) ;
465
+ * placement = MonoItemPlacement :: MultipleCgus ;
466
+ }
467
+ Entry :: Vacant ( e) => {
468
+ e. insert ( MonoItemPlacement :: SingleCgu { cgu_name : cgu. name ( ) } ) ;
469
+ }
470
+ }
496
471
}
497
472
}
498
-
499
- return ;
500
473
}
501
474
502
475
// For each internalization candidates in each codegen unit, check if it is
@@ -509,21 +482,24 @@ fn internalize_symbols<'tcx>(
509
482
// This item is no candidate for internalizing, so skip it.
510
483
continue ;
511
484
}
512
- debug_assert_eq ! ( mono_item_placements[ item] , home_cgu) ;
513
-
514
- if let Some ( user_items) = cx. usage_map . get_user_items ( * item) {
515
- if user_items
516
- . iter ( )
517
- . filter_map ( |user_item| {
518
- // Some user mono items might not have been
519
- // instantiated. We can safely ignore those.
520
- mono_item_placements. get ( user_item)
521
- } )
522
- . any ( |placement| * placement != home_cgu)
523
- {
524
- // Found a user from another CGU, so skip to the next item
525
- // without marking this one as internal.
526
- continue ;
485
+
486
+ if !single_codegen_unit {
487
+ debug_assert_eq ! ( mono_item_placements[ item] , home_cgu) ;
488
+
489
+ if let Some ( user_items) = cx. usage_map . get_user_items ( * item) {
490
+ if user_items
491
+ . iter ( )
492
+ . filter_map ( |user_item| {
493
+ // Some user mono items might not have been
494
+ // instantiated. We can safely ignore those.
495
+ mono_item_placements. get ( user_item)
496
+ } )
497
+ . any ( |placement| * placement != home_cgu)
498
+ {
499
+ // Found a user from another CGU, so skip to the next item
500
+ // without marking this one as internal.
501
+ continue ;
502
+ }
527
503
}
528
504
}
529
505
@@ -864,15 +840,10 @@ fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<
864
840
cgu. size_estimate( )
865
841
) ;
866
842
867
- // The order of `cgu.items()` is non-deterministic; sort it by name
868
- // to give deterministic output.
869
- let mut items: Vec < _ > = cgu. items ( ) . iter ( ) . collect ( ) ;
870
- items. sort_by_key ( |( item, _) | item. symbol_name ( tcx) . name ) ;
871
- for ( item, linkage) in items {
843
+ for ( item, linkage) in cgu. items_in_deterministic_order ( tcx) {
872
844
let symbol_name = item. symbol_name ( tcx) . name ;
873
845
let symbol_hash_start = symbol_name. rfind ( 'h' ) ;
874
846
let symbol_hash = symbol_hash_start. map_or ( "<no hash>" , |i| & symbol_name[ i..] ) ;
875
-
876
847
let size = item. size_estimate ( tcx) ;
877
848
let _ = with_no_trimmed_paths ! ( writeln!(
878
849
s,
@@ -951,12 +922,8 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
951
922
let ( codegen_units, _) = tcx. sess . time ( "partition_and_assert_distinct_symbols" , || {
952
923
sync:: join (
953
924
|| {
954
- let mut codegen_units = partition (
955
- tcx,
956
- & mut items. iter ( ) . copied ( ) ,
957
- tcx. sess . codegen_units ( ) ,
958
- & usage_map,
959
- ) ;
925
+ let mut codegen_units =
926
+ partition ( tcx, items. iter ( ) . copied ( ) , tcx. sess . codegen_units ( ) , & usage_map) ;
960
927
codegen_units[ 0 ] . make_primary ( ) ;
961
928
& * tcx. arena . alloc_from_iter ( codegen_units)
962
929
} ,
0 commit comments