@@ -212,7 +212,7 @@ impl<L: RelooperLabel> Relooper<L> {
212
212
let loop_parents = Vec :: from_iter ( loop_parents) ;
213
213
214
214
let scc_test = |i| !& scc. contains ( & i) ;
215
- let ( loop_node, loop_id) = self . make_loop ( & loop_headers, & loop_parents, & scc , scc_test) ;
215
+ let ( loop_node, loop_id) = self . make_loop ( & loop_headers, & loop_parents, scc_test) ;
216
216
217
217
// Fix edges which are branching outside the loop
218
218
let filtered_graph = EdgeFiltered :: from_fn ( & self . graph , filter_edges) ;
@@ -393,14 +393,12 @@ impl<L: RelooperLabel> Relooper<L> {
393
393
continue ;
394
394
}
395
395
396
- panic ! ( "Merging branches which reach each other in a complex manner are not yet supported (dominator: {:?})" , self . graph[ dominator] ) ;
397
-
398
396
// Multiple nodes get turned into a LoopMulti
399
- /* let loop_headers = dominated_nodes.iter().map(|&i| i).collect();
397
+ let loop_headers = dominated_nodes. iter ( ) . map ( |& i| i) . collect ( ) ;
400
398
let loop_parents: Vec < NodeIndex > = merged_branch. parent_nodes . difference ( & FnvHashSet :: from_iter ( dominated_nodes. iter ( ) . map ( |& i| i) ) ) . map ( |& i| i) . collect ( ) ;
401
399
402
400
let loop_parents_test = |i| loop_parents. contains ( & i) ;
403
- self.make_loop(&loop_headers, &loop_parents, &loop_headers, loop_parents_test);*/
401
+ self . make_loop ( & loop_headers, & loop_parents, loop_parents_test) ;
404
402
}
405
403
406
404
// Find the common dominator of a list of nodes
@@ -638,7 +636,7 @@ impl<L: RelooperLabel> Relooper<L> {
638
636
639
637
// Make a loop
640
638
// scc can be empty when the loop is for handling merging branches that can reach each other
641
- fn make_loop < F : Fn ( NodeIndex ) -> bool > ( & mut self , loop_headers : & Vec < NodeIndex > , loop_parents : & Vec < NodeIndex > , loop_nodes : & Vec < NodeIndex > , loop_parent_filter : F ) -> ( NodeIndex , LoopId ) {
639
+ fn make_loop < F : Fn ( NodeIndex ) -> bool > ( & mut self , loop_headers : & Vec < NodeIndex > , loop_parents : & Vec < NodeIndex > , loop_parent_filter : F ) -> ( NodeIndex , LoopId ) {
642
640
let multi_loop = loop_headers. len ( ) > 1 ;
643
641
644
642
// Add the new node
@@ -693,20 +691,40 @@ impl<L: RelooperLabel> Relooper<L> {
693
691
}
694
692
}
695
693
694
+ let filtered_graph = EdgeFiltered :: from_fn ( & self . graph , filter_edges) ;
695
+ let dominators = algo:: dominators:: simple_fast ( & filtered_graph, self . graph_root ) ;
696
+
696
697
// If branching to a loop header, convert to a back edge
697
- for & node in loop_nodes {
698
- let mut edges = self . graph . neighbors ( node) . detach ( ) ;
699
- while let Some ( ( edge, target) ) = edges. next ( & self . graph ) {
700
- if loop_headers. contains ( & target) {
701
- self . graph [ edge] = if multi_loop { Edge :: LoopContinueIntoMulti ( loop_id) } else { Edge :: LoopContinue ( loop_id) } ;
698
+ // Walk through the graph manually
699
+ let mut stack = loop_headers. clone ( ) ;
700
+ let mut discovered = self . graph . visit_map ( ) ;
701
+ while let Some ( node) = stack. pop ( ) {
702
+ if discovered. visit ( node) {
703
+ let mut edges = self . graph . neighbors ( node) . detach ( ) ;
704
+ while let Some ( ( edge, target) ) = edges. next ( & self . graph ) {
705
+ if loop_headers. contains ( & target) {
706
+ self . graph [ edge] = if multi_loop { Edge :: LoopContinueIntoMulti ( loop_id) } else { Edge :: LoopContinue ( loop_id) } ;
707
+ }
708
+ else {
709
+ match self . graph [ edge] {
710
+ Edge :: Forward | Edge :: ForwardMulti ( _) | Edge :: Next => {
711
+ // If the target node is dominated by the loop node then add it to the stack
712
+ let target_dominators = dominators. strict_dominators ( target) . unwrap ( ) ;
713
+ for dom in target_dominators {
714
+ if dom == loop_node && !discovered. is_visited ( & target) {
715
+ stack. push ( target) ;
716
+ }
717
+ }
718
+ } ,
719
+ _ => { } ,
720
+ } ;
721
+ }
702
722
}
703
- } ;
723
+ }
704
724
}
705
725
706
726
// If we have multiple parents, fix the ForwardMulti edges so that the loop won't be outputted multiple times
707
727
if loop_parents. len ( ) > 1 {
708
- let filtered_graph = EdgeFiltered :: from_fn ( & self . graph , filter_edges) ;
709
- let dominators = algo:: dominators:: simple_fast ( & filtered_graph, self . graph_root ) ;
710
728
let dominator = dominators. immediate_dominator ( loop_node) . unwrap ( ) ;
711
729
for & node in loop_parents {
712
730
let mut edges = self . graph . neighbors ( node) . detach ( ) ;
0 commit comments