docc 0.8.3 (0d44999b)
C++ API Reference
Loading...
Searching...
No Matches
users.h
Go to the documentation of this file.
1#pragma once
2
3#include <memory>
4#include <unordered_map>
5#include <unordered_set>
6
7#include <boost/functional/hash.hpp>
8
10#include "sdfg/element.h"
14#include "sdfg/users/user.h"
15
16namespace sdfg {
17namespace users {
18
19class Users : public analysis::Analysis, protected LegacyUserVisitor {
21 friend class UsersView;
22
23private:
25
26 std::vector<std::unique_ptr<User>> users_;
27
28 // Users in traversal order, and each traversed node's [begin, end) slice of it.
29 std::vector<User*> order_;
30 std::unordered_map<const structured_control_flow::ControlFlowNode*, std::pair<size_t, size_t>> ranges_;
31 structured_control_flow::ControlFlowNode* current_owner_ = nullptr;
32 std::unordered_map<const structured_control_flow::ControlFlowNode*, bool> may_return_;
33 std::unordered_map<const structured_control_flow::ControlFlowNode*, std::vector<size_t>> loop_conditions_;
34
35 // Lookup of users by (element, use, loop part); the few candidates are matched by container name.
36 struct UserKey {
37 size_t element_id;
38 Use use;
39 uint8_t loop_part;
40
41 bool operator==(const UserKey& other) const = default;
42 };
43
44 struct UserKeyHash {
45 std::size_t operator()(const UserKey& k) const {
46 std::size_t h = k.element_id;
47 boost::hash_combine(h, static_cast<int>(k.use));
48 boost::hash_combine(h, k.loop_part);
49 return h;
50 }
51 };
52
53 static UserKey user_key(Element* element, Use use, bool is_init, bool is_condition, bool is_update);
54
55 std::unordered_map<UserKey, std::vector<User*>, UserKeyHash> users_lookup_;
56
57 // Users of each container, by use type (only containers with at least one user).
58 struct ContainerUsers {
59 std::vector<User*> uses;
60 std::vector<User*> reads;
61 std::vector<User*> writes;
62 std::vector<User*> views;
63 std::vector<User*> moves;
64 };
65
66 std::unordered_map<std::string, ContainerUsers> container_users_;
67
68 const ContainerUsers& container_users(const std::string& container) const;
69
70 // Enclosing owner and range begin of each node currently being traversed.
71 std::vector<std::pair<structured_control_flow::ControlFlowNode*, size_t>> traversal_stack_;
72
73 void on_enter(structured_control_flow::ControlFlowNode& node) override;
74 void on_leave(structured_control_flow::ControlFlowNode& node) override;
75 void on_use(const std::string& container, Element* element, Use use, LoopPart part) override;
76
77 void add_user(std::unique_ptr<User> user);
78
79 // Structural dominance helpers over regions (control-flow nodes).
80 using Node = structured_control_flow::ControlFlowNode;
81
82 bool traversed(const Node& node) const;
83
84 const Node* child_towards(const Node& ancestor, const Node* node) const;
85
86 const Node* common_ancestor(const User& a, const User& b) const;
87
88 bool may_return(const Node& node);
89
90 const std::vector<size_t>& loop_conditions(const structured_control_flow::StructuredLoop& loop);
91
92 bool must_exit(const User& a, const Node& region);
93
94 bool no_escape(const User& b, const Node& region);
95
96 bool post_dominates_entry(const User& a, const Node& region);
97
98 // Structural reachability as [begin, end) slices of order_.
99 using Interval = std::pair<size_t, size_t>;
100
101 size_t loop_reentry(const structured_control_flow::StructuredLoop& loop);
102
103 void forward_intervals(const User& user, const Node& stop, bool cut_at_stop, std::vector<Interval>& out);
104
105 void exit_intervals(const User& user, const Node& region, std::vector<Interval>& out);
106
107 void entry_intervals(const User& user, const Node& region, std::vector<Interval>& out);
108
109 std::unordered_set<User*>
110 collect_uses(const std::vector<Interval>& intervals, const User* skip1, const User* skip2, bool skip_returns) const;
111
112public:
114
116
117 std::string name() const override {
118 return "Users";
119 }
120
121 void run(analysis::AnalysisManager& analysis_manager) override;
122
124 const std::string& container,
125 Element* element,
126 Use use,
127 bool is_init = false,
128 bool is_condition = false,
129 bool is_update = false
130 );
131
133 const std::string& container,
134 Element* element,
135 Use use,
136 bool is_init = false,
137 bool is_condition = false,
138 bool is_update = false
139 );
140
141 /**** Users ****/
142
143 std::vector<User*> uses() const;
144
145 std::vector<User*> uses(const std::string& container) const;
146
147 size_t num_uses(const std::string& container) const;
148
149 std::vector<User*> writes() const;
150
151 const std::vector<User*>& writes(const std::string& container) const;
152
153 size_t num_writes(const std::string& container) const;
154
155 std::vector<User*> reads() const;
156
157 const std::vector<User*>& reads(const std::string& container) const;
158
159 size_t num_reads(const std::string& container) const;
160
161 std::vector<User*> views() const;
162
163 const std::vector<User*>& views(const std::string& container) const;
164
165 size_t num_views(const std::string& container) const;
166
167 std::vector<User*> moves() const;
168
169 const std::vector<User*>& moves(const std::string& container) const;
170
171 size_t num_moves(const std::string& container) const;
172
174
175 std::unordered_set<std::string> locals(structured_control_flow::ControlFlowNode& node);
176
177 const std::unordered_set<User*> all_uses_between(User& user1, User& user2);
178
179 const std::unordered_set<User*> all_uses_after(User& user);
180
181 const std::vector<std::string> all_containers_in_order();
182
184 bool dominates(User& user1, User& user2);
185
187 bool post_dominates(User& user1, User& user2);
188};
189
191private:
192 Users& users_;
194 size_t begin_ = 0;
195 size_t end_ = 0;
196
197public:
199
200 bool contains(const User& user) const;
201
202 /**** Users ****/
203
204 std::vector<User*> uses() const;
205
206 std::vector<User*> uses(const std::string& container) const;
207
208 std::vector<User*> writes() const;
209
210 std::vector<User*> writes(const std::string& container) const;
211
212 std::vector<User*> reads() const;
213
214 std::vector<User*> reads(const std::string& container) const;
215
216 std::vector<User*> views() const;
217
218 std::vector<User*> views(const std::string& container) const;
219
220 std::vector<User*> moves() const;
221
222 std::vector<User*> moves(const std::string& container) const;
223
224 std::unordered_set<User*> all_uses_after(User& user);
225
226 const std::vector<std::string> all_containers_in_order();
227};
228
229} // namespace users
230} // namespace sdfg
Definition element.h:159
Definition structured_sdfg.h:30
Definition analysis.h:53
Definition analysis.h:12
UsersView(Users &users, const structured_control_flow::ControlFlowNode &node)
Users(StructuredSDFG &sdfg)
Base class for all structured control flow nodes in a StructuredSDFG.
Definition control_flow_node.h:44
LoopPart
Definition legacy_user_visitor.h:16
Definition user.h:28
std::vector< User * > uses(const std::string &container) const
std::vector< User * > uses() const
std::vector< User * > views(const std::string &container) const
std::vector< User * > moves(const std::string &container) const
bool contains(const User &user) const
std::vector< User * > writes(const std::string &container) const
const std::vector< std::string > all_containers_in_order()
std::vector< User * > reads() const
std::vector< User * > views() const
UsersView(Users &users, const structured_control_flow::ControlFlowNode &node)
std::vector< User * > moves() const
std::vector< User * > reads(const std::string &container) const
std::vector< User * > writes() const
std::unordered_set< User * > all_uses_after(User &user)
Definition users.h:19
friend class UsersView
Definition users.h:21
std::vector< User * > writes() const
std::unordered_set< std::string > locals(structured_control_flow::ControlFlowNode &node)
static structured_control_flow::ControlFlowNode * scope(User *user)
std::vector< User * > views() const
const std::vector< User * > & writes(const std::string &container) const
Users(StructuredSDFG &sdfg, structured_control_flow::ControlFlowNode &node)
size_t num_views(const std::string &container) const
std::vector< User * > reads() const
const std::vector< User * > & views(const std::string &container) const
User * get_user(const std::string &container, Element *element, Use use, bool is_init=false, bool is_condition=false, bool is_update=false)
const std::unordered_set< User * > all_uses_between(User &user1, User &user2)
std::vector< User * > uses(const std::string &container) const
const std::vector< User * > & moves(const std::string &container) const
const std::unordered_set< User * > all_uses_after(User &user)
void run(analysis::AnalysisManager &analysis_manager) override
std::vector< User * > moves() const
Users(StructuredSDFG &sdfg)
size_t num_moves(const std::string &container) const
size_t num_uses(const std::string &container) const
const std::vector< std::string > all_containers_in_order()
bool dominates(User &user1, User &user2)
Strict dominance between two users, derived from.
std::string name() const override
Definition users.h:117
const std::vector< User * > & reads(const std::string &container) const
bool post_dominates(User &user1, User &user2)
Strict post-dominance between two users, derived from the structured control flow.
std::vector< User * > uses() const
size_t num_reads(const std::string &container) const
bool has_user(const std::string &container, Element *element, Use use, bool is_init=false, bool is_condition=false, bool is_update=false)
size_t num_writes(const std::string &container) const
Definition base_user_visitor.h:5
Use
Definition user.h:20
Definition analysis.h:7