Thorin 1.9.0
The Higher ORder INtermediate representation
Loading...
Searching...
No Matches
pass.cpp
Go to the documentation of this file.
1#include "thorin/pass/pass.h"
2
4#include "thorin/util/util.h"
5
6#include "absl/container/fixed_array.h"
7
8namespace thorin {
9
10Pass::Pass(PassMan& man, std::string_view name)
11 : man_(man)
12 , name_(name)
13 , index_(man.passes().size()) {}
14
15void PassMan::push_state() {
16 if (fixed_point()) {
17 states_.emplace_back(passes().size());
18
19 // copy over from prev_state to curr_state
20 auto&& prev_state = states_[states_.size() - 2];
21 curr_state().curr_mut = prev_state.stack.top();
22 curr_state().stack = prev_state.stack;
23 curr_state().mut2visit = prev_state.mut2visit;
24 curr_state().old_ops.assign(curr_state().curr_mut->ops().begin(), curr_state().curr_mut->ops().end());
25
26 for (size_t i = 0; i != passes().size(); ++i) curr_state().data[i] = passes_[i]->copy(prev_state.data[i]);
27 }
28}
29
30void PassMan::pop_states(size_t undo) {
31 while (states_.size() != undo) {
32 for (size_t i = 0, e = curr_state().data.size(); i != e; ++i) passes_[i]->dealloc(curr_state().data[i]);
33
34 if (undo != 0) // only reset if not final cleanup
35 curr_state().curr_mut->reset(curr_state().old_ops);
36
37 states_.pop_back();
38 }
39}
40
42 world().verify().ILOG("run");
43
44 auto num = passes().size();
45 states_.emplace_back(num);
46 for (size_t i = 0; i != num; ++i) curr_state().data[i] = passes_[i]->alloc();
47
48 for (auto&& pass : passes_) world().ILOG(" + {}", pass->name());
49 world().debug_dump();
50
51 for (auto&& pass : passes_) pass->prepare();
52
53 auto externals = world().externals();
54 for (const auto& [_, mut] : externals) {
55 analyzed(mut);
56 if (mut->is_set()) curr_state().stack.push(mut);
57 }
58
59 while (!curr_state().stack.empty()) {
60 push_state();
61 curr_mut_ = pop(curr_state().stack);
62 world().VLOG("=== state {}: {} ===", states_.size() - 1, curr_mut_);
63
64 if (!curr_mut_->is_set()) continue;
65
66 for (auto&& pass : passes_)
67 if (pass->inspect()) pass->enter();
68
69 curr_mut_->world().DLOG("curr_mut: {} : {}", curr_mut_, curr_mut_->type());
70 for (size_t i = 0, e = curr_mut_->num_ops(); i != e; ++i) curr_mut_->reset(i, rewrite(curr_mut_->op(i)));
71
72 world().VLOG("=== analyze ===");
73 proxy_ = false;
74 auto undo = No_Undo;
75 for (auto op : curr_mut_->extended_ops()) undo = std::min(undo, analyze(op));
76
77 if (undo == No_Undo) {
78 assert(!proxy_ && "proxies must not occur anymore after leaving a mut with No_Undo");
79 world().DLOG("=== done ===");
80 } else {
81 pop_states(undo);
82 world().DLOG("=== undo: {} -> {} ===", undo, curr_state().stack.top());
83 }
84 }
85
86 world().verify().ILOG("finished");
87 pop_states(0);
88
89 world().debug_dump();
90 Phase::run<Cleanup>(world());
91}
92
93Ref PassMan::rewrite(Ref old_def) {
94 if (!old_def->dep()) return old_def;
95
96 if (auto mut = old_def->isa_mut()) {
97 curr_state().mut2visit.emplace(mut, curr_undo());
98 return map(mut, mut);
99 }
100
101 if (auto new_def = lookup(old_def)) {
102 if (old_def == *new_def)
103 return old_def;
104 else
105 return map(old_def, rewrite(*new_def));
106 }
107
108 auto new_type = old_def->type() ? rewrite(old_def->type()) : nullptr;
109 auto new_ops = absl::FixedArray<const Def*>(old_def->num_ops());
110 for (size_t i = 0, e = old_def->num_ops(); i != e; ++i) new_ops[i] = rewrite(old_def->op(i));
111 auto new_def = old_def->rebuild(new_type, new_ops);
112
113 if (auto proxy = new_def->isa<Proxy>()) {
114 if (auto&& pass = passes_[proxy->pass()]; pass->inspect()) {
115 if (auto rw = pass->rewrite(proxy); rw != proxy) return map(old_def, rewrite(rw));
116 }
117 } else {
118 for (auto&& pass : passes_) {
119 if (!pass->inspect()) continue;
120
121 if (auto var = new_def->isa<Var>()) {
122 if (auto rw = pass->rewrite(var); rw != var) return map(old_def, rewrite(rw));
123 } else {
124 if (auto rw = pass->rewrite(new_def); rw != new_def) return map(old_def, rewrite(rw));
125 }
126 }
127 }
128
129 return map(old_def, new_def);
130}
131
132undo_t PassMan::analyze(Ref def) {
133 undo_t undo = No_Undo;
134
135 if (!def->dep() || analyzed(def)) {
136 // do nothing
137 } else if (auto mut = def->isa_mut()) {
138 if (mut->is_set()) curr_state().stack.push(mut);
139 } else if (auto proxy = def->isa<Proxy>()) {
140 proxy_ = true;
141 undo = passes_[proxy->pass()]->analyze(proxy);
142 } else {
143 auto var = def->isa<Var>();
144 if (!var)
145 for (auto op : def->extended_ops()) undo = std::min(undo, analyze(op));
146
147 for (auto&& pass : passes_)
148 if (pass->inspect()) undo = std::min(undo, var ? pass->analyze(var) : pass->analyze(def));
149 }
150
151 return undo;
152}
153
154} // namespace thorin
Def * reset(size_t i, const Def *def)
Successively reset from left to right.
Definition def.h:291
auto ops() const
Definition def.h:268
Defs extended_ops() const
Definition def.cpp:447
bool is_set() const
Yields true if empty or the last op is set.
Definition def.cpp:315
unsigned dep() const
Definition def.h:335
const Def * op(size_t i) const
Definition def.h:269
size_t num_ops() const
Definition def.h:270
Ref rebuild(World &w, Ref type, Defs ops) const
Def::rebuilds this Def while using new_op as substitute for its i'th Def::op.
Definition def.h:498
const Def * type() const
Yields the raw type of this Def, i.e. maybe nullptr.
Definition def.h:248
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:449
World & world() const
Definition def.cpp:421
An optimizer that combines several optimizations in an optimal way.
Definition pass.h:107
const auto & passes() const
Definition pass.h:115
bool fixed_point() const
Definition pass.h:116
World & world() const
Definition pass.h:114
Def * curr_mut() const
Definition pass.h:117
void run()
Run all registered passes on the whole World.
Definition pass.cpp:41
Pass(PassMan &, std::string_view name)
Definition pass.cpp:10
Helper class to retrieve Infer::arg if present.
Definition def.h:87
const auto & externals() const
Definition world.h:150
void debug_dump()
Dump in Debug build if World::log::level is Log::Level::Debug.
Definition dump.cpp:458
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if THORIN_ENABLE_CHECKS.
Definition world.cpp:551
Definition span.h:103
Ref op(trait o, Ref type)
Definition core.h:35
Definition cfg.h:11
static constexpr undo_t No_Undo
Definition pass.h:15
size_t undo_t
Definition pass.h:14
auto pop(S &s) -> decltype(s.top(), typename S::value_type())
Definition util.h:78