Skip to content

Commit edd1f38

Browse files
committed
Store item size estimate in MonoItemData.
This means we call `MonoItem::size_estimate` (which involves a query) less often: just once per mono item, and then once more per inline item placement. After that we can reuse the stored value as necessary. This means `CodegenUnit::compute_size_estimate` is cheaper.
1 parent b52f9eb commit edd1f38

File tree

2 files changed

+22
-18
lines changed

2 files changed

+22
-18
lines changed

compiler/rustc_middle/src/mir/mono.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ pub struct CodegenUnit<'tcx> {
243243
pub struct MonoItemData {
244244
pub linkage: Linkage,
245245
pub visibility: Visibility,
246+
pub size_estimate: usize,
246247
}
247248

248249
/// Specifies the linkage type for a `MonoItem`.
@@ -327,16 +328,16 @@ impl<'tcx> CodegenUnit<'tcx> {
327328
base_n::encode(hash, base_n::CASE_INSENSITIVE)
328329
}
329330

330-
pub fn compute_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
331-
// Estimate the size of a codegen unit as (approximately) the number of MIR
332-
// statements it corresponds to.
333-
self.size_estimate = self.items.keys().map(|mi| mi.size_estimate(tcx)).sum();
331+
pub fn compute_size_estimate(&mut self) {
332+
// The size of a codegen unit as the sum of the sizes of the items
333+
// within it.
334+
self.size_estimate = self.items.values().map(|data| data.size_estimate).sum();
334335
}
335336

336-
#[inline]
337337
/// Should only be called if [`compute_size_estimate`] has previously been called.
338338
///
339339
/// [`compute_size_estimate`]: Self::compute_size_estimate
340+
#[inline]
340341
pub fn size_estimate(&self) -> usize {
341342
// Items are never zero-sized, so if we have items the estimate must be
342343
// non-zero, unless we forgot to call `compute_size_estimate` first.

compiler/rustc_monomorphize/src/partitioning.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,12 @@ where
222222
for mono_item in mono_items {
223223
// Handle only root items directly here. Inlined items are handled at
224224
// the bottom of the loop based on reachability.
225+
let size_estimate = mono_item.size_estimate(cx.tcx);
225226
match mono_item.instantiation_mode(cx.tcx) {
226227
InstantiationMode::GloballyShared { .. } => {}
227228
InstantiationMode::LocalCopy => {
228229
num_unique_inlined_items += 1;
229-
unique_inlined_items_size += mono_item.size_estimate(cx.tcx);
230+
unique_inlined_items_size += size_estimate;
230231
continue;
231232
}
232233
}
@@ -258,7 +259,7 @@ where
258259
internalization_candidates.insert(mono_item);
259260
}
260261

261-
cgu.items_mut().insert(mono_item, MonoItemData { linkage, visibility });
262+
cgu.items_mut().insert(mono_item, MonoItemData { linkage, visibility, size_estimate });
262263

263264
// Get all inlined items that are reachable from `mono_item` without
264265
// going via another root item. This includes drop-glue, functions from
@@ -272,9 +273,11 @@ where
272273
// the `insert` will be a no-op.
273274
for inlined_item in reachable_inlined_items {
274275
// This is a CGU-private copy.
275-
let linkage = Linkage::Internal;
276-
let visibility = Visibility::Default;
277-
cgu.items_mut().insert(inlined_item, MonoItemData { linkage, visibility });
276+
cgu.items_mut().entry(inlined_item).or_insert_with(|| MonoItemData {
277+
linkage: Linkage::Internal,
278+
visibility: Visibility::Default,
279+
size_estimate: inlined_item.size_estimate(cx.tcx),
280+
});
278281
}
279282
}
280283

@@ -289,7 +292,7 @@ where
289292
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
290293

291294
for cgu in codegen_units.iter_mut() {
292-
cgu.compute_size_estimate(cx.tcx);
295+
cgu.compute_size_estimate();
293296
}
294297

295298
return PlacedMonoItems {
@@ -352,7 +355,7 @@ fn merge_codegen_units<'tcx>(
352355
&& codegen_units.iter().any(|cgu| cgu.size_estimate() < NON_INCR_MIN_CGU_SIZE))
353356
{
354357
// Sort small cgus to the back.
355-
codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
358+
codegen_units.sort_by_key(|cgu| cmp::Reverse(cgu.size_estimate()));
356359

357360
let mut smallest = codegen_units.pop().unwrap();
358361
let second_smallest = codegen_units.last_mut().unwrap();
@@ -361,7 +364,7 @@ fn merge_codegen_units<'tcx>(
361364
// may be duplicate inlined items, in which case the destination CGU is
362365
// unaffected. Recalculate size estimates afterwards.
363366
second_smallest.items_mut().extend(smallest.items_mut().drain());
364-
second_smallest.compute_size_estimate(cx.tcx);
367+
second_smallest.compute_size_estimate();
365368

366369
// Record that `second_smallest` now contains all the stuff that was
367370
// in `smallest` before.
@@ -882,15 +885,15 @@ fn debug_dump<'a, 'tcx: 'a>(
882885
num_cgus += 1;
883886
all_cgu_sizes.push(cgu.size_estimate());
884887

885-
for (item, _) in cgu.items() {
888+
for (item, data) in cgu.items() {
886889
match item.instantiation_mode(tcx) {
887890
InstantiationMode::GloballyShared { .. } => {
888891
root_items += 1;
889-
root_size += item.size_estimate(tcx);
892+
root_size += data.size_estimate;
890893
}
891894
InstantiationMode::LocalCopy => {
892895
placed_inlined_items += 1;
893-
placed_inlined_size += item.size_estimate(tcx);
896+
placed_inlined_size += data.size_estimate;
894897
}
895898
}
896899
}
@@ -932,7 +935,7 @@ fn debug_dump<'a, 'tcx: 'a>(
932935
let mean_size = size as f64 / num_items as f64;
933936

934937
let mut placed_item_sizes: Vec<_> =
935-
cgu.items().iter().map(|(item, _)| item.size_estimate(tcx)).collect();
938+
cgu.items().values().map(|data| data.size_estimate).collect();
936939
placed_item_sizes.sort_unstable_by_key(|&n| cmp::Reverse(n));
937940
let sizes = list(&placed_item_sizes);
938941

@@ -946,11 +949,11 @@ fn debug_dump<'a, 'tcx: 'a>(
946949
let symbol_name = item.symbol_name(tcx).name;
947950
let symbol_hash_start = symbol_name.rfind('h');
948951
let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
949-
let size = item.size_estimate(tcx);
950952
let kind = match item.instantiation_mode(tcx) {
951953
InstantiationMode::GloballyShared { .. } => "root",
952954
InstantiationMode::LocalCopy => "inlined",
953955
};
956+
let size = data.size_estimate;
954957
let _ = with_no_trimmed_paths!(writeln!(
955958
s,
956959
" - {item} [{linkage:?}] [{symbol_hash}] ({kind}, size: {size})"

0 commit comments

Comments
 (0)