Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • llvm/hercules
1 result
Show changes
Commits on Source (4)
......@@ -50,6 +50,11 @@ pub fn delete_uncalled(
// that all nodes in all functions will be mutable, so panic if any
// edit fails.
for editor in editors.iter_mut() {
// Don't make edits to dead functions as they may include calls to dead functions
if new_idx[editor.func_id().idx()].is_none() {
continue;
}
let callsites: Vec<_> = editor
.node_ids()
.filter(|id| editor.func().nodes[id.idx()].is_call())
......
......@@ -30,7 +30,7 @@ pub fn forkify(
for l in natural_loops {
// FIXME: Run on all-bottom level loops, as they can be independently optimized without recomputing analyses.
if forkify_loop(
if editor.is_mutable(l.0) && forkify_loop(
editor,
control_subgraph,
fork_join_map,
......@@ -166,6 +166,7 @@ pub fn forkify_loop(
return false;
}
// Get all phis used outside of the loop, they need to be reductionable.
// For now just assume all phis will be phis used outside of the loop, except for the canonical iv.
// FIXME: We need a different definiton of `loop_nodes` to check for phis used outside hte loop than the one
......@@ -182,7 +183,6 @@ pub fn forkify_loop(
let reductionable_phis: Vec<_> = analyze_phis(&editor, &l, &candidate_phis, &loop_nodes)
.into_iter()
.collect();
// TODO: Handle multiple loop body lasts.
// If there are multiple candidates for loop body last, return false.
if editor
......@@ -327,7 +327,7 @@ pub fn forkify_loop(
.collect();
// Start failable edit:
editor.edit(|mut edit| {
let result = editor.edit(|mut edit| {
let thread_id = Node::ThreadID {
control: fork_id,
dimension: dimension,
......@@ -405,7 +405,7 @@ pub fn forkify_loop(
Ok(edit)
});
return true;
return result;
}
nest! {
......@@ -457,7 +457,7 @@ pub fn analyze_phis<'a>(
// External Phi
if let Node::Phi { control, data: _ } = data {
if *control != natural_loop.header {
if !natural_loop.control[control.idx()] {
return true;
}
}
......@@ -539,16 +539,7 @@ pub fn analyze_phis<'a>(
// PHIs on the frontier of the uses by the candidate phi, i.e in uses_for_dependance need
// to have headers that postdominate the loop continue latch. The value of the PHI used needs to be defined
// by the time the reduce is triggered (at the end of the loop's internal control).
// If anything in the intersection is a phi (that isn't this own phi), then the reduction cycle depends on control.
// Which is not allowed.
if intersection
.iter()
.any(|cycle_node| editor.node(cycle_node).is_phi() && *cycle_node != *phi)
|| editor.node(loop_continue_latch).is_phi()
{
return LoopPHI::ControlDependant(*phi);
}
// No nodes in data cycles with this phi (in the loop) are used outside the loop, besides the loop_continue_latch.
// If some other node in the cycle is used, there is not a valid node to assign it after making the cycle a reduce.
if intersection
......
use core::panic;
use std::collections::HashSet;
use bitvec::prelude::*;
......@@ -73,8 +74,13 @@ pub fn calculate_loop_nodes(editor: &FunctionEditor, natural_loop: &Loop) -> Has
// External Phi
if let Node::Phi { control, data: _ } = data {
if !natural_loop.control[control.idx()] {
return true;
match natural_loop.control.get(control.idx()) {
Some(v) => if !*v {
return true;
},
None => {
panic!("unexpceted index: {:?} for loop {:?}", control, natural_loop.header);
},
}
}
// External Reduce
......@@ -84,14 +90,26 @@ pub fn calculate_loop_nodes(editor: &FunctionEditor, natural_loop: &Loop) -> Has
reduct: _,
} = data
{
if !natural_loop.control[control.idx()] {
return true;
match natural_loop.control.get(control.idx()) {
Some(v) => if !*v {
return true;
},
None => {
panic!("unexpceted index: {:?} for loop {:?}", control, natural_loop.header);
},
}
}
// External Control
if data.is_control() && !natural_loop.control[node.idx()] {
return true;
if data.is_control() {
match natural_loop.control.get(node.idx()) {
Some(v) => if !*v {
return true;
},
None => {
panic!("unexpceted index: {:?} for loop {:?}", node, natural_loop.header);
},
}
}
return false;
......
......@@ -1859,9 +1859,9 @@ fn run_pass(
let Some(mut func) = func else {
continue;
};
forkify(&mut func, control_subgraph, fork_join_map, loop_nest);
changed |= func.modified();
inner_changed |= func.modified();
let c = forkify(&mut func, control_subgraph, fork_join_map, loop_nest);
changed |= c;
inner_changed |= c;
}
pm.delete_gravestones();
pm.clear_analyses();
......
......@@ -2,6 +2,7 @@ use std::collections::HashMap;
use std::collections::HashSet;
use std::hash::Hash;
#[derive(Debug)]
pub struct Env<K, V> {
table: HashMap<K, Vec<V>>,
scope: Vec<HashSet<K>>,
......@@ -98,6 +99,11 @@ impl<K: Eq + Hash + Copy, V> Env<K, V> {
let mut new_scopes: HashMap<K, Vec<usize>> = HashMap::new();
for (k, vs) in std::mem::take(&mut self.table) {
if vs.is_empty() {
assert!(!scopes.contains_key(&k));
continue;
}
let scope_list = scopes.remove(&k).unwrap();
assert!(scope_list.len() == vs.len());
......