3#include <absl/container/fixed_array.h>
10 ILOG(
"iter: {}", i++);
14 concr2abstr(init(def));
15 for (
auto def :
old_world().externals().muts())
16 concr2abstr(init(def));
22const Def* SCCP::init(
const Def* def) {
23 if (
auto mut = def->
isa_mut())
return init(mut);
27const Def* SCCP::init(Def* mut) {
28 if (
auto var = mut->has_var()) concr2abstr(var, var);
32const Def* SCCP::concr2abstr(
const Def* concr) {
33 if (
auto [_, ins] = visited_.emplace(concr); !ins) {
34 if (
auto i = concr2abstr_.find(concr); i != concr2abstr_.end())
return i->second;
38 if (
auto mut = concr->isa_mut()) {
39 concr2abstr(mut, mut);
41 for (
auto d : mut->deps())
46 return concr2abstr(concr, concr2abstr_impl(concr)).first;
49const Def* SCCP::concr2abstr_impl(
const Def* def) {
50 if (
auto type = def->type()) concr2abstr(type);
52 if (
auto branch = Branch(def)) {
53 auto abstr = concr2abstr(branch.cond());
55 if (l && *l)
return concr2abstr(branch.tt());
56 if (l && !*l)
return concr2abstr(branch.ff());
57 }
else if (
auto app = def->isa<
App>()) {
58 if (
auto lam = app->callee()->isa_mut<
Lam>(); lam && lam->is_set()) {
59 auto ins = concr2abstr(lam, lam).second;
61 auto n = app->num_args();
62 auto abstr_args = absl::FixedArray<const Def*>(n);
63 auto abstr_vars = absl::FixedArray<const Def*>(n);
64 for (
size_t i = 0; i != n; ++i) {
65 auto abstr = concr2abstr(app->targ(i));
66 abstr_vars[i] = concr2abstr(lam->tvar(i), abstr).first;
67 abstr_args[i] = abstr;
70 concr2abstr(lam->var(),
old_world().tuple(abstr_vars));
73 for (
auto d : lam->deps())
78 }
else if (
auto var = def->isa<
Var>()) {
79 assert(var->mut()->isa<
Lam>());
83 auto n = def->num_ops();
84 auto abstrs = absl::FixedArray<const Def*>(n);
85 for (
size_t i = 0; i != n; ++i)
86 abstrs[i] = concr2abstr(def->op(i));
91std::pair<const Def*, bool> SCCP::concr2abstr(
const Def* concr,
const Def* abstr) {
92 auto [_, v_ins] = visited_.emplace(concr);
93 auto [i, c2a_ins] = concr2abstr_.emplace(concr, abstr);
98 i->second = join(concr, i->second, abstr);
100 return {i->second, v_ins};
103const Def* SCCP::join(
const Def* concr,
const Def* abstr1,
const Def* abstr2) {
104 const Def* result =
nullptr;
105 if (abstr1 == abstr2)
return abstr1;
107 if (abstr1->isa<
Bot>())
109 else if (abstr2->isa<
Bot>())
114 todo_ |= abstr1 != result;
119 if (
auto old_lam = old_app->
callee()->
isa_mut<
Lam>(); old_lam && old_lam->
is_set() && !old_lam->is_external()) {
120 if (old_lam->has_var()) {
121 size_t num_old = old_lam->num_vars();
124 if (
auto i = lam2lam_.find(old_lam); i != lam2lam_.end())
129 for (
size_t i = 0; i != num_old; ++i) {
130 auto old_var = old_lam->var(num_old, i);
131 auto abstr = concr2abstr_[old_var];
132 if (abstr == old_var) new_doms.emplace_back(
rewrite(old_lam->tdom(i)));
136 size_t num_new = new_doms.size();
137 auto new_vars = absl::FixedArray<const Def*>(num_old);
139 lam2lam_[old_lam] = new_lam;
142 for (
size_t i = 0, j = 0; i != num_old; ++i) {
143 auto old_var = old_lam->var(num_old, i);
144 auto abstr = concr2abstr_[old_var];
145 new_vars[i] = abstr == old_var ? new_lam->
var(num_new, j++) :
rewrite(abstr);
148 map(old_lam->var(), new_vars);
153 size_t num_new = new_lam->
num_vars();
154 auto new_args = absl::FixedArray<const Def*>(num_new);
155 for (
size_t i = 0, j = 0; i != num_old; ++i) {
156 auto old_var = old_lam->var(num_old, i);
157 auto abstr = concr2abstr_[old_var];
158 if (abstr == old_var) new_args[j++] =
rewrite(old_app->targ(i));
161 return map(old_app,
new_world().app(new_lam, new_args));
165 return Rewriter::rewrite_imm_App(old_app);
const Def * callee() const
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
nat_t num_vars() noexcept
Lam * set(Filter filter, const Def *body)
static std::optional< T > isa(const Def *def)
World & new_world()
Create new Defs into this.
World & old_world()
Get old Defs from here.
virtual const Def * map(const Def *old_def, const Def *new_def)
virtual const Def * rewrite(const Def *)
const Def * rewrite_imm_App(const App *) final
bool analyze() final
You can do an optional fixed-point loop on the RWPhase::old_world before rewriting.
const Type * type(const Def *level)
const Def * app(const Def *callee, const Def *arg)
const Def * bot(const Def *type)
Lam * mut_lam(const Pi *pi)
Vector< const Def * > DefVec