dpc/passes/opt/
dce.rs

1use rustc_hash::FxHashSet;
2
3use crate::passes::{MIRPass, MIRPassData, Pass};
4use crate::project::{OptimizationLevel, ProjectSettings};
5
6use super::get_instr_calls;
7
8pub struct DCEPass;
9
10impl Pass for DCEPass {
11	fn get_name(&self) -> &'static str {
12		"dead_code_elimination"
13	}
14
15	fn should_run(&self, proj: &ProjectSettings) -> bool {
16		proj.op_level >= OptimizationLevel::Basic
17	}
18}
19
20impl MIRPass for DCEPass {
21	fn run_pass(&mut self, data: &mut MIRPassData) -> anyhow::Result<()> {
22		// Find used functions
23		let mut used = FxHashSet::default();
24		for func in data.mir.functions.values() {
25			let block = &func.block;
26
27			for instr in &block.contents {
28				let calls = get_instr_calls(&instr.kind);
29				for call in calls {
30					used.insert(call.function.clone());
31				}
32			}
33		}
34
35		// Remove unused functions
36		let mut unused = FxHashSet::default();
37		for (func_id, func) in &data.mir.functions {
38			if func.interface.annotations.preserve {
39				continue;
40			}
41			if !used.contains(func_id) {
42				unused.insert(func_id.clone());
43			}
44		}
45		for unused in unused {
46			data.mir.functions.remove(&unused);
47		}
48
49		Ok(())
50	}
51}