use std::collections::HashMap;
use crate::ir::{Expr, Statement};
use super::{expr_has_side_effects, rename_expr_vars, rename_stmt_vars};
pub fn eliminate_common_subexprs(stmts: Vec<Statement>) -> Vec<Statement> {
let mut seen: Vec<(Expr, String)> = Vec::new();
let mut renames: HashMap<String, String> = HashMap::new();
for stmt in &stmts {
if let Statement::Let { name, value, .. } = stmt {
if !expr_has_side_effects(value) {
let normalized = rename_expr_vars(value, &renames);
if let Some((_, first_name)) = seen.iter().find(|(expr, _)| *expr == normalized) {
renames.insert(name.clone(), first_name.clone());
} else {
seen.push((normalized, name.clone()));
}
}
}
}
if renames.is_empty() {
return stmts;
}
stmts.into_iter()
.filter(|stmt| {
if let Statement::Let { name, .. } = stmt {
!renames.contains_key(name)
} else {
true
}
})
.map(|stmt| rename_stmt_vars(stmt, &renames))
.collect()
}