rustc_mir: use Instance more in the inliner.
This commit is contained in:
parent
8c942c1511
commit
708fc0b692
@ -1,13 +1,12 @@
|
|||||||
//! Inlining pass for MIR functions
|
//! Inlining pass for MIR functions
|
||||||
|
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
use rustc_hir::def_id::DefId;
|
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||||
use rustc_middle::mir::visit::*;
|
use rustc_middle::mir::visit::*;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
use rustc_middle::ty::subst::Subst;
|
||||||
use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
@ -30,8 +29,7 @@ pub struct Inline;
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
struct CallSite<'tcx> {
|
struct CallSite<'tcx> {
|
||||||
callee: DefId,
|
callee: Instance<'tcx>,
|
||||||
substs: SubstsRef<'tcx>,
|
|
||||||
bb: BasicBlock,
|
bb: BasicBlock,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
}
|
}
|
||||||
@ -101,12 +99,18 @@ impl Inliner<'tcx> {
|
|||||||
local_change = false;
|
local_change = false;
|
||||||
while let Some(callsite) = callsites.pop_front() {
|
while let Some(callsite) = callsites.pop_front() {
|
||||||
debug!("checking whether to inline callsite {:?}", callsite);
|
debug!("checking whether to inline callsite {:?}", callsite);
|
||||||
if !self.tcx.is_mir_available(callsite.callee) {
|
|
||||||
debug!("checking whether to inline callsite {:?} - MIR unavailable", callsite);
|
if let InstanceDef::Item(_) = callsite.callee.def {
|
||||||
|
if !self.tcx.is_mir_available(callsite.callee.def_id()) {
|
||||||
|
debug!(
|
||||||
|
"checking whether to inline callsite {:?} - MIR unavailable",
|
||||||
|
callsite,
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let callee_body = if let Some(callee_def_id) = callsite.callee.as_local() {
|
let callee_body = if let Some(callee_def_id) = callsite.callee.def_id().as_local() {
|
||||||
let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
|
let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
|
||||||
// Avoid a cycle here by only using `optimized_mir` only if we have
|
// Avoid a cycle here by only using `optimized_mir` only if we have
|
||||||
// a lower `HirId` than the callee. This ensures that the callee will
|
// a lower `HirId` than the callee. This ensures that the callee will
|
||||||
@ -119,19 +123,21 @@ impl Inliner<'tcx> {
|
|||||||
&& self_hir_id < callee_hir_id
|
&& self_hir_id < callee_hir_id
|
||||||
&& caller_body.generator_kind.is_none()
|
&& caller_body.generator_kind.is_none()
|
||||||
{
|
{
|
||||||
self.tcx.optimized_mir(callsite.callee)
|
self.tcx.instance_mir(callsite.callee.def)
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This cannot result in a cycle since the callee MIR is from another crate
|
// This cannot result in a cycle since the callee MIR is from another crate
|
||||||
// and is already optimized.
|
// and is already optimized.
|
||||||
self.tcx.optimized_mir(callsite.callee)
|
self.tcx.instance_mir(callsite.callee.def)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let callee_body: &Body<'tcx> = &*callee_body;
|
||||||
|
|
||||||
let callee_body = if self.consider_optimizing(callsite, callee_body) {
|
let callee_body = if self.consider_optimizing(callsite, callee_body) {
|
||||||
self.tcx.subst_and_normalize_erasing_regions(
|
self.tcx.subst_and_normalize_erasing_regions(
|
||||||
&callsite.substs,
|
&callsite.callee.substs,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
callee_body,
|
callee_body,
|
||||||
)
|
)
|
||||||
@ -204,21 +210,16 @@ impl Inliner<'tcx> {
|
|||||||
// To resolve an instance its substs have to be fully normalized, so
|
// To resolve an instance its substs have to be fully normalized, so
|
||||||
// we do this here.
|
// we do this here.
|
||||||
let normalized_substs = self.tcx.normalize_erasing_regions(self.param_env, substs);
|
let normalized_substs = self.tcx.normalize_erasing_regions(self.param_env, substs);
|
||||||
let instance =
|
let callee =
|
||||||
Instance::resolve(self.tcx, self.param_env, callee_def_id, normalized_substs)
|
Instance::resolve(self.tcx, self.param_env, callee_def_id, normalized_substs)
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()?;
|
.flatten()?;
|
||||||
|
|
||||||
if let InstanceDef::Virtual(..) = instance.def {
|
if let InstanceDef::Virtual(..) | InstanceDef::Intrinsic(_) = callee.def {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(CallSite {
|
return Some(CallSite { callee, bb, source_info: terminator.source_info });
|
||||||
callee: instance.def_id(),
|
|
||||||
substs: instance.substs,
|
|
||||||
bb,
|
|
||||||
source_info: terminator.source_info,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +244,7 @@ impl Inliner<'tcx> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee);
|
let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());
|
||||||
|
|
||||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) {
|
||||||
debug!("`#[track_caller]` present - not inlining");
|
debug!("`#[track_caller]` present - not inlining");
|
||||||
@ -282,8 +283,8 @@ impl Inliner<'tcx> {
|
|||||||
// Only inline local functions if they would be eligible for cross-crate
|
// Only inline local functions if they would be eligible for cross-crate
|
||||||
// inlining. This is to ensure that the final crate doesn't have MIR that
|
// inlining. This is to ensure that the final crate doesn't have MIR that
|
||||||
// reference unexported symbols
|
// reference unexported symbols
|
||||||
if callsite.callee.is_local() {
|
if callsite.callee.def_id().is_local() {
|
||||||
if callsite.substs.non_erasable_generics().count() == 0 && !hinted {
|
if callsite.callee.substs.non_erasable_generics().count() == 0 && !hinted {
|
||||||
debug!(" callee is an exported function - not inlining");
|
debug!(" callee is an exported function - not inlining");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -336,7 +337,7 @@ impl Inliner<'tcx> {
|
|||||||
work_list.push(target);
|
work_list.push(target);
|
||||||
// If the place doesn't actually need dropping, treat it like
|
// If the place doesn't actually need dropping, treat it like
|
||||||
// a regular goto.
|
// a regular goto.
|
||||||
let ty = place.ty(callee_body, tcx).subst(tcx, callsite.substs).ty;
|
let ty = place.ty(callee_body, tcx).subst(tcx, callsite.callee.substs).ty;
|
||||||
if ty.needs_drop(tcx, self.param_env) {
|
if ty.needs_drop(tcx, self.param_env) {
|
||||||
cost += CALL_PENALTY;
|
cost += CALL_PENALTY;
|
||||||
if let Some(unwind) = unwind {
|
if let Some(unwind) = unwind {
|
||||||
@ -399,7 +400,7 @@ impl Inliner<'tcx> {
|
|||||||
|
|
||||||
for v in callee_body.vars_and_temps_iter() {
|
for v in callee_body.vars_and_temps_iter() {
|
||||||
let v = &callee_body.local_decls[v];
|
let v = &callee_body.local_decls[v];
|
||||||
let ty = v.ty.subst(tcx, callsite.substs);
|
let ty = v.ty.subst(tcx, callsite.callee.substs);
|
||||||
// Cost of the var is the size in machine-words, if we know
|
// Cost of the var is the size in machine-words, if we know
|
||||||
// it.
|
// it.
|
||||||
if let Some(size) = type_size_of(tcx, self.param_env, ty) {
|
if let Some(size) = type_size_of(tcx, self.param_env, ty) {
|
||||||
@ -583,7 +584,9 @@ impl Inliner<'tcx> {
|
|||||||
// tmp2 = tuple_tmp.2
|
// tmp2 = tuple_tmp.2
|
||||||
//
|
//
|
||||||
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
|
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
|
||||||
if tcx.is_closure(callsite.callee) {
|
// FIXME(eddyb) make this check for `"rust-call"` ABI combined with
|
||||||
|
// `callee_body.spread_arg == None`, instead of special-casing closures.
|
||||||
|
if tcx.is_closure(callsite.callee.def_id()) {
|
||||||
let mut args = args.into_iter();
|
let mut args = args.into_iter();
|
||||||
let self_ = self.create_temp_if_necessary(
|
let self_ = self.create_temp_if_necessary(
|
||||||
args.next().unwrap(),
|
args.next().unwrap(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user