@@ -5,12 +5,12 @@ use crate::dominator_tree::DominatorTree;
5
5
use crate :: entity:: entity_impl;
6
6
use crate :: entity:: SecondaryMap ;
7
7
use crate :: entity:: { Keys , PrimaryMap } ;
8
- use crate :: flowgraph:: { BlockPredecessor , ControlFlowGraph } ;
8
+ use crate :: flowgraph:: ControlFlowGraph ;
9
9
use crate :: ir:: { Block , Function , Layout } ;
10
10
use crate :: packed_option:: PackedOption ;
11
11
use crate :: timing;
12
12
use alloc:: vec:: Vec ;
13
- use smallvec:: { smallvec , SmallVec } ;
13
+ use smallvec:: SmallVec ;
14
14
15
15
/// A opaque reference to a code loop.
16
16
#[ derive( Copy , Clone , PartialEq , Eq , Hash ) ]
@@ -190,6 +190,19 @@ impl LoopAnalysis {
190
190
self . valid = false ;
191
191
}
192
192
193
+ // Determines if a block dominates any predecessor
194
+ // and thus is a loop header.
195
+ fn is_block_loop_header (
196
+ block : Block ,
197
+ cfg : & ControlFlowGraph ,
198
+ domtree : & DominatorTree ,
199
+ layout : & Layout ,
200
+ ) -> bool {
201
+ // A block is a loop header if it dominates any of its predecessors.
202
+ cfg. pred_iter ( block)
203
+ . any ( |pred| domtree. dominates ( block, pred. inst , layout) )
204
+ }
205
+
193
206
// Traverses the CFG in reverse postorder and create a loop object for every block having a
194
207
// back edge.
195
208
fn find_loop_headers (
@@ -198,21 +211,13 @@ impl LoopAnalysis {
198
211
domtree : & DominatorTree ,
199
212
layout : & Layout ,
200
213
) {
201
- // We traverse the CFG in reverse postorder
202
- for & block in domtree. cfg_postorder ( ) . iter ( ) . rev ( ) {
203
- for BlockPredecessor {
204
- inst : pred_inst, ..
205
- } in cfg. pred_iter ( block)
206
- {
207
- // If the block dominates one of its predecessors it is a back edge
208
- if domtree. dominates ( block, pred_inst, layout) {
209
- // This block is a loop header, so we create its associated loop
210
- let lp = self . loops . push ( LoopData :: new ( block, None ) ) ;
211
- self . block_loop_map [ block] = lp. into ( ) ;
212
- break ;
213
- // We break because we only need one back edge to identify a loop header.
214
- }
215
- }
214
+ for & block in domtree
215
+ . cfg_rpo ( )
216
+ . filter ( |& & block| Self :: is_block_loop_header ( block, cfg, domtree, layout) )
217
+ {
218
+ // This block is a loop header, so we create its associated loop
219
+ let lp = self . loops . push ( LoopData :: new ( block, None ) ) ;
220
+ self . block_loop_map [ block] = lp. into ( ) ;
216
221
}
217
222
}
218
223
@@ -229,16 +234,15 @@ impl LoopAnalysis {
229
234
// We handle each loop header in reverse order, corresponding to a pseudo postorder
230
235
// traversal of the graph.
231
236
for lp in self . loops ( ) . rev ( ) {
232
- for BlockPredecessor {
233
- block : pred,
234
- inst : pred_inst,
235
- } in cfg. pred_iter ( self . loops [ lp] . header )
236
- {
237
- // We follow the back edges
238
- if domtree. dominates ( self . loops [ lp] . header , pred_inst, layout) {
239
- stack. push ( pred) ;
240
- }
241
- }
237
+ // Push all predecessors of this header that it dominates onto the stack.
238
+ stack. extend (
239
+ cfg. pred_iter ( self . loops [ lp] . header )
240
+ . filter ( |pred| {
241
+ // We follow the back edges
242
+ domtree. dominates ( self . loops [ lp] . header , pred. inst , layout)
243
+ } )
244
+ . map ( |pred| pred. block ) ,
245
+ ) ;
242
246
while let Some ( node) = stack. pop ( ) {
243
247
let continue_dfs: Option < Block > ;
244
248
match self . block_loop_map [ node] . expand ( ) {
@@ -283,16 +287,14 @@ impl LoopAnalysis {
283
287
// Now we have handled the popped node and need to continue the DFS by adding the
284
288
// predecessors of that node
285
289
if let Some ( continue_dfs) = continue_dfs {
286
- for BlockPredecessor { block : pred, .. } in cfg. pred_iter ( continue_dfs) {
287
- stack. push ( pred)
288
- }
290
+ stack. extend ( cfg. pred_iter ( continue_dfs) . map ( |pred| pred. block ) ) ;
289
291
}
290
292
}
291
293
}
292
294
}
293
295
294
296
fn assign_loop_levels ( & mut self ) {
295
- let mut stack: SmallVec < [ Loop ; 8 ] > = smallvec ! [ ] ;
297
+ let mut stack: SmallVec < [ Loop ; 8 ] > = SmallVec :: new ( ) ;
296
298
for lp in self . loops . keys ( ) {
297
299
if self . loops [ lp] . level == LoopLevel :: invalid ( ) {
298
300
stack. push ( lp) ;
0 commit comments