pub fn dominators(
graph: &SqliteGraph,
entry: i64,
) -> Result<DominatorResult, SqliteGraphError>Expand description
Computes dominators and immediate dominators for a CFG entry node.
Uses Cooper et al.’s simple_fast iterative algorithm (2001) to compute:
- Full dominance sets: for each node, all nodes that dominate it
- Immediate dominator tree: each node’s closest strict dominator
§Arguments
graph- The control flow graph to analyzeentry- The entry node ID (must exist in graph)
§Returns
DominatorResult containing dominance sets and immediate dominator tree.
§Algorithm Steps
- Get all nodes: Fetch all entity IDs from the graph
- Initialize: Each node dominates all nodes (optimistic), entry dominates only itself
- Compute reverse postorder: DFS from entry, process nodes in postorder
- Iterate to fixed point:
- For each node in reverse postorder (except entry):
- Intersect all predecessors’ dominator sets
- Union with {node} (node dominates itself)
- Update if changed
- For each node in reverse postorder (except entry):
- Extract immediate dominators: Find closest strict dominator for each node
§Complexity
- Time: O(N²) worst case, O(E) to O(N log N) in practice
- Space: O(N²) for dominance sets
§Error Handling
- Returns
SqliteGraphError::NotFoundif entry node doesn’t exist - Handles unreachable nodes gracefully (they have empty/undefined dominators)
- Has iteration limit (1000) to prevent infinite loops
§Example
ⓘ
use sqlitegraph::{SqliteGraph, algo::dominators};
let graph = SqliteGraph::open_in_memory()?;
// ... build CFG ...
let result = dominators(&graph, 0)?;
// Check entry dominates all reachable nodes
for &node in result.dom.keys() {
assert!(result.dominates(0, node));
}
// Immediate dominator forms a tree
assert_eq!(result.immediate_dominator(0), None);