@@ -66,6 +66,7 @@ impl TempState {
66
66
/// A "root candidate" for promotion, which will become the
67
67
/// returned value in a promoted MIR, unless it's a subset
68
68
/// of a larger candidate.
69
+ #[ derive( Debug ) ]
69
70
pub enum Candidate {
70
71
/// Borrow of a constant temporary.
71
72
Ref ( Location ) ,
@@ -190,15 +191,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
190
191
/// promoted MIR, recursing through temps.
191
192
fn promote_temp ( & mut self , temp : Local ) -> Local {
192
193
let old_keep_original = self . keep_original ;
193
- let ( bb, stmt_idx) = match self . temps [ temp] {
194
- TempState :: Defined {
195
- location : Location { block, statement_index } ,
196
- uses
197
- } if uses > 0 => {
194
+ let loc = match self . temps [ temp] {
195
+ TempState :: Defined { location, uses } if uses > 0 => {
198
196
if uses > 1 {
199
197
self . keep_original = true ;
200
198
}
201
- ( block , statement_index )
199
+ location
202
200
}
203
201
state => {
204
202
span_bug ! ( self . promoted. span, "{:?} not promotable: {:?}" ,
@@ -209,91 +207,80 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
209
207
self . temps [ temp] = TempState :: PromotedOut ;
210
208
}
211
209
212
- let no_stmts = self . source [ bb] . statements . len ( ) ;
210
+ let no_stmts = self . source [ loc. block ] . statements . len ( ) ;
211
+ let new_temp = self . promoted . local_decls . push (
212
+ LocalDecl :: new_temp ( self . source . local_decls [ temp] . ty ) ) ;
213
+
214
+ debug ! ( "promote({:?} @ {:?}/{:?}, {:?})" ,
215
+ temp, loc, no_stmts, self . keep_original) ;
213
216
214
217
// First, take the Rvalue or Call out of the source MIR,
215
218
// or duplicate it, depending on keep_original.
216
- let ( mut rvalue, mut call) = ( None , None ) ;
217
- let source_info = if stmt_idx < no_stmts {
218
- let statement = & mut self . source [ bb] . statements [ stmt_idx] ;
219
- let rhs = match statement. kind {
220
- StatementKind :: Assign ( _, ref mut rhs) => rhs,
221
- _ => {
222
- span_bug ! ( statement. source_info. span, "{:?} is not an assignment" ,
223
- statement) ;
224
- }
219
+ if loc. statement_index < no_stmts {
220
+ let ( mut rvalue, source_info) = {
221
+ let statement = & mut self . source [ loc. block ] . statements [ loc. statement_index ] ;
222
+ let rhs = match statement. kind {
223
+ StatementKind :: Assign ( _, ref mut rhs) => rhs,
224
+ _ => {
225
+ span_bug ! ( statement. source_info. span, "{:?} is not an assignment" ,
226
+ statement) ;
227
+ }
228
+ } ;
229
+
230
+ ( if self . keep_original {
231
+ rhs. clone ( )
232
+ } else {
233
+ let unit = Rvalue :: Aggregate ( AggregateKind :: Tuple , vec ! [ ] ) ;
234
+ mem:: replace ( rhs, unit)
235
+ } , statement. source_info )
225
236
} ;
226
- if self . keep_original {
227
- rvalue = Some ( rhs. clone ( ) ) ;
228
- } else {
229
- let unit = Rvalue :: Aggregate ( AggregateKind :: Tuple , vec ! [ ] ) ;
230
- rvalue = Some ( mem:: replace ( rhs, unit) ) ;
231
- }
232
- statement. source_info
233
- } else if self . keep_original {
234
- let terminator = self . source [ bb] . terminator ( ) . clone ( ) ;
235
- call = Some ( terminator. kind ) ;
236
- terminator. source_info
237
+
238
+ self . visit_rvalue ( & mut rvalue, loc) ;
239
+ self . assign ( new_temp, rvalue, source_info. span ) ;
237
240
} else {
238
- let terminator = self . source [ bb] . terminator_mut ( ) ;
239
- let target = match terminator. kind {
240
- TerminatorKind :: Call {
241
- destination : ref mut dest @ Some ( _) ,
242
- ref mut cleanup, ..
243
- } => {
244
- // No cleanup necessary.
245
- cleanup. take ( ) ;
246
-
247
- // We'll put a new destination in later.
248
- dest. take ( ) . unwrap ( ) . 1
249
- }
250
- ref kind => {
251
- span_bug ! ( terminator. source_info. span, "{:?} not promotable" , kind) ;
241
+ let mut terminator = if self . keep_original {
242
+ self . source [ loc. block ] . terminator ( ) . clone ( )
243
+ } else {
244
+ let terminator = self . source [ loc. block ] . terminator_mut ( ) ;
245
+ let target = match terminator. kind {
246
+ TerminatorKind :: Call { destination : Some ( ( _, target) ) , .. } => target,
247
+ ref kind => {
248
+ span_bug ! ( terminator. source_info. span, "{:?} not promotable" , kind) ;
249
+ }
250
+ } ;
251
+ Terminator {
252
+ source_info : terminator. source_info ,
253
+ kind : mem:: replace ( & mut terminator. kind , TerminatorKind :: Goto {
254
+ target : target
255
+ } )
252
256
}
253
257
} ;
254
- call = Some ( mem:: replace ( & mut terminator. kind , TerminatorKind :: Goto {
255
- target : target
256
- } ) ) ;
257
- terminator. source_info
258
- } ;
259
258
260
- // Then, recurse for components in the Rvalue or Call.
261
- if stmt_idx < no_stmts {
262
- self . visit_rvalue ( rvalue. as_mut ( ) . unwrap ( ) , Location {
263
- block : bb,
264
- statement_index : stmt_idx
265
- } ) ;
266
- } else {
267
- self . visit_terminator_kind ( bb, call. as_mut ( ) . unwrap ( ) , Location {
268
- block : bb,
269
- statement_index : no_stmts
270
- } ) ;
271
- }
272
-
273
- let new_temp = self . promoted . local_decls . push (
274
- LocalDecl :: new_temp ( self . source . local_decls [ temp] . ty ) ) ;
275
-
276
- // Inject the Rvalue or Call into the promoted MIR.
277
- if stmt_idx < no_stmts {
278
- self . assign ( new_temp, rvalue. unwrap ( ) , source_info. span ) ;
279
- } else {
280
259
let last = self . promoted . basic_blocks ( ) . last ( ) . unwrap ( ) ;
281
260
let new_target = self . new_block ( ) ;
282
- let mut call = call. unwrap ( ) ;
283
- match call {
284
- TerminatorKind :: Call { ref mut destination, ..} => {
285
- * destination = Some ( ( Lvalue :: Local ( new_temp) , new_target) ) ;
261
+
262
+ terminator. kind = match terminator. kind {
263
+ TerminatorKind :: Call { mut func, mut args, .. } => {
264
+ self . visit_operand ( & mut func, loc) ;
265
+ for arg in & mut args {
266
+ self . visit_operand ( arg, loc) ;
267
+ }
268
+ TerminatorKind :: Call {
269
+ func : func,
270
+ args : args,
271
+ cleanup : None ,
272
+ destination : Some ( ( Lvalue :: Local ( new_temp) , new_target) )
273
+ }
286
274
}
287
- _ => bug ! ( )
288
- }
289
- let terminator = self . promoted [ last] . terminator_mut ( ) ;
290
- terminator. source_info . span = source_info. span ;
291
- terminator. kind = call;
292
- }
275
+ ref kind => {
276
+ span_bug ! ( terminator. source_info. span, "{:?} not promotable" , kind) ;
277
+ }
278
+ } ;
293
279
294
- // Restore the old duplication state.
295
- self . keep_original = old_keep_original ;
280
+ * self . promoted [ last ] . terminator_mut ( ) = terminator ;
281
+ } ;
296
282
283
+ self . keep_original = old_keep_original;
297
284
new_temp
298
285
}
299
286
@@ -355,6 +342,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
355
342
mut temps : IndexVec < Local , TempState > ,
356
343
candidates : Vec < Candidate > ) {
357
344
// Visit candidates in reverse, in case they're nested.
345
+ debug ! ( "promote_candidates({:?})" , candidates) ;
358
346
for candidate in candidates. into_iter ( ) . rev ( ) {
359
347
let ( span, ty) = match candidate {
360
348
Candidate :: Ref ( Location { block : bb, statement_index : stmt_idx } ) => {
0 commit comments