@@ -129,14 +129,13 @@ struct PlacedRootMonoItems<'tcx> {
129129 /// The codegen units, sorted by name to make things deterministic.
130130 codegen_units : Vec < CodegenUnit < ' tcx > > ,
131131
132- roots : FxHashSet < MonoItem < ' tcx > > ,
133132 internalization_candidates : FxHashSet < MonoItem < ' tcx > > ,
134133}
135134
136135// The output CGUs are sorted by name.
137136fn partition < ' tcx , I > (
138137 tcx : TyCtxt < ' tcx > ,
139- mono_items : & mut I ,
138+ mono_items : I ,
140139 max_cgu_count : usize ,
141140 usage_map : & UsageMap < ' tcx > ,
142141) -> Vec < CodegenUnit < ' tcx > >
@@ -150,7 +149,7 @@ where
150149 // In the first step, we place all regular monomorphizations into their
151150 // respective 'home' codegen unit. Regular monomorphizations are all
152151 // 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 } = {
154153 let _prof_timer = tcx. prof . generic_activity ( "cgu_partitioning_place_roots" ) ;
155154 place_root_mono_items ( cx, mono_items)
156155 } ;
@@ -174,9 +173,9 @@ where
174173 // monomorphizations have to go into each codegen unit. These additional
175174 // monomorphizations can be drop-glue, functions from external crates, and
176175 // local functions the definition of which is marked with `#[inline]`.
177- let mono_item_placements = {
176+ {
178177 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)
180179 } ;
181180
182181 for cgu in & mut codegen_units {
@@ -189,12 +188,7 @@ where
189188 // more freedom to optimize.
190189 if !tcx. sess . link_dead_code ( ) {
191190 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) ;
198192 }
199193
200194 let instrument_dead_code =
@@ -239,12 +233,11 @@ where
239233
240234fn place_root_mono_items < ' tcx , I > (
241235 cx : & PartitioningCx < ' _ , ' tcx > ,
242- mono_items : & mut I ,
236+ mono_items : I ,
243237) -> PlacedRootMonoItems < ' tcx >
244238where
245239 I : Iterator < Item = MonoItem < ' tcx > > ,
246240{
247- let mut roots = FxHashSet :: default ( ) ;
248241 let mut codegen_units = FxHashMap :: default ( ) ;
249242 let is_incremental_build = cx. tcx . sess . opts . incremental . is_some ( ) ;
250243 let mut internalization_candidates = FxHashSet :: default ( ) ;
@@ -295,7 +288,6 @@ where
295288 }
296289
297290 codegen_unit. items_mut ( ) . insert ( mono_item, ( linkage, visibility) ) ;
298- roots. insert ( mono_item) ;
299291 }
300292
301293 // Always ensure we have at least one CGU; otherwise, if we have a
@@ -308,7 +300,7 @@ where
308300 let mut codegen_units: Vec < _ > = codegen_units. into_values ( ) . collect ( ) ;
309301 codegen_units. sort_by ( |a, b| a. name ( ) . as_str ( ) . cmp ( b. name ( ) . as_str ( ) ) ) ;
310302
311- PlacedRootMonoItems { codegen_units, roots , internalization_candidates }
303+ PlacedRootMonoItems { codegen_units, internalization_candidates }
312304}
313305
314306// This function requires the CGUs to be sorted by name on input, and ensures
@@ -404,67 +396,28 @@ fn merge_codegen_units<'tcx>(
404396 codegen_units. sort_by ( |a, b| a. name ( ) . as_str ( ) . cmp ( b. name ( ) . as_str ( ) ) ) ;
405397}
406398
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-
416399fn place_inlined_mono_items < ' tcx > (
417400 cx : & PartitioningCx < ' _ , ' tcx > ,
418401 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+ ) {
425403 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 ( ) ;
428406 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) ;
433410 }
434411
435412 // 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) ) ;
445415
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 ) ) ;
463418 }
464419 }
465420
466- return mono_item_placements;
467-
468421 fn get_reachable_inlined_items < ' tcx > (
469422 tcx : TyCtxt < ' tcx > ,
470423 item : MonoItem < ' tcx > ,
@@ -483,20 +436,40 @@ fn place_inlined_mono_items<'tcx>(
483436fn internalize_symbols < ' tcx > (
484437 cx : & PartitioningCx < ' _ , ' tcx > ,
485438 codegen_units : & mut [ CodegenUnit < ' tcx > ] ,
486- mono_item_placements : FxHashMap < MonoItem < ' tcx > , MonoItemPlacement > ,
487439 internalization_candidates : FxHashSet < MonoItem < ' tcx > > ,
488440) {
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+ }
496471 }
497472 }
498-
499- return ;
500473 }
501474
502475 // For each internalization candidates in each codegen unit, check if it is
@@ -509,21 +482,24 @@ fn internalize_symbols<'tcx>(
509482 // This item is no candidate for internalizing, so skip it.
510483 continue ;
511484 }
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+ }
527503 }
528504 }
529505
@@ -864,15 +840,10 @@ fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<
864840 cgu. size_estimate( )
865841 ) ;
866842
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) {
872844 let symbol_name = item. symbol_name ( tcx) . name ;
873845 let symbol_hash_start = symbol_name. rfind ( 'h' ) ;
874846 let symbol_hash = symbol_hash_start. map_or ( "<no hash>" , |i| & symbol_name[ i..] ) ;
875-
876847 let size = item. size_estimate ( tcx) ;
877848 let _ = with_no_trimmed_paths ! ( writeln!(
878849 s,
@@ -951,12 +922,8 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
951922 let ( codegen_units, _) = tcx. sess . time ( "partition_and_assert_distinct_symbols" , || {
952923 sync:: join (
953924 || {
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) ;
960927 codegen_units[ 0 ] . make_primary ( ) ;
961928 & * tcx. arena . alloc_from_iter ( codegen_units)
962929 } ,
0 commit comments