6#include "absl/container/fixed_array.h"
13 , index_(man.passes().size()) {}
15void PassMan::push_state() {
17 states_.emplace_back(
passes().size());
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;
26 for (
size_t i = 0; i !=
passes().size(); ++i) curr_state().data[i] = passes_[i]->copy(prev_state.data[i]);
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]);
35 curr_state().curr_mut->
reset(curr_state().old_ops);
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();
48 for (
auto&& pass : passes_)
world().ILOG(
" + {}", pass->name());
51 for (
auto&& pass : passes_) pass->prepare();
54 for (
const auto& [_, mut] : externals) {
56 if (mut->is_set()) curr_state().stack.push(mut);
59 while (!curr_state().stack.empty()) {
61 curr_mut_ =
pop(curr_state().stack);
62 world().VLOG(
"=== state {}: {} ===", states_.size() - 1, curr_mut_);
64 if (!curr_mut_->
is_set())
continue;
66 for (
auto&& pass : passes_)
67 if (pass->inspect()) pass->enter();
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)));
72 world().VLOG(
"=== analyze ===");
75 for (
auto op : curr_mut_->
extended_ops()) undo = std::min(undo, analyze(op));
78 assert(!proxy_ &&
"proxies must not occur anymore after leaving a mut with No_Undo");
79 world().DLOG(
"=== done ===");
82 world().DLOG(
"=== undo: {} -> {} ===", undo, curr_state().stack.top());
93Ref PassMan::rewrite(
Ref old_def) {
94 if (!old_def->
dep())
return old_def;
96 if (
auto mut = old_def->
isa_mut()) {
97 curr_state().mut2visit.emplace(mut, curr_undo());
101 if (
auto new_def = lookup(old_def)) {
102 if (old_def == *new_def)
105 return map(old_def, rewrite(*new_def));
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);
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));
118 for (
auto&& pass : passes_) {
119 if (!pass->inspect())
continue;
121 if (
auto var = new_def->isa<
Var>()) {
122 if (
auto rw = pass->rewrite(var); rw != var)
return map(old_def, rewrite(rw));
124 if (
auto rw = pass->rewrite(new_def); rw != new_def)
return map(old_def, rewrite(rw));
129 return map(old_def, new_def);
132undo_t PassMan::analyze(Ref def) {
135 if (!def->dep() || analyzed(def)) {
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>()) {
141 undo = passes_[proxy->pass()]->analyze(proxy);
143 auto var = def->isa<
Var>();
145 for (
auto op : def->extended_ops()) undo = std::min(undo, analyze(op));
147 for (
auto&& pass : passes_)
148 if (pass->inspect()) undo = std::min(undo, var ? pass->analyze(var) : pass->analyze(def));
bool is_set() const
Yields true if empty or the last op is set.
const Def * op(size_t i) const
Defs extended_ops() const
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
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.
Def * reset(size_t i, const Def *def)
Successively reset from left to right.
An optimizer that combines several optimizations in an optimal way.
void run()
Run all registered passes on the whole World.
const auto & passes() const
Pass(PassMan &, std::string_view name)
virtual void run()
Entry point and generates some debug output; invokes Phase::start.
Helper class to retrieve Infer::arg if present.
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if MIM_ENABLE_CHECKS.
const auto & externals() const
void debug_dump()
Dump in Debug build if World::log::level is Log::Level::Debug.
auto pop(S &s) -> decltype(s.top(), typename S::value_type())
static constexpr undo_t No_Undo