MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
static_arg_opt.cpp
Go to the documentation of this file.
2
3namespace mim {
4
6 for (auto def : old_world().externals().muts())
7 analyze(def);
8 return false; // no fixed-point necessary
9}
10
11void StaticArgOpt::analyze(const Def* def) {
12 if (auto [_, ins] = analyzed_.emplace(def); !ins) return;
13
14 if (auto app = def->isa<App>())
15 if (auto lam = app->callee()->isa_mut<Lam>(); lam && lam->has_var()) visit(app, lam);
16
17 for (auto d : def->deps())
18 analyze(d);
19}
20
21void StaticArgOpt::visit(const App* app, Lam* lam) {
22 auto mask = fe::Bitset();
23 for (size_t i = 0, n = lam->num_tdoms(); i != n; ++i)
24 if (app->targ(i) == lam->tvar(i)) mask.set(i);
25 if (mask.any()) lam2sites_[lam].emplace_back(std::move(mask)); // only lam's own body can mention lam's vars
26}
27
28Sieve StaticArgOpt::sieve(Lam* lam) {
29 if (auto s = fe::lookup(lam2sieve_, lam)) return *s;
30
31 auto n = lam->num_tdoms();
32
33 // A *mutable* Pi is a dependent one; splitting it would require loop's doms to refer to wrap's vars.
34 auto i = lam2sites_.find(lam);
35 if (i == lam2sites_.end() || !lam->is_set() || !lam->is_closed() || lam->type()->isa_mut<Pi>())
36 return lam2sieve_.emplace(lam, Sieve(n)).first->second;
37
38 const auto& sites = i->second;
39
40 // A static *function* arg is what SAT is after, as it exposes the loop's free var to inlining (Santos §7).
41 // So seed the split with the rightmost Pi-typed dom and keep only the sites forwarding it; ∀ if there is none.
42 auto pool = fe::Bitset(sites.size(), true);
43 for (size_t d = n; d-- != 0;) {
44 if (!lam->tdom(d)->isa<Pi>()) continue;
45 auto seeded = false;
46 for (const auto& mask : sites)
47 seeded |= mask[d];
48 if (seeded)
49 for (size_t s = 0, e = sites.size(); s != e; ++s)
50 pool.set(s, sites[s][d]);
51 break;
52 }
53
54 auto statics = fe::Bitset(n, true);
55 for (size_t s = 0, e = sites.size(); s != e; ++s)
56 if (pool[s]) statics &= sites[s];
57 if (statics.none()) return lam2sieve_.emplace(lam, Sieve(n)).first->second;
58
59 log().d("statics of {}: {}", lam, statics);
60 return lam2sieve_.emplace(lam, Sieve(n, [&statics](size_t d) { return !statics[d]; })).first->second;
61}
62
64 auto sieve = this->sieve(old_lam);
65 if (sieve.all()) return RWPhase::rewrite_mut_Lam(old_lam);
66
67 auto& w = new_world();
68 auto n = old_lam->num_tdoms();
69 auto loop_doms = rewrite(sieve.gather(old_lam->tdoms()));
70
71 auto wrap = w.mut_lam(rewrite(old_lam->type())->as<Pi>())->set(old_lam->dbg_key());
72 auto loop = w.mut_lam(loop_doms, rewrite(old_lam->codom()))->set(old_lam->dbg_key());
73 loop->debug_suffix("_loop");
74 log().d("{} → wrap {}, loop {}", old_lam, wrap, loop);
75 old2loop_[old_lam] = loop;
76
77 // The body lives in loop; the static vars stay wrap's and are free in loop.
78 auto vars = DefVec(n, [&](size_t d) {
79 auto j = sieve[d];
80 return j == Sieve::Gone ? wrap->tvar(d) : loop->var(sieve.num_new(), j);
81 });
82
83 map(old_lam, wrap);
84 map(old_lam->var(), vars);
85 loop->set(rewrite(old_lam->filter()), rewrite(old_lam->body()));
86 wrap->app(false, loop, sieve.gather(wrap->tvars()));
87 return wrap;
88}
89
90const Def* StaticArgOpt::rewrite_imm_App(const App* old_app) {
91 if (auto old_lam = old_app->callee()->isa_mut<Lam>()) {
92 if (auto sieve = this->sieve(old_lam); !sieve.all()) {
93 rewrite(old_lam); // make sure wrap/loop exist
94 if (auto loop = fe::lookup(old2loop_, old_lam)) {
95 for (size_t d = 0, n = old_lam->num_tdoms(); d != n; ++d)
96 if (sieve[d] == Sieve::Gone && old_app->targ(d) != old_lam->tvar(d))
97 return RWPhase::rewrite_imm_App(old_app); // not our class: go through wrap
98 invalidate();
99 return new_world().app(loop, rewrite(sieve.gather(old_app->targs())));
100 }
101 }
102 }
103
104 return RWPhase::rewrite_imm_App(old_app);
105}
106
107} // namespace mim
auto targs(Projector auto f) const noexcept
Definition lam.h:252
const Def * callee() const
Definition lam.h:237
const Def * targ(nat_t i) const noexcept
Definition lam.h:252
Base class for all Defs.
Definition def.h:289
Defs deps() const noexcept
Definition def.cpp:486
const Def * tvar(nat_t i) noexcept
Definition def.h:492
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:588
DbgKey dbg_key() const
Cheap handle for other->set(this->dbg_key()).
Definition def.h:631
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:492
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
nat_t num_tdoms() const noexcept
Definition lam.h:117
const Pi * type() const
Definition lam.h:112
const Def * body() const
Definition lam.h:104
auto tdoms(Projector auto f) const noexcept
Definition lam.h:117
const Def * codom() const
Definition lam.h:114
void invalidate(bool todo=true)
Signals that another round of fixed-point iteration is required, either as part of.
Definition phase.h:79
const fe::Log & log() const
Definition phase.h:60
A dependent function type.
Definition lam.h:14
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
const Def * map(const Def *old_def, const Def *new_def)
Definition rewrite.cpp:29
virtual const Def * rewrite_mut_Lam(Lam *)
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:62
Filters the components of an aggregate and keeps track of where the survivors end up.
Definition tuple.h:116
Sieve(size_t num)
Definition tuple.h:123
static constexpr size_t Gone
Definition tuple.h:118
const Def * rewrite_mut_Lam(Lam *) final
bool analyze() final
Runs the optional pre-analysis on old_world(), typically to a fixed point, before rewriting begins.
const Def * rewrite_imm_App(const App *) final
const Def * app(const Def *callee, const Def *arg)
Definition world.cpp:416
Definition ast.h:16
fe::Vector< const Def * > DefVec
Definition def.h:98