use vyre::ir::Program;
use vyre_primitives::bitset::and_not::bitset_and_not;
use vyre_primitives::graph::csr_forward_traverse::bitset_words;
pub(crate) const OP_ID: &str = "weir::control_dependence";
#[must_use]
pub fn control_dependence(
node_count: u32,
successor_pdom: &str,
pdom_n: &str,
out: &str,
) -> Program {
let words = bitset_words(node_count);
vyre_harness::region::tag_program(OP_ID, bitset_and_not(successor_pdom, pdom_n, out, words))
}
#[must_use]
#[cfg(any(test, feature = "cpu-parity"))]
#[deprecated(
note = "reference oracle only; production code must dispatch the Weir Program on a concrete GPU backend or use weir::oracle for parity evidence"
)]
pub(crate) fn cpu_ref(successor_pdom: &[u32], pdom_n: &[u32]) -> Vec<u32> {
vyre_primitives::bitset::and_not::cpu_ref(successor_pdom, pdom_n)
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ControlDependence;
impl super::soundness::SoundnessTagged for ControlDependence {
fn soundness(&self) -> super::soundness::Soundness {
super::soundness::Soundness::Exact
}
}
inventory::submit! {
vyre_harness::OpEntry::new(
OP_ID,
|| control_dependence(4, "succ_pdom", "pdom", "out"),
Some(|| {
let u32s = crate::dispatch_decode::pack_u32;
vec![vec![u32s(&[0b1111]), u32s(&[0b0001]), u32s(&[0])]]
}),
Some(|| {
let u32s = crate::dispatch_decode::pack_u32;
vec![vec![u32s(&[0b1110])]]
}),
)
}
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use super::*;
#[test]
fn classical_control_dep() {
assert_eq!(cpu_ref(&[0b1111], &[0b0001]), vec![0b1110]);
}
#[test]
fn full_pdom_means_no_control_dep() {
assert_eq!(cpu_ref(&[0xFFFF], &[0xFFFF]), vec![0]);
}
#[test]
fn no_pdom_gives_full_control_dep() {
assert_eq!(cpu_ref(&[0xFFFF], &[0]), vec![0xFFFF]);
}
#[test]
fn empty_succ_pdom_yields_empty() {
assert_eq!(cpu_ref(&[0], &[0xFFFF]), vec![0]);
}
}