Skip to content

Commit b2c3948

Browse files
committed
Split the CGU merging loop.
It has two conditions. This commit splits it in two, one per condition. The next commit will change the first loop.
1 parent 77b053a commit b2c3948

File tree

1 file changed

+30
-20
lines changed

1 file changed

+30
-20
lines changed

compiler/rustc_monomorphize/src/partitioning.rs

+30-20
Original file line numberDiff line numberDiff line change
@@ -318,31 +318,50 @@ fn merge_codegen_units<'tcx>(
318318
let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
319319
codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
320320

321+
// Repeatedly merge the two smallest codegen units as long as we have more
322+
// CGUs than the upper limit.
323+
while codegen_units.len() > cx.tcx.sess.codegen_units().as_usize() {
324+
// Sort small cgus to the back.
325+
codegen_units.sort_by_key(|cgu| cmp::Reverse(cgu.size_estimate()));
326+
327+
let mut smallest = codegen_units.pop().unwrap();
328+
let second_smallest = codegen_units.last_mut().unwrap();
329+
330+
// Move the items from `smallest` to `second_smallest`. Some of them
331+
// may be duplicate inlined items, in which case the destination CGU is
332+
// unaffected. Recalculate size estimates afterwards.
333+
second_smallest.items_mut().extend(smallest.items_mut().drain());
334+
second_smallest.compute_size_estimate();
335+
336+
// Record that `second_smallest` now contains all the stuff that was
337+
// in `smallest` before.
338+
let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
339+
cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
340+
}
341+
321342
// Having multiple CGUs can drastically speed up compilation. But for
322343
// non-incremental builds, tiny CGUs slow down compilation *and* result in
323344
// worse generated code. So we don't allow CGUs smaller than this (unless
324345
// there is just one CGU, of course). Note that CGU sizes of 100,000+ are
325346
// common in larger programs, so this isn't all that large.
326347
const NON_INCR_MIN_CGU_SIZE: usize = 1800;
327348

328-
// Repeatedly merge the two smallest codegen units as long as:
329-
// - we have more CGUs than the upper limit, or
330-
// - (Non-incremental builds only) the user didn't specify a CGU count, and
331-
// there are multiple CGUs, and some are below the minimum size.
349+
// Repeatedly merge the two smallest codegen units as long as: it's a
350+
// non-incremental build, and the user didn't specify a CGU count, and
351+
// there are multiple CGUs, and some are below the minimum size.
332352
//
333353
// The "didn't specify a CGU count" condition is because when an explicit
334354
// count is requested we observe it as closely as possible. For example,
335355
// the `compiler_builtins` crate sets `codegen-units = 10000` and it's
336356
// critical they aren't merged. Also, some tests use explicit small values
337357
// and likewise won't work if small CGUs are merged.
338-
while codegen_units.len() > cx.tcx.sess.codegen_units().as_usize()
339-
|| (cx.tcx.sess.opts.incremental.is_none()
340-
&& matches!(cx.tcx.sess.codegen_units(), CodegenUnits::Default(_))
341-
&& codegen_units.len() > 1
342-
&& codegen_units.iter().any(|cgu| cgu.size_estimate() < NON_INCR_MIN_CGU_SIZE))
358+
while cx.tcx.sess.opts.incremental.is_none()
359+
&& matches!(cx.tcx.sess.codegen_units(), CodegenUnits::Default(_))
360+
&& codegen_units.len() > 1
361+
&& codegen_units.iter().any(|cgu| cgu.size_estimate() < NON_INCR_MIN_CGU_SIZE)
343362
{
344363
// Sort small cgus to the back.
345-
codegen_units.sort_by_key(|cgu| cmp::Reverse(cgu.size_estimate()));
364+
codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
346365

347366
let mut smallest = codegen_units.pop().unwrap();
348367
let second_smallest = codegen_units.last_mut().unwrap();
@@ -353,16 +372,7 @@ fn merge_codegen_units<'tcx>(
353372
second_smallest.items_mut().extend(smallest.items_mut().drain());
354373
second_smallest.compute_size_estimate();
355374

356-
// Record that `second_smallest` now contains all the stuff that was
357-
// in `smallest` before.
358-
let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
359-
cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
360-
361-
debug!(
362-
"CodegenUnit {} merged into CodegenUnit {}",
363-
smallest.name(),
364-
second_smallest.name()
365-
);
375+
// Don't update `cgu_contents`, that's only for incremental builds.
366376
}
367377

368378
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);

0 commit comments

Comments
 (0)