Skip to content
Snippets Groups Projects
Commit 738383c9 authored by Aaron Councilman's avatar Aaron Councilman
Browse files

Fix SROA bug, resolves #11

parent dd6a5c2a
No related branches found
No related tags found
1 merge request!64Some bugfixes
Pipeline #200367 failed
......@@ -40,6 +40,12 @@ use crate::*;
* replaced by a direct def of the field value
*/
pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types: &Vec<TypeID>) {
let mut types: HashMap<NodeID, TypeID> = types
.iter()
.enumerate()
.map(|(i, t)| (NodeID::new(i), *t))
.collect();
// This map stores a map from NodeID to an index tree which can be used to lookup the NodeID
// that contains the corresponding fields of the original value
let mut field_map: HashMap<NodeID, IndexTree<NodeID>> = HashMap::new();
......@@ -64,17 +70,15 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
second: _,
third: _,
op: TernaryOperator::Select,
} if editor.get_type(types[node.idx()]).is_product() => product_nodes.push(*node),
} if editor.get_type(types[&node]).is_product() => product_nodes.push(*node),
Node::Read { collect, .. } if editor.get_type(types[collect.idx()]).is_product() => {
Node::Read { collect, .. } if editor.get_type(types[&collect]).is_product() => {
product_nodes.push(*node)
}
// We add all calls to the call/return list and check their arguments later
Node::Call { .. } => call_return_nodes.push(*node),
Node::Return { control: _, data }
if editor.get_type(types[data.idx()]).is_product() =>
{
Node::Return { control: _, data } if editor.get_type(types[&data]).is_product() => {
call_return_nodes.push(*node)
}
......@@ -92,10 +96,9 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
for node in call_return_nodes {
match &editor.func().nodes[node.idx()] {
Node::Return { control, data } => {
assert!(editor.get_type(types[data.idx()]).is_product());
assert!(editor.get_type(types[&data]).is_product());
let control = *control;
let new_data =
reconstruct_product(editor, types[data.idx()], *data, &mut product_nodes);
let new_data = reconstruct_product(editor, types[&data], *data, &mut product_nodes);
editor.edit(|mut edit| {
edit.add_node(Node::Return {
control,
......@@ -116,18 +119,18 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
let args = args.clone();
// If the call returns a product, we generate reads for each field
let fields = if editor.get_type(types[node.idx()]).is_product() {
Some(generate_reads(editor, types[node.idx()], node))
let fields = if editor.get_type(types[&node]).is_product() {
Some(generate_reads(editor, types[&node], node))
} else {
None
};
let mut new_args = vec![];
for arg in args {
if editor.get_type(types[arg.idx()]).is_product() {
if editor.get_type(types[&arg]).is_product() {
new_args.push(reconstruct_product(
editor,
types[arg.idx()],
types[&arg],
arg,
&mut product_nodes,
));
......@@ -145,6 +148,13 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
let edit = edit.replace_all_uses(node, new_call)?;
let edit = edit.delete_node(node)?;
// Since we've replaced uses of calls with the new node, we update the type
// information so that we can retrieve the type of the new call if needed
// Because the other nodes we've created so far are only used in very
// particular ways (i.e. are not used by arbitrary nodes) we don't need their
// type information but do for the new calls
types.insert(new_call, types[&node]);
match fields {
None => {}
Some(fields) => {
......@@ -194,7 +204,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
for node in product_nodes {
match editor.func().nodes[node.idx()] {
Node::Parameter { .. } => {
field_map.insert(node, generate_reads(editor, types[node.idx()], node));
field_map.insert(node, generate_reads(editor, types[&node], node));
}
Node::Constant { id } => {
field_map.insert(node, generate_constant_fields(editor, id));
......@@ -221,7 +231,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
Node::Phi { control, data } => {
let control = *control;
let data = data.clone();
let fields = allocate_fields(editor, types[node.idx()], &mut next_id);
let fields = allocate_fields(editor, types[&node], &mut next_id);
field_map.insert(node, fields.clone());
item = WorkItem::AllocatedPhi {
......@@ -239,7 +249,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
let control = *control;
let init = *init;
let reduct = *reduct;
let fields = allocate_fields(editor, types[node.idx()], &mut next_id);
let fields = allocate_fields(editor, types[&node], &mut next_id);
field_map.insert(node, fields.clone());
item = WorkItem::AllocatedReduce {
......@@ -259,7 +269,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
let first = *first;
let second = *second;
let third = *third;
let fields = allocate_fields(editor, types[node.idx()], &mut next_id);
let fields = allocate_fields(editor, types[&node], &mut next_id);
field_map.insert(node, fields.clone());
item = WorkItem::AllocatedTernary {
......@@ -277,7 +287,7 @@ pub fn sroa(editor: &mut FunctionEditor, reverse_postorder: &Vec<NodeID>, types:
indices,
} => {
if let Some(index_map) = field_map.get(collect) {
if editor.get_type(types[data.idx()]).is_product() {
if editor.get_type(types[&data]).is_product() {
if let Some(data_idx) = field_map.get(data) {
field_map.insert(
node,
......
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