vyre-foundation 0.4.1

Foundation layer: IR, type system, memory model, wire format. Zero application semantics. Part of the vyre GPU compiler.
Documentation
use super::{const_loop_empty, const_truth};
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 { ordering } => out.push(Node::barrier_with_ordering(ordering)),
            Node::IndirectDispatch {
                count_buffer,
                count_offset,
            } => out.push(Node::IndirectDispatch {
                count_buffer,
                count_offset,
            }),
            Node::AsyncLoad {
                source,
                destination,
                offset,
                size,
                tag,
            } => out.push(Node::async_load_ext(
                source,
                destination,
                *offset,
                *size,
                tag,
            )),
            Node::AsyncStore {
                source,
                destination,
                offset,
                size,
                tag,
            } => out.push(Node::async_store(source, destination, *offset, *size, tag)),
            Node::AsyncWait { tag } => out.push(Node::async_wait(&tag)),
            Node::Region {
                generator,
                source_region,
                body,
            } => {
                let body_nodes =
                    std::sync::Arc::try_unwrap(body).unwrap_or_else(|arc| (*arc).clone());
                out.push(Node::Region {
                    generator,
                    source_region,
                    body: std::sync::Arc::new(eliminate_unreachable(body_nodes)),
                });
            }
            Node::Trap { .. } | Node::Resume { .. } => out.push(node.clone()),
            Node::Opaque(extension) => out.push(Node::Opaque(extension.clone())),
        }
    }
    out
}