MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
branch_clos_elim.cpp
Go to the documentation of this file.
2
4
6
7namespace {
8
9std::tuple<fe::Vector<ClosLit>, const Def*> isa_branch(const Def* callee) {
10 if (auto closure_proj = callee->isa<Extract>()) {
11 auto sw = Switch(closure_proj->tuple());
12 if (sw && sw.tuple()->isa<Tuple>() && isa_clos_type(sw.extract()->type())) {
13 auto branches = fe::Vector<ClosLit>();
14 for (size_t i = 0, n = sw.num_targets(); i != n; ++i)
15 if (auto c = isa_clos_lit(sw.target(i)))
16 branches.emplace_back(c);
17 else
18 return {};
19 return {branches, sw.index()};
20 }
21 }
22 return {};
23}
24
25} // namespace
26
28 if (!Pi::isa_cn(app->callee_type())) return RWPhase::rewrite_imm_App(app);
29
30 auto& w = new_world();
31 if (auto [branches, index] = isa_branch(app->callee()); index) {
32 log().d("flatten branch: {}", app->callee());
33 auto ep = env_param(branches[0].fnc_type());
34 auto new_branches = w.tuple(DefVec(branches.size(), [&](size_t i) -> const Def* {
35 auto c = branches[i];
36 if (auto it = branch2dropped_.find(c); it != branch2dropped_.end()) return it->second;
37 // Specialize the closure's lam with its env inlined.
38 // The Pi is computed on the old-world closure type and then rewritten -
39 // rewriting the (mutable, existential) closure type itself does not survive the world change.
40 // Memoize the stub first: rewriting the lam below revisits this very branch.
41 auto dropped_lam = w.mut_lam(rewrite(clos_type_to_pi(c.type()))->as<Pi>())->set(c.fnc_as_lam()->dbg_key());
42 branch2dropped_[c] = dropped_lam;
43 auto clam = rewrite(c.fnc_as_lam())->as_mut<Lam>();
44 dropped_lam->set(clam->reduce(clos_insert_env(ep, rewrite(c.env()), dropped_lam->var())));
45 return dropped_lam;
46 }));
47 return w.app(w.extract(new_branches, rewrite(index)), clos_remove_env(ep, rewrite(app->arg())));
48 }
49
50 return RWPhase::rewrite_imm_App(app);
51}
52
53} // namespace mim::plug::clos::phase
const Pi * callee_type() const
Definition lam.h:239
const Def * callee() const
Definition lam.h:237
const Def * arg() const
Definition lam.h:251
Base class for all Defs.
Definition def.h:289
const fe::Log & log() const
Definition phase.h:60
static const Pi * isa_cn(const Def *d)
Definition lam.h:50
World & new_world()
Create new Defs into this.
Definition phase.h:379
const Def * rewrite_imm_App(const App *) override
Definition phase.cpp:223
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:62
Switch(const Def *)
Definition tuple.cpp:84
const Def * rewrite_imm_App(const App *) final
ClosLit isa_clos_lit(const Def *def, bool fn_isa_lam=true)
Tries to match a closure literal.
Definition clos.cpp:49
const Def * clos_remove_env(size_t ep, size_t i, std::function< const Def *(size_t)> f)
Definition clos.cpp:120
const Sigma * isa_clos_type(const Def *def)
Definition clos.cpp:86
size_t env_param(Defs doms)
Describes where the environment is placed in the argument list: right after a leading mem....
Definition clos.h:107
fe::Vector< const Def * > DefVec
Definition def.h:98