12std::tuple<const Proxy*, Lam*> split_phixy(
const Proxy* phixy) {
13 return {phixy->op(0)->as<
Proxy>(), phixy->op(1)->as_mut<
Lam>()};
27 for (
size_t i = 1, e =
proxy->num_ops(); i != e; i += 2)
37 auto [
mem, id] =
slot->args<2>();
38 auto [_, ptr] =
slot->projs<2>();
40 DLOG(
"sloxy: '{}'", sloxy);
41 if (!keep_.contains(sloxy)) {
42 set_val(
curr_mut(), sloxy,
world().bot(get_sloxy_type(sloxy)));
47 auto [
mem, ptr] =
load->args<2>();
50 auto [
mem, ptr, val] =
store->args<3>();
58 return mem2phi(app, mem_lam);
60 for (
size_t i = 0, e = def->
num_ops(); i != e; ++i) {
62 if (mem2phi_.contains(lam))
return def->
refine(i, eta_exp_->proxy(lam));
70const Def* SSA::get_val(
Lam* lam,
const Proxy* sloxy) {
71 auto& sloxy2val = lam2sloxy2val_[lam];
72 if (
auto i = sloxy2val.find(sloxy); i != sloxy2val.end()) {
74 DLOG(
"get_val found: '{}': '{}': '{}'", sloxy, val, lam);
77 DLOG(
"cannot install phi for '{}' in '{}'", sloxy, lam);
79 }
else if (
auto pred =
data(lam).pred) {
80 DLOG(
"get_val recurse: '{}': '{}' -> '{}'", sloxy, pred, lam);
81 return get_val(pred, sloxy);
83 auto phixy =
proxy(get_sloxy_type(sloxy), {sloxy, lam},
Phixy)->set(sloxy->
dbg());
84 phixy->debug_prefix(
"_phi_");
85 DLOG(
"get_val phixy: '{}' '{}'", sloxy, lam);
86 return set_val(lam, sloxy, phixy);
90const Def* SSA::set_val(
Lam* lam,
const Proxy* sloxy,
const Def* val) {
91 DLOG(
"set_val: '{}': '{}': '{}'", sloxy, val, lam);
92 return lam2sloxy2val_[lam][sloxy] = val;
95const Def* SSA::mem2phi(
const App* app,
Lam* mem_lam) {
96 auto&& sloxys = lam2sloxys_[mem_lam];
97 if (sloxys.empty())
return app;
100 for (
auto i = sloxys.begin(), e = sloxys.end(); i != e;) {
102 if (keep_.contains(sloxy)) {
105 phis.emplace_back(sloxy);
106 types.emplace_back(get_sloxy_type(sloxy));
111 size_t num_phis = phis.size();
112 if (num_phis == 0)
return app;
114 auto&& [phi_lam, old_phis] = mem2phi_[mem_lam];
115 if (phi_lam ==
nullptr || old_phis != phis) {
118 eta_exp_->new2old(phi_lam, mem_lam);
119 DLOG(
"new phi_lam '{}'", phi_lam);
121 auto num_mem_vars = mem_lam->num_vars();
122 DefVec traxy_ops(2 * num_phis + 1);
123 traxy_ops[0] = phi_lam->var();
124 for (
size_t i = 0;
auto sloxy : sloxys) {
125 traxy_ops[2 * i + 1] = sloxy;
126 traxy_ops[2 * i + 2] = phi_lam->
var(num_mem_vars + i);
129 auto traxy =
proxy(phi_lam->var()->type(), traxy_ops,
Traxy);
131 auto new_vars =
DefVec(num_mem_vars, [&](
size_t i) {
return traxy->proj(i); });
132 phi_lam->set(mem_lam->reduce(
world().tuple(mem_lam->dom(), new_vars)));
134 DLOG(
"reuse phi_lam '{}'", phi_lam);
137 DLOG(
"mem_lam => phi_lam: '{}': '{}' => '{}': '{}'", mem_lam, mem_lam->type()->dom(), phi_lam, phi_lam->dom());
138 auto sloxy = sloxys.begin();
139 auto args =
DefVec(num_phis, [&](
auto) {
return get_val(
curr_mut(), *sloxy++); });
145 auto sloxy_lam =
proxy->op(0)->as_mut<
Lam>();
147 if (keep_.emplace(
proxy).second) {
148 DLOG(
"keep: '{}'; pointer needed",
proxy);
154 auto [sloxy, mem_lam] = split_phixy(
proxy);
155 if (lam2sloxys_[mem_lam].emplace(sloxy).second) {
156 DLOG(
"phi needed: phixy '{}' for sloxy '{}' for mem_lam '{}'",
proxy, sloxy, mem_lam);
164 for (
size_t i = 0, e = def->
num_ops(); i != e; ++i) {
166 auto& succ_info =
data(succ_lam);
170 for (
auto writable =
data(
curr_mut()).writable;
auto&& w : writable)
171 succ_info.writable.insert(w);
174 if (succ_info.pred) {
175 DLOG(
"several preds in non-callee position; wait for EtaExp");
176 succ_info.pred =
nullptr;
static auto isa(const Def *def)
static auto as(const Def *def)
Def * set(size_t i, const Def *)
Successively set from left to right.
const Def * refine(size_t i, const Def *new_op) const
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
const Def * op(size_t i) const noexcept
const Def * var(nat_t a, nat_t i) noexcept
bool is_external() const noexcept
constexpr size_t num_ops() const noexcept
Performs η-expansion: f -> λx.f x, if f is a Lam with more than one user and does not appear in calle...
undo_t undo_visit(Def *mut) const
undo_t undo_enter(Def *mut) const
Lam * set(Filter filter, const Def *body)
static const Lam * isa_basicblock(const Def *d)
const Proxy * proxy(const Def *type, Defs ops, u32 tag=0)
virtual void init(PassMan *)
const Proxy * isa_proxy(const Def *def, u32 tag=0)
Check whether given def is a Proxy whose Proxy::pass matches this Pass's IPass::index.
const Proxy * as_proxy(const Def *def, u32 tag=0)
const Def * app(const Def *callee, const Def *arg)
const Def * tuple(Defs ops)
Lam * mut_lam(const Pi *pi)
const Def * rewrite(const Proxy *) override
void init(PassMan *) final
undo_t analyze(const Proxy *) override
void enter() override
Invoked just before Pass::rewriteing PassMan::curr_mut's body.
#define DLOG(...)
Vaporizes to nothingness in Debug build.
const Def * op_remem(const Def *mem)
Vector< const Def * > DefVec
std::pair< const App *, Lam * > isa_apped_mut_lam(const Def *def)
const Def * merge_sigma(const Def *def, Defs defs)
Lam * isa_workable(Lam *lam)
These are Lams that are neither nullptr, nor Lam::is_external, nor Lam::is_unset.
const App * isa_callee(const Def *def, size_t i)
static constexpr undo_t No_Undo
const Def * merge_tuple(const Def *def, Defs defs)