@@ -93,96 +93,79 @@ impl Inliner<'tcx> {
9393 return ;
9494 }
9595
96- let mut local_change;
9796 let mut changed = false ;
97+ while let Some ( callsite) = callsites. pop_front ( ) {
98+ debug ! ( "checking whether to inline callsite {:?}" , callsite) ;
9899
99- loop {
100- local_change = false ;
101- while let Some ( callsite) = callsites. pop_front ( ) {
102- debug ! ( "checking whether to inline callsite {:?}" , callsite) ;
103-
104- if let InstanceDef :: Item ( _) = callsite. callee . def {
105- if !self . tcx . is_mir_available ( callsite. callee . def_id ( ) ) {
106- debug ! (
107- "checking whether to inline callsite {:?} - MIR unavailable" ,
108- callsite,
109- ) ;
110- continue ;
111- }
100+ if let InstanceDef :: Item ( _) = callsite. callee . def {
101+ if !self . tcx . is_mir_available ( callsite. callee . def_id ( ) ) {
102+ debug ! ( "checking whether to inline callsite {:?} - MIR unavailable" , callsite, ) ;
103+ continue ;
112104 }
105+ }
113106
114- let callee_body = if let Some ( callee_def_id) = callsite. callee . def_id ( ) . as_local ( ) {
115- let callee_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( callee_def_id) ;
116- // Avoid a cycle here by only using `instance_mir` only if we have
117- // a lower `HirId` than the callee. This ensures that the callee will
118- // not inline us. This trick only works without incremental compilation.
119- // So don't do it if that is enabled. Also avoid inlining into generators,
120- // since their `optimized_mir` is used for layout computation, which can
121- // create a cycle, even when no attempt is made to inline the function
122- // in the other direction.
123- if !self . tcx . dep_graph . is_fully_enabled ( )
124- && self_hir_id < callee_hir_id
125- && caller_body. generator_kind . is_none ( )
126- {
127- self . tcx . instance_mir ( callsite. callee . def )
128- } else {
129- continue ;
130- }
131- } else {
132- // This cannot result in a cycle since the callee MIR is from another crate
133- // and is already optimized.
107+ let callee_body = if let Some ( callee_def_id) = callsite. callee . def_id ( ) . as_local ( ) {
108+ let callee_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( callee_def_id) ;
109+ // Avoid a cycle here by only using `instance_mir` only if we have
110+ // a lower `HirId` than the callee. This ensures that the callee will
111+ // not inline us. This trick only works without incremental compilation.
112+ // So don't do it if that is enabled. Also avoid inlining into generators,
113+ // since their `optimized_mir` is used for layout computation, which can
114+ // create a cycle, even when no attempt is made to inline the function
115+ // in the other direction.
116+ if !self . tcx . dep_graph . is_fully_enabled ( )
117+ && self_hir_id < callee_hir_id
118+ && caller_body. generator_kind . is_none ( )
119+ {
134120 self . tcx . instance_mir ( callsite. callee . def )
135- } ;
136-
137- let callee_body: & Body < ' tcx > = & * callee_body;
138-
139- let callee_body = if self . consider_optimizing ( callsite, callee_body) {
140- self . tcx . subst_and_normalize_erasing_regions (
141- & callsite. callee . substs ,
142- self . param_env ,
143- callee_body,
144- )
145121 } else {
146122 continue ;
147- } ;
123+ }
124+ } else {
125+ // This cannot result in a cycle since the callee MIR is from another crate
126+ // and is already optimized.
127+ self . tcx . instance_mir ( callsite. callee . def )
128+ } ;
148129
149- // Copy only unevaluated constants from the callee_body into the caller_body.
150- // Although we are only pushing `ConstKind::Unevaluated` consts to
151- // `required_consts`, here we may not only have `ConstKind::Unevaluated`
152- // because we are calling `subst_and_normalize_erasing_regions`.
153- caller_body. required_consts . extend (
154- callee_body. required_consts . iter ( ) . copied ( ) . filter ( |& constant| {
155- matches ! ( constant. literal. val, ConstKind :: Unevaluated ( _, _, _) )
156- } ) ,
157- ) ;
130+ let callee_body: & Body < ' tcx > = & * callee_body;
158131
159- let start = caller_body. basic_blocks ( ) . len ( ) ;
160- debug ! ( "attempting to inline callsite {:?} - body={:?}" , callsite, callee_body) ;
161- if !self . inline_call ( callsite, caller_body, callee_body) {
162- debug ! ( "attempting to inline callsite {:?} - failure" , callsite) ;
163- continue ;
164- }
165- debug ! ( "attempting to inline callsite {:?} - success" , callsite) ;
166-
167- // Add callsites from inlined function
168- for ( bb, bb_data) in caller_body. basic_blocks ( ) . iter_enumerated ( ) . skip ( start) {
169- if let Some ( new_callsite) =
170- self . get_valid_function_call ( bb, bb_data, caller_body)
171- {
172- // Don't inline the same function multiple times.
173- if callsite. callee != new_callsite. callee {
174- callsites. push_back ( new_callsite) ;
175- }
132+ let callee_body = if self . consider_optimizing ( callsite, callee_body) {
133+ self . tcx . subst_and_normalize_erasing_regions (
134+ & callsite. callee . substs ,
135+ self . param_env ,
136+ callee_body,
137+ )
138+ } else {
139+ continue ;
140+ } ;
141+
142+ // Copy only unevaluated constants from the callee_body into the caller_body.
143+ // Although we are only pushing `ConstKind::Unevaluated` consts to
144+ // `required_consts`, here we may not only have `ConstKind::Unevaluated`
145+ // because we are calling `subst_and_normalize_erasing_regions`.
146+ caller_body. required_consts . extend ( callee_body. required_consts . iter ( ) . copied ( ) . filter (
147+ |& constant| matches ! ( constant. literal. val, ConstKind :: Unevaluated ( _, _, _) ) ,
148+ ) ) ;
149+
150+ let start = caller_body. basic_blocks ( ) . len ( ) ;
151+ debug ! ( "attempting to inline callsite {:?} - body={:?}" , callsite, callee_body) ;
152+ if !self . inline_call ( callsite, caller_body, callee_body) {
153+ debug ! ( "attempting to inline callsite {:?} - failure" , callsite) ;
154+ continue ;
155+ }
156+ debug ! ( "attempting to inline callsite {:?} - success" , callsite) ;
157+
158+ // Add callsites from inlined function
159+ for ( bb, bb_data) in caller_body. basic_blocks ( ) . iter_enumerated ( ) . skip ( start) {
160+ if let Some ( new_callsite) = self . get_valid_function_call ( bb, bb_data, caller_body) {
161+ // Don't inline the same function multiple times.
162+ if callsite. callee != new_callsite. callee {
163+ callsites. push_back ( new_callsite) ;
176164 }
177165 }
178-
179- local_change = true ;
180- changed = true ;
181166 }
182167
183- if !local_change {
184- break ;
185- }
168+ changed = true ;
186169 }
187170
188171 // Simplify if we inlined anything.
0 commit comments