@@ -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