11 , index_(man.passes().size()) {}
13void PassMan::push_state() {
15 states_.emplace_back(
passes().size());
18 auto&& prev_state = states_[states_.size() - 2];
19 curr_state().curr_mut = prev_state.stack.top();
20 curr_state().stack = prev_state.stack;
21 curr_state().mut2visit = prev_state.mut2visit;
24 for (
size_t i = 0; i !=
passes().size(); ++i) curr_state().data[i] = passes_[i]->copy(prev_state.data[i]);
28void PassMan::pop_states(
size_t undo) {
29 while (states_.size() != undo) {
30 for (
size_t i = 0, e = curr_state().data.size(); i != e; ++i) passes_[i]->dealloc(curr_state().data[i]);
33 curr_state().curr_mut->
reset(curr_state().old_ops);
42 auto num =
passes().size();
43 states_.emplace_back(num);
44 for (
size_t i = 0; i != num; ++i) curr_state().data[i] = passes_[i]->alloc();
46 for (
auto&& pass : passes_)
world().ILOG(
" + {}", pass->name());
49 for (
auto&& pass : passes_) pass->prepare();
51 for (
auto mut :
world().copy_externals()) {
53 if (mut->is_set()) curr_state().stack.push(mut);
56 while (!curr_state().stack.empty()) {
58 curr_mut_ =
pop(curr_state().stack);
59 world().VLOG(
"=== state {}: {} ===", states_.size() - 1, curr_mut_);
61 if (!curr_mut_->
is_set())
continue;
63 for (
auto&& pass : passes_)
64 if (pass->inspect()) pass->enter();
66 curr_mut_->
world().DLOG(
"curr_mut: {} : {}", curr_mut_, curr_mut_->
type());
67 for (
size_t i = 0, e = curr_mut_->
num_ops(); i != e; ++i) curr_mut_->
reset(i, rewrite(curr_mut_->
op(i)));
69 world().VLOG(
"=== analyze ===");
72 for (
auto op : curr_mut_->
deps()) undo = std::min(undo, analyze(op));
75 assert(!proxy_ &&
"proxies must not occur anymore after leaving a mut with No_Undo");
76 world().DLOG(
"=== done ===");
79 world().DLOG(
"=== undo: {} -> {} ===", undo, curr_state().stack.top());
90Ref PassMan::rewrite(
Ref old_def) {
91 if (!old_def->
has_dep())
return old_def;
93 if (
auto mut = old_def->
isa_mut()) {
94 curr_state().mut2visit.emplace(mut, curr_undo());
98 if (
auto new_def = lookup(old_def)) {
99 if (old_def == *new_def)
102 return map(old_def, rewrite(*new_def));
105 auto new_type = old_def->
type() ? rewrite(old_def->
type()) : nullptr;
106 auto new_ops = absl::FixedArray<const Def*>(old_def->
num_ops());
107 for (
size_t i = 0, e = old_def->
num_ops(); i != e; ++i) new_ops[i] = rewrite(old_def->
op(i));
108 auto new_def = old_def->
rebuild(new_type, new_ops);
110 if (
auto proxy = new_def->isa<
Proxy>()) {
111 if (
auto&& pass = passes_[proxy->pass()]; pass->inspect()) {
112 if (
auto rw = pass->rewrite(proxy); rw != proxy)
return map(old_def, rewrite(rw));
115 for (
auto&& pass : passes_) {
116 if (!pass->inspect())
continue;
118 if (
auto var = new_def->isa<
Var>()) {
119 if (
auto rw = pass->rewrite(var); rw != var)
return map(old_def, rewrite(rw));
121 if (
auto rw = pass->rewrite(new_def); rw != new_def)
return map(old_def, rewrite(rw));
126 return map(old_def, new_def);
129undo_t PassMan::analyze(Ref def) {
132 if (!def->has_dep() || analyzed(def)) {
134 }
else if (
auto mut = def->isa_mut()) {
135 if (mut->is_set()) curr_state().stack.push(mut);
136 }
else if (
auto proxy = def->isa<
Proxy>()) {
138 undo = passes_[proxy->pass()]->analyze(proxy);
140 auto var = def->isa<
Var>();
142 for (
auto op : def->deps()) undo = std::min(undo, analyze(op));
144 for (
auto&& pass : passes_)
145 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.
Ref op(size_t i) const noexcept
World & world() const noexcept
constexpr auto ops() const noexcept
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
Def * reset(size_t i, Ref def)
Successively reset from left to right.
Ref type() const noexcept
Yields the raw type of this Def, i.e. maybe nullptr.
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.
constexpr size_t num_ops() const noexcept
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.
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