MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
pass.cpp
Go to the documentation of this file.
1#include "mim/pass.h"
2
3#include <memory>
4
5#include <absl/container/fixed_array.h>
6
7#include "mim/driver.h"
8#include "mim/phase.h"
9
10#include "mim/util/util.h"
11
12namespace mim {
13
14/*
15 * Stage
16 */
17
19 : world_(world)
20 , annex_(annex)
21 , name_(world.annex(annex)->sym()) {}
22
23std::unique_ptr<Stage> Stage::recreate() {
24 auto ctor = driver().stage(annex());
25 auto ptr = (*ctor)(world());
26 ptr->apply(*this);
27 return ptr;
28}
29
30void Pass::init(PassMan* man) { man_ = man; }
31
32/*
33 * PassMan
34 */
35
37 for (auto&& pass : passes)
38 if (auto&& man = pass->isa<PassMan>())
39 apply(std::move(man->passes_));
40 else
41 add(std::move(pass));
42}
43
44void PassMan::apply(const App* app) {
45 auto passes = Passes();
46 for (auto arg : app->args())
47 if (auto stage = Stage::create(driver().stages(), arg))
48 passes.emplace_back(std::unique_ptr<Pass>(static_cast<Pass*>(stage.release())));
49
50 apply(std::move(passes));
51}
52
53void PassMan::push_state() {
54 if (fixed_point()) {
55 states_.emplace_back(passes().size());
56
57 // copy over from prev_state to curr_state
58 auto&& prev_state = states_[states_.size() - 2];
59 curr_state().curr_mut = prev_state.stack.top();
60 curr_state().stack = prev_state.stack;
61 curr_state().mut2visit = prev_state.mut2visit;
62 curr_state().old_ops.assign(curr_state().curr_mut->ops().begin(), curr_state().curr_mut->ops().end());
63
64 for (size_t i = 0; i != passes().size(); ++i)
65 curr_state().data[i] = passes_[i]->copy(prev_state.data[i]);
66 }
67}
68
69void PassMan::pop_states(size_t undo) {
70 while (states_.size() != undo) {
71 for (size_t i = 0, e = curr_state().data.size(); i != e; ++i)
72 passes_[i]->dealloc(curr_state().data[i]);
73
74 if (undo != 0) // only reset if not final cleanup
75 curr_state().curr_mut->set(curr_state().old_ops);
76
77 states_.pop_back();
78 }
79}
80
82 world().verify().ILOG("🔥 run");
83 for (auto&& pass : passes_)
84 ILOG(" 🔹 `{}`", pass->name());
85 world().debug_dump();
86
87 auto num = passes().size();
88 states_.emplace_back(num);
89 for (size_t i = 0; i != num; ++i) {
90 auto pass = passes_[i].get();
91 pass->index_ = i;
92 pass->init(this);
93 curr_state().data[i] = pass->alloc();
94 }
95
96 for (auto&& pass : passes_)
97 pass->prepare();
98
99 for (auto mut : world().copy_externals()) {
100 analyzed(mut);
101 if (mut->is_set()) curr_state().stack.push(mut);
102 }
103
104 while (!curr_state().stack.empty()) {
105 push_state();
106 curr_mut_ = pop(curr_state().stack);
107 VLOG("⚙️ state {}: `{}`", states_.size() - 1, curr_mut_);
108
109 if (!curr_mut_->is_set()) continue;
110
111 for (auto&& pass : passes_)
112 if (pass->inspect()) pass->enter();
113
114 DLOG("curr_mut: {} : {}", curr_mut_, curr_mut_->type());
115
116 auto new_defs = absl::FixedArray<const Def*>(curr_mut_->num_ops());
117 for (size_t i = 0, e = curr_mut_->num_ops(); i != e; ++i)
118 new_defs[i] = rewrite(curr_mut_->op(i));
119 curr_mut_->set(new_defs);
120
121 VLOG("🔍 analyze");
122 proxy_ = false;
123 auto undo = No_Undo;
124 for (auto op : curr_mut_->deps())
125 undo = std::min(undo, analyze(op));
126
127 if (undo == No_Undo) {
128 assert(!proxy_ && "proxies must not occur anymore after leaving a mut with No_Undo");
129 DLOG("=== done ===");
130 } else {
131 pop_states(undo);
132 DLOG("=== undo: {} -> {} ===", undo, curr_state().stack.top());
133 }
134 }
135
136 world().verify().ILOG("🔒 finished");
137 pop_states(0);
138
139 world().debug_dump();
140
142}
143
144const Def* PassMan::rewrite(const Def* old_def) {
145 if (!old_def->has_dep()) return old_def;
146
147 if (auto mut = old_def->isa_mut()) {
148 curr_state().mut2visit.emplace(mut, curr_undo());
149 return map(mut, mut);
150 }
151
152 if (auto new_def = lookup(old_def)) {
153 if (old_def == *new_def)
154 return old_def;
155 else
156 return map(old_def, rewrite(*new_def));
157 }
158
159 auto new_type = old_def->type() ? rewrite(old_def->type()) : nullptr;
160 auto new_ops = absl::FixedArray<const Def*>(old_def->num_ops());
161 for (size_t i = 0, e = old_def->num_ops(); i != e; ++i)
162 new_ops[i] = rewrite(old_def->op(i));
163 auto new_def = old_def->rebuild(new_type, new_ops);
164
165 if (auto proxy = new_def->isa<Proxy>()) {
166 if (auto&& pass = passes_[proxy->pass()]; pass->inspect()) {
167 if (auto rw = pass->rewrite(proxy); rw != proxy) return map(old_def, rewrite(rw));
168 }
169 } else {
170 for (auto&& pass : passes_) {
171 if (!pass->inspect()) continue;
172
173 if (auto var = new_def->isa<Var>()) {
174 if (auto rw = pass->rewrite(var); rw != var) return map(old_def, rewrite(rw));
175 } else {
176 if (auto rw = pass->rewrite(new_def); rw != new_def) return map(old_def, rewrite(rw));
177 }
178 }
179 }
180
181 return map(old_def, new_def);
182}
183
184undo_t PassMan::analyze(const Def* def) {
185 undo_t undo = No_Undo;
186
187 if (!def->has_dep() || analyzed(def)) {
188 // do nothing
189 } else if (auto mut = def->isa_mut()) {
190 if (mut->is_set()) curr_state().stack.push(mut);
191 } else if (auto proxy = def->isa<Proxy>()) {
192 proxy_ = true;
193 undo = passes_[proxy->pass()]->analyze(proxy);
194 } else {
195 auto var = def->isa<Var>();
196 if (!var)
197 for (auto op : def->deps())
198 undo = std::min(undo, analyze(op));
199
200 for (auto&& pass : passes_)
201 if (pass->inspect()) undo = std::min(undo, var ? pass->analyze(var) : pass->analyze(def));
202 }
203
204 return undo;
205}
206
207} // namespace mim
Base class for all Defs.
Definition def.h:251
Defs deps() const noexcept
Definition def.cpp:464
constexpr auto ops() const noexcept
Definition def.h:305
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:482
const Def * op(size_t i) const noexcept
Definition def.h:308
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:295
const Def * rebuild(World &w, const Def *type, Defs ops) const
Def::rebuilds this Def while using new_op as substitute for its i'th Def::op.
Definition def.h:545
bool has_dep() const
Definition def.h:357
constexpr size_t num_ops() const noexcept
Definition def.h:309
auto stage(flags_t flags)
Definition driver.h:80
Def * curr_mut() const
Definition pass.h:189
void apply(Passes &&)
Definition pass.cpp:36
void run()
Run all registered passes on the whole World.
Definition pass.cpp:81
void add(std::unique_ptr< Pass > &&pass)
Definition pass.h:207
PassMan(World &world, flags_t annex)
Definition pass.h:174
const auto & passes() const
Definition pass.h:187
bool fixed_point() const
Definition pass.h:188
const Proxy * proxy(const Def *type, Defs ops, u32 tag=0)
Definition pass.h:141
Pass(World &world, std::string name)
Definition pass.h:87
virtual void init(PassMan *)
Definition pass.cpp:30
PassMan & man()
Definition pass.h:97
friend class PassMan
Definition pass.h:166
virtual void run()
Entry point and generates some debug output; invokes Phase::start.
Definition phase.cpp:13
World & world()
Definition pass.h:64
virtual std::unique_ptr< Stage > recreate()
Creates a new instance; needed by a fixed-point PhaseMan.
Definition pass.cpp:23
std::string name_
Definition pass.h:76
static auto create(const Flags2Stages &stages, const Def *def)
Definition pass.h:40
Stage(World &world, std::string name)
Definition pass.h:30
Driver & driver()
Definition pass.h:65
flags_t annex() const
Definition pass.h:68
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:36
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if MIM_ENABLE_CHECKS.
Definition world.cpp:702
void debug_dump()
Dump in Debug build if World::log::level is Log::Level::Debug.
Definition dump.cpp:493
#define ILOG(...)
Definition log.h:91
#define VLOG(...)
Definition log.h:92
#define DLOG(...)
Vaporizes to nothingness in Debug build.
Definition log.h:95
Definition ast.h:14
auto pop(S &s) -> decltype(s.top(), typename S::value_type())
Definition util.h:83
u64 flags_t
Definition types.h:45
std::deque< std::unique_ptr< Pass > > Passes
Definition pass.h:16
size_t undo_t
Definition pass.h:21
static constexpr undo_t No_Undo
Definition pass.h:22
@ Var
Definition def.h:114
@ Proxy
Definition def.h:114