sonatina_codegen/optim/
insn_simplify.rs

1//! This module contains a solver for instruction simplification.
2
3use 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}