MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
lower_for.cpp
Go to the documentation of this file.
2
3#include <mim/driver.h>
4#include <mim/lam.h>
5#include <mim/tuple.h>
6
7#include <mim/plug/ll/ll.h>
8#include <mim/plug/mem/mem.h>
9
11
13
14namespace {
15
16const Def* merge(bool term, const Def* elem, const Def* prod, const Def* mem) {
17 auto& w = elem->world();
18 if (mem) return w.prod(term, Def::cat(elem, prod->projs()));
19 return w.prod(term, {elem, prod});
20}
21
22} // namespace
23
24const Def* LowerFor::rewrite_imm_App(const App* app) {
25 if (auto for_ax = Axm::isa<affine::For>(app)) {
26 log().d("lower for: {}", for_ax);
27 auto [old_body, old_exit, args] = for_ax->uncurry_args<3>();
28 auto [new_begin, new_end, new_step, new_init] = args->projs<4>([this](const Def* def) { return rewrite(def); });
29
30 const Def* vec_axm = nullptr;
31 if (auto ll_vec = Axm::isa<ll::vec>(old_body)) {
32 old_body = ll_vec->arg();
33 if (old_world().driver().is_loaded("ll")) vec_axm = ll_vec->axm();
34 } else if (auto ll_novec = Axm::isa<ll::novec>(old_body)) {
35 old_body = ll_novec->arg();
36 if (old_world().driver().is_loaded("ll")) vec_axm = ll_novec->axm();
37 }
38
39 auto old_body_lam = old_body->isa_mut<Lam>();
40 auto old_exit_lam = old_exit->isa_mut<Lam>();
41 if (!old_body_lam) old_body_lam = Lam::eta_expand(old_body);
42 if (!old_exit_lam) old_exit_lam = Lam::eta_expand(old_exit);
43
44 auto new_mem = mem::mem_def(new_init);
45 auto new_head_dom = merge(false, new_begin->type(), new_init->type(), new_mem);
46 auto new_head_lam = new_world().mut_con(new_head_dom)->set("head");
47 auto new_phis = new_head_lam->vars();
48 auto new_iter = new_phis.front();
49 auto new_acc = new_world().tuple(new_phis.view().subspan(1));
50 new_mem = mem::mem_var(new_head_lam);
51 auto new_bb_dom = new_mem ? new_mem->type() : new_world().sigma();
52
53 auto new_body = new_world().mut_con(new_bb_dom)->set("new_body");
54 auto new_exit = new_world().mut_con(new_bb_dom)->set("new_exit");
55 auto new_yield = new_world().mut_con(new_init->type())->set("new_yield");
56 auto new_cmp = new_world().call(core::icmp::ul, Defs{new_iter, new_end});
57 auto new_inc = new_world().call(core::wrap::add, core::Mode::nsuw, Defs{new_iter, new_step});
58
59 if (vec_axm) new_cmp = new_world().app(new_world().app(rewrite(vec_axm), new_cmp->type()), new_cmp);
60
61 new_head_lam->branch(false, new_cmp, new_body, new_exit, new_mem);
62 new_yield->app(false, new_head_lam, merge(true, new_inc, new_yield->var(), new_mem));
63
64 // `new_acc` references the head's phis, including the head's mem var.
65 // Each new bb receives its own mem, so re-thread the acc's mem through the bb's own mem var.
66 auto acc_for = [&](Lam* bb) -> const Def* {
67 if (!new_mem) return new_acc;
68 auto bb_mem = mem::mem_var(bb);
69 auto elems = DefVec();
70 for (auto phi : new_phis.view().subspan(1))
71 elems.emplace_back(Axm::isa<mem::M>(phi->type()) ? bb_mem : phi);
72 return new_world().tuple(elems);
73 };
74
75 push(Vars(old_body_lam->has_var()));
76 map(old_body_lam->var(), {new_iter, acc_for(new_body), new_yield});
77 auto new_body_filter = rewrite(old_body_lam->filter());
78 auto new_body_value = rewrite(old_body_lam->body());
79 new_body->set({new_body_filter, new_body_value});
80 pop();
81
82 push(Vars(old_exit_lam->has_var()));
83 map(old_exit_lam->var(), acc_for(new_exit));
84 auto new_exit_filter = rewrite(old_exit_lam->filter());
85 auto new_exit_value = rewrite(old_exit_lam->body());
86 new_exit->set({new_exit_filter, new_exit_value});
87 pop();
88
89 return new_world().app(new_head_lam, merge(true, new_begin, new_init, new_mem));
90 }
91
92 return RWPhase::rewrite_imm_App(app);
93}
94
95} // namespace mim::plug::affine::phase
static auto isa(const Def *def)
Definition axm.h:112
Base class for all Defs.
Definition def.h:289
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:588
static DefVec cat(Defs a, Defs b)
Definition tuple.cpp:138
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:492
auto vars(Projector auto f) noexcept
Definition def.h:492
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:1119
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
Definition def.h:496
A function.
Definition lam.h:91
const Def * filter() const
Definition lam.h:103
Lam * set(Filter filter, const Def *body)
Definition lam.cpp:34
static Lam * eta_expand(Filter, const Def *f)
Definition lam.cpp:84
const Def * body() const
Definition lam.h:104
const fe::Log & log() const
Definition phase.h:60
Driver & driver()
Definition phase.h:59
const fe::Vector< std::string > & args()
Command-line arguments passed to this Phase's plugin via -X <plugin>:<arg>.
Definition phase.cpp:23
World & new_world()
Create new Defs into this.
Definition phase.h:379
World & old_world()
Get old Defs from here.
Definition phase.h:378
const Def * rewrite_imm_App(const App *) override
Definition phase.cpp:223
void pop()
Definition rewrite.h:41
const Def * map(const Def *old_def, const Def *new_def)
Definition rewrite.cpp:29
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:62
void push(Vars old_vars={}, Vars new_vars={})
Definition rewrite.h:40
const Def * call(const Def *callee, auto &&arg, Args &&... args)
Definition world.h:674
const Def * sigma(Defs ops)
Definition world.cpp:506
const Def * app(const Def *callee, const Def *arg)
Definition world.cpp:416
const Def * tuple(Defs ops)
Definition world.cpp:516
Lam * mut_con(const Def *dom)
Definition world.h:427
const Def * rewrite_imm_App(const App *) final
Definition lower_for.cpp:24
const Def * mem_var(Lam *lam)
Returns the memory argument of a function if it has one.
Definition mem.h:51
const Def * mem_def(const Def *def)
Returns the (first) element of type mem.M a from the given tuple.
Definition mem.h:38
fe::View< const Def * > Defs
Definition def.h:96
fe::Vector< const Def * > DefVec
Definition def.h:98
fe::Patricia< const Var, DefKey >::Set Vars
Definition def.h:115