Skip to content

Commit 0b3909e

Browse files
committed
Reinstate the Loop(Multiple) code, and properly fix all LoopContinue edges
1 parent c53027f commit 0b3909e

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

relooper/src/lib.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ impl<L: RelooperLabel> Relooper<L> {
212212
let loop_parents = Vec::from_iter(loop_parents);
213213

214214
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);
216216

217217
// Fix edges which are branching outside the loop
218218
let filtered_graph = EdgeFiltered::from_fn(&self.graph, filter_edges);
@@ -393,14 +393,12 @@ impl<L: RelooperLabel> Relooper<L> {
393393
continue;
394394
}
395395

396-
panic!("Merging branches which reach each other in a complex manner are not yet supported (dominator: {:?})", self.graph[dominator]);
397-
398396
// 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();
400398
let loop_parents: Vec<NodeIndex> = merged_branch.parent_nodes.difference(&FnvHashSet::from_iter(dominated_nodes.iter().map(|&i| i))).map(|&i| i).collect();
401399

402400
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);
404402
}
405403

406404
// Find the common dominator of a list of nodes
@@ -638,7 +636,7 @@ impl<L: RelooperLabel> Relooper<L> {
638636

639637
// Make a loop
640638
// 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) {
642640
let multi_loop = loop_headers.len() > 1;
643641

644642
// Add the new node
@@ -693,20 +691,40 @@ impl<L: RelooperLabel> Relooper<L> {
693691
}
694692
}
695693

694+
let filtered_graph = EdgeFiltered::from_fn(&self.graph, filter_edges);
695+
let dominators = algo::dominators::simple_fast(&filtered_graph, self.graph_root);
696+
696697
// 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+
}
702722
}
703-
};
723+
}
704724
}
705725

706726
// If we have multiple parents, fix the ForwardMulti edges so that the loop won't be outputted multiple times
707727
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);
710728
let dominator = dominators.immediate_dominator(loop_node).unwrap();
711729
for &node in loop_parents {
712730
let mut edges = self.graph.neighbors(node).detach();

0 commit comments

Comments
 (0)