@@ -5,12 +5,12 @@ use crate::dominator_tree::DominatorTree;
55use crate :: entity:: entity_impl;
66use crate :: entity:: SecondaryMap ;
77use crate :: entity:: { Keys , PrimaryMap } ;
8- use crate :: flowgraph:: { BlockPredecessor , ControlFlowGraph } ;
8+ use crate :: flowgraph:: ControlFlowGraph ;
99use crate :: ir:: { Block , Function , Layout } ;
1010use crate :: packed_option:: PackedOption ;
1111use crate :: timing;
1212use alloc:: vec:: Vec ;
13- use smallvec:: { smallvec , SmallVec } ;
13+ use smallvec:: SmallVec ;
1414
1515/// A opaque reference to a code loop.
1616#[ derive( Copy , Clone , PartialEq , Eq , Hash ) ]
@@ -190,6 +190,19 @@ impl LoopAnalysis {
190190 self . valid = false ;
191191 }
192192
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+
193206 // Traverses the CFG in reverse postorder and create a loop object for every block having a
194207 // back edge.
195208 fn find_loop_headers (
@@ -198,21 +211,13 @@ impl LoopAnalysis {
198211 domtree : & DominatorTree ,
199212 layout : & Layout ,
200213 ) {
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 ( ) ;
216221 }
217222 }
218223
@@ -229,16 +234,15 @@ impl LoopAnalysis {
229234 // We handle each loop header in reverse order, corresponding to a pseudo postorder
230235 // traversal of the graph.
231236 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+ ) ;
242246 while let Some ( node) = stack. pop ( ) {
243247 let continue_dfs: Option < Block > ;
244248 match self . block_loop_map [ node] . expand ( ) {
@@ -283,16 +287,14 @@ impl LoopAnalysis {
283287 // Now we have handled the popped node and need to continue the DFS by adding the
284288 // predecessors of that node
285289 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 ) ) ;
289291 }
290292 }
291293 }
292294 }
293295
294296 fn assign_loop_levels ( & mut self ) {
295- let mut stack: SmallVec < [ Loop ; 8 ] > = smallvec ! [ ] ;
297+ let mut stack: SmallVec < [ Loop ; 8 ] > = SmallVec :: new ( ) ;
296298 for lp in self . loops . keys ( ) {
297299 if self . loops [ lp] . level == LoopLevel :: invalid ( ) {
298300 stack. push ( lp) ;
0 commit comments