vyre-lower 0.6.4

Substrate-neutral lowering: vyre Program → KernelDescriptor consumed by vyre-emit-* crates.
Documentation
//! Test: dead store dataflow-analysis integration.
use vyre_foundation::ir::DataType;
use vyre_lower::{
    analyses::{weir_alias::AliasFactSet, weir_reaching_def::ReachingDefFactSet},
    rewrites::{run_all, run_all_with_dataflow_analysis_facts},
    BindingLayout, BindingSlot, BindingVisibility, Dispatch, KernelBody, KernelDescriptor,
    KernelOp, KernelOpKind, LiteralValue, MemoryClass,
};

fn binding() -> BindingSlot {
    BindingSlot {
        slot: 0,
        element_type: DataType::U32,
        element_count: None,
        memory_class: MemoryClass::Global,
        visibility: BindingVisibility::ReadWrite,
        name: "buf".into(),
    }
}

#[test]
fn dataflow_analysis_pipeline_applies_reaching_def_memory_dse() {
    let desc = KernelDescriptor {
        id: "dataflow_analysis_pipeline_dead_store".into(),
        bindings: BindingLayout {
            slots: vec![binding()],
        },
        dispatch: Dispatch::new(64, 1, 1),
        body: KernelBody {
            ops: vec![
                KernelOp {
                    kind: KernelOpKind::Literal,
                    operands: vec![0],
                    result: Some(10),
                },
                KernelOp {
                    kind: KernelOpKind::Literal,
                    operands: vec![1],
                    result: Some(1),
                },
                KernelOp {
                    kind: KernelOpKind::Literal,
                    operands: vec![2],
                    result: Some(2),
                },
                KernelOp {
                    kind: KernelOpKind::Copy,
                    operands: vec![10],
                    result: Some(11),
                },
                KernelOp {
                    kind: KernelOpKind::StoreGlobal,
                    operands: vec![0, 10, 1],
                    result: None,
                },
                KernelOp {
                    kind: KernelOpKind::StoreGlobal,
                    operands: vec![0, 11, 2],
                    result: None,
                },
            ],
            child_bodies: vec![],
            literals: vec![
                LiteralValue::U32(0),
                LiteralValue::U32(3),
                LiteralValue::U32(9),
            ],
        },
    };

    assert_eq!(store_count(&run_all(&desc)), 2);

    let alias_facts = AliasFactSet::default();
    let mut reaching_defs = ReachingDefFactSet::default();
    reaching_defs.set_reaching_defs(11, vec![10]);

    let optimized = run_all_with_dataflow_analysis_facts(&desc, &alias_facts, &reaching_defs);
    assert_eq!(store_count(&optimized), 1);
}

fn store_count(desc: &KernelDescriptor) -> usize {
    desc.body
        .ops
        .iter()
        .filter(|op| matches!(op.kind, KernelOpKind::StoreGlobal))
        .count()
}