about summary refs log tree commit diff
path: root/compiler/rustc_middle/src/mir/traversal.rs
diff options
context:
space:
mode:
authorRémy Rakic <remy.rakic+github@gmail.com>2023-06-14 20:00:23 +0000
committerRémy Rakic <remy.rakic+github@gmail.com>2023-06-14 23:01:36 +0000
commit0b4b0869a7968a2612c9bd93019a021ce168c557 (patch)
treea24bb47f52b32279152058dfd84d813eb58c28c6 /compiler/rustc_middle/src/mir/traversal.rs
parent0eec39b67d12d121095a1da4e24109ce4dc41054 (diff)
downloadrust-0b4b0869a7968a2612c9bd93019a021ce168c557.tar.gz
rust-0b4b0869a7968a2612c9bd93019a021ce168c557.zip
make `traversal::postorder` traverse RPO cache backwards
Diffstat (limited to 'compiler/rustc_middle/src/mir/traversal.rs')
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs40
1 files changed, 36 insertions, 4 deletions
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 780003f5fa0..6d44234d11f 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -188,10 +188,6 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
     }
 }
 
-pub fn postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> Postorder<'a, 'tcx> {
-    Postorder::new(&body.basic_blocks, START_BLOCK)
-}
-
 impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
     type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
 
@@ -219,6 +215,42 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
     }
 }
 
+/// Creates an iterator over the `Body`'s basic blocks, that:
+/// - returns basic blocks in a postorder,
+/// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the
+///   postorder itself.
+pub fn postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> PostorderIter<'a, 'tcx> {
+    let blocks = body.basic_blocks.reverse_postorder();
+    let len = blocks.len();
+    PostorderIter { body, blocks, idx: len }
+}
+
+#[derive(Clone)]
+pub struct PostorderIter<'a, 'tcx> {
+    body: &'a Body<'tcx>,
+    blocks: &'a [BasicBlock],
+    idx: usize,
+}
+
+impl<'a, 'tcx> Iterator for PostorderIter<'a, 'tcx> {
+    type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
+
+    fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> {
+        if self.idx == 0 {
+            return None;
+        }
+        self.idx -= 1;
+
+        self.blocks.get(self.idx).map(|&bb| (bb, &self.body[bb]))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.idx, Some(self.idx))
+    }
+}
+
+impl<'a, 'tcx> ExactSizeIterator for PostorderIter<'a, 'tcx> {}
+
 /// Reverse postorder traversal of a graph
 ///
 /// Reverse postorder is the reverse order of a postorder traversal.