weirflow 0.1.0

GPU-first dataflow analysis primitives for Vyre and Santh compiler pipelines.
Documentation
//! `weir::escape::escape_analyze`, `weir::callgraph::callgraph_build`,
//! and `weir::range::range_propagate`  -  three multi-buffer
//! propagation primitives.
//!
//! Op id: `weir::tests::df::escape_callgraph_range`. Soundness:
//! `MayOver` for escape (one fixpoint step over OR), `Exact` for
//! callgraph and range (per-node propagation steps). Tests pin
//! the buffer set + entry-vector non-emptiness; the OR-fixpoint
//! semantics for escape's body are also exercised through
//! Program-level inspection.

use weir::callgraph;
use weir::escape;
use weir::range;

#[test]
fn escape_analyze_program_three_buffers() {
    let prog = escape::escape_analyze("pts", "cg", "esc");
    let mut names: Vec<&str> = prog.buffers().iter().map(|b| b.name()).collect();
    names.sort();
    assert_eq!(names, vec!["cg", "esc", "pts"]);
    assert!(!prog.entry().is_empty());
}

#[test]
fn escape_analyze_with_count_scales() {
    for &n in &[1u32, 32, 64, 256, 1024] {
        let prog = escape::escape_analyze_with_count("pts", "cg", "esc", n);
        assert_eq!(prog.buffers().len(), 3);
        assert!(!prog.entry().is_empty());
    }
}

#[test]
fn callgraph_build_program_includes_call_site_buffers() {
    let prog = callgraph::callgraph_build("direct", "indirect", "pts_closure", "matrix");
    let mut names: Vec<&str> = prog.buffers().iter().map(|b| b.name()).collect();
    names.sort();
    assert!(names.contains(&"direct"), "missing direct in {names:?}");
    assert!(names.contains(&"indirect"), "missing indirect in {names:?}");
    assert!(
        names.contains(&"pts_closure"),
        "missing pts_closure in {names:?}"
    );
    assert!(names.contains(&"matrix"), "missing matrix in {names:?}");
    assert!(!prog.entry().is_empty());
}

#[test]
fn callgraph_build_with_count_scales() {
    for &n in &[1u32, 32, 256] {
        let prog = callgraph::callgraph_build_with_count("d", "i", "p", "m", n);
        assert!(prog.buffers().len() >= 4);
        assert!(!prog.entry().is_empty());
    }
}

#[test]
fn range_propagate_program_includes_dataflow_buffers() {
    let prog = range::range_propagate("defs", "edges", "ranges");
    let mut names: Vec<&str> = prog.buffers().iter().map(|b| b.name()).collect();
    names.sort();
    assert!(names.contains(&"defs"));
    assert!(names.contains(&"edges"));
    assert!(names.contains(&"ranges"));
    assert!(!prog.entry().is_empty());
}

#[test]
fn range_propagate_with_count_scales() {
    for &n in &[1u32, 32, 256] {
        let prog = range::try_range_propagate_with_count("d", "e", "r", n)
            .expect("range_propagate_with_count should build for scale case");
        assert!(prog.buffers().len() >= 3);
        assert!(!prog.entry().is_empty());
    }
}