vyre-foundation 0.4.1

Foundation layer: IR, type system, memory model, wire format. Zero application semantics. Part of the vyre GPU compiler.
Documentation
//! Region-inline pass registered through the unified pass substrate.
//!
//! Wraps the [`region_inline_engine`] transform so it runs under
//! scheduler control rather than as a hard-coded pre-pass.

use crate::ir::Program;
use crate::optimizer::{fingerprint_program, vyre_pass, PassAnalysis, PassResult};

#[vyre_pass(name = "region_inline", requires = [], invalidates = ["cse", "dce"])]
/// Built-in region-inline pass.
pub struct RegionInlinePass;

impl RegionInlinePass {
    /// Run when the program has at least one top-level region.
    #[must_use]
    pub fn analyze(program: &Program) -> PassAnalysis {
        if program
            .entry()
            .iter()
            .any(|n| matches!(n, crate::ir::Node::Region { .. }))
        {
            PassAnalysis::RUN
        } else {
            PassAnalysis::SKIP
        }
    }

    /// Flatten small regions into the surrounding body.
    #[must_use]
    pub fn transform(program: Program) -> PassResult {
        let before = fingerprint_program(&program);
        let optimized = super::region_inline_engine::run(program);
        PassResult {
            changed: fingerprint_program(&optimized) != before,
            program: optimized,
        }
    }

    /// Fingerprint this pass's visible input.
    #[must_use]
    pub fn fingerprint(program: &Program) -> u64 {
        fingerprint_program(program)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::ir::{Expr, Node};

    #[test]
    fn region_inline_analyze_skips_without_regions() {
        let p = Program::new_raw(vec![], [1, 1, 1], vec![Node::let_bind("x", Expr::u32(1))]);
        assert_eq!(RegionInlinePass::analyze(&p), PassAnalysis::SKIP);
    }

    #[test]
    fn region_inline_analyze_runs_with_regions() {
        let p = Program::wrapped(
            vec![],
            [1, 1, 1],
            vec![Node::Region {
                generator: "test_gen".into(),
                source_region: None,
                body: vec![Node::let_bind("x", Expr::u32(1))].into(),
            }],
        );
        assert_eq!(RegionInlinePass::analyze(&p), PassAnalysis::RUN);
    }

    #[test]
    fn region_inline_transform_flattens_regions() {
        let inner_let = Node::let_bind("x", Expr::u32(1));
        let p = Program::wrapped(
            vec![],
            [1, 1, 1],
            vec![Node::Region {
                generator: "test_gen".into(),
                source_region: None,
                body: vec![inner_let.clone()].into(),
            }],
        );
        let result = RegionInlinePass::transform(p);

        assert!(result.changed, "Region inline failed to detect change");
        assert!(
            !result
                .program
                .entry()
                .iter()
                .any(|n| matches!(n, Node::Region { .. })),
            "Region inline should have removed all Region nodes"
        );
        // The inner_let should now be at the top level
        assert_eq!(result.program.entry().len(), 1);
        assert!(matches!(result.program.entry()[0], Node::Let { .. }));
    }
}