Skip to main content

weir/
value_set.rs

1//! `value_set`  -  constant-value set: enumerate constants reachable
2//! to a node. Used by dataflow consumers for "magic-number reaches sink"
3//! patterns.
4
5use vyre::ir::Program;
6use vyre_primitives::bitset::and::bitset_and;
7use vyre_primitives::graph::csr_forward_traverse::bitset_words;
8
9pub(crate) const OP_ID: &str = "weir::value_set";
10
11/// Build a value-set query Program.
12///
13/// Inputs:
14/// - `const_in_buf`: per-node bitset where bit `n` is set iff some
15///   constant value reaches the entry of `n`
16///   (host-supplied via constant propagation).
17/// - `query_set`:    per-node bitset of nodes being queried.
18/// - `out`:          per-node bitset; bit `n` set iff `n` is in
19///   `query_set` AND has a reaching constant.
20#[must_use]
21pub fn value_set(node_count: u32, const_in_buf: &str, query_set: &str, out: &str) -> Program {
22    let words = bitset_words(node_count);
23    vyre_harness::region::tag_program(OP_ID, bitset_and(const_in_buf, query_set, out, words))
24}
25
26/// reference oracle.
27#[must_use]
28#[cfg(any(test, feature = "cpu-parity"))]
29#[deprecated(
30    note = "reference oracle only; production code must dispatch the Weir Program on a concrete GPU backend or use weir::oracle for parity evidence"
31)]
32pub(crate) fn cpu_ref(const_in: &[u32], query_set: &[u32]) -> Vec<u32> {
33    vyre_primitives::bitset::and::cpu_ref(const_in, query_set)
34}
35
36/// Soundness marker for [`value_set`].
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
38pub struct ValueSet;
39impl super::soundness::SoundnessTagged for ValueSet {
40    fn soundness(&self) -> super::soundness::Soundness {
41        super::soundness::Soundness::MayOver
42    }
43}
44
45inventory::submit! {
46    vyre_harness::OpEntry::new(
47        OP_ID,
48        || value_set(4, "consts", "query", "out"),
49        Some(|| {
50            let u32s = crate::dispatch_decode::pack_u32;
51            vec![vec![u32s(&[0b1111]), u32s(&[0b0011]), u32s(&[0])]]
52        }),
53        Some(|| {
54            let u32s = crate::dispatch_decode::pack_u32;
55            vec![vec![u32s(&[0b0011])]]
56        }),
57    )
58}
59
60#[cfg(test)]
61#[allow(deprecated)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn constants_reach_query() {
67        assert_eq!(cpu_ref(&[0b1111], &[0b0011]), vec![0b0011]);
68    }
69
70    #[test]
71    fn no_constants_yields_empty() {
72        assert_eq!(cpu_ref(&[0], &[0xFFFF]), vec![0]);
73    }
74
75    #[test]
76    fn empty_query_yields_empty() {
77        assert_eq!(cpu_ref(&[0xFFFF], &[0]), vec![0]);
78    }
79
80    #[test]
81    fn distributes_over_words() {
82        let r = cpu_ref(&[0xFF00, 0x00FF], &[0x0FF0, 0x0FF0]);
83        assert_eq!(r, vec![0x0F00, 0x00F0]);
84    }
85}