11 , root_(make_node(r)) {
18 , root_(make_node(nullptr)) {
20 make_node(mut, root_);
28void Nest::populate(
bool transitive) {
29 std::queue<Node*> queue;
34 for (
auto child : root_->children_.mut_nodes())
37 while (!queue.empty()) {
38 auto curr_node = fe::pop(queue);
39 for (
auto op : curr_node->mut()->deps()) {
40 for (
auto local_mut : op->local_muts()) {
41 if (node(local_mut))
continue;
43 if (transitive && local_mut->is_closed()) queue.push(make_node(local_mut, root_));
47 queue.push(make_node(local_mut, innermost(local_mut)));
55 if (
auto n = node(fv->binder()); n && n->level() > res->level()) res = n;
60 if (
auto mut = def->isa_mut())
return innermost(root_, mut->free_vars());
61 auto res = innermost(root_, def->local_vars());
62 for (
auto mut : def->local_muts())
63 res = innermost(res, mut->free_vars());
68 auto node = std::unique_ptr<Node>(
new Node(*
this, mut,
inest));
69 auto res = node.get();
70 mut2node_.emplace(mut, std::move(node));
72 if (
auto var = mut->has_var()) vars_ =
world().
vars().insert(vars_, var);
78 auto path = fe::Vector<Node*>();
79 calc_sibl_deps(root_, path);
86 for (
auto child : root_->children_.mut_nodes())
88 root_->postorder_number_ = ++n;
91 for (
auto& [mut, node] : mut2node_)
92 if (mut && node->children().num() != 0) calc_dominance(node.get());
96void Nest::calc_sibl_deps(
Node* curr, fe::Vector<Node*>& path) {
97 path.emplace_back(curr);
99 for (
auto op : curr->mut()->deps()) {
100 for (
auto local_mut :
op->local_muts()) {
101 if (
auto local_node = node(local_mut)) {
102 if (local_node->is_root()) local_node->recursive_ =
true;
103 if (local_node == curr) {
104 local_node->link(local_node);
105 }
else if (
auto inest = local_node->inest_) {
107 if (
auto l =
inest->level() + 1; l < path.size() && path[l - 1] ==
inest) {
108 assert(
inest->children().contains(path[l]->mut()));
109 path[
l]->link(local_node);
117 for (
auto child : curr->children_.mut_nodes())
118 calc_sibl_deps(child, path);
122void Nest::calc_SCCs(
Node* curr) {
124 for (uint32_t i = 0;
auto child : curr->children_.mut_nodes())
125 if (child->idx_ == Node::Unvisited) i = child->tarjan(i, stack);
127 for (
auto child : curr->children_.mut_nodes()) {
128 child->loop_depth_ = child->is_recursive() ? curr->loop_depth() + 1 : curr->loop_depth();
133uint32_t Nest::Node::tarjan(uint32_t i, Stack& stack) {
134 this->idx_ = this->low_ = i++;
135 this->on_stack_ =
true;
138 for (
auto dep : this->sibl_deps_.nodes_) {
139 if (dep->idx_ == Unvisited) i = dep->tarjan(i, stack);
140 if (dep->on_stack_) this->low_ = std::min(this->low_, dep->low_);
143 if (this->idx_ == this->low_) {
144 inest_->topo_.emplace_front(std::make_unique<SCC>());
145 SCC*
scc = inest_->topo_.front().get();
149 node = fe::pop(stack);
150 node->on_stack_ =
false;
151 node->recursive_ =
true;
152 node->low_ = this->idx_;
157 }
while (node !=
this);
159 if (num == 1 && !this->sibl_deps_.contains(
this)) this->recursive_ =
false;
165void Nest::number(
Node* node,
size_t& n) {
166 if (node->postorder_number_)
return;
167 node->postorder_number_ = 0;
168 for (
auto op : node->mut()->deps())
169 for (
auto mut :
op->local_muts())
170 if (
auto succ = this->node(mut)) number(succ, n);
171 node->postorder_number_ = ++n;
176 if (n->postorder_number_ < m->postorder_number_)
177 n = n->idom_ ? n->idom_ : n->
inest();
178 else if (m->postorder_number_ < n->postorder_number_)
179 m = m->idom_ ? m->idom_ : m->
inest();
184void Nest::sibl_post_order(
Node* node, ankerl::unordered_dense::set<const Node*>& visited, fe::Vector<Node*>&
nodes) {
185 if (!visited.insert(node).second)
return;
186 for (
auto succ : node->sibl_deps_.nodes_)
187 sibl_post_order(succ, visited,
nodes);
188 nodes.push_back(node);
194void Nest::calc_dominance(Node* parent) {
196 for (
auto op : parent->mut()->deps()) {
197 for (
auto local_mut : op->local_muts())
198 if (
auto node = this->node(local_mut); node && node->inest_ == parent) node->idom_ = parent;
202 ankerl::unordered_dense::set<const Node*> visited;
203 fe::Vector<Node*>
nodes;
204 for (
auto op : parent->mut()->deps()) {
205 for (
auto mut :
op->local_muts())
206 if (
auto node = this->node(mut); node && node->inest_ == parent) sibl_post_order(node, visited,
nodes);
210 for (
bool todo =
true; todo;) {
212 for (
auto node :
nodes | std::views::reverse) {
214 if (node->idom_ == parent)
continue;
216 const Node* new_idom =
nullptr;
217 for (
auto user : node->sibl_rev_deps_.nodes_)
218 if (user->idom_) new_idom = new_idom ?
lca(new_idom, user) : user;
219 if (node->idom_ != new_idom) {
220 node->idom_ = new_idom;
GIDSet< const Node * > SCC
Strongly Connected Component.
const SCC & scc() const
The SCC among its siblings this Node belongs to; the Nest::root() has none.
const Node * inest() const
Immediate nester/parent of this Node.
const Node * inest(const Def *def) const
The innermost Node binding a free Var of def, or the root() if there is none.
static const Node * lca(const Node *n, const Node *m)
Least common ancestor of n and m.
const Node * root() const
Vars vars() const
All Vars occurring in this Nest.
bool contains(const Def *def) const
The World represents the whole program and manages creation of MimIR nodes (Defs).
fe::Patricia< const Var, DefKey >::Set Vars