use fnv;
use crate::sir::StatementKind::{Assign, AssignLiteral};
use crate::sir::*;
pub fn simplify_assignments(prog: &mut SirProgram) -> WeldResult<()> {
for func in prog.funcs.iter_mut() {
simplify_assignments_in_function(func)?
}
Ok(())
}
fn simplify_assignments_in_function(func: &mut SirFunction) -> WeldResult<()> {
if !func.loop_body || !func.innermost_loop {
return Ok(());
}
let mut assignments = fnv::FnvHashMap::default();
let mut validset = fnv::FnvHashSet::default();
for block in func.blocks.iter() {
for statement in block.statements.iter() {
if let Assign(ref source) = statement.kind {
let target = statement.output.as_ref().unwrap();
if validset.contains(target) {
continue;
}
let is_valid = match assignments.get(target) {
Some(ref current_source) => *current_source != source,
None => {
assignments.insert(target.clone(), source.clone());
false
}
};
if is_valid {
validset.insert(assignments.remove(target).unwrap());
}
}
if let AssignLiteral(_) = statement.kind {
validset.insert(statement.output.clone().unwrap());
assignments.remove(statement.output.as_ref().unwrap());
}
}
}
for block in func.blocks.iter_mut() {
block.statements.retain(|ref statement| {
if let Assign(_) = statement.kind {
let target = statement.output.as_ref().unwrap();
!assignments.contains_key(target)
} else {
true
}
});
for (key, value) in assignments.iter() {
block.substitute_symbol(key, value);
}
}
Ok(())
}