Avoid MIR bloat in inlining
In 126578 we ended up with more binary size increases than expected. This change attempts to avoid inlining large things into small things, to avoid that kind of increase, in cases when top-down inlining will still be able to do that inlining later.
This commit is contained in:
parent
c3774be741
commit
23c8ed14c9
18 changed files with 387 additions and 847 deletions
|
@ -85,13 +85,18 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
|
|||
}
|
||||
|
||||
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
|
||||
let mut this = Inliner {
|
||||
tcx,
|
||||
param_env,
|
||||
codegen_fn_attrs: tcx.codegen_fn_attrs(def_id),
|
||||
codegen_fn_attrs,
|
||||
history: Vec::new(),
|
||||
changed: false,
|
||||
caller_is_inline_forwarder: matches!(
|
||||
codegen_fn_attrs.inline,
|
||||
InlineAttr::Hint | InlineAttr::Always
|
||||
) && body_is_forwarder(body),
|
||||
};
|
||||
let blocks = START_BLOCK..body.basic_blocks.next_index();
|
||||
this.process_blocks(body, blocks);
|
||||
|
@ -111,6 +116,9 @@ struct Inliner<'tcx> {
|
|||
history: Vec<DefId>,
|
||||
/// Indicates that the caller body has been modified.
|
||||
changed: bool,
|
||||
/// Indicates that the caller is #[inline] and just calls another function,
|
||||
/// and thus we can inline less into it as it'll be inlined itself.
|
||||
caller_is_inline_forwarder: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> Inliner<'tcx> {
|
||||
|
@ -485,7 +493,9 @@ impl<'tcx> Inliner<'tcx> {
|
|||
) -> Result<(), &'static str> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let mut threshold = if cross_crate_inlinable {
|
||||
let mut threshold = if self.caller_is_inline_forwarder {
|
||||
self.tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30)
|
||||
} else if cross_crate_inlinable {
|
||||
self.tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100)
|
||||
} else {
|
||||
self.tcx.sess.opts.unstable_opts.inline_mir_threshold.unwrap_or(50)
|
||||
|
@ -504,6 +514,8 @@ impl<'tcx> Inliner<'tcx> {
|
|||
let mut checker =
|
||||
CostChecker::new(self.tcx, self.param_env, Some(callsite.callee), callee_body);
|
||||
|
||||
checker.add_function_level_costs();
|
||||
|
||||
// Traverse the MIR manually so we can account for the effects of inlining on the CFG.
|
||||
let mut work_list = vec![START_BLOCK];
|
||||
let mut visited = BitSet::new_empty(callee_body.basic_blocks.len());
|
||||
|
@ -1091,3 +1103,37 @@ fn try_instance_mir<'tcx>(
|
|||
}
|
||||
Ok(tcx.instance_mir(instance))
|
||||
}
|
||||
|
||||
fn body_is_forwarder(body: &Body<'_>) -> bool {
|
||||
let TerminatorKind::Call { target, .. } = body.basic_blocks[START_BLOCK].terminator().kind
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
if let Some(target) = target {
|
||||
let TerminatorKind::Return = body.basic_blocks[target].terminator().kind else {
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
let max_blocks = if !body.is_polymorphic {
|
||||
2
|
||||
} else if target.is_none() {
|
||||
3
|
||||
} else {
|
||||
4
|
||||
};
|
||||
if body.basic_blocks.len() > max_blocks {
|
||||
return false;
|
||||
}
|
||||
|
||||
body.basic_blocks.iter_enumerated().all(|(bb, bb_data)| {
|
||||
bb == START_BLOCK
|
||||
|| matches!(
|
||||
bb_data.terminator().kind,
|
||||
TerminatorKind::Return
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::UnwindResume
|
||||
| TerminatorKind::UnwindTerminate(_)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue