kecc/opt/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
mod deadcode;
mod gvn;
mod mem2reg;
pub(crate) mod opt_utils;
mod simplify_cfg;

pub use deadcode::Deadcode;
pub use gvn::Gvn;
pub use mem2reg::Mem2reg;
pub use simplify_cfg::{
    SimplifyCfg, SimplifyCfgConstProp, SimplifyCfgEmpty, SimplifyCfgMerge, SimplifyCfgReach,
};

use crate::ir;

pub trait Optimize<T> {
    fn optimize(&mut self, code: &mut T) -> bool;
}

pub type O0 = Null;
pub type O1 = Repeat<(SimplifyCfg, (Mem2reg, (Gvn, Deadcode)))>;

#[derive(Default, Clone, Copy, Debug)]
pub struct Null;

#[derive(Default, Debug)]
pub struct Repeat<O> {
    inner: O,
}

#[derive(Default, Debug)]
pub struct FunctionPass<T: Optimize<ir::FunctionDefinition>> {
    inner: T,
}

impl Optimize<ir::TranslationUnit> for Null {
    fn optimize(&mut self, _code: &mut ir::TranslationUnit) -> bool {
        false
    }
}

impl<T, O1: Optimize<T>, O2: Optimize<T>> Optimize<T> for (O1, O2) {
    fn optimize(&mut self, code: &mut T) -> bool {
        self.0.optimize(code) | self.1.optimize(code)
    }
}

impl<T, O: Optimize<T>> Optimize<T> for Repeat<O> {
    fn optimize(&mut self, code: &mut T) -> bool {
        if !self.inner.optimize(code) {
            return false;
        }

        while self.inner.optimize(code) {}
        true
    }
}

impl<T> Optimize<ir::TranslationUnit> for FunctionPass<T>
where
    T: Optimize<ir::FunctionDefinition>,
{
    fn optimize(&mut self, code: &mut ir::TranslationUnit) -> bool {
        code.decls
            .values_mut()
            .fold(false, |b, decl| b | self.optimize(decl))
    }
}

impl<T> Optimize<ir::Declaration> for FunctionPass<T>
where
    T: Optimize<ir::FunctionDefinition>,
{
    fn optimize(&mut self, code: &mut ir::Declaration) -> bool {
        let Some((_, Some(fdef))) = code.get_function_mut() else {
            return false;
        };
        self.inner.optimize(fdef)
    }
}