12 if (
auto [_, ins] = analyzed_.emplace(def); !ins)
return;
14 if (
auto app = def->isa<
App>())
15 if (
auto lam = app->callee()->isa_mut<
Lam>(); lam && lam->
has_var()) visit(app, lam);
17 for (
auto d : def->
deps())
21void StaticArgOpt::visit(
const App* app, Lam* lam) {
22 auto mask = fe::Bitset();
23 for (
size_t i = 0, n = lam->num_tdoms(); i != n; ++i)
24 if (app->targ(i) == lam->tvar(i)) mask.set(i);
25 if (mask.any()) lam2sites_[lam].emplace_back(std::move(mask));
28fe::Bitset StaticArgOpt::statics(
Lam* lam) {
29 if (
auto i = lam2statics_.find(lam); i != lam2statics_.end())
return i->second;
32 auto i = lam2sites_.find(lam);
33 if (i == lam2sites_.end() || !lam->is_set() || !lam->is_closed() || lam->type()->isa_mut<Pi>())
34 return lam2statics_[lam] = fe::Bitset();
36 const auto& sites = i->second;
37 auto n = lam->num_tdoms();
41 auto pool = fe::Bitset();
42 for (
size_t s = 0, e = sites.size(); s != e; ++s)
44 for (
size_t d = n;
d-- != 0;) {
45 if (!lam->tdom(d)->isa<Pi>())
continue;
47 for (
const auto& mask : sites)
50 for (
size_t s = 0, e = sites.size(); s != e; ++s)
51 pool.set(s, sites[s][d]);
55 auto res = fe::Bitset();
56 for (
size_t d = 0;
d != n; ++
d)
58 for (
size_t s = 0, e = sites.size(); s != e; ++s)
59 if (pool[s]) res &= sites[
s];
60 if (res.none())
return lam2statics_[lam] = fe::Bitset();
62 log().d(
"statics of {}: {}", lam, res);
63 return lam2statics_[lam] = res;
68 if (
auto statics = this->statics(old_lam); statics.any()) {
70 auto n = old_lam->num_tdoms();
72 for (
size_t i = 0; i != n; ++i)
73 if (!statics[i]) loop_doms.emplace_back(
rewrite(old_lam->tdom(i)));
77 loop->debug_suffix(
"_loop");
78 log().d(
"{} → wrap {}, loop {}", old_lam, wrap, loop);
79 old2wrap_loop_[old_lam] = {wrap, loop};
83 for (
size_t i = 0, j = 0; i != n; ++i) {
85 vars[i] = wrap->tvar(i);
87 vars[i] = loop->var(loop_doms.size(), j++);
88 args.emplace_back(wrap->tvar(i));
95 wrap->app(
false, loop,
args);
100 return RWPhase::rewrite_mut_Lam(old_lam);
105 if (
auto statics = this->statics(old_lam); statics.any()) {
107 if (
auto i = old2wrap_loop_.find(old_lam); i != old2wrap_loop_.end()) {
108 auto loop = i->second.second;
109 auto n = old_lam->num_tdoms();
111 for (
size_t i = 0; i != n; ++i) {
112 auto old_arg = old_app->targ(i);
115 else if (old_arg != old_lam->tvar(i))
116 return RWPhase::rewrite_imm_App(old_app);
124 return RWPhase::rewrite_imm_App(old_app);
const Def * callee() const
Defs deps() const noexcept
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
DbgKey dbg_key() const
Cheap handle for other->set(this->dbg_key()).
const Def * var(nat_t a, nat_t i) noexcept
const Var * has_var()
Only returns not nullptr, if Var of this mutable has ever been created.
const Def * filter() const
const Def * codom() const
void invalidate(bool todo=true)
Signals that another round of fixed-point iteration is required, either as part of.
const fe::Log & log() const
const fe::Vector< std::string > & args()
Command-line arguments passed to this Phase's plugin via -X <plugin>:<arg>.
A dependent function type.
bool is_bootstrapping() const
Returns whether we are currently bootstrapping (rewriting annexes).
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_mut_Lam(Lam *) final
bool analyze() final
Runs the optional pre-analysis on Phase::world, typically to a fixed point, before rewriting begins.
const Def * rewrite_imm_App(const App *) final
const Def * app(const Def *callee, const Def *arg)
fe::Vector< const Def * > DefVec