MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
sccp.cpp
Go to the documentation of this file.
1#include "mim/phase/sccp.h"
2
3#include <absl/container/fixed_array.h>
4
5namespace mim {
6
8 int i = 0;
9 while (todo_) {
10 ILOG("iter: {}", i++);
11 todo_ = false;
12 visited_.clear();
13 for (auto def : old_world().annexes())
14 concr2abstr(init(def));
15 for (auto def : old_world().externals().muts())
16 concr2abstr(init(def));
17 }
18
19 return false; // no fixed-point necessary
20}
21
22const Def* SCCP::init(const Def* def) {
23 if (auto mut = def->isa_mut()) return init(mut);
24 return def;
25}
26
27const Def* SCCP::init(Def* mut) {
28 if (auto var = mut->has_var()) concr2abstr(var, var);
29 return mut;
30}
31
32const Def* SCCP::concr2abstr(const Def* concr) {
33 if (auto [_, ins] = visited_.emplace(concr); !ins) {
34 if (auto i = concr2abstr_.find(concr); i != concr2abstr_.end()) return i->second;
35 // in some rare cyclic cases we haven't built the immutable yet
36 }
37
38 if (auto mut = concr->isa_mut()) {
39 concr2abstr(mut, mut);
40 init(mut);
41 for (auto d : mut->deps())
42 concr2abstr(d);
43 return mut;
44 }
45
46 return concr2abstr(concr, concr2abstr_impl(concr)).first;
47}
48
49const Def* SCCP::concr2abstr_impl(const Def* def) {
50 if (auto type = def->type()) concr2abstr(type);
51
52 if (auto branch = Branch(def)) {
53 auto abstr = concr2abstr(branch.cond());
54 auto l = Lit::isa<bool>(abstr);
55 if (l && *l) return concr2abstr(branch.tt());
56 if (l && !*l) return concr2abstr(branch.ff());
57 } else if (auto app = def->isa<App>()) {
58 if (auto lam = app->callee()->isa_mut<Lam>(); lam && lam->is_set()) {
59 auto ins = concr2abstr(lam, lam).second;
60
61 auto n = app->num_args();
62 auto abstr_args = absl::FixedArray<const Def*>(n);
63 auto abstr_vars = absl::FixedArray<const Def*>(n);
64 for (size_t i = 0; i != n; ++i) {
65 auto abstr = concr2abstr(app->targ(i));
66 abstr_vars[i] = concr2abstr(lam->tvar(i), abstr).first;
67 abstr_args[i] = abstr;
68 }
69
70 concr2abstr(lam->var(), old_world().tuple(abstr_vars));
71
72 if (ins)
73 for (auto d : lam->deps())
74 concr2abstr(d);
75
76 return old_world().app(lam, abstr_args);
77 }
78 } else if (auto var = def->isa<Var>()) {
79 assert(var->mut()->isa<Lam>());
80 return old_world().bot(var->type());
81 }
82
83 auto n = def->num_ops();
84 auto abstrs = absl::FixedArray<const Def*>(n);
85 for (size_t i = 0; i != n; ++i)
86 abstrs[i] = concr2abstr(def->op(i));
87
88 return def->rebuild(old_world(), def->type(), abstrs);
89}
90
91std::pair<const Def*, bool> SCCP::concr2abstr(const Def* concr, const Def* abstr) {
92 auto [_, v_ins] = visited_.emplace(concr);
93 auto [i, c2a_ins] = concr2abstr_.emplace(concr, abstr);
94
95 if (c2a_ins)
96 todo_ = true;
97 else
98 i->second = join(concr, i->second, abstr);
99
100 return {i->second, v_ins};
101}
102
103const Def* SCCP::join(const Def* concr, const Def* abstr1, const Def* abstr2) {
104 const Def* result = nullptr;
105 if (abstr1 == abstr2) return abstr1;
106
107 if (abstr1->isa<Bot>())
108 result = abstr2;
109 else if (abstr2->isa<Bot>())
110 result = abstr1;
111 else // abstr1 != abstr2
112 result = concr;
113
114 todo_ |= abstr1 != result;
115 return result;
116}
117
118const Def* SCCP::rewrite_imm_App(const App* old_app) {
119 if (auto old_lam = old_app->callee()->isa_mut<Lam>(); old_lam && old_lam->is_set() && !old_lam->is_external()) {
120 if (old_lam->has_var()) {
121 size_t num_old = old_lam->num_vars();
122
123 Lam* new_lam;
124 if (auto i = lam2lam_.find(old_lam); i != lam2lam_.end())
125 new_lam = i->second;
126 else {
127 // build new dom
128 auto new_doms = DefVec();
129 for (size_t i = 0; i != num_old; ++i) {
130 auto old_var = old_lam->var(num_old, i);
131 auto abstr = concr2abstr_[old_var];
132 if (abstr == old_var) new_doms.emplace_back(rewrite(old_lam->tdom(i)));
133 }
134
135 // build new lam
136 size_t num_new = new_doms.size();
137 auto new_vars = absl::FixedArray<const Def*>(num_old);
138 new_lam = new_world().mut_lam(new_doms, rewrite(old_lam->codom()))->set(old_lam->dbg());
139 lam2lam_[old_lam] = new_lam;
140
141 // build new var
142 for (size_t i = 0, j = 0; i != num_old; ++i) {
143 auto old_var = old_lam->var(num_old, i);
144 auto abstr = concr2abstr_[old_var];
145 new_vars[i] = abstr == old_var ? new_lam->var(num_new, j++) : rewrite(abstr);
146 }
147
148 map(old_lam->var(), new_vars);
149 new_lam->set(rewrite(old_lam->filter()), rewrite(old_lam->body()));
150 }
151
152 // build new app
153 size_t num_new = new_lam->num_vars();
154 auto new_args = absl::FixedArray<const Def*>(num_new);
155 for (size_t i = 0, j = 0; i != num_old; ++i) {
156 auto old_var = old_lam->var(num_old, i);
157 auto abstr = concr2abstr_[old_var];
158 if (abstr == old_var) new_args[j++] = rewrite(old_app->targ(i));
159 }
160
161 return map(old_app, new_world().app(new_lam, new_args));
162 }
163 }
164
165 return Rewriter::rewrite_imm_App(old_app);
166}
167
168} // namespace mim
const Def * callee() const
Definition lam.h:277
Base class for all Defs.
Definition def.h:251
bool is_set() const
Yields true if empty or the last op is set.
Definition def.cpp:295
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:485
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:429
nat_t num_vars() noexcept
Definition def.h:429
A function.
Definition lam.h:111
Lam * set(Filter filter, const Def *body)
Definition lam.cpp:29
static std::optional< T > isa(const Def *def)
Definition def.h:824
World & new_world()
Create new Defs into this.
Definition phase.h:100
World & old_world()
Get old Defs from here.
Definition phase.h:99
virtual const Def * map(const Def *old_def, const Def *new_def)
Definition rewrite.h:59
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:27
const Def * rewrite_imm_App(const App *) final
Definition sccp.cpp:118
bool analyze() final
You can do an optional fixed-point loop on the RWPhase::old_world before rewriting.
Definition sccp.cpp:7
const Type * type(const Def *level)
Definition world.cpp:107
const Def * app(const Def *callee, const Def *arg)
Definition world.cpp:199
const Def * bot(const Def *type)
Definition world.h:502
Lam * mut_lam(const Pi *pi)
Definition world.h:323
#define ILOG(...)
Definition log.h:91
Definition ast.h:14
Vector< const Def * > DefVec
Definition def.h:77
TExt< false > Bot
Definition lattice.h:171
@ Lam
Definition def.h:114
@ Var
Definition def.h:114
@ App
Definition def.h:114