vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
use super::{LiveResult, reachable_prefix, expr_has_effect, collect_expr_refs};
use crate::ir::Node;
use std::collections::HashSet;

#[inline]
pub(crate) fn eliminate_dead_lets(nodes: &[Node], live_after: HashSet<String>) -> LiveResult {
    let reachable_prefix = reachable_prefix(nodes);
    let mut live = live_after;
    let mut kept = Vec::with_capacity(reachable_prefix.len());

    for node in reachable_prefix.iter().rev() {
        match node {
            Node::Let { name, value } if !live.contains(name) && !expr_has_effect(value) => {}
            Node::Let { name, value } => {
                live.remove(name);
                collect_expr_refs(value, &mut live);
                kept.push(Node::let_bind(name, value.clone()));
            }
            Node::Assign { name, value } => {
                live.insert(name.clone());
                collect_expr_refs(value, &mut live);
                kept.push(Node::assign(name, value.clone()));
            }
            Node::Store {
                buffer,
                index,
                value,
            } => {
                collect_expr_refs(index, &mut live);
                collect_expr_refs(value, &mut live);
                kept.push(Node::store(buffer, index.clone(), value.clone()));
            }
            Node::If {
                cond,
                then,
                otherwise,
            } => {
                let then_result = eliminate_dead_lets(then, live.clone());
                let otherwise_result = eliminate_dead_lets(otherwise, live.clone());
                let mut branch_live = then_result.live_in;
                branch_live.extend(otherwise_result.live_in);
                collect_expr_refs(cond, &mut branch_live);
                live = branch_live;
                kept.push(Node::if_then_else(
                    cond.clone(),
                    then_result.nodes,
                    otherwise_result.nodes,
                ));
            }
            Node::Loop {
                var,
                from,
                to,
                body,
            } => {
                let mut body_live_after = live.clone();
                body_live_after.insert(var.clone());
                let body_result = eliminate_dead_lets(body, body_live_after);
                live.extend(body_result.live_in);
                live.remove(var);
                collect_expr_refs(from, &mut live);
                collect_expr_refs(to, &mut live);
                kept.push(Node::loop_for(
                    var,
                    from.clone(),
                    to.clone(),
                    body_result.nodes,
                ));
            }
            Node::Block(block_nodes) => {
                let block_result = eliminate_dead_lets(block_nodes, live.clone());
                live.extend(block_result.live_in);
                kept.push(Node::block(block_result.nodes));
            }
            Node::Return => kept.push(Node::Return),
            Node::Barrier => kept.push(Node::Barrier),
        }
    }

    kept.reverse();
    LiveResult {
        nodes: kept,
        live_in: live,
    }
}