3#include <absl/container/fixed_array.h>
14 , index_(
man.passes().size()) {}
16void PassMan::push_state() {
18 states_.emplace_back(
passes().size());
21 auto&& prev_state = states_[states_.size() - 2];
22 curr_state().curr_mut = prev_state.stack.top();
23 curr_state().stack = prev_state.stack;
24 curr_state().mut2visit = prev_state.mut2visit;
27 for (
size_t i = 0; i !=
passes().size(); ++i)
28 curr_state().data[i] = passes_[i]->copy(prev_state.data[i]);
32void PassMan::pop_states(
size_t undo) {
33 while (states_.size() != undo) {
34 for (
size_t i = 0, e = curr_state().data.size(); i != e; ++i)
35 passes_[i]->dealloc(curr_state().data[i]);
38 curr_state().curr_mut->set(curr_state().old_ops);
47 auto num =
passes().size();
48 states_.emplace_back(num);
49 for (
size_t i = 0; i != num; ++i)
50 curr_state().data[i] = passes_[i]->alloc();
52 for (
auto&& pass : passes_)
53 world().ILOG(
" + {}", pass->name());
56 for (
auto&& pass : passes_)
59 for (
auto mut :
world().copy_externals()) {
61 if (mut->is_set()) curr_state().stack.push(mut);
64 while (!curr_state().stack.empty()) {
66 curr_mut_ =
pop(curr_state().stack);
67 world().VLOG(
"=== state {}: {} ===", states_.size() - 1, curr_mut_);
69 if (!curr_mut_->is_set())
continue;
71 for (
auto&& pass : passes_)
72 if (pass->inspect()) pass->enter();
74 curr_mut_->world().DLOG(
"curr_mut: {} : {}", curr_mut_, curr_mut_->type());
76 auto new_defs = absl::FixedArray<const Def*>(curr_mut_->num_ops());
77 for (
size_t i = 0, e = curr_mut_->num_ops(); i != e; ++i)
78 new_defs[i] = rewrite(curr_mut_->op(i));
79 curr_mut_->set(new_defs);
81 world().VLOG(
"=== analyze ===");
84 for (
auto op : curr_mut_->
deps())
85 undo = std::min(undo, analyze(op));
88 assert(!proxy_ &&
"proxies must not occur anymore after leaving a mut with No_Undo");
89 world().DLOG(
"=== done ===");
92 world().DLOG(
"=== undo: {} -> {} ===", undo, curr_state().stack.top());
103const Def* PassMan::rewrite(
const Def* old_def) {
104 if (!old_def->
has_dep())
return old_def;
106 if (
auto mut = old_def->
isa_mut()) {
107 curr_state().mut2visit.emplace(mut, curr_undo());
108 return map(mut, mut);
111 if (
auto new_def = lookup(old_def)) {
112 if (old_def == *new_def)
115 return map(old_def, rewrite(*new_def));
118 auto new_type = old_def->
type() ? rewrite(old_def->
type()) : nullptr;
119 auto new_ops = absl::FixedArray<const Def*>(old_def->
num_ops());
120 for (
size_t i = 0, e = old_def->
num_ops(); i != e; ++i)
121 new_ops[i] = rewrite(old_def->
op(i));
122 auto new_def = old_def->
rebuild(new_type, new_ops);
124 if (
auto proxy = new_def->isa<
Proxy>()) {
125 if (
auto&& pass = passes_[proxy->pass()]; pass->inspect()) {
126 if (
auto rw = pass->rewrite(proxy); rw != proxy)
return map(old_def, rewrite(rw));
129 for (
auto&& pass : passes_) {
130 if (!pass->inspect())
continue;
132 if (
auto var = new_def->isa<
Var>()) {
133 if (
auto rw = pass->rewrite(var); rw != var)
return map(old_def, rewrite(rw));
135 if (
auto rw = pass->rewrite(new_def); rw != new_def)
return map(old_def, rewrite(rw));
140 return map(old_def, new_def);
146 if (!def->has_dep() || analyzed(def)) {
148 }
else if (
auto mut = def->isa_mut()) {
149 if (mut->is_set()) curr_state().stack.push(mut);
150 }
else if (
auto proxy = def->isa<
Proxy>()) {
152 undo = passes_[proxy->pass()]->analyze(proxy);
154 auto var = def->isa<
Var>();
156 for (
auto op : def->deps())
157 undo = std::min(undo, analyze(op));
159 for (
auto&& pass : passes_)
160 if (pass->inspect()) undo = std::min(undo, var ? pass->analyze(var) : pass->analyze(def));
Defs deps() const noexcept
constexpr auto ops() const noexcept
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
const Def * op(size_t i) const noexcept
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
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.
constexpr size_t num_ops() const noexcept
void run()
Run all registered passes on the whole World.
const auto & passes() const
Pass(PassMan &, std::string_view name)
std::string_view name() const
virtual void run()
Entry point and generates some debug output; invokes Phase::start.
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if MIM_ENABLE_CHECKS.
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