@@ -330,14 +330,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals {
330
330
// count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
331
331
// `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
332
332
// fixedpoint where there are no more unused locals.
333
- loop {
334
- let mut remove_statements = RemoveStatements :: new ( & mut used_locals, tcx) ;
335
- remove_statements. visit_body ( body) ;
336
-
337
- if !remove_statements. modified {
338
- break ;
339
- }
340
- }
333
+ remove_unused_definitions ( & mut used_locals, body) ;
341
334
342
335
// Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s.
343
336
let map = make_local_map ( & mut body. local_decls , & used_locals) ;
@@ -487,44 +480,40 @@ impl Visitor<'_> for UsedLocals {
487
480
}
488
481
}
489
482
490
- struct RemoveStatements < ' a , ' tcx > {
483
+ /// Removes unused definitions. Updates the used locals to reflect the changes made.
484
+ fn remove_unused_definitions < ' a , ' tcx > (
491
485
used_locals : & ' a mut UsedLocals ,
492
- tcx : TyCtxt < ' tcx > ,
493
- modified : bool ,
494
- }
495
-
496
- impl < ' a , ' tcx > RemoveStatements < ' a , ' tcx > {
497
- fn new ( used_locals : & ' a mut UsedLocals , tcx : TyCtxt < ' tcx > ) -> Self {
498
- Self { used_locals, tcx, modified : false }
499
- }
500
- }
501
-
502
- impl < ' a , ' tcx > MutVisitor < ' tcx > for RemoveStatements < ' a , ' tcx > {
503
- fn tcx ( & self ) -> TyCtxt < ' tcx > {
504
- self . tcx
505
- }
486
+ body : & mut Body < ' tcx > ,
487
+ ) {
488
+ // The use counts are updated as we remove the statements. A local might become unused
489
+ // during the retain operation, leading to a temporary inconsistency (storage statements or
490
+ // definitions referencing the local might remain). For correctness it is crucial that this
491
+ // computation reaches a fixed point.
492
+
493
+ let mut modified = true ;
494
+ while modified {
495
+ modified = false ;
496
+
497
+ for data in body. basic_blocks_mut ( ) {
498
+ // Remove unnecessary StorageLive and StorageDead annotations.
499
+ data. statements . retain ( |statement| {
500
+ let keep = match & statement. kind {
501
+ StatementKind :: StorageLive ( local) | StatementKind :: StorageDead ( local) => {
502
+ used_locals. is_used ( * local)
503
+ }
504
+ StatementKind :: Assign ( box ( place, _) ) => used_locals. is_used ( place. local ) ,
505
+ _ => true ,
506
+ } ;
506
507
507
- fn visit_basic_block_data ( & mut self , block : BasicBlock , data : & mut BasicBlockData < ' tcx > ) {
508
- // Remove unnecessary StorageLive and StorageDead annotations.
509
- data. statements . retain ( |statement| {
510
- let keep = match & statement. kind {
511
- StatementKind :: StorageLive ( local) | StatementKind :: StorageDead ( local) => {
512
- self . used_locals . is_used ( * local)
508
+ if !keep {
509
+ trace ! ( "removing statement {:?}" , statement) ;
510
+ modified = true ;
511
+ used_locals. statement_removed ( statement) ;
513
512
}
514
- StatementKind :: Assign ( box ( place, _) ) => self . used_locals . is_used ( place. local ) ,
515
- _ => true ,
516
- } ;
517
-
518
- if !keep {
519
- trace ! ( "removing statement {:?}" , statement) ;
520
- self . modified = true ;
521
- self . used_locals . statement_removed ( statement) ;
522
- }
523
513
524
- keep
525
- } ) ;
526
-
527
- self . super_basic_block_data ( block, data) ;
514
+ keep
515
+ } ) ;
516
+ }
528
517
}
529
518
}
530
519
0 commit comments