28 nests_.try_emplace(lam, std::make_unique<Nest>(lam));
31 for (
auto external :
world().externals().muts())
32 if (
auto lam = external->isa_mut<
Lam>()) {
33 current_external_ = lam;
42const Def* CPS2DSPhase::rewrite_lam(
Lam* lam) {
43 if (
auto i = rewritten_.find(lam); i != rewritten_.end())
return i->second;
44 if (lam2lam_.contains(lam))
return lam;
46 world().DLOG(
"skipped {}", lam);
54 auto filter = rewrite(lam->
filter());
56 if (
auto body = lam->
body()->isa<
App>(); !body) {
57 world().DLOG(
" non-app body {}, skipped", lam->
body());
58 auto new_body = rewrite(lam->
body());
60 return rewritten_[lam] = lam;
63 auto body = lam->
body()->as<
App>();
64 auto new_arg = rewrite(body->arg());
66 auto new_callee = rewrite(body->callee());
67 auto new_lam = result_lam(lam);
69 world().DLOG(
"Result of rewrite {} set for {}", lam->
unique_name(), new_lam->unique_name());
74 new_lam->unset()->app(filter, new_callee, new_arg);
76 return rewritten_[lam] = lam;
79const Def* CPS2DSPhase::rewrite(
const Def* def) {
80 if (
auto i = rewritten_.find(def); i != rewritten_.end())
return i->second;
82 if (
auto lam = def->isa_mut<
Lam>())
return rewrite_lam(lam);
84 if (
auto app = def->isa<
App>()) {
86 auto cps_lam = rewrite(
cps2ds->arg())->as<
Lam>();
88 auto call_arg = rewrite(app->arg());
95 auto early = scheduler(app).early(app);
96 auto late = scheduler(app).late(current_external_, app);
99 world().DLOG(
"scheduling {} between {} (level {}) and {} (level {}) at {}", app,
100 early->mut() ? early->mut()->unique_name() :
"root", early->level(),
101 late->mut() ? late->mut()->unique_name() :
"root", late->level(),
102 node->mut() ? node->mut()->unique_name() :
"root");
104 auto lam = result_lam(node->mut()->as_mut<
Lam>());
110 auto cn_dom = cps_lam->ret_dom();
111 auto cont = make_continuation(cn_dom, app, cps_lam->sym());
113 world().DLOG(
"continuation created: {} : {}", cont, cont->type());
117 auto filter = rewritten_[lam->
filter()] = rewrite(lam->
filter());
118 auto body =
world().
app(cps_lam,
world().tuple({call_arg, cont}));
119 rewritten_[lam] = lam->
unset()->
set(filter, body);
120 lam2lam_[lam] = cont;
135 DefVec new_ops{def->ops(), [
this](
const Def*
d) {
return rewrite(d); }};
136 auto new_def = def->rebuild(def->type(), new_ops);
137 rewritten_[def] = new_def;
141Lam* CPS2DSPhase::make_continuation(
const Def* cn_type,
const Def* arg, Sym prefix) {
143 world().DLOG(
"make_continuation {} : {} ({})", prefix, cn_type, arg);
149 rewritten_[arg] = cont->
var();
154Lam* CPS2DSPhase::result_lam(
Lam* lam) {
155 if (
auto i = lam2lam_.find(lam); i != lam2lam_.end())
156 if (i->second != lam)
return result_lam(i->second);
160Scheduler& CPS2DSPhase::scheduler(
const Def* def) {
161 auto get_or_make = [&](
const Def* lam,
const Nest& nest) -> Scheduler& {
162 if (
auto sched = scheduler_.find(lam); sched != scheduler_.end()) {
164 world().DLOG(
"found existing scheduler for {}", lam);
166 return sched->second;
169 world().DLOG(
"creating new scheduler for {}", lam);
171 auto [it, inserted] = scheduler_.
insert({lam, Scheduler(nest)});
175 for (
const auto& [lam, nest] : nests_) {
177 world().DLOG(
"looking for scheduler in {} for {}", lam, def);
179 if (nest->contains(def))
return get_or_make(lam, *nest);
182 world().DLOG(
"no scheduler found for {}, using current external {}", def, current_external_);
184 return get_or_make(current_external_, curr_external_nest());
187const Nest& CPS2DSPhase::curr_external_nest()
const {
188 auto i = nests_.find(current_external_);
189 assert(i != nests_.end());
static auto isa(const Def *def)
bool is_set() const
Yields true if empty or the last op is set.
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
const Def * var(nat_t a, nat_t i) noexcept
std::string unique_name() const
name + "_" + Def::gid
const T * isa_imm() const
const Def * filter() const
Lam * set(Filter filter, const Def *body)
Lam * set_filter(Filter)
Set filter first.
const Def * codom() const
static const Node * lca(const Node *n, const Node *m)
Least common ancestor of n and m.
std::string_view name() const
const Def * insert(const Def *d, const Def *i, const Def *val)
const Def * app(const Def *callee, const Def *arg)
void for_each(bool elide_empty, std::function< void(Def *)>)
void debug_dump()
Dump in Debug build if World::log::level is Log::Level::Debug.
Sym append_suffix(Sym name, std::string suffix)
Appends a suffix or an increasing number if the suffix already exists.
const Def * var(Def *mut)
Lam * mut_con(const Def *dom)
void dump(std::ostream &os)
Dump to os.
void start() final
Actual entry.
Vector< const Def * > DefVec