@@ -151,8 +151,7 @@ impl<'tcx> Inliner<'tcx> {
151
151
let callee_attrs = self . tcx . codegen_fn_attrs ( callsite. callee . def_id ( ) ) ;
152
152
self . check_codegen_attributes ( callsite, callee_attrs) ?;
153
153
self . check_mir_is_available ( caller_body, & callsite. callee ) ?;
154
- let callee_body = self . tcx . instance_mir ( callsite. callee . def ) ;
155
- self . check_mir_body ( callsite, callee_body, callee_attrs) ?;
154
+ let callee_body = self . check_mir_body ( callsite, callee_attrs) ?;
156
155
157
156
if !self . tcx . consider_optimizing ( || {
158
157
format ! ( "Inline {:?} into {:?}" , callsite. callee, caller_body. source)
@@ -385,43 +384,54 @@ impl<'tcx> Inliner<'tcx> {
385
384
386
385
/// Returns inlining decision that is based on the examination of callee MIR body.
387
386
/// Assumes that codegen attributes have been checked for compatibility already.
388
- #[ instrument( level = "debug" , skip( self , callee_body ) ) ]
387
+ #[ instrument( level = "debug" , skip( self ) ) ]
389
388
fn check_mir_body (
390
389
& self ,
391
390
callsite : & CallSite < ' tcx > ,
392
- callee_body : & Body < ' tcx > ,
393
391
callee_attrs : & CodegenFnAttrs ,
394
- ) -> Result < ( ) , & ' static str > {
395
- let cost_info = body_cost ( self . tcx , self . param_env , callee_body, |ty| {
396
- callsite. callee . subst_mir ( self . tcx , & ty)
397
- } ) ;
392
+ ) -> Result < & ' tcx Body < ' tcx > , & ' static str > {
393
+ if let InlineAttr :: Always = callee_attrs. inline {
394
+ debug ! ( "INLINING {:?} because inline(always)" , callsite, ) ;
395
+ let callee_body = self . tcx . instance_mir ( callsite. callee . def ) ;
396
+ return Ok ( callee_body) ;
397
+ }
398
398
399
399
let mut threshold = if callee_attrs. requests_inline ( ) {
400
400
self . tcx . sess . opts . unstable_opts . inline_mir_hint_threshold . unwrap_or ( 100 )
401
401
} else {
402
402
self . tcx . sess . opts . unstable_opts . inline_mir_threshold . unwrap_or ( 50 )
403
403
} ;
404
404
405
+ let callee_summary = self . tcx . instance_mir_summary ( callsite. callee . def ) ;
405
406
// Give a bonus functions with a small number of blocks,
406
407
// We normally have two or three blocks for even
407
408
// very small functions.
408
- if cost_info . bbcount <= 3 {
409
+ if callee_summary . bbcount <= 3 {
409
410
threshold += threshold / 4 ;
410
411
}
412
+ if callee_summary. diverges {
413
+ threshold = 0 ;
414
+ }
411
415
debug ! ( " final inline threshold = {}" , threshold) ;
412
416
413
- if cost_info. diverges {
414
- threshold = 0 ;
417
+ // Fast reject based on unsubstituted MIR.
418
+ if callee_summary. inlining_cost >= 2 * threshold {
419
+ return Err ( "summary cost above threshold" ) ;
415
420
}
416
421
422
+ let callee_body = self . tcx . instance_mir ( callsite. callee . def ) ;
423
+ let cost_info = body_cost ( self . tcx , self . param_env , callee_body, |ty| {
424
+ callsite. callee . subst_mir ( self . tcx , & ty)
425
+ } ) ;
426
+
417
427
let cost = cost_info. cost ;
418
428
419
429
if let InlineAttr :: Always = callee_attrs. inline {
420
430
debug ! ( "INLINING {:?} because inline(always) [cost={}]" , callsite, cost) ;
421
- Ok ( ( ) )
431
+ Ok ( callee_body )
422
432
} else if cost <= threshold {
423
433
debug ! ( "INLINING {:?} [cost={} <= threshold={}]" , callsite, cost, threshold) ;
424
- Ok ( ( ) )
434
+ Ok ( callee_body )
425
435
} else {
426
436
debug ! ( "NOT inlining {:?} [cost={} > threshold={}]" , callsite, cost, threshold) ;
427
437
Err ( "cost above threshold" )
0 commit comments