@@ -66,6 +66,7 @@ impl TempState {
6666/// A "root candidate" for promotion, which will become the
6767/// returned value in a promoted MIR, unless it's a subset
6868/// of a larger candidate.
69+ #[ derive( Debug ) ]
6970pub enum Candidate {
7071 /// Borrow of a constant temporary.
7172 Ref ( Location ) ,
@@ -190,15 +191,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
190191 /// promoted MIR, recursing through temps.
191192 fn promote_temp ( & mut self , temp : Local ) -> Local {
192193 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 => {
198196 if uses > 1 {
199197 self . keep_original = true ;
200198 }
201- ( block , statement_index )
199+ location
202200 }
203201 state => {
204202 span_bug ! ( self . promoted. span, "{:?} not promotable: {:?}" ,
@@ -209,91 +207,80 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
209207 self . temps [ temp] = TempState :: PromotedOut ;
210208 }
211209
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) ;
213216
214217 // First, take the Rvalue or Call out of the source MIR,
215218 // 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 )
225236 } ;
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 ) ;
237240 } 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+ } )
252256 }
253257 } ;
254- call = Some ( mem:: replace ( & mut terminator. kind , TerminatorKind :: Goto {
255- target : target
256- } ) ) ;
257- terminator. source_info
258- } ;
259258
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 {
280259 let last = self . promoted . basic_blocks ( ) . last ( ) . unwrap ( ) ;
281260 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+ }
286274 }
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+ } ;
293279
294- // Restore the old duplication state.
295- self . keep_original = old_keep_original ;
280+ * self . promoted [ last ] . terminator_mut ( ) = terminator ;
281+ } ;
296282
283+ self . keep_original = old_keep_original;
297284 new_temp
298285 }
299286
@@ -355,6 +342,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
355342 mut temps : IndexVec < Local , TempState > ,
356343 candidates : Vec < Candidate > ) {
357344 // Visit candidates in reverse, in case they're nested.
345+ debug ! ( "promote_candidates({:?})" , candidates) ;
358346 for candidate in candidates. into_iter ( ) . rev ( ) {
359347 let ( span, ty) = match candidate {
360348 Candidate :: Ref ( Location { block : bb, statement_index : stmt_idx } ) => {
0 commit comments