about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2020-10-22 00:00:00 +0000
committerTomasz Miąsko <tomasz.miasko@gmail.com>2020-10-26 10:33:45 +0100
commite1e48ae29b52d214f93d816e99056aacb102a90a (patch)
tree57886a9baf86fae3a9a264e4828b6ba90ede1bc6 /compiler
parenta6b64be8b51d680ca8185e519be81937c1a98ed0 (diff)
downloadrust-e1e48ae29b52d214f93d816e99056aacb102a90a.tar.gz
rust-e1e48ae29b52d214f93d816e99056aacb102a90a.zip
simplify-locals: Change RemoveStatements visitor into a function
No functionl changes intended.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_mir/src/transform/simplify.rs73
1 files changed, 31 insertions, 42 deletions
diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs
index f4ba297b570..f88156588e5 100644
--- a/compiler/rustc_mir/src/transform/simplify.rs
+++ b/compiler/rustc_mir/src/transform/simplify.rs
@@ -330,14 +330,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals {
         // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
         // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
         // fixedpoint where there are no more unused locals.
-        loop {
-            let mut remove_statements = RemoveStatements::new(&mut used_locals, tcx);
-            remove_statements.visit_body(body);
-
-            if !remove_statements.modified {
-                break;
-            }
-        }
+        remove_unused_definitions(&mut used_locals, body);
 
         // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s.
         let map = make_local_map(&mut body.local_decls, &used_locals);
@@ -487,44 +480,40 @@ impl Visitor<'_> for UsedLocals {
     }
 }
 
-struct RemoveStatements<'a, 'tcx> {
+/// Removes unused definitions. Updates the used locals to reflect the changes made.
+fn remove_unused_definitions<'a, 'tcx>(
     used_locals: &'a mut UsedLocals,
-    tcx: TyCtxt<'tcx>,
-    modified: bool,
-}
-
-impl<'a, 'tcx> RemoveStatements<'a, 'tcx> {
-    fn new(used_locals: &'a mut UsedLocals, tcx: TyCtxt<'tcx>) -> Self {
-        Self { used_locals, tcx, modified: false }
-    }
-}
-
-impl<'a, 'tcx> MutVisitor<'tcx> for RemoveStatements<'a, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
+    body: &mut Body<'tcx>,
+) {
+    // The use counts are updated as we remove the statements. A local might become unused
+    // during the retain operation, leading to a temporary inconsistency (storage statements or
+    // definitions referencing the local might remain). For correctness it is crucial that this
+    // computation reaches a fixed point.
+
+    let mut modified = true;
+    while modified {
+        modified = false;
+
+        for data in body.basic_blocks_mut() {
+            // Remove unnecessary StorageLive and StorageDead annotations.
+            data.statements.retain(|statement| {
+                let keep = match &statement.kind {
+                    StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
+                        used_locals.is_used(*local)
+                    }
+                    StatementKind::Assign(box (place, _)) => used_locals.is_used(place.local),
+                    _ => true,
+                };
 
-    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
-        // Remove unnecessary StorageLive and StorageDead annotations.
-        data.statements.retain(|statement| {
-            let keep = match &statement.kind {
-                StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
-                    self.used_locals.is_used(*local)
+                if !keep {
+                    trace!("removing statement {:?}", statement);
+                    modified = true;
+                    used_locals.statement_removed(statement);
                 }
-                StatementKind::Assign(box (place, _)) => self.used_locals.is_used(place.local),
-                _ => true,
-            };
-
-            if !keep {
-                trace!("removing statement {:?}", statement);
-                self.modified = true;
-                self.used_locals.statement_removed(statement);
-            }
 
-            keep
-        });
-
-        self.super_basic_block_data(block, data);
+                keep
+            });
+        }
     }
 }