Skip to content

Commit 5a343c8

Browse files
committed
rustc_mir: use Instance more in the inliner.
1 parent 1493015 commit 5a343c8

File tree

1 file changed

+36
-27
lines changed

1 file changed

+36
-27
lines changed

src/librustc_mir/transform/inline.rs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
//! Inlining pass for MIR functions
22
3-
use rustc_hir::def_id::DefId;
4-
53
use rustc_index::bit_set::BitSet;
64
use rustc_index::vec::{Idx, IndexVec};
75

86
use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
97
use rustc::mir::visit::*;
108
use rustc::mir::*;
119
use rustc::session::config::Sanitizer;
12-
use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
10+
use rustc::ty::subst::{InternalSubsts, Subst};
1311
use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
1412

1513
use super::simplify::{remove_dead_blocks, CfgSimplifier};
@@ -32,8 +30,7 @@ pub struct Inline;
3230

3331
#[derive(Copy, Clone, Debug)]
3432
struct CallSite<'tcx> {
35-
callee: DefId,
36-
substs: SubstsRef<'tcx>,
33+
callee: Instance<'tcx>,
3734
bb: BasicBlock,
3835
source_info: SourceInfo,
3936
}
@@ -97,13 +94,19 @@ impl Inliner<'tcx> {
9794
local_change = false;
9895
while let Some(callsite) = callsites.pop_front() {
9996
debug!("checking whether to inline callsite {:?}", callsite);
100-
if !self.tcx.is_mir_available(callsite.callee) {
101-
debug!("checking whether to inline callsite {:?} - MIR unavailable", callsite);
102-
continue;
97+
98+
if let InstanceDef::Item(callee_def_id) = callsite.callee.def {
99+
if !self.tcx.is_mir_available(callee_def_id) {
100+
debug!(
101+
"checking whether to inline callsite {:?} - MIR unavailable",
102+
callsite,
103+
);
104+
continue;
105+
}
103106
}
104107

105108
let self_node_id = self.tcx.hir().as_local_node_id(self.source.def_id()).unwrap();
106-
let callee_node_id = self.tcx.hir().as_local_node_id(callsite.callee);
109+
let callee_node_id = self.tcx.hir().as_local_node_id(callsite.callee.def_id());
107110

108111
let callee_body = if let Some(callee_node_id) = callee_node_id {
109112
// Avoid a cycle here by only using `optimized_mir` only if we have
@@ -113,19 +116,21 @@ impl Inliner<'tcx> {
113116
if !self.tcx.dep_graph.is_fully_enabled()
114117
&& self_node_id.as_u32() < callee_node_id.as_u32()
115118
{
116-
self.tcx.optimized_mir(callsite.callee)
119+
self.tcx.instance_mir(callsite.callee.def)
117120
} else {
118121
continue;
119122
}
120123
} else {
121124
// This cannot result in a cycle since the callee MIR is from another crate
122125
// and is already optimized.
123-
self.tcx.optimized_mir(callsite.callee)
126+
self.tcx.instance_mir(callsite.callee.def)
124127
};
125128

129+
let callee_body: &Body<'tcx> = &*callee_body;
130+
126131
let callee_body = if self.consider_optimizing(callsite, callee_body) {
127132
self.tcx.subst_and_normalize_erasing_regions(
128-
&callsite.substs,
133+
&callsite.callee.substs,
129134
param_env,
130135
callee_body,
131136
)
@@ -186,18 +191,13 @@ impl Inliner<'tcx> {
186191
let terminator = bb_data.terminator();
187192
if let TerminatorKind::Call { func: ref op, .. } = terminator.kind {
188193
if let ty::FnDef(callee_def_id, substs) = op.ty(caller_body, self.tcx).kind {
189-
let instance = Instance::resolve(self.tcx, param_env, callee_def_id, substs)?;
194+
let callee = Instance::resolve(self.tcx, param_env, callee_def_id, substs)?;
190195

191-
if let InstanceDef::Virtual(..) = instance.def {
196+
if let InstanceDef::Virtual(..) | InstanceDef::Intrinsic(_) = callee.def {
192197
return None;
193198
}
194199

195-
return Some(CallSite {
196-
callee: instance.def_id(),
197-
substs: instance.substs,
198-
bb,
199-
source_info: terminator.source_info,
200-
});
200+
return Some(CallSite { callee, bb, source_info: terminator.source_info });
201201
}
202202
}
203203

@@ -222,7 +222,7 @@ impl Inliner<'tcx> {
222222
return false;
223223
}
224224

225-
let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee);
225+
let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());
226226

227227
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) {
228228
debug!("`#[track_caller]` present - not inlining");
@@ -267,8 +267,8 @@ impl Inliner<'tcx> {
267267
// Only inline local functions if they would be eligible for cross-crate
268268
// inlining. This is to ensure that the final crate doesn't have MIR that
269269
// reference unexported symbols
270-
if callsite.callee.is_local() {
271-
if callsite.substs.non_erasable_generics().count() == 0 && !hinted {
270+
if callsite.callee.def_id().is_local() {
271+
if callsite.callee.substs.non_erasable_generics().count() == 0 && !hinted {
272272
debug!(" callee is an exported function - not inlining");
273273
return false;
274274
}
@@ -324,7 +324,7 @@ impl Inliner<'tcx> {
324324
work_list.push(target);
325325
// If the location doesn't actually need dropping, treat it like
326326
// a regular goto.
327-
let ty = location.ty(callee_body, tcx).subst(tcx, callsite.substs).ty;
327+
let ty = location.ty(callee_body, tcx).subst(tcx, callsite.callee.substs).ty;
328328
if ty.needs_drop(tcx, param_env) {
329329
cost += CALL_PENALTY;
330330
if let Some(unwind) = unwind {
@@ -374,7 +374,7 @@ impl Inliner<'tcx> {
374374

375375
for v in callee_body.vars_and_temps_iter() {
376376
let v = &callee_body.local_decls[v];
377-
let ty = v.ty.subst(tcx, callsite.substs);
377+
let ty = v.ty.subst(tcx, callsite.callee.substs);
378378
// Cost of the var is the size in machine-words, if we know
379379
// it.
380380
if let Some(size) = type_size_of(tcx, param_env, ty) {
@@ -402,7 +402,7 @@ impl Inliner<'tcx> {
402402
&self,
403403
callsite: CallSite<'tcx>,
404404
caller_body: &mut BodyAndCache<'tcx>,
405-
mut callee_body: BodyAndCache<'tcx>,
405+
mut callee_body: Body<'tcx>,
406406
) -> bool {
407407
let terminator = caller_body[callsite.bb].terminator.take().unwrap();
408408
match terminator.kind {
@@ -504,6 +504,13 @@ impl Inliner<'tcx> {
504504
caller_body.var_debug_info.push(var_debug_info);
505505
}
506506

507+
// HACK(eddyb) work around the `basic_blocks` field of `mir::Body`
508+
// being private, due to `BodyAndCache` implementing `DerefMut`
509+
// to `mir::Body` (which would allow bypassing `basic_blocks_mut`).
510+
// The only way to make `basic_blocks` public again would be to
511+
// remove that `DerefMut` impl and add more `*_mut` accessors.
512+
let mut callee_body = BodyAndCache::new(callee_body);
513+
507514
for (bb, mut block) in callee_body.basic_blocks_mut().drain_enumerated(..) {
508515
integrator.visit_basic_block_data(bb, &mut block);
509516
caller_body.basic_blocks_mut().push(block);
@@ -557,7 +564,9 @@ impl Inliner<'tcx> {
557564
// tmp2 = tuple_tmp.2
558565
//
559566
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
560-
if tcx.is_closure(callsite.callee) {
567+
// FIXME(eddyb) make this check for `"rust-call"` ABI combined with
568+
// `callee_body.spread_arg == None`, instead of special-casing closures.
569+
if tcx.is_closure(callsite.callee.def_id()) {
561570
let mut args = args.into_iter();
562571
let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
563572
let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);

0 commit comments

Comments
 (0)