weirflow 0.1.0

GPU-first dataflow analysis primitives for Vyre and Santh compiler pipelines.
Documentation
//! Parity test: GPU-resident dominator-set construction matches the CPU
//! reference oracle.

#![cfg(test)]

use vyre::DispatchConfig;
use vyre_driver_cuda::CudaBackend;
use weir::oracle::graph::{dominator_sets as compute_cpu, dominator_sets_via as compute_via};

fn run_dispatch(
    backend: &CudaBackend,
) -> impl Fn(&vyre::ir::Program, &[Vec<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(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_dominators_chain() {
    let backend = live_dispatcher();
    let dispatch = run_dispatch(&backend);
    let succ = vec![vec![1u32], vec![2], vec![3], vec![]];
    let cpu = compute_cpu(4, &succ, 0);
    let gpu = compute_via(&dispatch, 4, &succ, 0, 32).expect("dispatch");
    assert_eq!(gpu, cpu, "chain dominator divergence");
}

#[test]
fn cuda_dominators_diamond() {
    let backend = live_dispatcher();
    let dispatch = run_dispatch(&backend);
    // 0 -> {1, 2} -> 3.
    let succ = vec![vec![1u32, 2], vec![3], vec![3], vec![]];
    let cpu = compute_cpu(4, &succ, 0);
    let gpu = compute_via(&dispatch, 4, &succ, 0, 32).expect("dispatch");
    assert_eq!(gpu, cpu, "diamond dominator divergence");
}

#[test]
fn cuda_dominators_deep_nest() {
    let backend = live_dispatcher();
    let dispatch = run_dispatch(&backend);
    // 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7.
    let succ: Vec<Vec<u32>> = (0..8u32)
        .map(|i| if i + 1 < 8 { vec![i + 1] } else { vec![] })
        .collect();
    let cpu = compute_cpu(8, &succ, 0);
    let gpu = compute_via(&dispatch, 8, &succ, 0, 32).expect("dispatch");
    assert_eq!(gpu, cpu, "deep-nest dominator divergence");
}

#[test]
fn cuda_dominators_loop_with_back_edge() {
    let backend = live_dispatcher();
    let dispatch = run_dispatch(&backend);
    // 0 -> 1 -> 2 -> 3, 2 -> 1 (back-edge).
    let succ = vec![vec![1u32], vec![2], vec![1, 3], vec![]];
    let cpu = compute_cpu(4, &succ, 0);
    let gpu = compute_via(&dispatch, 4, &succ, 0, 32).expect("dispatch");
    assert_eq!(gpu, cpu, "loop dominator divergence");
}

#[test]
fn cuda_dominators_disconnected() {
    let backend = live_dispatcher();
    let dispatch = run_dispatch(&backend);
    let succ = vec![vec![1u32], vec![], vec![]];
    let cpu = compute_cpu(3, &succ, 0);
    let gpu = compute_via(&dispatch, 3, &succ, 0, 32).expect("dispatch");
    assert_eq!(gpu, cpu, "disconnected dominator divergence");
}