use super::{const_truth, const_loop_empty};
use crate::ir::Node;
#[inline]
pub(crate) fn eliminate_unreachable(nodes: Vec<Node>) -> Vec<Node> {
let mut out = Vec::with_capacity(nodes.len());
for node in nodes {
match node {
Node::If {
cond,
then,
otherwise,
} => match const_truth(&cond) {
Some(true) => out.extend(eliminate_unreachable(then)),
Some(false) => out.extend(eliminate_unreachable(otherwise)),
None => out.push(Node::if_then_else(
cond,
eliminate_unreachable(then),
eliminate_unreachable(otherwise),
)),
},
Node::Loop {
var,
from,
to,
body,
} if const_loop_empty(&from, &to) => {
let _ = (var, body);
}
Node::Loop {
var,
from,
to,
body,
} => out.push(Node::loop_for(&var, from, to, eliminate_unreachable(body))),
Node::Block(block_nodes) => {
let block_nodes = eliminate_unreachable(block_nodes);
if !block_nodes.is_empty() {
out.push(Node::block(block_nodes));
}
}
Node::Return => {
out.push(Node::Return);
break;
}
Node::Let { name, value } => out.push(Node::let_bind(&name, value)),
Node::Assign { name, value } => out.push(Node::assign(&name, value)),
Node::Store {
buffer,
index,
value,
} => out.push(Node::store(&buffer, index, value)),
Node::Barrier => out.push(Node::Barrier),
}
}
out
}