1
1
//! Inlining pass for MIR functions
2
2
3
3
use rustc_attr as attr;
4
- use rustc_hir:: def_id:: DefId ;
5
4
use rustc_index:: bit_set:: BitSet ;
6
5
use rustc_index:: vec:: { Idx , IndexVec } ;
7
6
use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
8
7
use rustc_middle:: mir:: visit:: * ;
9
8
use rustc_middle:: mir:: * ;
10
- use rustc_middle:: ty:: subst:: { Subst , SubstsRef } ;
9
+ use rustc_middle:: ty:: subst:: Subst ;
11
10
use rustc_middle:: ty:: { self , ConstKind , Instance , InstanceDef , ParamEnv , Ty , TyCtxt } ;
12
11
use rustc_target:: spec:: abi:: Abi ;
13
12
@@ -30,8 +29,7 @@ pub struct Inline;
30
29
31
30
#[ derive( Copy , Clone , Debug ) ]
32
31
struct CallSite < ' tcx > {
33
- callee : DefId ,
34
- substs : SubstsRef < ' tcx > ,
32
+ callee : Instance < ' tcx > ,
35
33
bb : BasicBlock ,
36
34
source_info : SourceInfo ,
37
35
}
@@ -101,12 +99,18 @@ impl Inliner<'tcx> {
101
99
local_change = false ;
102
100
while let Some ( callsite) = callsites. pop_front ( ) {
103
101
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
+ }
107
111
}
108
112
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 ( ) {
110
114
let callee_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( callee_def_id) ;
111
115
// Avoid a cycle here by only using `optimized_mir` only if we have
112
116
// a lower `HirId` than the callee. This ensures that the callee will
@@ -119,19 +123,21 @@ impl Inliner<'tcx> {
119
123
&& self_hir_id < callee_hir_id
120
124
&& caller_body. generator_kind . is_none ( )
121
125
{
122
- self . tcx . optimized_mir ( callsite. callee )
126
+ self . tcx . instance_mir ( callsite. callee . def )
123
127
} else {
124
128
continue ;
125
129
}
126
130
} else {
127
131
// This cannot result in a cycle since the callee MIR is from another crate
128
132
// and is already optimized.
129
- self . tcx . optimized_mir ( callsite. callee )
133
+ self . tcx . instance_mir ( callsite. callee . def )
130
134
} ;
131
135
136
+ let callee_body: & Body < ' tcx > = & * callee_body;
137
+
132
138
let callee_body = if self . consider_optimizing ( callsite, callee_body) {
133
139
self . tcx . subst_and_normalize_erasing_regions (
134
- & callsite. substs ,
140
+ & callsite. callee . substs ,
135
141
self . param_env ,
136
142
callee_body,
137
143
)
@@ -204,21 +210,16 @@ impl Inliner<'tcx> {
204
210
// To resolve an instance its substs have to be fully normalized, so
205
211
// we do this here.
206
212
let normalized_substs = self . tcx . normalize_erasing_regions ( self . param_env , substs) ;
207
- let instance =
213
+ let callee =
208
214
Instance :: resolve ( self . tcx , self . param_env , callee_def_id, normalized_substs)
209
215
. ok ( )
210
216
. flatten ( ) ?;
211
217
212
- if let InstanceDef :: Virtual ( ..) = instance . def {
218
+ if let InstanceDef :: Virtual ( ..) | InstanceDef :: Intrinsic ( _ ) = callee . def {
213
219
return None ;
214
220
}
215
221
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 } ) ;
222
223
}
223
224
}
224
225
@@ -243,7 +244,7 @@ impl Inliner<'tcx> {
243
244
return false ;
244
245
}
245
246
246
- let codegen_fn_attrs = tcx. codegen_fn_attrs ( callsite. callee ) ;
247
+ let codegen_fn_attrs = tcx. codegen_fn_attrs ( callsite. callee . def_id ( ) ) ;
247
248
248
249
if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: TRACK_CALLER ) {
249
250
debug ! ( "`#[track_caller]` present - not inlining" ) ;
@@ -282,8 +283,8 @@ impl Inliner<'tcx> {
282
283
// Only inline local functions if they would be eligible for cross-crate
283
284
// inlining. This is to ensure that the final crate doesn't have MIR that
284
285
// 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 {
287
288
debug ! ( " callee is an exported function - not inlining" ) ;
288
289
return false ;
289
290
}
@@ -336,7 +337,7 @@ impl Inliner<'tcx> {
336
337
work_list. push ( target) ;
337
338
// If the place doesn't actually need dropping, treat it like
338
339
// 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 ;
340
341
if ty. needs_drop ( tcx, self . param_env ) {
341
342
cost += CALL_PENALTY ;
342
343
if let Some ( unwind) = unwind {
@@ -399,7 +400,7 @@ impl Inliner<'tcx> {
399
400
400
401
for v in callee_body. vars_and_temps_iter ( ) {
401
402
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 ) ;
403
404
// Cost of the var is the size in machine-words, if we know
404
405
// it.
405
406
if let Some ( size) = type_size_of ( tcx, self . param_env , ty) {
@@ -583,7 +584,9 @@ impl Inliner<'tcx> {
583
584
// tmp2 = tuple_tmp.2
584
585
//
585
586
// 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 ( ) ) {
587
590
let mut args = args. into_iter ( ) ;
588
591
let self_ = self . create_temp_if_necessary (
589
592
args. next ( ) . unwrap ( ) ,
0 commit comments