weirflow 0.1.0

GPU-first dataflow analysis primitives for Vyre and Santh compiler pipelines.
Documentation
//! Parity test: GPU loop-summarize widening matches reference oracle.

#![cfg(test)]

use vyre::DispatchConfig;
use vyre_driver_cuda::CudaBackend;
use weir::loop_sum::loop_summarize_borrowed_via;
use weir::oracle::summary::loop_summarize as loop_summarize_cpu;

fn run_dispatch(
    backend: &CudaBackend,
) -> impl Fn(&vyre::ir::Program, &[&[u8]], Option<[u32; 3]>) -> Result<Vec<Vec<u8>>, String> + '_ {
    move |program, inputs, grid_override| {
        let mut config = DispatchConfig::default();
        config.grid_override = grid_override;
        backend
            .dispatch_borrowed(program, inputs, &config)
            .map_err(|err| err.to_string())
    }
}

fn live_dispatcher() -> CudaBackend {
    CudaBackend::acquire()
        .expect("CudaBackend::acquire failed on a host that must have an NVIDIA GPU.")
}

#[test]
fn cuda_loop_summarize_widens_lo_to_neg_inf() {
    let backend = live_dispatcher();
    let dispatch = run_dispatch(&backend);
    // Var 0: prev=[10..20], new=[9..25] → lo widens to -∞ (0), hi widens to +∞.
    // Var 1: prev=[5..10], new=[6..9] → both kept.
    // Var 2: prev=[0..100], new=[0..90] → both kept.
    // Var 3: prev=[30..40], new=[29..41] → lo widens, hi widens.
    let cfg = vec![10u32, 20, 5, 10, 0, 100, 30, 40];
    let ranges = vec![9u32, 25, 6, 9, 0, 90, 29, 41];
    let cpu = loop_summarize_cpu(&cfg, &ranges, 4);
    let gpu = loop_summarize_borrowed_via(&dispatch, &cfg, &ranges, 4).expect("dispatch");
    assert_eq!(gpu, cpu);
    assert_eq!(gpu, vec![0u32, u32::MAX, 5, 10, 0, 100, 0, u32::MAX]);
}

#[test]
fn cuda_loop_summarize_stable_intervals_kept() {
    let backend = live_dispatcher();
    let dispatch = run_dispatch(&backend);
    let cfg = vec![5u32, 10, 100, 200];
    let ranges = vec![5u32, 10, 100, 200];
    let cpu = loop_summarize_cpu(&cfg, &ranges, 2);
    let gpu = loop_summarize_borrowed_via(&dispatch, &cfg, &ranges, 2).expect("dispatch");
    assert_eq!(gpu, cpu);
    assert_eq!(gpu, cfg);
}

#[test]
fn cuda_loop_summarize_only_lo_widens() {
    let backend = live_dispatcher();
    let dispatch = run_dispatch(&backend);
    // prev=[10..20], new=[5..20] → lo widens to 0, hi kept.
    let cfg = vec![10u32, 20];
    let ranges = vec![5u32, 20];
    let cpu = loop_summarize_cpu(&cfg, &ranges, 1);
    let gpu = loop_summarize_borrowed_via(&dispatch, &cfg, &ranges, 1).expect("dispatch");
    assert_eq!(gpu, cpu);
    assert_eq!(gpu, vec![0u32, 20]);
}

#[test]
fn cuda_loop_summarize_only_hi_widens() {
    let backend = live_dispatcher();
    let dispatch = run_dispatch(&backend);
    // prev=[10..20], new=[10..30] → lo kept, hi widens to u32::MAX.
    let cfg = vec![10u32, 20];
    let ranges = vec![10u32, 30];
    let cpu = loop_summarize_cpu(&cfg, &ranges, 1);
    let gpu = loop_summarize_borrowed_via(&dispatch, &cfg, &ranges, 1).expect("dispatch");
    assert_eq!(gpu, cpu);
    assert_eq!(gpu, vec![10u32, u32::MAX]);
}