weirflow 0.1.0

GPU-first dataflow analysis primitives for Vyre and Santh compiler pipelines.
Documentation
use super::*;

#[test]
fn cuda_reaching_resident_sequence_window_uses_final_convergence_readback_only() {
    let backend = CudaBackendRegistration::new(live_dispatcher());
    let edge_offsets = vec![0u32, 1, 2, 3, 4, 4];
    let edge_targets = vec![1u32, 2, 3, 4];
    let edge_kind_mask = vec![edge_kind::CONTROL; 4];
    let seed_bits = vec![0b00001u32];
    let cpu = reaching_closure_cpu(5, &edge_offsets, &edge_targets, &edge_kind_mask, &seed_bits);
    let plan = prepare_reaching_plan(5, &edge_offsets, &edge_targets, &edge_kind_mask)
        .expect("reaching plan must prepare for sequence-window resident CUDA parity");
    let config = DispatchConfig::default();
    let pipeline = backend
        .compile_native(plan.program(), &config)
        .expect("CUDA native compile must succeed for resident reaching sequence-window parity")
        .expect("CUDA backend registration must return a native compiled pipeline for resident reaching sequence-window parity");
    let resident_plan = FixedPointResidentPlan::new(&backend, plan.graph(), pipeline)
        .expect("CUDA backend must upload reaching sequence-window resident plan resources");
    let mut scratch = weir::fixed_point_scratch::FixedPointScratch::default();
    let mut resident_frontier = FixedPointResidentFrontierScratch::default();

    backend.reset_telemetry();
    let gpu = resident_plan
        .reaching_reusing_frontier_sequence_window(
            &backend,
            &plan,
            &seed_bits,
            16,
            &mut scratch,
            &mut resident_frontier,
        )
        .expect("sequence-window resident CUDA reaching dispatch must converge");
    let telemetry = backend.telemetry_snapshot();

    assert_eq!(gpu, cpu);
    assert_eq!(gpu, vec![0b11111u32]);
    assert_eq!(
        telemetry.readback_bytes, 8,
        "Fix: sequence-window reaching resident solve must read only final frontier plus one changed flag, not poll every iteration."
    );
    assert!(
        telemetry.sync_points < 16,
        "Fix: sequence-window reaching resident solve must not synchronize once per fixed-point iteration; observed {} sync points.",
        telemetry.sync_points
    );
    assert!(
        telemetry.param_upload_bytes < telemetry.kernel_launches.saturating_mul(4),
        "Fix: sequence-window reaching resident solve must hoist repeated fixed-point launch parameter uploads; observed {} parameter bytes across {} launches.",
        telemetry.param_upload_bytes,
        telemetry.kernel_launches
    );
    resident_plan
        .free_with_frontier(&backend, &mut resident_frontier)
        .expect("sequence-window resident reaching plan and frontier resources must free cleanly");
}

#[test]
fn cuda_reaching_resident_sequence_window_reads_changed_flag_not_previous_frontier() {
    let backend = CudaBackendRegistration::new(live_dispatcher());
    let node_count = 65_u32;
    let edge_offsets = (0..=node_count)
        .map(|node| node.min(node_count - 1))
        .collect::<Vec<_>>();
    let edge_targets = (1..node_count).collect::<Vec<_>>();
    let edge_kind_mask = vec![edge_kind::CONTROL; edge_targets.len()];
    let seed_bits = vec![1u32, 0, 0];
    let cpu = reaching_closure_cpu(
        node_count,
        &edge_offsets,
        &edge_targets,
        &edge_kind_mask,
        &seed_bits,
    );
    let plan = prepare_reaching_plan(node_count, &edge_offsets, &edge_targets, &edge_kind_mask)
        .expect("multiword reaching plan must prepare for resident CUDA changed-flag parity");
    let config = DispatchConfig::default();
    let pipeline = backend
        .compile_native(plan.program(), &config)
        .expect("CUDA native compile must succeed for multiword resident reaching sequence-window parity")
        .expect("CUDA backend registration must return a native compiled pipeline for multiword resident reaching sequence-window parity");
    let resident_plan = FixedPointResidentPlan::new(&backend, plan.graph(), pipeline).expect(
        "CUDA backend must upload multiword reaching sequence-window resident plan resources",
    );
    let mut scratch = weir::fixed_point_scratch::FixedPointScratch::default();
    let mut resident_frontier = FixedPointResidentFrontierScratch::default();

    backend.reset_telemetry();
    let gpu = resident_plan
        .reaching_reusing_frontier_sequence_window(
            &backend,
            &plan,
            &seed_bits,
            128,
            &mut scratch,
            &mut resident_frontier,
        )
        .expect("multiword changed-flag resident CUDA reaching dispatch must converge");
    let telemetry = backend.telemetry_snapshot();

    assert_eq!(gpu, cpu);
    assert_eq!(gpu, vec![u32::MAX, u32::MAX, 1]);
    assert_eq!(
        telemetry.readback_bytes, 16,
        "Fix: multiword changed-flag sequence window must read one 4-byte changed flag plus the 12-byte final frontier; reading a previous frontier would be 24 bytes."
    );
    assert!(
        telemetry.sync_points <= 2,
        "Fix: changed-flag sequence window must use one seed-upload fence and one resident-window fence, not per-iteration synchronization; observed {} sync points.",
        telemetry.sync_points
    );
    resident_plan
        .free_with_frontier(&backend, &mut resident_frontier)
        .expect("multiword sequence-window resident reaching resources must free cleanly");
}