MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
schedule.cpp
Go to the documentation of this file.
1#include "mim/schedule.h"
2
3#include <queue>
4
5#include "mim/world.h"
6
7namespace mim {
8
10 : nest_(&nest) {
11 std::queue<const Def*> queue;
12 DefSet done;
13
14 auto enqueue = [&](const Def* def, size_t i, const Def* op) {
15 if (nest.contains(op)) {
16 assert_emplace(def2uses_[op], def, i);
17 if (auto [_, ins] = done.emplace(op); ins) queue.push(op);
18 }
19 };
20
21 for (auto mut : nest.muts()) {
22 queue.push(mut);
23 assert_emplace(done, mut);
24 }
25
26 while (!queue.empty()) {
27 auto def = queue.front();
28 queue.pop();
29
30 if (!def->is_set()) continue;
31
32 for (size_t i = 0, e = def->num_ops(); i != e; ++i) {
33 // all reachable muts have already been registered above
34 // NOTE we might still see references to unreachable muts in the schedule
35 if (!def->op(i)->isa_mut()) enqueue(def, i, def->op(i));
36 }
37
38 if (!def->type()->isa_mut()) enqueue(def, -1, def->type());
39 }
40}
41
42const Nest::Node* Scheduler::early(const Def* def) {
43 if (auto i = early_.find(def); i != early_.end()) return i->second;
44 if (def->has_const_dep() || !nest().contains(def)) return early_[def] = nest().root();
45 if (auto var = def->isa<Var>()) return early_[def] = nest()[var->mut()];
46
47 auto result = nest().root();
48 for (auto op : def->deps()) {
49 if (!op->isa_mut() && nest().contains(op)) {
50 auto node = early(op);
51 if (node->level() > result->level()) result = node;
52 }
53 }
54
55 return early_[def] = result;
56}
57
58const Nest::Node* Scheduler::late(Def* curr_mut, const Def* def) {
59 if (auto i = late_.find(def); i != late_.end()) return i->second;
60 if (def->has_const_dep() || !nest().contains(def)) return late_[def] = nest().root();
61
62 const Nest::Node* result = nullptr;
63 if (auto mut = def->isa_mut()) {
64 result = nest()[mut];
65 } else if (auto var = def->isa<Var>()) {
66 result = nest()[var->mut()];
67 } else {
68 for (auto use : uses(def)) {
69 auto mut = late(curr_mut, use);
70 result = result ? Nest::lca(result, mut) : mut;
71 }
72 }
73
74 if (!result) result = nest()[curr_mut];
75
76 return late_[def] = result;
77}
78
79const Nest::Node* Scheduler::smart(Def* curr_mut, const Def* def) {
80 if (auto i = smart_.find(def); i != smart_.end()) return i->second;
81
82 auto e = early(def);
83 auto l = late(curr_mut, def);
84 auto s = l;
85
86 int depth = l->loop_depth();
87 for (auto i = l; i != e;) {
88 i = i->parent();
89
90 if (i == nullptr) {
91 world().ELOG("this should never occur - don't know where to put {}", def);
92 s = l;
93 break;
94 }
95
96 if (int curr_depth = i->loop_depth(); curr_depth < depth) {
97 s = i;
98 depth = curr_depth;
99 }
100 }
101
102 return smart_[def] = s;
103}
104
105static void post_order(const Nest& nest, const Nest::Node* node, Scheduler::Schedule& res, MutSet& done) {
106 if (!node->mut()->isa<Lam>()) return;
107 if (auto [_, ins] = done.emplace(node->mut()); !ins) return;
108 for (auto mut : node->mut()->mut_local_muts())
109 if (auto next = nest.mut2node(mut)) post_order(nest, next, res, done);
110 res.emplace_back(node->mut());
111}
112
113// untill we have sth better ...
114Scheduler::Schedule Scheduler::schedule(const Nest& nest) {
115 Schedule schedule;
116 MutSet done;
117 post_order(nest, nest.root(), schedule, done);
118 std::ranges::reverse(schedule); // post-order → reverse post-order
119 return schedule;
120}
121
122} // namespace mim
Base class for all Defs.
Definition def.h:212
Defs deps() const
Definition def.cpp:410
Muts mut_local_muts()
All local_muts() of this mutable's deps().
Definition def.cpp:298
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:432
bool has_const_dep() const
Neither a Dep::Mut nor a Dep::Var; can often be used as shortcut as an optimization.
Definition def.h:317
Ref type() const noexcept
Yields the raw type of this Def, i.e. maybe nullptr.
Definition def.h:241
A function.
Definition lam.h:105
Def * mut() const
The mutable capsulated in this Node or nullptr, if it's a virtual root comprising several Nodes.
Definition nest.h:22
Builds a nesting tree of all immutables‍/binders.
Definition nest.h:11
auto muts() const
Definition nest.h:137
const Node * root() const
Definition nest.h:129
const auto & mut2node() const
Definition nest.h:141
bool contains(const Def *def) const
Definition nest.h:131
const Nest & nest() const
Definition schedule.h:61
Scheduler()=default
Definition ast.h:14
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
Definition util.h:104
GIDSet< Def * > MutSet
Definition def.h:69
GIDSet< const Def * > DefSet
Definition def.h:59
static void post_order(const Nest &nest, const Nest::Node *node, Scheduler::Schedule &res, MutSet &done)
Definition schedule.cpp:105