use std::collections::BTreeSet;
use crate::hir::common::{HirBlock, HirExpr, HirLValue, HirProto, HirStmt, TempId};
use super::visit::{HirVisitor, visit_proto};
use super::walk::{HirRewritePass, rewrite_proto};
#[cfg(test)]
mod tests;
pub(super) fn remove_dead_unresolved_temp_materializations_in_proto(proto: &mut HirProto) -> bool {
let live_reads = collect_live_temp_reads(proto);
let mut pass = DeadUnresolvedTempPass {
live_reads: &live_reads,
};
rewrite_proto(proto, &mut pass)
}
struct DeadUnresolvedTempPass<'a> {
live_reads: &'a BTreeSet<TempId>,
}
impl HirRewritePass for DeadUnresolvedTempPass<'_> {
fn rewrite_block(&mut self, block: &mut HirBlock) -> bool {
let original_len = block.stmts.len();
block
.stmts
.retain(|stmt| !is_dead_unresolved_temp_materialization(stmt, self.live_reads));
block.stmts.len() != original_len
}
}
fn collect_live_temp_reads(proto: &HirProto) -> BTreeSet<TempId> {
let mut collector = TempReadCollector::default();
visit_proto(proto, &mut collector);
collector.reads
}
#[derive(Default)]
struct TempReadCollector {
reads: BTreeSet<TempId>,
}
impl HirVisitor for TempReadCollector {
fn visit_expr(&mut self, expr: &HirExpr) {
if let HirExpr::TempRef(temp) = expr {
self.reads.insert(*temp);
}
}
}
fn is_dead_unresolved_temp_materialization(stmt: &HirStmt, live_reads: &BTreeSet<TempId>) -> bool {
let HirStmt::Assign(assign) = stmt else {
return false;
};
matches!(
(assign.targets.as_slice(), assign.values.as_slice()),
([HirLValue::Temp(temp)], [HirExpr::Unresolved(_)]) if !live_reads.contains(temp)
)
}