43 stack_.reserve(looptree.
cfg().
size());
61 const CFG<forward>& cfg()
const {
return looptree_.cfg(); }
62 Number& number(
const CFNode* n) {
return numbers_[n]; }
63 size_t& lowlink(
const CFNode* n) {
return number(n).low; }
64 size_t& dfs(
const CFNode* n) {
return number(n).dfs; }
65 bool on_stack(
const CFNode* n) {
66 assert(set_.contains(n));
67 return (states_[n] & OnStack) != 0;
69 bool in_scc(
const CFNode* n) {
return states_[n] & InSCC; }
70 bool is_head(
const CFNode* n) {
return states_[n] & IsHead; }
72 bool is_leaf(
const CFNode* n,
size_t num) {
74 for (
const auto& succ : cfg().succs(n))
75 if (!is_head(succ) && n == succ)
return false;
81 void push(
const CFNode* n) {
82 assert(set_.contains(n) && (states_[n] & OnStack) == 0);
83 stack_.emplace_back(n);
84 states_[n] |= OnStack;
87 int visit(
const CFNode* n,
int counter) {
89 numbers_[n] = Number(counter++);
95 int walk_scc(
const CFNode* cur,
Head* parent,
int depth,
int scc_counter);
98 LoopTree<forward>& looptree_;
99 typename CFG<forward>::template Map<Number> numbers_;
100 typename CFG<forward>::template Map<uint8_t> states_;
103 std::vector<const CFNode*> stack_;
106template<
bool forward>
void LoopTreeBuilder<forward>::build() {
107 for (
const auto& n : cfg().reverse_post_order())
110 auto head =
new Head(
nullptr, 0, std::vector<const CFNode*>(0));
111 looptree_.root_.reset(head);
112 recurse(head, {cfg().entry()}, 1);
115template<
bool forward>
void LoopTreeBuilder<forward>::recurse(Head* parent,
View<const CFNode*> heads,
int depth) {
116 size_t curr_new_child = 0;
117 for (
const auto& head : heads) {
119 walk_scc(head, parent, depth, 0);
122 for (
size_t e = parent->num_children(); curr_new_child != e; ++curr_new_child)
123 for (
const auto& head : parent->child(curr_new_child)->cf_nodes()) states_[head] |= IsHead;
126 for (
const auto& node : parent->children())
127 if (
auto new_parent = node->template isa<Head>()) recurse(new_parent, new_parent->cf_nodes(), depth + 1);
130template<
bool forward>
131int LoopTreeBuilder<forward>::walk_scc(
const CFNode* cur, Head* parent,
int depth,
int scc_counter) {
132 scc_counter =
visit(cur, scc_counter);
134 for (
const auto& succ : cfg().succs(cur)) {
135 if (is_head(succ))
continue;
136 if (!set_.contains(succ)) {
137 scc_counter = walk_scc(succ, parent, depth, scc_counter);
138 lowlink(cur) = std::min(lowlink(cur), lowlink(succ));
139 }
else if (on_stack(succ))
140 lowlink(cur) = std::min(lowlink(cur), lowlink(succ));
144 if (lowlink(cur) == dfs(cur)) {
145 std::vector<const CFNode*> heads;
148 size_t num = 0,
e = stack_.size(), b =
e - 1;
150 states_[stack_[b]] |= InSCC;
152 }
while (stack_[b--] != cur);
155 for (
size_t i = ++b; i !=
e; ++i) {
156 const CFNode* n = stack_[i];
158 if (cfg().entry() == n)
159 heads.emplace_back(n);
161 for (
const auto& pred : cfg().preds(n)) {
165 heads.emplace_back(n);
172 if (is_leaf(cur, num)) {
173 assert(heads.size() == 1);
174 looptree_.leaves_[heads.front()] =
new Leaf(index_++, parent, depth, heads);
176 new Head(parent, depth, heads);
179 for (
size_t i = b; i !=
e; ++i) states_[stack_[i]] &= ~(OnStack | InSCC);
190template<
bool forward>
193 , cf_nodes_(cf_nodes.begin(), cf_nodes.end())
198template<
bool forward>
209 if (
auto l = n->template isa<typename LT::Leaf>())
return print(os,
"<{} | dfs: {}", l->cf_node(), l->index());
210 if (
auto h = n->template isa<typename LT::Head>())
return print(os,
"[{, }]", h->cf_nodes());
216template class LoopTree<true>;
217template class LoopTree<false>;
218template std::ostream& operator<< <true>(std::ostream&,
const typename LoopTree<true>::Base*);
219template std::ostream& operator<< <false>(std::ostream&,
const typename LoopTree<false>::Base*);
IndexSet< CFG< forward >, const CFNode * > Set
typename LoopTree< forward >::Head Head
LoopTreeBuilder(LoopTree< forward > &looptree)
typename LoopTree< forward >::Leaf Leaf
typename LoopTree< forward >::Base Base
Represents a node of a loop nesting forest.
Base(Head *parent, int depth, View< const CFNode * >)
A Head owns further nodes as children.
A Leaf only holds a single CFNode and does not have any children.
Calculates a loop nesting forest rooted at LoopTree::root_.
friend class LoopTreeBuilder< forward >
const CFG< forward > & cfg() const
LoopTree(const LoopTree &)=delete
This is a thin wrapper for std::span<T, N> with the following additional features:
bool visit(IndexSet< Indexer, Key > &set, const Key &key)
std::ostream & print(std::ostream &os, const char *s)
Base case.
std::ostream & operator<<(std::ostream &, const CFNode *)
void visit_first(IndexSet< Indexer, Key > &set, const Key &key)