tenflowers_core/graph/optimization/passes/
dead_code.rs1use crate::graph::{Graph, NodeId};
6use crate::Result;
7use std::cell::RefCell;
8use std::collections::HashSet;
9
10use super::pass_support::{get_node_inputs, get_node_outputs, OptimizationPass};
11
12pub struct DeadCodeEliminationPass {
15 pub(super) outputs: RefCell<HashSet<NodeId>>,
16}
17impl DeadCodeEliminationPass {
18 pub fn new() -> Self {
19 Self {
20 outputs: RefCell::new(HashSet::new()),
21 }
22 }
23 pub fn with_outputs(outputs: HashSet<NodeId>) -> Self {
27 Self {
28 outputs: RefCell::new(outputs),
29 }
30 }
31 pub(super) fn is_output_node(&self, graph: &Graph, node_id: NodeId) -> bool {
32 let outputs = get_node_outputs(graph, node_id);
33 outputs.is_empty() || self.is_marked_as_output(node_id)
34 }
35 pub(super) fn is_marked_as_output(&self, node_id: NodeId) -> bool {
36 self.outputs.borrow().contains(&node_id)
37 }
38 #[allow(clippy::only_used_in_recursion)]
39 pub(super) fn mark_reachable(
40 &self,
41 graph: &Graph,
42 node_id: NodeId,
43 reachable: &mut HashSet<NodeId>,
44 ) {
45 if reachable.contains(&node_id) {
46 return;
47 }
48 reachable.insert(node_id);
49 for input_id in get_node_inputs(graph, node_id) {
50 self.mark_reachable(graph, input_id, reachable);
51 }
52 }
53}
54impl OptimizationPass for DeadCodeEliminationPass {
55 fn apply(&self, graph: &mut Graph) -> Result<bool> {
56 let mut changed = false;
57 let mut reachable = HashSet::new();
58 for node in graph.nodes() {
59 if self.is_output_node(graph, node.id) {
60 self.mark_reachable(graph, node.id, &mut reachable);
61 }
62 }
63 let mut nodes_to_remove = Vec::new();
64 for node in graph.nodes() {
65 if !reachable.contains(&node.id) {
66 nodes_to_remove.push(node.id);
67 changed = true;
68 }
69 }
70 for node_id in nodes_to_remove {
71 graph.remove_node(node_id)?;
72 }
73 Ok(changed)
74 }
75 fn name(&self) -> &str {
76 "DeadCodeElimination"
77 }
78 fn is_applicable(&self, graph: &Graph) -> bool {
79 graph.node_count() > 0
80 }
81 fn priority(&self) -> u32 {
82 50
83 }
84 fn set_outputs(&self, outputs: &HashSet<NodeId>) {
85 *self.outputs.borrow_mut() = outputs.clone();
86 }
87}
88impl Default for DeadCodeEliminationPass {
89 fn default() -> Self {
90 Self::new()
91 }
92}