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

take action on SLF lattice

parent a6bee2c2
No related branches found
No related tags found
1 merge request!109Simple Store Load Forwarding
Pipeline #201007 passed
......@@ -25,6 +25,7 @@ pub enum Pass {
PhiElim,
Forkify,
ForkGuardElim,
SLF,
WritePredication,
Predication,
SROA,
......@@ -470,6 +471,38 @@ impl PassManager {
}
self.clear_analyses();
}
Pass::SLF => {
self.make_def_uses();
self.make_reverse_postorders();
self.make_typing();
let def_uses = self.def_uses.as_ref().unwrap();
let reverse_postorders = self.reverse_postorders.as_ref().unwrap();
let typing = self.typing.as_ref().unwrap();
for idx in 0..self.module.functions.len() {
let constants_ref =
RefCell::new(std::mem::take(&mut self.module.constants));
let dynamic_constants_ref =
RefCell::new(std::mem::take(&mut self.module.dynamic_constants));
let types_ref = RefCell::new(std::mem::take(&mut self.module.types));
let mut editor = FunctionEditor::new(
&mut self.module.functions[idx],
FunctionID::new(idx),
&constants_ref,
&dynamic_constants_ref,
&types_ref,
&def_uses[idx],
);
slf(&mut editor, &reverse_postorders[idx], &typing[idx]);
self.module.constants = constants_ref.take();
self.module.dynamic_constants = dynamic_constants_ref.take();
self.module.types = types_ref.take();
println!("{}", self.module.functions[idx].name);
self.module.functions[idx].delete_gravestones();
}
self.clear_analyses();
}
Pass::WritePredication => {
self.make_def_uses();
let def_uses = self.def_uses.as_ref().unwrap();
......
......@@ -54,7 +54,10 @@ impl Semilattice for SLFLattice {
}
fn bottom() -> Self {
panic!()
let mut subvalues = BTreeMap::new();
// The empty indices set overlaps with all possible indices sets.
subvalues.insert(Box::new([]) as Box<[Index]>, None);
SLFLattice { subvalues }
}
}
......@@ -63,7 +66,7 @@ impl Semilattice for SLFLattice {
* known values inside collections and replaces reads of those values with the
* values directly.
*/
pub fn slf(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>) {
pub fn slf(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, typing: &Vec<TypeID>) {
// First, run a dataflow analysis that looks at known values inside
// collections. Thanks to the value semantics of Hercules IR, this analysis
// is relatively simple and straightforward.
......@@ -95,9 +98,63 @@ pub fn slf(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>) {
// Start with the indices of the `collect` input.
let mut value = inputs[0].clone();
// Any indices sets that overlap with `indices` become `None`,
// since we no longer know what's stored there.
for (other_indices, subvalue) in value.subvalues.iter_mut() {
if indices_may_overlap(other_indices, indices) {
*subvalue = None;
}
}
// Track `data` at `indices`.
value.subvalues.insert(indices.clone(), Some(data));
value
}
_ => SLFLattice::top(),
_ => SLFLattice::bottom(),
}
});
// Second, look for reads where the indices set either:
// 1. Equal the indices of a known sub-value. Then, the read can be replaced
// by the known sub-value.
// 2. Otherwise, if the indices set doesn't overlap with any known or
// unknown sub-value, then the read can be replaced by a zero constant.
// 3. Otherwise, the read can't be replaced.
// Keep track of which nodes we've already replaced, since a sub-value we
// knew previously may be the ID of an old node replaced previously.
let mut replacements = BTreeMap::new();
for id in editor.node_ids() {
let Node::Read {
collect,
ref indices,
} = editor.func().nodes[id.idx()]
else {
continue;
};
let subvalues = &lattice[collect.idx()].subvalues;
if let Some(sub_value) = subvalues.get(indices)
&& let Some(mut known) = *sub_value
{
while let Some(replacement) = replacements.get(&known) {
known = *replacement;
}
editor.edit(|mut edit| {
edit = edit.replace_all_uses(id, known)?;
edit.delete_node(id)
});
replacements.insert(id, known);
} else if !subvalues
.keys()
.any(|other_indices| indices_may_overlap(other_indices, indices))
{
editor.edit(|mut edit| {
let zero = edit.add_zero_constant(typing[id.idx()]);
let zero = edit.add_node(Node::Constant { id: zero });
edit = edit.replace_all_uses(id, zero)?;
edit.delete_node(id)
});
}
}
}
......@@ -182,6 +182,8 @@ pub fn compile_ir(
add_pass!(pm, verify, WritePredication);
add_pass!(pm, verify, PhiElim);
add_pass!(pm, verify, DCE);
add_pass!(pm, verify, SLF);
add_pass!(pm, verify, DCE);
add_pass!(pm, verify, Predication);
add_pass!(pm, verify, DCE);
add_pass!(pm, verify, CCP);
......
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