@@ -151,8 +151,7 @@ impl<'tcx> Inliner<'tcx> {
151151 let callee_attrs = self . tcx . codegen_fn_attrs ( callsite. callee . def_id ( ) ) ;
152152 self . check_codegen_attributes ( callsite, callee_attrs) ?;
153153 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) ?;
156155
157156 if !self . tcx . consider_optimizing ( || {
158157 format ! ( "Inline {:?} into {:?}" , callsite. callee, caller_body. source)
@@ -385,43 +384,54 @@ impl<'tcx> Inliner<'tcx> {
385384
386385 /// Returns inlining decision that is based on the examination of callee MIR body.
387386 /// Assumes that codegen attributes have been checked for compatibility already.
388- #[ instrument( level = "debug" , skip( self , callee_body ) ) ]
387+ #[ instrument( level = "debug" , skip( self ) ) ]
389388 fn check_mir_body (
390389 & self ,
391390 callsite : & CallSite < ' tcx > ,
392- callee_body : & Body < ' tcx > ,
393391 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+ }
398398
399399 let mut threshold = if callee_attrs. requests_inline ( ) {
400400 self . tcx . sess . opts . unstable_opts . inline_mir_hint_threshold . unwrap_or ( 100 )
401401 } else {
402402 self . tcx . sess . opts . unstable_opts . inline_mir_threshold . unwrap_or ( 50 )
403403 } ;
404404
405+ let callee_summary = self . tcx . instance_mir_summary ( callsite. callee . def ) ;
405406 // Give a bonus functions with a small number of blocks,
406407 // We normally have two or three blocks for even
407408 // very small functions.
408- if cost_info . bbcount <= 3 {
409+ if callee_summary . bbcount <= 3 {
409410 threshold += threshold / 4 ;
410411 }
412+ if callee_summary. diverges {
413+ threshold = 0 ;
414+ }
411415 debug ! ( " final inline threshold = {}" , threshold) ;
412416
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" ) ;
415420 }
416421
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+
417427 let cost = cost_info. cost ;
418428
419429 if let InlineAttr :: Always = callee_attrs. inline {
420430 debug ! ( "INLINING {:?} because inline(always) [cost={}]" , callsite, cost) ;
421- Ok ( ( ) )
431+ Ok ( callee_body )
422432 } else if cost <= threshold {
423433 debug ! ( "INLINING {:?} [cost={} <= threshold={}]" , callsite, cost, threshold) ;
424- Ok ( ( ) )
434+ Ok ( callee_body )
425435 } else {
426436 debug ! ( "NOT inlining {:?} [cost={} > threshold={}]" , callsite, cost, threshold) ;
427437 Err ( "cost above threshold" )
0 commit comments