about summary refs log tree commit diff
path: root/compiler/rustc_middle/src/mir/traversal.rs
diff options
context:
space:
mode:
authorBen Kimock <kimockb@gmail.com>2024-08-19 19:04:43 -0400
committerBen Kimock <kimockb@gmail.com>2024-09-21 01:06:59 -0400
commit0ea5dc506f50cf8e2732c715878ecf09ea0db480 (patch)
treefbd70826c455558345b87f836adff155fae93cc9 /compiler/rustc_middle/src/mir/traversal.rs
parent5ba6db1b648d93fbbab4ae0466e40db682fa45fc (diff)
downloadrust-0ea5dc506f50cf8e2732c715878ecf09ea0db480.tar.gz
rust-0ea5dc506f50cf8e2732c715878ecf09ea0db480.zip
Don't alloca for unused locals
Diffstat (limited to 'compiler/rustc_middle/src/mir/traversal.rs')
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs95
1 files changed, 87 insertions, 8 deletions
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 245e9096bad..1d55a38f30b 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -1,4 +1,5 @@
 use super::*;
+use crate::mir::visit::Visitor;
 
 /// Preorder traversal of a graph.
 ///
@@ -232,6 +233,90 @@ pub fn postorder<'a, 'tcx>(
     reverse_postorder(body).rev()
 }
 
+struct UsedLocals(BitSet<Local>);
+
+impl<'tcx> Visitor<'tcx> for UsedLocals {
+    fn visit_local(
+        &mut self,
+        local: Local,
+        _ctx: crate::mir::visit::PlaceContext,
+        _location: Location,
+    ) {
+        self.0.insert(local);
+    }
+}
+
+struct MonoReachablePostorder<'a, 'tcx> {
+    basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
+    visited: BitSet<BasicBlock>,
+    visit_stack: Vec<(BasicBlock, Successors<'a>)>,
+    locals: UsedLocals,
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+}
+
+impl<'a, 'tcx> MonoReachablePostorder<'a, 'tcx> {
+    fn new(
+        body: &'a Body<'tcx>,
+        tcx: TyCtxt<'tcx>,
+        instance: Instance<'tcx>,
+    ) -> MonoReachablePostorder<'a, 'tcx> {
+        let basic_blocks = &body.basic_blocks;
+        let mut po = MonoReachablePostorder {
+            basic_blocks,
+            visited: BitSet::new_empty(basic_blocks.len()),
+            visit_stack: Vec::new(),
+            locals: UsedLocals(BitSet::new_empty(body.local_decls.len())),
+            tcx,
+            instance,
+        };
+
+        po.visit(START_BLOCK);
+        po.traverse_successor();
+        po
+    }
+
+    fn visit(&mut self, bb: BasicBlock) {
+        if !self.visited.insert(bb) {
+            return;
+        }
+        let data = &self.basic_blocks[bb];
+        self.locals.visit_basic_block_data(bb, data);
+        let successors = data.mono_successors(self.tcx, self.instance);
+        self.visit_stack.push((bb, successors));
+    }
+
+    fn traverse_successor(&mut self) {
+        while let Some(bb) = self.visit_stack.last_mut().and_then(|(_, iter)| iter.next_back()) {
+            self.visit(bb);
+        }
+    }
+}
+
+impl<'tcx> Iterator for MonoReachablePostorder<'_, 'tcx> {
+    type Item = BasicBlock;
+
+    fn next(&mut self) -> Option<BasicBlock> {
+        let (bb, _) = self.visit_stack.pop()?;
+        self.traverse_successor();
+        Some(bb)
+    }
+}
+
+pub fn mono_reachable_reverse_postorder<'a, 'tcx>(
+    body: &'a Body<'tcx>,
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+) -> (Vec<BasicBlock>, BitSet<Local>) {
+    let mut iter = MonoReachablePostorder::new(body, tcx, instance);
+    let mut items = Vec::with_capacity(body.basic_blocks.len());
+    while let Some(block) = iter.next() {
+        items.push(block);
+    }
+    items.reverse();
+    (items, iter.locals.0)
+}
+
 /// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular
 /// order.
 ///
@@ -358,14 +443,8 @@ impl<'a, 'tcx> Iterator for MonoReachable<'a, 'tcx> {
 
             let data = &self.body[idx];
 
-            if let Some((bits, targets)) =
-                Body::try_const_mono_switchint(self.tcx, self.instance, data)
-            {
-                let target = targets.target_for_value(bits);
-                self.add_work([target]);
-            } else {
-                self.add_work(data.terminator().successors());
-            }
+            let targets = data.mono_successors(self.tcx, self.instance);
+            self.add_work(targets);
 
             return Some((idx, data));
         }