15uint64_t CFNode::gid_counter_ = 0;
17void CFNode::link(
const CFNode* other)
const {
18 this->succs_.emplace(other);
19 other->preds_.emplace(
this);
28 , entry_(node(scope.entry()))
29 , exit_(node(scope.exit())) {
30 std::queue<Def*> cfg_queue;
33 auto cfg_enqueue = [&](
Def* mut) {
34 if (mut->is_set() && cfg_done.emplace(mut).second) cfg_queue.push(mut);
39 while (!cfg_queue.empty()) {
40 auto src =
pop(cfg_queue);
41 std::queue<const Def*> queue;
44 auto enqueue = [&](
const Def* def) {
45 if (def->isa<
Var>())
return;
47 if (
scope.
bound(def) && done.emplace(def).second) {
48 if (
auto dst = def->isa_mut()) {
50 node(src)->link(node(dst));
58 while (!queue.empty()) {
59 auto def =
pop(queue);
60 for (
auto op : def->
ops()) enqueue(op);
69 auto&& n = nodes_[mut];
70 if (n ==
nullptr) n =
new CFNode(mut);
75 for (
const auto& p : nodes_)
delete p.second;
81void CFA::link_to_exit() {
85 std::queue<const CFNode*> queue;
88 for (
auto p :
nodes()) {
90 if (n != exit() && n->succs().empty()) n->link(exit());
93 auto backwards_reachable = [&](
const CFNode* n) {
94 auto enqueue = [&](
const CFNode* n) {
95 if (reachable.emplace(n).second) queue.push(n);
100 while (!queue.empty())
101 for (
auto pred :
pop(queue)->preds()) enqueue(pred);
104 std::stack<const CFNode*> stack;
107 auto push = [&](
const CFNode* n) {
108 if (on_stack.emplace(n).second) {
116 backwards_reachable(exit());
119 while (!stack.empty()) {
120 auto n = stack.top();
123 for (
auto succ : n->succs()) todo |= push(succ);
126 if (!reachable.contains(n)) {
128 backwards_reachable(n);
138 for (
const auto& p :
nodes()) {
140 if (in != entry() && in->preds_.size() == 0) {
141 world().VLOG(
"missing predecessors: {}", in->mut());
148 assert(
false &&
"CFG not sound");
154template<
bool forward>
159 assert_unused(
index == 0);
163 auto& n_index = forward ? n->f_index_ : n->b_index_;
164 n_index = size_t(-2);
166 for (
auto succ : succs(n))
167 if (index(succ) ==
size_t(-1)) i = post_order_visit(succ, i);
const B_CFG & b_cfg() const
const Scope & scope() const
const MutMap< const CFNode * > & nodes() const
const F_CFG & f_cfg() const
const LoopTree< forward > & looptree() const
const DomFrontierBase< forward > & domfrontier() const
const DomTreeBase< forward > & domtree() const
const CFNodes & preds(const CFNode *n) const
static size_t index(const CFNode *n)
const CFNodes & succs(const CFNode *n) const
const CFNode * entry() const
A Dominance Frontier Graph.
Calculates a loop nesting forest rooted at LoopTree::root_.
A Scope represents a region of Defs that are live from the view of an entry's Var.
bool bound(const Def *def) const
auto pop(S &s) -> decltype(s.top(), typename S::value_type())
absl::flat_hash_set< K, GIDHash< K >, GIDEq< K > > GIDSet
T & lazy_init(const This *self, std::unique_ptr< T > &ptr)
void error(Loc loc, const char *f, Args &&... args)
GIDSet< const Def * > DefSet
GIDSet< const CFNode * > CFNodes
std::ostream & operator<<(std::ostream &, const CFNode *)