Thorin 1.9.0
The Higher ORder INtermediate representation
Loading...
Searching...
No Matches
cfg.h
Go to the documentation of this file.
1#pragma once
2
3#include <vector>
4
8#include "thorin/util/print.h"
9#include "thorin/util/span.h"
10
11namespace thorin {
12
13class CFNode;
14// clang-format off
15template<bool> class LoopTree;
16template<bool> class DomTreeBase;
17template<bool> class DomFrontierBase;
18// clang-format on
19
20/// @name Control Flow
21///@{
23///@}
24
25/// A Control-Flow Node.
26/// Managed by CFA.
27class CFNode {
28public:
30 : mut_(mut)
31 , gid_(gid_counter_++) {}
32
33 uint64_t gid() const { return gid_; }
34 Def* mut() const { return mut_; }
35
36private:
37 const CFNodes& preds() const { return preds_; }
38 const CFNodes& succs() const { return succs_; }
39 void link(const CFNode* other) const;
40
41 mutable size_t f_index_ = -1; ///< RPO index in a **forward** CFG.
42 mutable size_t b_index_ = -1; ///< RPO index in a **backwards** CFG.
43
44 Def* mut_;
45 size_t gid_;
46 static uint64_t gid_counter_;
47 mutable CFNodes preds_;
48 mutable CFNodes succs_;
49
50 friend class CFA;
51 template<bool> friend class CFG;
52};
53
54/// @name std::ostream operator
55///@{
56std::ostream& operator<<(std::ostream&, const CFNode*);
57///@}
58
59//------------------------------------------------------------------------------
60
61/// Control Flow Analysis.
62class CFA {
63public:
64 CFA(const CFA&) = delete;
65 CFA& operator=(CFA) = delete;
66
67 explicit CFA(const Scope& scope);
68 ~CFA();
69
70 const Scope& scope() const { return scope_; }
71 World& world() const { return scope().world(); }
72 size_t size() const { return nodes().size(); }
73 const MutMap<const CFNode*>& nodes() const { return nodes_; }
74 const F_CFG& f_cfg() const;
75 const B_CFG& b_cfg() const;
76 const CFNode* operator[](Def* mut) const {
77 auto i = nodes_.find(mut);
78 return i == nodes_.end() ? nullptr : i->second;
79 }
80
81private:
82 void link_to_exit();
83 void verify();
84 const CFNodes& preds(Def* mut) const {
85 auto cn = nodes_.find(mut)->second;
86 assert(cn);
87 return cn->preds();
88 }
89 const CFNodes& succs(Def* mut) const {
90 auto cn = nodes_.find(mut)->second;
91 assert(cn);
92 return cn->succs();
93 }
94 const CFNode* entry() const { return entry_; }
95 const CFNode* exit() const { return exit_; }
96 const CFNode* node(Def*);
97
98 const Scope& scope_;
99 MutMap<const CFNode*> nodes_;
100 const CFNode* entry_;
101 const CFNode* exit_;
102 mutable std::unique_ptr<const F_CFG> f_cfg_;
103 mutable std::unique_ptr<const B_CFG> b_cfg_;
104
105 template<bool> friend class CFG;
106};
107
108//------------------------------------------------------------------------------
109
110/// A Control-Flow Graph.
111/// A small wrapper for the information obtained by a CFA.
112/// The template parameter @p forward determines the direction of the edges:
113/// * `true` means a conventional CFG.
114/// * `false* means that all edges in this CFG are reversed.
115/// Thus, a [dominance analysis](DomTreeBase), for example, becomes a post-dominance analysis.
116template<bool forward> class CFG {
117public:
118 template<class Value> using Map = IndexMap<CFG<forward>, const CFNode*, Value>;
120
121 CFG(const CFG&) = delete;
122 CFG& operator=(CFG) = delete;
123
124 explicit CFG(const CFA&);
125
126 const CFA& cfa() const { return cfa_; }
127 size_t size() const { return cfa().size(); }
128 const CFNodes& preds(const CFNode* n) const;
129 const CFNodes& succs(const CFNode* n) const;
130 const CFNodes& preds(Def* mut) const { return preds(cfa()[mut]); }
131 const CFNodes& succs(Def* mut) const { return succs(cfa()[mut]); }
132 size_t num_preds(const CFNode* n) const { return preds(n).size(); }
133 size_t num_succs(const CFNode* n) const { return succs(n).size(); }
134 size_t num_preds(Def* mut) const { return num_preds(cfa()[mut]); }
135 size_t num_succs(Def* mut) const { return num_succs(cfa()[mut]); }
136 const CFNode* entry() const { return forward ? cfa().entry() : cfa().exit(); }
137 const CFNode* exit() const { return forward ? cfa().exit() : cfa().entry(); }
138
139 auto reverse_post_order() const { return rpo_.array().view(); }
140 auto post_order() const { return std::views::reverse(rpo_.array()); }
141 /// Maps from reverse post-order index to CFNode.
142 const CFNode* reverse_post_order(size_t i) const { return rpo_.array()[i]; }
143 /// Maps from post-order index to CFNode.
144 const CFNode* post_order(size_t i) const { return rpo_.array()[size() - 1 - i]; }
145 const CFNode* operator[](Def* mut) const { return cfa()[mut]; } ///< Maps from @p mut to CFNode.
146 const DomTreeBase<forward>& domtree() const;
147 const LoopTree<forward>& looptree() const;
149
150 static size_t index(const CFNode* n) { return forward ? n->f_index_ : n->b_index_; }
151
152private:
153 size_t post_order_visit(const CFNode* n, size_t i);
154
155 const CFA& cfa_;
156 Map<const CFNode*> rpo_;
157 mutable std::unique_ptr<const DomTreeBase<forward>> domtree_;
158 mutable std::unique_ptr<const LoopTree<forward>> looptree_;
159 mutable std::unique_ptr<const DomFrontierBase<forward>> domfrontier_;
160};
161
162//------------------------------------------------------------------------------
163
164} // namespace thorin
Control Flow Analysis.
Definition cfg.h:62
CFA(const CFA &)=delete
World & world() const
Definition cfg.h:71
CFA & operator=(CFA)=delete
const MutMap< const CFNode * > & nodes() const
Definition cfg.h:73
size_t size() const
Definition cfg.h:72
const Scope & scope() const
Definition cfg.h:70
const B_CFG & b_cfg() const
Definition cfg.cpp:82
const F_CFG & f_cfg() const
Definition cfg.cpp:81
const CFNode * operator[](Def *mut) const
Definition cfg.h:76
A Control-Flow Graph.
Definition cfg.h:116
size_t num_succs(Def *mut) const
Definition cfg.h:135
const CFNodes & succs(Def *mut) const
Definition cfg.h:131
const CFNode * reverse_post_order(size_t i) const
Maps from reverse post-order index to CFNode.
Definition cfg.h:142
const LoopTree< forward > & looptree() const
Definition cfg.cpp:181
CFG & operator=(CFG)=delete
size_t size() const
Definition cfg.h:127
auto reverse_post_order() const
Definition cfg.h:139
const CFNodes & preds(const CFNode *n) const
Definition cfg.cpp:178
const CFNode * entry() const
Definition cfg.h:136
static size_t index(const CFNode *n)
Definition cfg.h:150
const CFNode * post_order(size_t i) const
Maps from post-order index to CFNode.
Definition cfg.h:144
CFG(const CFG &)=delete
const DomTreeBase< forward > & domtree() const
Definition cfg.cpp:180
size_t num_preds(const CFNode *n) const
Definition cfg.h:132
auto post_order() const
Definition cfg.h:140
size_t num_preds(Def *mut) const
Definition cfg.h:134
const CFNode * exit() const
Definition cfg.h:137
const CFNodes & succs(const CFNode *n) const
Definition cfg.cpp:179
const CFNode * operator[](Def *mut) const
Maps from mut to CFNode.
Definition cfg.h:145
const DomFrontierBase< forward > & domfrontier() const
Definition cfg.cpp:182
const CFA & cfa() const
Definition cfg.h:126
const CFNodes & preds(Def *mut) const
Definition cfg.h:130
size_t num_succs(const CFNode *n) const
Definition cfg.h:133
A Control-Flow Node.
Definition cfg.h:27
Def * mut() const
Definition cfg.h:34
CFNode(Def *mut)
Definition cfg.h:29
uint64_t gid() const
Definition cfg.h:33
Base class for all Defs.
Definition def.h:222
A Dominance Frontier Graph.
Definition domfrontier.h:12
A Dominance Tree.
Definition domtree.h:11
Calculates a loop nesting forest rooted at LoopTree::root_.
Definition looptree.h:16
A Scope represents a region of Defs that are live from the view of an entry's Var.
Definition scope.h:22
World & world() const
Definition scope.h:32
The World represents the whole program and manages creation of Thorin nodes (Defs).
Definition world.h:35
Definition cfg.h:11
GIDMap< Def *, To > MutMap
Definition def.h:69
GIDSet< const CFNode * > CFNodes
Definition cfg.h:22
std::ostream & operator<<(std::ostream &, const CFNode *)
Definition cfg.cpp:25
absl::flat_hash_set< K, GIDHash< K >, GIDEq< K > > GIDSet
Definition util.h:180