Skip to content
Snippets Groups Projects
Commit 536a4add authored by Russel Arbore's avatar Russel Arbore
Browse files

Better method of calculating reduce cycles

parent d19be298
No related branches found
No related tags found
1 merge request!177Better method of calculating reduce cycles
Pipeline #201644 passed
...@@ -85,8 +85,9 @@ pub fn compute_fork_join_nesting( ...@@ -85,8 +85,9 @@ pub fn compute_fork_join_nesting(
*/ */
pub fn reduce_cycles( pub fn reduce_cycles(
function: &Function, function: &Function,
def_use: &ImmutableDefUseMap,
fork_join_map: &HashMap<NodeID, NodeID>, fork_join_map: &HashMap<NodeID, NodeID>,
fork_join_nest: &HashMap<NodeID, Vec<NodeID>>, nodes_in_fork_joins: &HashMap<NodeID, HashSet<NodeID>>,
) -> HashMap<NodeID, HashSet<NodeID>> { ) -> HashMap<NodeID, HashSet<NodeID>> {
let reduces = (0..function.nodes.len()) let reduces = (0..function.nodes.len())
.filter(|idx| function.nodes[*idx].is_reduce()) .filter(|idx| function.nodes[*idx].is_reduce())
...@@ -101,69 +102,50 @@ pub fn reduce_cycles( ...@@ -101,69 +102,50 @@ pub fn reduce_cycles(
let (join, _, reduct) = function.nodes[reduce.idx()].try_reduce().unwrap(); let (join, _, reduct) = function.nodes[reduce.idx()].try_reduce().unwrap();
let fork = join_fork_map[&join]; let fork = join_fork_map[&join];
// DFS the uses of `reduct` until finding the reduce itself. // Find nodes in the fork-join that the reduce can reach through uses.
let mut current_visited = HashSet::new(); let mut reachable_uses = HashSet::new();
let mut in_cycle = HashSet::new(); let mut workset = vec![];
reduce_cycle_dfs_helper( reachable_uses.insert(reduct);
function, workset.push(reduct);
reduct, while let Some(pop) = workset.pop() {
fork, for u in get_uses(&function.nodes[pop.idx()]).as_ref() {
reduce, if !reachable_uses.contains(u)
&mut current_visited, && nodes_in_fork_joins[&fork].contains(u)
&mut in_cycle, && *u != reduce
fork_join_nest, {
); reachable_uses.insert(*u);
result.insert(reduce, in_cycle); workset.push(*u);
} }
}
}
result // Find nodes in the fork-join that the reduce can reach through users.
} let mut reachable_users = HashSet::new();
workset.clear();
reachable_users.insert(reduce);
workset.push(reduce);
while let Some(pop) = workset.pop() {
for u in def_use.get_users(pop) {
if !reachable_users.contains(u)
&& nodes_in_fork_joins[&fork].contains(u)
&& *u != reduce
{
reachable_users.insert(*u);
workset.push(*u);
}
}
}
fn reduce_cycle_dfs_helper( // The reduce cycle is the insersection of nodes reachable through uses
function: &Function, // and users.
iter: NodeID, let intersection = reachable_uses
fork: NodeID, .intersection(&reachable_users)
reduce: NodeID, .map(|id| *id)
current_visited: &mut HashSet<NodeID>, .collect();
in_cycle: &mut HashSet<NodeID>, result.insert(reduce, intersection);
fork_join_nest: &HashMap<NodeID, Vec<NodeID>>,
) -> bool {
let isnt_outside_fork_join = |id: NodeID| {
let node = &function.nodes[id.idx()];
node.try_phi()
.map(|(control, _)| control)
.or(node.try_reduce().map(|(control, _, _)| control))
.map(|control| fork_join_nest[&control].contains(&fork))
.unwrap_or(true)
};
if iter == reduce || in_cycle.contains(&iter) {
return true;
} }
current_visited.insert(iter); result
let mut found_reduce = false;
// This doesn't short circuit on purpose.
for u in get_uses(&function.nodes[iter.idx()]).as_ref() {
found_reduce |= !current_visited.contains(u)
&& !function.nodes[u.idx()].is_control()
&& isnt_outside_fork_join(*u)
&& reduce_cycle_dfs_helper(
function,
*u,
fork,
reduce,
current_visited,
in_cycle,
fork_join_nest,
)
}
if found_reduce {
in_cycle.insert(iter);
}
current_visited.remove(&iter);
found_reduce
} }
/* /*
......
...@@ -399,18 +399,23 @@ impl PassManager { ...@@ -399,18 +399,23 @@ impl PassManager {
pub fn make_reduce_cycles(&mut self) { pub fn make_reduce_cycles(&mut self) {
if self.reduce_cycles.is_none() { if self.reduce_cycles.is_none() {
self.make_def_uses();
self.make_fork_join_maps(); self.make_fork_join_maps();
self.make_fork_join_nests(); self.make_nodes_in_fork_joins();
let def_uses = self.def_uses.as_ref().unwrap().iter();
let fork_join_maps = self.fork_join_maps.as_ref().unwrap().iter(); let fork_join_maps = self.fork_join_maps.as_ref().unwrap().iter();
let fork_join_nests = self.fork_join_nests.as_ref().unwrap().iter(); let nodes_in_fork_joins = self.nodes_in_fork_joins.as_ref().unwrap().iter();
self.reduce_cycles = Some( self.reduce_cycles = Some(
self.functions self.functions
.iter() .iter()
.zip(fork_join_maps) .zip(fork_join_maps)
.zip(fork_join_nests) .zip(nodes_in_fork_joins)
.map(|((function, fork_join_map), fork_join_nest)| { .zip(def_uses)
reduce_cycles(function, fork_join_map, fork_join_nest) .map(
}) |(((function, fork_join_map), nodes_in_fork_joins), def_use)| {
reduce_cycles(function, def_use, fork_join_map, nodes_in_fork_joins)
},
)
.collect(), .collect(),
); );
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment