@@ -41,6 +41,12 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> {
4141 }
4242}
4343
44+ /// Preorder traversal of a graph.
45+ ///
46+ /// This function creates an iterator over the `Body`'s basic blocks, that
47+ /// returns basic blocks in a preorder.
48+ ///
49+ /// See [`Preorder`]'s docs to learn what is preorder traversal.
4450pub fn preorder < ' a , ' tcx > ( body : & ' a Body < ' tcx > ) -> Preorder < ' a , ' tcx > {
4551 Preorder :: new ( body, START_BLOCK )
4652}
@@ -178,7 +184,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
178184 // When we yield `C` and call `traverse_successor`, we push `B` to the stack, but
179185 // since we've already visited `E`, that child isn't added to the stack. The last
180186 // two iterations yield `B` and finally `A` for a final traversal of [E, D, C, B, A]
181- while let Some ( & mut ( _ , ref mut iter ) ) = self . visit_stack . last_mut ( ) && let Some ( bb ) = iter. next_back ( ) {
187+ while let Some ( bb ) = self . visit_stack . last_mut ( ) . and_then ( | ( _ , iter ) | iter. next_back ( ) ) {
182188 if self . visited . insert ( bb) {
183189 if let Some ( term) = & self . basic_blocks [ bb] . terminator {
184190 self . visit_stack . push ( ( bb, term. successors ( ) ) ) ;
@@ -188,16 +194,14 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
188194 }
189195}
190196
191- impl < ' a , ' tcx > Iterator for Postorder < ' a , ' tcx > {
192- type Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) ;
197+ impl < ' tcx > Iterator for Postorder < ' _ , ' tcx > {
198+ type Item = BasicBlock ;
193199
194- fn next ( & mut self ) -> Option < ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > {
195- let next = self . visit_stack . pop ( ) ;
196- if next. is_some ( ) {
197- self . traverse_successor ( ) ;
198- }
200+ fn next ( & mut self ) -> Option < BasicBlock > {
201+ let ( bb, _) = self . visit_stack . pop ( ) ?;
202+ self . traverse_successor ( ) ;
199203
200- next . map ( | ( bb , _ ) | ( bb , & self . basic_blocks [ bb ] ) )
204+ Some ( bb )
201205 }
202206
203207 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -215,18 +219,43 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
215219 }
216220}
217221
218- /// Creates an iterator over the `Body`'s basic blocks, that:
222+ /// Postorder traversal of a graph.
223+ ///
224+ /// This function creates an iterator over the `Body`'s basic blocks, that:
219225/// - returns basic blocks in a postorder,
220226/// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the
221227/// postorder itself.
228+ ///
229+ /// See [`Postorder`]'s docs to learn what is postorder traversal.
222230pub fn postorder < ' a , ' tcx > (
223231 body : & ' a Body < ' tcx > ,
224232) -> impl Iterator < Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > + ExactSizeIterator + DoubleEndedIterator
225233{
226234 reverse_postorder ( body) . rev ( )
227235}
228236
229- /// Reverse postorder traversal of a graph
237+ /// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular
238+ /// order.
239+ ///
240+ /// This is clearer than writing `preorder` in cases where the order doesn't matter.
241+ pub fn reachable < ' a , ' tcx > (
242+ body : & ' a Body < ' tcx > ,
243+ ) -> impl ' a + Iterator < Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > {
244+ preorder ( body)
245+ }
246+
247+ /// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`.
248+ pub fn reachable_as_bitset ( body : & Body < ' _ > ) -> BitSet < BasicBlock > {
249+ let mut iter = preorder ( body) ;
250+ iter. by_ref ( ) . for_each ( drop) ;
251+ iter. visited
252+ }
253+
254+ /// Reverse postorder traversal of a graph.
255+ ///
256+ /// This function creates an iterator over the `Body`'s basic blocks, that:
257+ /// - returns basic blocks in a reverse postorder,
258+ /// - makes use of the `BasicBlocks` CFG cache's reverse postorder.
230259///
231260/// Reverse postorder is the reverse order of a postorder traversal.
232261/// This is different to a preorder traversal and represents a natural
@@ -246,65 +275,6 @@ pub fn postorder<'a, 'tcx>(
246275/// A reverse postorder traversal of this graph is either `A B C D` or `A C B D`
247276/// Note that for a graph containing no loops (i.e., A DAG), this is equivalent to
248277/// a topological sort.
249- ///
250- /// Construction of a `ReversePostorder` traversal requires doing a full
251- /// postorder traversal of the graph, therefore this traversal should be
252- /// constructed as few times as possible. Use the `reset` method to be able
253- /// to re-use the traversal
254- #[ derive( Clone ) ]
255- pub struct ReversePostorder < ' a , ' tcx > {
256- body : & ' a Body < ' tcx > ,
257- blocks : Vec < BasicBlock > ,
258- idx : usize ,
259- }
260-
261- impl < ' a , ' tcx > ReversePostorder < ' a , ' tcx > {
262- pub fn new ( body : & ' a Body < ' tcx > , root : BasicBlock ) -> ReversePostorder < ' a , ' tcx > {
263- let blocks: Vec < _ > = Postorder :: new ( & body. basic_blocks , root) . map ( |( bb, _) | bb) . collect ( ) ;
264- let len = blocks. len ( ) ;
265- ReversePostorder { body, blocks, idx : len }
266- }
267- }
268-
269- impl < ' a , ' tcx > Iterator for ReversePostorder < ' a , ' tcx > {
270- type Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) ;
271-
272- fn next ( & mut self ) -> Option < ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > {
273- if self . idx == 0 {
274- return None ;
275- }
276- self . idx -= 1 ;
277-
278- self . blocks . get ( self . idx ) . map ( |& bb| ( bb, & self . body [ bb] ) )
279- }
280-
281- fn size_hint ( & self ) -> ( usize , Option < usize > ) {
282- ( self . idx , Some ( self . idx ) )
283- }
284- }
285-
286- impl < ' a , ' tcx > ExactSizeIterator for ReversePostorder < ' a , ' tcx > { }
287-
288- /// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular
289- /// order.
290- ///
291- /// This is clearer than writing `preorder` in cases where the order doesn't matter.
292- pub fn reachable < ' a , ' tcx > (
293- body : & ' a Body < ' tcx > ,
294- ) -> impl ' a + Iterator < Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > {
295- preorder ( body)
296- }
297-
298- /// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`.
299- pub fn reachable_as_bitset ( body : & Body < ' _ > ) -> BitSet < BasicBlock > {
300- let mut iter = preorder ( body) ;
301- ( & mut iter) . for_each ( drop) ;
302- iter. visited
303- }
304-
305- /// Creates an iterator over the `Body`'s basic blocks, that:
306- /// - returns basic blocks in a reverse postorder,
307- /// - makes use of the `BasicBlocks` CFG cache's reverse postorder.
308278pub fn reverse_postorder < ' a , ' tcx > (
309279 body : & ' a Body < ' tcx > ,
310280) -> impl Iterator < Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > + ExactSizeIterator + DoubleEndedIterator
0 commit comments