duskphantom_middle/transform/
load_elim.rs1use anyhow::Result;
18
19use crate::{
20 analysis::memory_ssa::{MemorySSA, Node},
21 ir::{instruction::InstType, FunPtr, InstPtr},
22 Program,
23};
24
25use super::Transform;
26
27pub fn optimize_program<'a>(
28 program: &'a mut Program,
29 memory_ssa: &'a mut MemorySSA,
30) -> Result<bool> {
31 LoadElim::new(program, memory_ssa).run_and_log()
32}
33
34pub struct LoadElim<'a, 'b> {
35 program: &'a mut Program,
36 memory_ssa: &'a mut MemorySSA<'b>,
37}
38
39impl<'a, 'b> Transform for LoadElim<'a, 'b> {
40 fn get_program_mut(&mut self) -> &mut Program {
41 self.program
42 }
43
44 fn name() -> String {
45 "load_elim".to_string()
46 }
47
48 fn run(&mut self) -> Result<bool> {
49 let mut changed = false;
50 for func in self.program.module.functions.clone() {
51 if func.is_lib() {
52 continue;
53 }
54 for bb in func.rpo_iter() {
55 for inst in bb.iter() {
56 changed |= self.process_inst(inst, func)?;
57 }
58 }
59 }
60 Ok(changed)
61 }
62}
63
64impl<'a, 'b> LoadElim<'a, 'b> {
65 pub fn new(program: &'a mut Program, memory_ssa: &'a mut MemorySSA<'b>) -> Self {
66 Self {
67 program,
68 memory_ssa,
69 }
70 }
71
72 fn process_inst(&mut self, mut inst: InstPtr, func: FunPtr) -> Result<bool> {
73 if inst.get_type() != InstType::Load {
75 return Ok(false);
76 }
77
78 let Some(load_node) = self.memory_ssa.get_inst_node(inst) else {
80 return Ok(false);
81 };
82
83 let Node::Normal(_, Some(src), _, _) = load_node.as_ref() else {
85 return Ok(false);
86 };
87
88 let predicted = self.memory_ssa.predict_read(*src, inst, func)?;
90
91 if let Some(predicted) = predicted {
93 inst.replace_self(&predicted);
94 self.memory_ssa.remove_node(load_node);
95 return Ok(true);
96 }
97 Ok(false)
98 }
99}