MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
phase.cpp
Go to the documentation of this file.
1#include "mim/phase.h"
2
3#include <memory>
4
5#include "mim/driver.h"
6
7namespace mim {
8
9/*
10 * Phase
11 */
12
13void Phase::run() {
14 world().verify().ILOG("🚀 Phase launch: `{}`", name());
15 start();
16 world().verify().ILOG("🏁 Phase finish: `{}`", name());
17}
18
19/*
20 * Analyzer
21 */
22
24 old2news_.clear();
25 push();
26 todo_ = false;
27}
28
30 for (const auto& [flags, e] : world().annexes())
31 rewrite_annex(flags, e.sym, e.def);
32
33 bootstrapping_ = false;
34
35 for (auto mut : world().externals().muts())
37}
38
39void Analysis::rewrite_annex(flags_t, Sym, const Def* def) { rewrite(def); }
41
43 auto _ = enter(mut);
44
45 for (auto d : mut->deps())
46 rewrite(d);
47
48 return mut;
49}
50
52 map(mut, mut);
53
54 if (auto [lam, var] = mut->isa_binder<Lam>(); lam)
55 for (auto v : var->tprojs()) {
56 map(v, v);
57 if (auto [i, ins] = lattice_.emplace(v, v); !ins && i->second != v) {
58 // var was mapped to sth else beforehand so we need another fixed-point round
59 invalidate();
60 i->second = v;
61 }
62 }
63
64 return rewrite_deps(mut);
65}
66
67/*
68 * RWPhase
69 */
70
72 int i = 0;
73 for (bool todo = true; todo;) {
74 VLOG("iteration: {}", i++);
75 todo = false;
76 todo |= analyze();
77 }
78
79 for (const auto& [flags, e] : old_world().annexes())
80 rewrite_annex(flags, e.sym, e.def);
81
82 bootstrapping_ = false;
83
84 for (auto mut : old_world().externals().muts())
86
88}
89
91 if (analysis_) {
92 analysis_->reset();
93 analysis_->run();
94 return analysis_->todo();
95 }
96
97 return false;
98}
99
100void RWPhase::rewrite_annex(flags_t f, Sym sym, const Def* def) { new_world().annexes().attach(f, sym, rewrite(def)); }
101
103 auto new_mut = rewrite(old_mut)->as_mut();
104 if (old_mut->is_external()) new_mut->externalize();
105}
106
107/*
108 * ReplMan
109 */
110
112 for (auto&& repl : repls)
113 if (auto&& man = repl->isa<ReplMan>())
114 apply(std::move(man->repls_));
115 else
116 add(std::move(repl));
117}
118
119void ReplMan::apply(const App* app) {
120 auto repls = Repls();
121 for (auto arg : app->args())
122 if (auto stage = Stage::create(driver().stages(), arg))
123 repls.emplace_back(std::unique_ptr<Repl>(static_cast<Repl*>(stage.release())));
124
125 apply(std::move(repls));
126}
127
128/*
129 * ReplManPhase
130 */
131
132void ReplManPhase::apply(const App* app) {
133 man_ = std::make_unique<ReplMan>(old_world(), annex());
134 auto repls = Repls();
135 for (auto arg : app->args())
136 if (auto stage = Phase::create(driver().stages(), arg))
137 repls.emplace_back(std::unique_ptr<Repl>(static_cast<Repl*>(stage.release())));
138 man_->apply(std::move(repls));
139}
140
142 auto& rmp = static_cast<ReplManPhase&>(stage);
143 swap(man_, rmp.man_);
144}
145
147 old_world().verify().ILOG("🔥 run");
148 for (auto&& repl : man().repls())
149 ILOG(" 🔹 `{}`", repl->name());
152}
153
154const Def* ReplManPhase::rewrite(const Def* def) {
155 for (bool todo = true; todo;) {
156 todo = false;
157 for (auto&& repl : man().repls())
158 if (auto subst = repl->replace(def)) todo = true, def = subst;
159 }
160
161 return Rewriter::rewrite(def);
162}
163
164/*
165 * PhaseMan
166 */
167
168void PhaseMan::apply(bool fp, Phases&& phases) {
169 fixed_point_ = fp;
170 phases_ = std::move(phases);
171 name_ += fixed_point_ ? " tt" : " ff";
172}
173
174void PhaseMan::apply(const App* app) {
175 auto [fp, args] = app->uncurry_args<2>();
176
177 auto phases = Phases();
178 for (auto arg : args->projs())
179 if (auto stage = create(driver().stages(), arg)) {
180 // clang-format off
181 if (auto pm = stage->isa<PassManPhase>(); pm && pm-> man().empty()) continue;
182 if (auto rp = stage->isa<ReplMan >(); rp && rp->repls().empty()) continue;
183 // clang-format on
184 phases.emplace_back(std::unique_ptr<Phase>(static_cast<Phase*>(stage.release())));
185 }
186
187 apply(Lit::as<bool>(fp), std::move(phases));
188}
189
190void PhaseMan::apply(Stage& stage) {
191 auto& man = static_cast<PhaseMan&>(stage);
192 Phases new_phases;
193 for (auto& old_phase : man.phases())
194 new_phases.emplace_back(std::unique_ptr<Phase>(static_cast<Phase*>(old_phase->recreate().release())));
195 apply(man.fixed_point(), std::move(new_phases));
196}
197
199 int iter = 0;
200 for (bool todo = true; todo; ++iter) {
201 todo = false;
202
203 if (fixed_point()) VLOG("🔄 fixed-point iteration: {}", iter);
204
205 for (auto& phase : phases()) {
206 phase->run();
207 todo |= phase->todo();
208 }
209
210 todo &= fixed_point();
211
212 if (todo) {
213 for (auto& old_phase : phases()) {
214 auto new_phase = std::unique_ptr<Phase>(static_cast<Phase*>(old_phase->recreate().release()));
215 swap(new_phase, old_phase);
216 }
217 }
218
220 }
221}
222
223/*
224 * PassManPhase
225 */
226
227void PassManPhase::apply(const App* app) {
228 man_ = std::make_unique<PassMan>(world(), annex());
229 auto passes = Passes();
230 for (auto arg : app->args())
231 if (auto stage = Phase::create(driver().stages(), arg))
232 passes.emplace_back(std::unique_ptr<Pass>(static_cast<Pass*>(stage.release())));
233
234 man_->apply(std::move(passes));
235}
236
238 auto& pmp = static_cast<PassManPhase&>(stage);
239 swap(man_, pmp.man_);
240}
241
242} // namespace mim
void start() override
Actual entry.
Definition phase.cpp:29
virtual void rewrite_annex(flags_t, Sym, const Def *)
Definition phase.cpp:39
Enter enter(Def *new_mut)
Definition phase.h:140
World & world()
Definition phase.h:102
Def2Def lattice_
Definition phase.h:165
virtual void rewrite_external(Def *)
Definition phase.cpp:40
virtual Def * rewrite_deps(Def *)
Walks mut's dependencies under its curr_mut() scope.
Definition phase.cpp:42
virtual void reset()
Clears the rewriter map and resets Phase::todo() for the next fixed-point iteration.
Definition phase.cpp:23
Def * rewrite_mut(Def *) override
Default "visit a mutable" entry point: maps mut -> mut, seeds Lam binder vars to top (v -> v) in the ...
Definition phase.cpp:51
static auto uncurry_args(const Def *def)
Definition lam.h:329
Base class for all Defs.
Definition def.h:246
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Definition def.h:502
Defs deps() const noexcept
Definition def.cpp:475
std::pair< D *, const Var * > isa_binder() const
Is this a mutable that introduces a Var?
Definition def.h:439
bool is_external() const noexcept
Definition def.h:474
A function.
Definition lam.h:110
static T as(const Def *def)
Definition def.h:844
Wraps a PassMan pipeline as a Phase.
Definition phase.h:332
PassManPhase(World &world, std::unique_ptr< PassMan > &&man)
Definition phase.h:336
void apply(const App *) final
Invoked if your Stage has additional args.
Definition phase.cpp:227
All Passes that want to be registered in the PassMan must implement this interface.
Definition pass.h:96
PhaseMan(World &world, flags_t annex)
Definition phase.h:361
bool fixed_point() const
Definition phase.h:371
auto & phases()
Definition phase.h:372
void start() final
Actual entry.
Definition phase.cpp:198
void apply(bool, Phases &&)
Definition phase.cpp:168
void invalidate(bool todo=true)
Signals that another round of fixed-point iteration is required, either as part of.
Definition phase.h:48
Phase(World &world, std::string name)
Definition phase.h:31
virtual void run()
Entry point and generates some debug output; invokes Phase::start.
Definition phase.cpp:13
bool todo() const
Definition phase.h:40
virtual void start()=0
Actual entry.
virtual bool analyze()
Runs the optional pre-analysis on RWPhase::old_world(), typically to a fixed point,...
Definition phase.cpp:90
World & new_world()
Create new Defs into this.
Definition phase.h:243
virtual void rewrite_annex(flags_t, Sym, const Def *)
Definition phase.cpp:100
void start() override
Actual entry.
Definition phase.cpp:71
World & old_world()
Get old Defs from here.
Definition phase.h:242
virtual void rewrite_external(Def *)
Definition phase.cpp:102
const Def * rewrite(const Def *) final
Definition phase.cpp:154
const ReplMan & man() const
Definition phase.h:312
void start() final
Actual entry.
Definition phase.cpp:146
ReplManPhase(World &world, std::unique_ptr< ReplMan > &&man)
Definition phase.h:302
void apply(const App *) final
Invoked if your Stage has additional args.
Definition phase.cpp:132
const auto & repls() const
Definition phase.h:274
ReplMan(World &world, flags_t annex)
Definition phase.h:266
void add(std::unique_ptr< Repl > &&repl)
Definition phase.h:273
void apply(Repls &&)
Definition phase.cpp:111
Simple Stage that searches for a pattern and replaces it.
Definition phase.h:256
Repl(World &world, flags_t annex)
Definition phase.h:258
friend void swap(Rewriter &rw1, Rewriter &rw2) noexcept
Definition rewrite.h:82
virtual void push()
Definition rewrite.h:38
virtual const Def * map(const Def *old_def, const Def *new_def)
Definition rewrite.h:45
std::deque< Def2Def > old2news_
Definition rewrite.h:93
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:56
Common base for Phase and Pass.
Definition pass.h:26
World & world()
Definition pass.h:77
std::string name_
Definition pass.h:89
std::string_view name() const
Definition pass.h:80
Driver & driver()
Definition pass.h:78
static std::unique_ptr< Stage > create(const Flags2Stages &stages, const Def *def)
Definition pass.h:50
flags_t annex() const
Definition pass.h:81
const Def * attach(flags_t, Sym, const Def *)
Definition world.cpp:43
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if MIM_ENABLE_CHECKS.
Definition world.cpp:744
Annexes & annexes()
Definition world.h:285
void debug_dump()
Dump in Debug build if World::log::level is Log::Level::Debug.
Definition dump.cpp:590
#define ILOG(...)
Definition log.h:90
#define VLOG(...)
Definition log.h:91
Definition ast.h:14
u64 flags_t
Definition types.h:39
std::deque< std::unique_ptr< Pass > > Passes
Definition pass.h:16
std::deque< std::unique_ptr< Repl > > Repls
Definition phase.h:21
std::deque< std::unique_ptr< Phase > > Phases
Definition phase.h:22