weirflow 0.1.0

GPU-first dataflow analysis primitives for Vyre and Santh compiler pipelines.
Documentation
//! `weir::summary::summarize_function`, `weir::loop_sum::loop_summarize`,
//! `weir::points_to::andersen_points_to`  -  three more multi-buffer
//! primitives.
//!
//! Op id: `weir::tests::df::summary_loop_points`. Soundness:
//! `Exact` for summarize and loop_sum (deterministic OR-merge);
//! `MayOver` for andersen_points_to (subset-closure with a bound
//! on iteration depth). Tests pin the buffer set + entry-vector
//! non-emptiness for each variant.

use vyre_primitives::graph::program_graph::ProgramGraphShape;
use weir::loop_sum;
use weir::points_to;
use weir::summary;

#[test]
fn summarize_function_program_includes_four_buffers() {
    let prog = summary::summarize_function("fn_ast", "cg", "cached", "summary");
    let mut names: Vec<&str> = prog.buffers().iter().map(|b| b.name()).collect();
    names.sort();
    assert!(names.contains(&"fn_ast"));
    assert!(names.contains(&"cg"));
    assert!(names.contains(&"cached"));
    assert!(names.contains(&"summary"));
    assert_eq!(prog.buffers().len(), 4);
    assert!(!prog.entry().is_empty());
}

#[test]
fn summarize_function_with_count_scales() {
    for &n in &[1u32, 32, 256, 1024] {
        let prog = summary::summarize_function_with_count("a", "c", "h", "s", n);
        assert!(prog.buffers().len() >= 4);
        assert!(!prog.entry().is_empty());
    }
}

#[test]
fn loop_summarize_program_three_buffers() {
    let prog = loop_sum::loop_summarize("cfg", "ranges", "summary");
    let mut names: Vec<&str> = prog.buffers().iter().map(|b| b.name()).collect();
    names.sort();
    assert!(names.contains(&"cfg"));
    assert!(names.contains(&"ranges"));
    assert!(names.contains(&"summary"));
    assert!(!prog.entry().is_empty());
}

#[test]
fn loop_summarize_with_count_scales() {
    for &n in &[1u32, 32, 256] {
        let prog = loop_sum::try_loop_summarize_with_count("c", "r", "s", n)
            .expect("loop_summarize_with_count should build for scale case");
        assert!(prog.buffers().len() >= 3);
        assert!(!prog.entry().is_empty());
    }
}

#[test]
fn andersen_points_to_emits_required_buffers() {
    let shape = ProgramGraphShape::new(64, 64);
    let prog = points_to::andersen_points_to(shape, "constraints", "pts_out");
    let names: Vec<&str> = prog.buffers().iter().map(|b| b.name()).collect();
    assert!(
        names.contains(&"constraints"),
        "missing constraints in {names:?}"
    );
    assert!(names.contains(&"pts_out"), "missing pts_out in {names:?}");
    assert!(!prog.entry().is_empty());
}

#[test]
fn andersen_points_to_scales_with_shape() {
    for &(nodes, edges) in &[(1u32, 1u32), (32, 64), (256, 512)] {
        let shape = ProgramGraphShape::new(nodes, edges);
        let prog = points_to::andersen_points_to(shape, "constraints", "pts_out");
        assert!(prog.buffers().len() >= 2);
        assert!(!prog.entry().is_empty());
    }
}