Skip to content

More aggressive CGU merging #112648

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
XXX: max-merge
  • Loading branch information
nnethercote committed Jun 15, 2023
commit eb1af88fdd40fc0ba6f807e1c50f7c5d087695be
52 changes: 46 additions & 6 deletions compiler/rustc_monomorphize/src/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,30 +319,70 @@ fn merge_codegen_units<'tcx>(
// - we have more CGUs than the upper limit, or
// - (Non-incremental builds only) the user didn't specify a CGU count, and
// there are multiple CGUs, and some are below the minimum size.
// - njn: update this comment
//
// The "didn't specify a CGU count" condition is because when an explicit
// count is requested we observe it as closely as possible. For example,
// the `compiler_builtins` crate sets `codegen-units = 10000` and it's
// critical they aren't merged. Also, some tests use explicit small values
// and likewise won't work if small CGUs are merged.
while codegen_units.len() > cx.tcx.sess.codegen_units().as_usize()
|| (cx.tcx.sess.opts.incremental.is_none()
&& matches!(cx.tcx.sess.codegen_units(), CodegenUnits::Default(_))
&& codegen_units.len() > 1
&& codegen_units.iter().any(|cgu| cgu.size_estimate() < NON_INCR_MIN_CGU_SIZE))
{
//eprintln!("-----");
loop {
// njn: where to put this?
// Sort small cgus to the back.
codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));

//eprintln!("cgus: {:?}", codegen_units.iter().map(|cgu| cgu.size_estimate()).collect::<Vec<_>>());

let merge1 = codegen_units.len() > cx.tcx.sess.codegen_units().as_usize();

let merge2 = cx.tcx.sess.opts.incremental.is_none()
&& matches!(cx.tcx.sess.codegen_units(), CodegenUnits::Default(_))
&& codegen_units.len() >= 2
&& codegen_units.iter().any(|cgu| cgu.size_estimate() < NON_INCR_MIN_CGU_SIZE);

// njn: addition is an imperfect measure, could be overlap
let merge3 = cx.tcx.sess.opts.incremental.is_none()
&& matches!(cx.tcx.sess.codegen_units(), CodegenUnits::Default(_))
&& codegen_units.len() >= 3
&& {
// eprintln!(
// "sz: {} >= {} + {}?",
// codegen_units[0].size_estimate(),
// codegen_units[codegen_units.len() - 2].size_estimate(),
// codegen_units[codegen_units.len() - 1].size_estimate());

codegen_units[0].size_estimate()
>= codegen_units[codegen_units.len() - 2].size_estimate()
+ codegen_units[codegen_units.len() - 1].size_estimate()
};

if !(merge1 || merge2 || merge3) {
break;
}

let mut smallest = codegen_units.pop().unwrap();
let second_smallest = codegen_units.last_mut().unwrap();

// let sm_size = smallest.size_estimate();
// let sec_sm_size = second_smallest.size_estimate();

// Move the items from `smallest` to `second_smallest`. Some of them
// may be duplicate inlined items, in which case the destination CGU is
// unaffected. Recalculate size estimates afterwards.
second_smallest.items_mut().extend(smallest.items_mut().drain());
second_smallest.create_size_estimate(cx.tcx);

// eprintln!(
// "merge: {} {} {}: {} + {} -> {}",
// merge1,
// merge2,
// merge3,
// sec_sm_size,
// sm_size,
// second_smallest.size_estimate()
// );

// Record that `second_smallest` now contains all the stuff that was
// in `smallest` before.
let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
Expand Down