sonatina_codegen/optim/
insn_simplify.rs1use std::collections::VecDeque;
4
5use sonatina_ir::{
6 func_cursor::{CursorLocation, FuncCursor, InsnInserter},
7 Function, Insn, InsnData, Value,
8};
9
10use super::simplify_impl::{simplify_insn, SimplifyResult};
11
12#[derive(Debug)]
13pub struct InsnSimplifySolver {
14 worklist: VecDeque<Insn>,
15}
16
17impl InsnSimplifySolver {
18 pub fn new() -> Self {
19 Self {
20 worklist: VecDeque::default(),
21 }
22 }
23
24 pub fn run(&mut self, func: &mut Function) {
25 let entry = match func.layout.entry_block() {
26 Some(entry) => entry,
27 None => return,
28 };
29 let mut inserter = InsnInserter::new(func, CursorLocation::BlockTop(entry));
30
31 while inserter.loc() != CursorLocation::NoWhere {
32 let insn = match inserter.insn() {
33 Some(insn) => insn,
34 None => {
35 inserter.proceed();
36 continue;
37 }
38 };
39
40 self.simplify(&mut inserter, insn);
41 }
42
43 while let Some(insn) = self.worklist.pop_front() {
44 if !inserter.func().layout.is_insn_inserted(insn) {
45 continue;
46 }
47
48 inserter.set_loc(CursorLocation::At(insn));
49 self.simplify(&mut inserter, insn);
50 }
51 }
52
53 pub fn simplify(&mut self, inserter: &mut InsnInserter, insn: Insn) {
54 match simplify_insn(&mut inserter.func_mut().dfg, insn) {
55 Some(SimplifyResult::Value(val)) => self.replace_insn_with_value(inserter, insn, val),
56
57 Some(SimplifyResult::Insn(data)) => {
58 self.replace_insn_with_data(inserter, insn, data);
59 }
60
61 None => inserter.proceed(),
62 }
63 }
64
65 pub fn clear(&mut self) {
66 self.worklist.clear();
67 }
68
69 pub fn replace_insn_with_value(
70 &mut self,
71 inserter: &mut InsnInserter,
72 insn: Insn,
73 value: Value,
74 ) {
75 if let Some(insn_result) = inserter.func().dfg.insn_result(insn) {
76 self.worklist
77 .extend(inserter.func().dfg.users(insn_result).copied());
78 self.worklist.push_back(insn);
79 inserter.func_mut().dfg.change_to_alias(insn_result, value);
80 };
81
82 inserter.remove_insn();
83 }
84
85 pub fn replace_insn_with_data(
86 &mut self,
87 inserter: &mut InsnInserter,
88 insn: Insn,
89 data: InsnData,
90 ) {
91 if let Some(res) = inserter.func().dfg.insn_result(insn) {
92 self.worklist
93 .extend(inserter.func().dfg.users(res).copied());
94 self.worklist.push_back(insn);
95 }
96
97 inserter.replace(data);
98 inserter.proceed();
99 }
100}
101
102impl Default for InsnSimplifySolver {
103 fn default() -> Self {
104 Self::new()
105 }
106}