MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
lower_typed_clos_prep.cpp
Go to the documentation of this file.
2
3#include <mim/plug/mem/mem.h>
4
6
7namespace {
8
9bool interesting_type(const Def* type, DefSet& visited) {
10 if (type->isa_mut()) visited.insert(type);
11 if (isa_clos_type(type)) return true;
12 if (auto sigma = type->isa<Sigma>())
13 return std::ranges::any_of(sigma->ops(),
14 [&](auto d) { return !visited.contains(d) && interesting_type(d, visited); });
15 if (auto arr = type->isa<Arr>()) return interesting_type(arr->body(), visited);
16 return false;
17}
18
19bool interesting_type(const Def* def) {
20 auto visited = DefSet();
21 return interesting_type(def->type(), visited);
22}
23
24void split(DefSet& out, const Def* def, bool as_callee) {
25 if (auto lam = def->isa<Lam>()) {
26 out.insert(lam);
27 } else if (auto [var, lam] = isa_var_proj<Lam>(def); var && lam) {
28 if (var->type()->isa<Pi>() || interesting_type(var)) out.insert(var);
29 } else if (auto c = isa_clos_lit(def, false)) {
30 split(out, c.fnc(), as_callee);
31 } else if (auto a = Axm::isa<attr>(def)) {
32 split(out, a->arg(), as_callee);
33 } else if (auto proj = def->isa<Extract>()) {
34 split(out, proj->tuple(), as_callee);
35 } else if (auto pack = def->isa<Pack>()) {
36 split(out, pack->body(), as_callee);
37 } else if (auto tuple = def->isa<Tuple>()) {
38 for (auto op : tuple->ops())
39 split(out, op, as_callee);
40 } else if (as_callee) {
41 out.insert(def);
42 }
43}
44
45DefSet split(const Def* def, bool keep_others) {
46 DefSet out;
47 split(out, def, keep_others);
48 return out;
49}
50
51} // namespace
52
53bool LowerTypedClosPrep::set_esc(const Def* def) {
54 auto changed = false;
55 for (auto d : split(def, false)) {
56 if (is_esc(d)) continue;
57 DLOG("set esc: {}", d);
58 esc_.emplace(d);
59 changed = true;
60 }
61 return changed;
62}
63
65 auto changed = false;
66 DefSet done;
67
68 auto visit = [&](auto&& visit, const Def* def) -> void {
69 if (!done.emplace(def).second) return;
70
71 if (auto c = isa_clos_lit(def, false)) {
72 DLOG("closure ({}, {})", c.env(), c.fnc());
73 if (!c.fnc_as_lam() || is_esc(c.fnc_as_lam()) || is_esc(c.env_var())) changed |= set_esc(c.env());
74 } else if (auto store = Axm::isa<mem::store>(def)) {
75 DLOG("store {}", store->arg(2));
76 changed |= set_esc(store->arg(2));
77 } else if (auto app = def->isa<App>(); app && Pi::isa_cn(app->callee_type())) {
78 DLOG("app {}", def);
79 auto callees = split(app->callee(), true);
80 for (auto i = 0_u64; i < app->num_args(); i++) {
81 if (!interesting_type(app->arg(i))) continue;
82 if (std::ranges::any_of(callees, [&](const Def* callee) {
83 if (auto lam = callee->isa_mut<Lam>()) return is_esc(lam->var(i));
84 return true;
85 }))
86 changed |= set_esc(app->arg(i));
87 }
88 }
89
90 if (auto mut = def->isa_mut()) {
91 if (mut->is_set())
92 for (auto op : mut->deps())
93 visit(visit, op);
94 } else {
95 for (auto op : def->deps())
96 visit(visit, op);
97 }
98 };
99
100 for (auto def : old_world().roots())
101 visit(visit, def);
102
103 return changed;
104}
105
107 if (!is_bootstrapping()) {
108 if (auto closure = isa_clos_lit(tuple, false)) {
109 auto fnc = closure.fnc();
110 if (!Axm::isa<attr>(fnc)) {
111 auto new_fnc = new_world().call(esc_.contains(fnc) ? attr::esc : attr::bottom, rewrite(fnc));
112 return clos_pack(rewrite(closure.env()), new_fnc, rewrite(closure->type()));
113 }
114 }
115 }
116 return RWPhase::rewrite_imm_Tuple(tuple);
117}
118
119} // namespace mim::plug::clos::phase
static auto isa(const Def *def)
Definition axm.h:107
Base class for all Defs.
Definition def.h:261
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:527
A function.
Definition lam.h:110
static const Pi * isa_cn(const Def *d)
Is this a continuation - i.e. is the Pi::codom mim::Bottom?
Definition lam.h:47
World & new_world()
Create new Defs into this.
Definition phase.h:368
bool is_bootstrapping() const
Returns whether we are currently bootstrapping (rewriting annexes).
Definition phase.h:356
World & old_world()
Get old Defs from here.
Definition phase.h:367
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:56
Data constructor for a Sigma.
Definition tuple.h:70
const Def * call(const Def *callee, T &&arg, Args &&... args)
Definition world.h:641
const Def * rewrite_imm_Tuple(const Tuple *) final
bool analyze() final
One escape-propagation round over the old world; RWPhase::start() iterates until fixpoint.
#define DLOG(...)
Vaporizes to nothingness in Debug build.
Definition log.h:94
ClosLit isa_clos_lit(const Def *def, bool fn_isa_lam=true)
Tries to match a closure literal.
Definition clos.cpp:50
std::tuple< const Extract *, N * > isa_var_proj(const Def *def)
If def is a projection var#i of the Var of some mutable of type N, returns (projection,...
Definition clos.h:72
const Def * clos_pack(const Def *env, const Def *fn, const Def *ct=nullptr)
Pack a typed closure.
Definition clos.cpp:59
const Sigma * isa_clos_type(const Def *def)
Definition clos.cpp:88
The tuple Plugin
GIDSet< const Def * > DefSet
Definition def.h:76
@ Pi
Definition def.h:109
@ Lam
Definition def.h:109
@ Arr
Definition def.h:109
@ Pack
Definition def.h:109
@ Sigma
Definition def.h:109
@ Extract
Definition def.h:109
@ Tuple
Definition def.h:109