12std::tuple<const Proxy*, Lam*> split_phixy(
const Proxy* phixy) {
13 return {phixy->op(0)->as<
Proxy>(), phixy->op(1)->as_mut<
Lam>()};
32 auto [
mem, id] =
slot->args<2>();
33 auto [_, ptr] =
slot->projs<2>();
35 world().DLOG(
"sloxy: '{}'", sloxy);
36 if (!keep_.contains(sloxy)) {
37 set_val(
curr_mut(), sloxy,
world().bot(get_sloxy_type(sloxy)));
42 auto [
mem, ptr] =
load->args<2>();
45 auto [
mem, ptr, val] =
store->args<3>();
53 return mem2phi(app, mem_lam);
55 for (
size_t i = 0, e = def->
num_ops(); i != e; ++i) {
57 if (mem2phi_.contains(lam))
return def->
refine(i, eta_exp_->
proxy(lam));
65Ref SSAConstr::get_val(
Lam* lam,
const Proxy* sloxy) {
66 auto& sloxy2val = lam2sloxy2val_[lam];
67 if (
auto i = sloxy2val.find(sloxy); i != sloxy2val.end()) {
69 world().DLOG(
"get_val found: '{}': '{}': '{}'", sloxy, val, lam);
72 world().DLOG(
"cannot install phi for '{}' in '{}'", sloxy, lam);
74 }
else if (
auto pred =
data(lam).pred) {
75 world().DLOG(
"get_val recurse: '{}': '{}' -> '{}'", sloxy, pred, lam);
76 return get_val(pred, sloxy);
78 auto phixy =
proxy(get_sloxy_type(sloxy), {sloxy, lam},
Phixy)->set(sloxy->
dbg());
79 phixy->debug_prefix(
"_phi_");
80 world().DLOG(
"get_val phixy: '{}' '{}'", sloxy, lam);
81 return set_val(lam, sloxy, phixy);
85Ref SSAConstr::set_val(Lam* lam,
const Proxy* sloxy, Ref val) {
86 world().DLOG(
"set_val: '{}': '{}': '{}'", sloxy, val, lam);
87 return lam2sloxy2val_[lam][sloxy] = val;
90Ref SSAConstr::mem2phi(
const App* app, Lam* mem_lam) {
91 auto&& sloxys = lam2sloxys_[mem_lam];
92 if (sloxys.empty())
return app;
95 for (
auto i = sloxys.begin(), e = sloxys.end(); i != e;) {
97 if (keep_.contains(sloxy)) {
100 phis.emplace_back(sloxy);
101 types.emplace_back(get_sloxy_type(sloxy));
106 size_t num_phis = phis.size();
107 if (num_phis == 0)
return app;
109 auto&& [phi_lam, old_phis] = mem2phi_[mem_lam];
110 if (phi_lam ==
nullptr || old_phis != phis) {
113 eta_exp_->
new2old(phi_lam, mem_lam);
114 world().DLOG(
"new phi_lam '{}'", phi_lam);
116 auto num_mem_vars = mem_lam->num_vars();
117 DefVec traxy_ops(2 * num_phis + 1);
118 traxy_ops[0] = phi_lam->var();
119 for (
size_t i = 0;
auto sloxy : sloxys) {
120 traxy_ops[2 * i + 1] = sloxy;
121 traxy_ops[2 * i + 2] = phi_lam->var(num_mem_vars + i);
124 auto traxy =
proxy(phi_lam->var()->type(), traxy_ops,
Traxy);
126 auto new_vars =
DefVec(num_mem_vars, [&](
size_t i) {
return traxy->proj(i); });
127 phi_lam->set(mem_lam->reduce(
world().tuple(mem_lam->dom(), new_vars)));
129 world().DLOG(
"reuse phi_lam '{}'", phi_lam);
132 world().DLOG(
"mem_lam => phi_lam: '{}': '{}' => '{}': '{}'", mem_lam, mem_lam->type()->dom(), phi_lam,
134 auto sloxy = sloxys.begin();
135 auto args =
DefVec(num_phis, [&](
auto) {
return get_val(
curr_mut(), *sloxy++); });
143 if (keep_.emplace(
proxy).second) {
144 world().DLOG(
"keep: '{}'; pointer needed",
proxy);
150 auto [sloxy, mem_lam] = split_phixy(
proxy);
151 if (lam2sloxys_[mem_lam].emplace(sloxy).second) {
152 world().DLOG(
"phi needed: phixy '{}' for sloxy '{}' for mem_lam '{}'",
proxy, sloxy, mem_lam);
160 for (
size_t i = 0, e = def->
num_ops(); i != e; ++i) {
162 auto& succ_info =
data(succ_lam);
166 for (
auto writable =
data(
curr_mut()).writable;
auto&& w : writable) succ_info.writable.insert(w);
169 if (succ_info.pred) {
170 world().DLOG(
"several preds in non-callee position; wait for EtaExp");
171 succ_info.pred =
nullptr;
Def * set(size_t i, const Def *def)
Successively set from left to right.
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
const Def * op(size_t i) const
const Def * refine(size_t i, const Def *new_op) const
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
void new2old(Lam *new_lam, Lam *old_lam)
const Proxy * proxy(Lam *lam)
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(Ref d)
const Proxy * isa_proxy(Ref def, u32 tag=0)
Check whether given def is a Proxy whose Proxy::pass matches this Pass's IPass::index.
const Proxy * as_proxy(Ref def, u32 tag=0)
const Proxy * proxy(Ref type, Defs ops, u32 tag=0)
Helper class to retrieve Infer::arg if present.
Ref app(Ref callee, Ref arg)
Lam * mut_lam(const Pi *pi)
Ref rewrite(const Proxy *) override
undo_t analyze(const Proxy *) override
void enter() override
Invoked just before Pass::rewriteing PassMan::curr_mut's body.
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)