11//! Inlining pass for MIR functions
22
33use rustc_attr as attr;
4- use rustc_hir:: def_id:: DefId ;
54use rustc_index:: bit_set:: BitSet ;
65use rustc_index:: vec:: { Idx , IndexVec } ;
76use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
87use rustc_middle:: mir:: visit:: * ;
98use rustc_middle:: mir:: * ;
10- use rustc_middle:: ty:: subst:: { Subst , SubstsRef } ;
9+ use rustc_middle:: ty:: subst:: Subst ;
1110use rustc_middle:: ty:: { self , ConstKind , Instance , InstanceDef , ParamEnv , Ty , TyCtxt } ;
1211use rustc_target:: spec:: abi:: Abi ;
1312
@@ -30,8 +29,7 @@ pub struct Inline;
3029
3130#[ derive( Copy , Clone , Debug ) ]
3231struct CallSite < ' tcx > {
33- callee : DefId ,
34- substs : SubstsRef < ' tcx > ,
32+ callee : Instance < ' tcx > ,
3533 bb : BasicBlock ,
3634 source_info : SourceInfo ,
3735}
@@ -101,12 +99,18 @@ impl Inliner<'tcx> {
10199 local_change = false ;
102100 while let Some ( callsite) = callsites. pop_front ( ) {
103101 debug ! ( "checking whether to inline callsite {:?}" , callsite) ;
104- if !self . tcx . is_mir_available ( callsite. callee ) {
105- debug ! ( "checking whether to inline callsite {:?} - MIR unavailable" , callsite) ;
106- continue ;
102+
103+ if let InstanceDef :: Item ( _) = callsite. callee . def {
104+ if !self . tcx . is_mir_available ( callsite. callee . def_id ( ) ) {
105+ debug ! (
106+ "checking whether to inline callsite {:?} - MIR unavailable" ,
107+ callsite,
108+ ) ;
109+ continue ;
110+ }
107111 }
108112
109- let callee_body = if let Some ( callee_def_id) = callsite. callee . as_local ( ) {
113+ let callee_body = if let Some ( callee_def_id) = callsite. callee . def_id ( ) . as_local ( ) {
110114 let callee_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( callee_def_id) ;
111115 // Avoid a cycle here by only using `optimized_mir` only if we have
112116 // a lower `HirId` than the callee. This ensures that the callee will
@@ -119,19 +123,21 @@ impl Inliner<'tcx> {
119123 && self_hir_id < callee_hir_id
120124 && caller_body. generator_kind . is_none ( )
121125 {
122- self . tcx . optimized_mir ( callsite. callee )
126+ self . tcx . instance_mir ( callsite. callee . def )
123127 } else {
124128 continue ;
125129 }
126130 } else {
127131 // This cannot result in a cycle since the callee MIR is from another crate
128132 // and is already optimized.
129- self . tcx . optimized_mir ( callsite. callee )
133+ self . tcx . instance_mir ( callsite. callee . def )
130134 } ;
131135
136+ let callee_body: & Body < ' tcx > = & * callee_body;
137+
132138 let callee_body = if self . consider_optimizing ( callsite, callee_body) {
133139 self . tcx . subst_and_normalize_erasing_regions (
134- & callsite. substs ,
140+ & callsite. callee . substs ,
135141 self . param_env ,
136142 callee_body,
137143 )
@@ -204,21 +210,16 @@ impl Inliner<'tcx> {
204210 // To resolve an instance its substs have to be fully normalized, so
205211 // we do this here.
206212 let normalized_substs = self . tcx . normalize_erasing_regions ( self . param_env , substs) ;
207- let instance =
213+ let callee =
208214 Instance :: resolve ( self . tcx , self . param_env , callee_def_id, normalized_substs)
209215 . ok ( )
210216 . flatten ( ) ?;
211217
212- if let InstanceDef :: Virtual ( ..) = instance . def {
218+ if let InstanceDef :: Virtual ( ..) | InstanceDef :: Intrinsic ( _ ) = callee . def {
213219 return None ;
214220 }
215221
216- return Some ( CallSite {
217- callee : instance. def_id ( ) ,
218- substs : instance. substs ,
219- bb,
220- source_info : terminator. source_info ,
221- } ) ;
222+ return Some ( CallSite { callee, bb, source_info : terminator. source_info } ) ;
222223 }
223224 }
224225
@@ -243,7 +244,7 @@ impl Inliner<'tcx> {
243244 return false ;
244245 }
245246
246- let codegen_fn_attrs = tcx. codegen_fn_attrs ( callsite. callee ) ;
247+ let codegen_fn_attrs = tcx. codegen_fn_attrs ( callsite. callee . def_id ( ) ) ;
247248
248249 if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: TRACK_CALLER ) {
249250 debug ! ( "`#[track_caller]` present - not inlining" ) ;
@@ -282,8 +283,8 @@ impl Inliner<'tcx> {
282283 // Only inline local functions if they would be eligible for cross-crate
283284 // inlining. This is to ensure that the final crate doesn't have MIR that
284285 // reference unexported symbols
285- if callsite. callee . is_local ( ) {
286- if callsite. substs . non_erasable_generics ( ) . count ( ) == 0 && !hinted {
286+ if callsite. callee . def_id ( ) . is_local ( ) {
287+ if callsite. callee . substs . non_erasable_generics ( ) . count ( ) == 0 && !hinted {
287288 debug ! ( " callee is an exported function - not inlining" ) ;
288289 return false ;
289290 }
@@ -336,7 +337,7 @@ impl Inliner<'tcx> {
336337 work_list. push ( target) ;
337338 // If the place doesn't actually need dropping, treat it like
338339 // a regular goto.
339- let ty = place. ty ( callee_body, tcx) . subst ( tcx, callsite. substs ) . ty ;
340+ let ty = place. ty ( callee_body, tcx) . subst ( tcx, callsite. callee . substs ) . ty ;
340341 if ty. needs_drop ( tcx, self . param_env ) {
341342 cost += CALL_PENALTY ;
342343 if let Some ( unwind) = unwind {
@@ -399,7 +400,7 @@ impl Inliner<'tcx> {
399400
400401 for v in callee_body. vars_and_temps_iter ( ) {
401402 let v = & callee_body. local_decls [ v] ;
402- let ty = v. ty . subst ( tcx, callsite. substs ) ;
403+ let ty = v. ty . subst ( tcx, callsite. callee . substs ) ;
403404 // Cost of the var is the size in machine-words, if we know
404405 // it.
405406 if let Some ( size) = type_size_of ( tcx, self . param_env , ty) {
@@ -583,7 +584,9 @@ impl Inliner<'tcx> {
583584 // tmp2 = tuple_tmp.2
584585 //
585586 // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
586- if tcx. is_closure ( callsite. callee ) {
587+ // FIXME(eddyb) make this check for `"rust-call"` ABI combined with
588+ // `callee_body.spread_arg == None`, instead of special-casing closures.
589+ if tcx. is_closure ( callsite. callee . def_id ( ) ) {
587590 let mut args = args. into_iter ( ) ;
588591 let self_ = self . create_temp_if_necessary (
589592 args. next ( ) . unwrap ( ) ,
0 commit comments