-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[MIR] Initial implementation of inlining #36593
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
Changes from 1 commit
5207298
064306b
11d95c8
d78103a
e30b211
638c603
b9d21d7
11da9d6
f027275
8ebd218
0f83f14
76cc7cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,8 @@ pub struct CallGraph { | |
} | ||
|
||
impl CallGraph { | ||
// FIXME: allow for construction of a callgraph that inspects | ||
// cross-crate MIRs if available. | ||
pub fn build<'tcx>(map: &MirMap<'tcx>) -> CallGraph { | ||
let def_ids = map.map.keys(); | ||
|
||
|
@@ -52,10 +54,12 @@ impl CallGraph { | |
callgraph | ||
} | ||
|
||
// Iterate over the strongly-connected components of the graph | ||
pub fn scc_iter<'g>(&'g self) -> SCCIterator<'g> { | ||
SCCIterator::new(&self.graph) | ||
} | ||
|
||
// Get the def_id for the given graph node | ||
pub fn def_id(&self, node: graph::NodeIndex) -> DefId { | ||
*self.graph.node_data(node) | ||
} | ||
|
@@ -93,6 +97,11 @@ struct StackElement<'g> { | |
children: graph::AdjacentTargets<'g, DefId, ()> | ||
} | ||
|
||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be in |
||
* Iterator over strongly-connected-components using Tarjan's algorithm[1] | ||
* | ||
* [1]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: |
||
pub struct SCCIterator<'g> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be factored into |
||
graph: &'g graph::Graph<DefId, ()>, | ||
index: usize, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -284,7 +284,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { | |
|
||
let tcx = self.tcx; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like an |
||
|
||
// Don't inline closures | ||
// Don't inline closures that have captures | ||
// FIXME: Handle closures better | ||
if callee_mir.upvar_decls.len() > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the problem here? I was sure closures with upvars are a prime inlining target. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure how to handle the debuginfo related stuff, so I'm punting on it for now. You're right, but this isn't intended to be a complete implementation right away. |
||
return false; | ||
} | ||
|
@@ -441,12 +442,12 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { | |
|
||
let terminator = caller_mir[callsite.bb].terminator.take().unwrap(); | ||
match terminator.kind { | ||
// FIXME: Handle inlining of diverging calls | ||
TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { | ||
|
||
debug!("Inlined {:?} into {:?}", callsite.callee, callsite.caller); | ||
|
||
let is_box_free = Some(callsite.callee) == self.tcx.lang_items.box_free_fn(); | ||
let bb_len = caller_mir.basic_blocks().len(); | ||
|
||
let mut var_map = IndexVec::with_capacity(callee_mir.var_decls.len()); | ||
let mut temp_map = IndexVec::with_capacity(callee_mir.temp_decls.len()); | ||
|
@@ -527,7 +528,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { | |
|
||
let return_block = destination.1; | ||
|
||
// Copy the arguments if needed. | ||
let args : Vec<_> = if is_box_free { | ||
assert!(args.len() == 1); | ||
// box_free takes a Box, but is defined with a *mut T, inlining | ||
|
@@ -580,7 +580,10 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { | |
|
||
vec![Operand::Consume(tmp)] | ||
} else { | ||
// Copy the arguments if needed. | ||
let tcx = self.tcx; | ||
// FIXME: Analysis of the usage of the arguments to avoid | ||
// unnecessary temporaries. | ||
args.iter().map(|a| { | ||
if let Operand::Consume(Lvalue::Temp(_)) = *a { | ||
// Reuse the operand if it's a temporary already | ||
|
@@ -606,6 +609,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { | |
}).collect() | ||
}; | ||
|
||
let bb_len = caller_mir.basic_blocks.len(); | ||
let mut integrator = Integrator { | ||
block_idx: bb_len, | ||
args: &args, | ||
|
@@ -663,6 +667,13 @@ fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParameterE | |
}) | ||
} | ||
|
||
/** | ||
* Integrator. | ||
* | ||
* Integrates blocks from the callee function into the calling function. | ||
* Updates block indices, references to locals and other control flow | ||
* stuff. | ||
*/ | ||
struct Integrator<'a, 'tcx: 'a> { | ||
block_idx: usize, | ||
args: &'a [Operand<'tcx>], | ||
|
@@ -707,6 +718,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { | |
let idx = arg.index(); | ||
if let Operand::Consume(ref lval) = self.args[idx] { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't |
||
*lvalue = lval.clone(); | ||
} else { | ||
bug!("Arg operand `{:?}` is not an Lvalue use.", arg) | ||
} | ||
} | ||
_ => self.super_lvalue(lvalue, _ctxt, _location) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think you can lifetime elide
'g
here