use vyre_primitives::graph::dominator_frontier::cpu_ref as dominator_frontier_cpu;
#[must_use]
pub fn compute_dominance_frontier(
node_count: u32,
dom_offsets: &[u32],
dom_targets: &[u32],
pred_offsets: &[u32],
pred_targets: &[u32],
seed: &[u32],
) -> Vec<u32> {
use crate::observability::{bump, dataflow_fixpoint_calls};
bump(&dataflow_fixpoint_calls);
dominator_frontier_cpu(
node_count,
dom_offsets,
dom_targets,
pred_offsets,
pred_targets,
seed,
)
}
#[must_use]
pub fn frontier_size(frontier: &[u32]) -> u32 {
frontier.iter().map(|w| w.count_ones()).sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn frontier_of_linear_chain_is_empty() {
let dom_offsets = vec![0, 4, 7, 9, 10];
let dom_targets = vec![0, 1, 2, 3, 1, 2, 3, 2, 3, 3];
let pred_offsets = vec![0, 0, 1, 2, 3];
let pred_targets = vec![0, 1, 2];
let seed = vec![0b0001];
let frontier = compute_dominance_frontier(
4,
&dom_offsets,
&dom_targets,
&pred_offsets,
&pred_targets,
&seed,
);
assert_eq!(frontier, vec![0u32]);
assert_eq!(frontier_size(&frontier), 0);
}
#[test]
fn frontier_of_diamond_seed_is_merge_node() {
let dom_offsets = vec![0, 4, 5, 6, 7];
let dom_targets = vec![0, 1, 2, 3, 1, 2, 3];
let pred_offsets = vec![0, 0, 1, 2, 4];
let pred_targets = vec![0, 0, 1, 2];
let seed = vec![0b0010]; let frontier = compute_dominance_frontier(
4,
&dom_offsets,
&dom_targets,
&pred_offsets,
&pred_targets,
&seed,
);
assert_eq!(frontier, vec![0b1000]);
assert_eq!(frontier_size(&frontier), 1);
}
#[test]
fn matches_primitive_directly() {
let dom_offsets = vec![0, 4, 5, 6, 7];
let dom_targets = vec![0, 1, 2, 3, 1, 2, 3];
let pred_offsets = vec![0, 0, 1, 2, 4];
let pred_targets = vec![0, 0, 1, 2];
let seed = vec![0b0011];
let via_substrate = compute_dominance_frontier(
4,
&dom_offsets,
&dom_targets,
&pred_offsets,
&pred_targets,
&seed,
);
let via_primitive = dominator_frontier_cpu(
4,
&dom_offsets,
&dom_targets,
&pred_offsets,
&pred_targets,
&seed,
);
assert_eq!(via_substrate, via_primitive);
}
#[test]
fn empty_seed_yields_empty_frontier() {
let dom_offsets = vec![0, 4, 5, 6, 7];
let dom_targets = vec![0, 1, 2, 3, 1, 2, 3];
let pred_offsets = vec![0, 0, 1, 2, 4];
let pred_targets = vec![0, 0, 1, 2];
let seed = vec![0u32];
let frontier = compute_dominance_frontier(
4,
&dom_offsets,
&dom_targets,
&pred_offsets,
&pred_targets,
&seed,
);
assert_eq!(frontier, vec![0u32]);
assert_eq!(frontier_size(&frontier), 0);
}
#[test]
fn seed_dominating_everything_has_empty_frontier() {
let dom_offsets = vec![0, 4, 5, 6, 7];
let dom_targets = vec![0, 1, 2, 3, 1, 2, 3];
let pred_offsets = vec![0, 0, 1, 2, 4];
let pred_targets = vec![0, 0, 1, 2];
let seed = vec![0b0001];
let frontier = compute_dominance_frontier(
4,
&dom_offsets,
&dom_targets,
&pred_offsets,
&pred_targets,
&seed,
);
assert_eq!(frontier, vec![0u32]);
}
#[test]
fn frontier_size_counts_set_bits() {
assert_eq!(frontier_size(&[0u32]), 0);
assert_eq!(frontier_size(&[0b1011u32]), 3);
assert_eq!(frontier_size(&[0xFFFFFFFFu32, 0b1u32]), 33);
}
}