Skip to content

Commit 7f741ee

Browse files
committed
rustc_mir: use Instance more in the inliner.
1 parent c7d8140 commit 7f741ee

File tree

1 file changed

+36
-26
lines changed

1 file changed

+36
-26
lines changed

src/librustc_mir/transform/inline.rs

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
44
use rustc::mir::visit::*;
55
use rustc::mir::*;
6-
use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
6+
use rustc::ty::subst::{InternalSubsts, Subst};
77
use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
88
use rustc_attr as attr;
9-
use rustc_hir::def_id::DefId;
109
use rustc_index::bit_set::BitSet;
1110
use rustc_index::vec::{Idx, IndexVec};
1211
use rustc_session::config::Sanitizer;
@@ -29,8 +28,7 @@ pub struct Inline;
2928

3029
#[derive(Copy, Clone, Debug)]
3130
struct CallSite<'tcx> {
32-
callee: DefId,
33-
substs: SubstsRef<'tcx>,
31+
callee: Instance<'tcx>,
3432
bb: BasicBlock,
3533
source_info: SourceInfo,
3634
}
@@ -94,13 +92,19 @@ impl Inliner<'tcx> {
9492
local_change = false;
9593
while let Some(callsite) = callsites.pop_front() {
9694
debug!("checking whether to inline callsite {:?}", callsite);
97-
if !self.tcx.is_mir_available(callsite.callee) {
98-
debug!("checking whether to inline callsite {:?} - MIR unavailable", callsite);
99-
continue;
95+
96+
if let InstanceDef::Item(callee_def_id) = callsite.callee.def {
97+
if !self.tcx.is_mir_available(callee_def_id) {
98+
debug!(
99+
"checking whether to inline callsite {:?} - MIR unavailable",
100+
callsite,
101+
);
102+
continue;
103+
}
100104
}
101105

102106
let self_node_id = self.tcx.hir().as_local_node_id(self.source.def_id()).unwrap();
103-
let callee_node_id = self.tcx.hir().as_local_node_id(callsite.callee);
107+
let callee_node_id = self.tcx.hir().as_local_node_id(callsite.callee.def_id());
104108

105109
let callee_body = if let Some(callee_node_id) = callee_node_id {
106110
// Avoid a cycle here by only using `optimized_mir` only if we have
@@ -110,19 +114,21 @@ impl Inliner<'tcx> {
110114
if !self.tcx.dep_graph.is_fully_enabled()
111115
&& self_node_id.as_u32() < callee_node_id.as_u32()
112116
{
113-
self.tcx.optimized_mir(callsite.callee)
117+
self.tcx.instance_mir(callsite.callee.def)
114118
} else {
115119
continue;
116120
}
117121
} else {
118122
// This cannot result in a cycle since the callee MIR is from another crate
119123
// and is already optimized.
120-
self.tcx.optimized_mir(callsite.callee)
124+
self.tcx.instance_mir(callsite.callee.def)
121125
};
122126

127+
let callee_body: &Body<'tcx> = &*callee_body;
128+
123129
let callee_body = if self.consider_optimizing(callsite, callee_body) {
124130
self.tcx.subst_and_normalize_erasing_regions(
125-
&callsite.substs,
131+
&callsite.callee.substs,
126132
param_env,
127133
callee_body,
128134
)
@@ -183,18 +189,13 @@ impl Inliner<'tcx> {
183189
let terminator = bb_data.terminator();
184190
if let TerminatorKind::Call { func: ref op, .. } = terminator.kind {
185191
if let ty::FnDef(callee_def_id, substs) = op.ty(caller_body, self.tcx).kind {
186-
let instance = Instance::resolve(self.tcx, param_env, callee_def_id, substs)?;
192+
let callee = Instance::resolve(self.tcx, param_env, callee_def_id, substs)?;
187193

188-
if let InstanceDef::Virtual(..) = instance.def {
194+
if let InstanceDef::Virtual(..) | InstanceDef::Intrinsic(_) = callee.def {
189195
return None;
190196
}
191197

192-
return Some(CallSite {
193-
callee: instance.def_id(),
194-
substs: instance.substs,
195-
bb,
196-
source_info: terminator.source_info,
197-
});
198+
return Some(CallSite { callee, bb, source_info: terminator.source_info });
198199
}
199200
}
200201

@@ -219,7 +220,7 @@ impl Inliner<'tcx> {
219220
return false;
220221
}
221222

222-
let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee);
223+
let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());
223224

224225
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) {
225226
debug!("`#[track_caller]` present - not inlining");
@@ -264,8 +265,8 @@ impl Inliner<'tcx> {
264265
// Only inline local functions if they would be eligible for cross-crate
265266
// inlining. This is to ensure that the final crate doesn't have MIR that
266267
// reference unexported symbols
267-
if callsite.callee.is_local() {
268-
if callsite.substs.non_erasable_generics().count() == 0 && !hinted {
268+
if callsite.callee.def_id().is_local() {
269+
if callsite.callee.substs.non_erasable_generics().count() == 0 && !hinted {
269270
debug!(" callee is an exported function - not inlining");
270271
return false;
271272
}
@@ -321,7 +322,7 @@ impl Inliner<'tcx> {
321322
work_list.push(target);
322323
// If the location doesn't actually need dropping, treat it like
323324
// a regular goto.
324-
let ty = location.ty(callee_body, tcx).subst(tcx, callsite.substs).ty;
325+
let ty = location.ty(callee_body, tcx).subst(tcx, callsite.callee.substs).ty;
325326
if ty.needs_drop(tcx, param_env) {
326327
cost += CALL_PENALTY;
327328
if let Some(unwind) = unwind {
@@ -371,7 +372,7 @@ impl Inliner<'tcx> {
371372

372373
for v in callee_body.vars_and_temps_iter() {
373374
let v = &callee_body.local_decls[v];
374-
let ty = v.ty.subst(tcx, callsite.substs);
375+
let ty = v.ty.subst(tcx, callsite.callee.substs);
375376
// Cost of the var is the size in machine-words, if we know
376377
// it.
377378
if let Some(size) = type_size_of(tcx, param_env, ty) {
@@ -399,7 +400,7 @@ impl Inliner<'tcx> {
399400
&self,
400401
callsite: CallSite<'tcx>,
401402
caller_body: &mut BodyAndCache<'tcx>,
402-
mut callee_body: BodyAndCache<'tcx>,
403+
mut callee_body: Body<'tcx>,
403404
) -> bool {
404405
let terminator = caller_body[callsite.bb].terminator.take().unwrap();
405406
match terminator.kind {
@@ -501,6 +502,13 @@ impl Inliner<'tcx> {
501502
caller_body.var_debug_info.push(var_debug_info);
502503
}
503504

505+
// HACK(eddyb) work around the `basic_blocks` field of `mir::Body`
506+
// being private, due to `BodyAndCache` implementing `DerefMut`
507+
// to `mir::Body` (which would allow bypassing `basic_blocks_mut`).
508+
// The only way to make `basic_blocks` public again would be to
509+
// remove that `DerefMut` impl and add more `*_mut` accessors.
510+
let mut callee_body = BodyAndCache::new(callee_body);
511+
504512
for (bb, mut block) in callee_body.basic_blocks_mut().drain_enumerated(..) {
505513
integrator.visit_basic_block_data(bb, &mut block);
506514
caller_body.basic_blocks_mut().push(block);
@@ -554,7 +562,9 @@ impl Inliner<'tcx> {
554562
// tmp2 = tuple_tmp.2
555563
//
556564
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
557-
if tcx.is_closure(callsite.callee) {
565+
// FIXME(eddyb) make this check for `"rust-call"` ABI combined with
566+
// `callee_body.spread_arg == None`, instead of special-casing closures.
567+
if tcx.is_closure(callsite.callee.def_id()) {
558568
let mut args = args.into_iter();
559569
let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
560570
let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);

0 commit comments

Comments
 (0)