9 , root_(make_node(r)) {
15 , root_(make_node(nullptr)) {
17 make_node(mut, root_);
23 , root_(make_node(nullptr)) {
24 world.for_each(
false, [
this](
Def* mut) { make_node(mut, root_); });
28void Nest::populate() {
29 std::queue<Node*> queue;
37 while (!queue.empty()) {
38 auto curr_node =
pop(queue);
39 for (
auto op : curr_node->mut()->deps()) {
41 if ((*
this)[local_mut] || !
contains(local_mut))
continue;
43 if (curr_node->level() < local_mut->free_vars().size()) {
44 for (
auto node = curr_node;; node = node->inest_) {
45 if (
auto var = node->mut()->has_var()) {
46 if (local_mut->free_vars().contains(var)) {
47 queue.push(make_node(local_mut, node));
55 for (
auto var : local_mut->free_vars()) {
56 if (
auto node = (*
this)[var->mut()]; node && node->level() > max) {
61 queue.push(make_node(local_mut, inest));
69 auto node = std::unique_ptr<Node>(
new Node(*
this, mut, inest));
70 auto res = node.get();
71 mut2node_.emplace(mut, std::move(node));
73 if (
auto var = mut->has_var()) vars_ =
world().
vars().insert(vars_, var);
78void Nest::assign_postorder_numbers()
const {
79 if (
root()->postorder_number_.has_value())
return;
83 std::function<void(
const Nest::Node*)> visit = [&](
const Nest::Node* node) {
84 if (node->postorder_number_.has_value())
return;
85 node->postorder_number_ = 0;
86 for (
auto op : node->mut()->deps()) {
88 if (
auto succ = node->nest()[mut]) visit(succ);
90 node->postorder_number_ = ++number;
98 for (
auto [_, node] :
root()->children())
100 root()->postorder_number_ = ++number;
104template<
bool bootstrapping>
108 if constexpr (!bootstrapping) {
112 if (n->postorder_number_ < m->postorder_number_)
113 n = n->idom_ ? n->idom_ : n->
inest();
114 else if (m->postorder_number_ < n->postorder_number_)
115 m = m->idom_ ? m->idom_ : m->
inest();
121void Nest::calc_sibl_deps(
Node* curr)
const {
123 for (
auto op : curr->mut()->deps()) {
125 if (
auto local_node =
const_cast<Nest&
>(*
this)[local_mut]) {
126 if (local_node == curr)
127 local_node->link(local_node);
128 else if (
auto inest = local_node->inest()) {
129 if (
auto curr_child = inest->curr_child) {
130 assert(inest->children().contains(curr_child->mut()));
131 curr_child->link(local_node);
139 for (
auto child : curr->children().nodes()) {
140 curr->curr_child = child;
141 calc_sibl_deps(child);
142 curr->curr_child =
nullptr;
146void Nest::calc_SCCs(
Node* curr)
const {
148 for (
auto [_, child] : curr->children()) {
149 child->loop_depth_ = child->is_recursive() ? curr->loop_depth() + 1 : curr->loop_depth();
154void Nest::Node::calc_SCCs() {
156 for (
int i = 0;
auto& [_, node] :
children())
157 if (node->idx_ == Unvisited) i = node->tarjan(i,
this, stack);
160uint32_t Nest::Node::tarjan(uint32_t i,
Node* inest, Stack& stack) {
161 this->idx_ = this->low_ = i++;
162 this->on_stack_ =
true;
165 for (
auto dep : this->sibl_deps_.nodes_) {
166 if (dep->idx_ == Unvisited) i = dep->tarjan(i, inest, stack);
167 if (dep->on_stack_) this->low_ = std::min(this->low_, dep->low_);
170 if (this->idx_ == this->low_) {
171 inest_->topo_.emplace_front(std::make_unique<SCC>());
172 SCC* scc = inest_->topo_.front().get();
177 node->on_stack_ =
false;
178 node->recursive_ =
true;
179 node->low_ = this->idx_;
183 auto [_, ins] = inest_->SCCs_.emplace(node, scc);
185 }
while (node !=
this);
187 if (num == 1 && !this->sibl_deps().
contains(
this)) this->recursive_ =
false;
196const Nest::Node* Nest::Node::calc_dominance()
const {
197 if (idom_ || is_root() || !inest()->mut())
return this;
198 nest().assign_postorder_numbers();
200 if (!inest()->mut()) idom_ = inest();
203 absl::flat_hash_set<const Node*> visited;
207 for (
auto op : inest()->mut()->deps()) {
209 if (
auto node = nest()[local_mut]; node && node->inest() == inest()) node->idom_ = inest();
212 std::function<void(
const Node*)> visit = [&](
const Node* node) {
213 if (visited.contains(node))
return;
214 visited.insert(node);
215 for (
auto child : node->sibl_deps())
217 nodes.push_back(node);
221 for (
auto op : inest()->mut()->deps()) {
223 if (
auto node = nest()[mut]; node && node->inest() == inest()) visit(node);
227 for (
bool todo =
true; todo;) {
229 for (
auto node :
nodes | std::ranges::views::reverse) {
231 if (node->idom_ == inest())
continue;
233 const Node* new_idom =
nullptr;
234 for (
auto user : node->sibl_deps<
false>())
235 if (user->idom_) new_idom = new_idom ?
Nest::lca<true>(new_idom, user) : user;
236 if (node->idom_ != new_idom) {
237 node->idom_ = new_idom;
Muts local_muts() const
Mutables reachable by following immutable deps(); mut->local_muts() is by definition the set { mut }...
const Children & children() const
const Node * inest() const
Immediate nester/parent of this Node.
Builds a nesting tree of all mutables‍/binders.
static const Node * lca(const Node *n, const Node *m)
Least common ancestor of n and m.
const Node * root() const
bool contains(const Def *def) const
The World represents the whole program and manages creation of MimIR nodes (Defs).
const Def * op(trait o, const Def *type)
auto pop(S &s) -> decltype(s.top(), typename S::value_type())
Vector(I, I, A=A()) -> Vector< typename std::iterator_traits< I >::value_type, Default_Inlined_Size< typename std::iterator_traits< I >::value_type >, A >