@@ -41,6 +41,12 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> {
41
41
}
42
42
}
43
43
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.
44
50
pub fn preorder < ' a , ' tcx > ( body : & ' a Body < ' tcx > ) -> Preorder < ' a , ' tcx > {
45
51
Preorder :: new ( body, START_BLOCK )
46
52
}
@@ -178,7 +184,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
178
184
// When we yield `C` and call `traverse_successor`, we push `B` to the stack, but
179
185
// since we've already visited `E`, that child isn't added to the stack. The last
180
186
// 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 ( ) ) {
182
188
if self . visited . insert ( bb) {
183
189
if let Some ( term) = & self . basic_blocks [ bb] . terminator {
184
190
self . visit_stack . push ( ( bb, term. successors ( ) ) ) ;
@@ -188,16 +194,14 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
188
194
}
189
195
}
190
196
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 ;
193
199
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 ( ) ;
199
203
200
- next . map ( | ( bb , _ ) | ( bb , & self . basic_blocks [ bb ] ) )
204
+ Some ( bb )
201
205
}
202
206
203
207
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -215,18 +219,43 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
215
219
}
216
220
}
217
221
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:
219
225
/// - returns basic blocks in a postorder,
220
226
/// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the
221
227
/// postorder itself.
228
+ ///
229
+ /// See [`Postorder`]'s docs to learn what is postorder traversal.
222
230
pub fn postorder < ' a , ' tcx > (
223
231
body : & ' a Body < ' tcx > ,
224
232
) -> impl Iterator < Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > + ExactSizeIterator + DoubleEndedIterator
225
233
{
226
234
reverse_postorder ( body) . rev ( )
227
235
}
228
236
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.
230
259
///
231
260
/// Reverse postorder is the reverse order of a postorder traversal.
232
261
/// This is different to a preorder traversal and represents a natural
@@ -246,65 +275,6 @@ pub fn postorder<'a, 'tcx>(
246
275
/// A reverse postorder traversal of this graph is either `A B C D` or `A C B D`
247
276
/// Note that for a graph containing no loops (i.e., A DAG), this is equivalent to
248
277
/// 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.
308
278
pub fn reverse_postorder < ' a , ' tcx > (
309
279
body : & ' a Body < ' tcx > ,
310
280
) -> impl Iterator < Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) > + ExactSizeIterator + DoubleEndedIterator
0 commit comments