docc 0.8.3 (0d44999b)
C++ API Reference
Loading...
Searching...
No Matches
data_dependency_analysis.h
Go to the documentation of this file.
1#pragma once
2
3#include <unordered_map>
4#include <unordered_set>
5
11
12namespace sdfg {
13namespace analysis {
14
28 friend class AnalysisManager;
29
30private:
32 // When set, only this loop nest is analyzed (instead of node_).
34
35 std::unordered_map<std::string, std::unordered_map<User*, std::unordered_set<User*>>> results_;
36
37 // Per-loop boundary snapshots taken at the moment of `visit_for`.
38 // - first = `undefined_for` (reads inside the loop body that look outside
39 // the loop body for their definition; equivalently, upward-exposed
40 // reads at the loop's boundary).
41 // - second = `open_definitions_for` (writes inside the loop body that may
42 // escape the loop body or feed a future iteration; equivalently,
43 // live-out definitions at the loop's boundary).
44 // This is the primitive consumed by `LoopCarriedDependencyAnalysis`.
45 std::unordered_map<
47 std::pair<std::unordered_set<User*>, std::unordered_map<User*, std::unordered_set<User*>>>>
48 loop_boundaries_;
49
50 std::list<std::unique_ptr<User>> undefined_users_;
51
52 // Per-run cache of whether a container is a scalar; queried for every candidate pair.
53 std::unordered_map<std::string, bool> scalar_containers_;
54
55 bool is_scalar(const std::string& container);
56
57 // When false (default), the symbolic-subset/disjointness helpers below
58 // (`supersedes_restrictive`, `intersects`, `closes`, `depends`) take
59 // conservative shortcuts and skip the expensive ISL queries. Sound but
60 // less precise. `LoopCarriedDependencyAnalysis` constructs its own
61 // detailed instance manually with `detailed_ = true` to obtain the
62 // precise boundary information it requires.
63 bool detailed_ = false;
64
65 // Per-run detailed `AssumptionsAnalysis` instance. Lazily constructed
66 // by `ensure_detailed_assumptions()` on first use, with
67 // `with_branch_conditions=true` so that IfElse-guard refinements (e.g.
68 // coupled constraints emitted by halo guards) reach the symbolic subset
69 // queries below. Bypasses `AnalysisManager` because the manager-cached
70 // `AssumptionsAnalysis` intentionally uses the cheaper, branch-
71 // condition-less form. Lazy init also handles direct `visit_*` entry
72 // points (e.g. tests) that don't go through `run()`.
73 std::unique_ptr<AssumptionsAnalysis> detailed_assumptions_;
74
75 // Returns the per-instance detailed assumptions analysis, constructing
76 // and `run()`ing it on first call. Must only be invoked behind a
77 // `detailed_` guard at the call site.
78 AssumptionsAnalysis& ensure_detailed_assumptions(analysis::AnalysisManager& analysis_manager);
79
80 bool supersedes_restrictive(User& previous, User& current, analysis::AnalysisManager& analysis_manager);
81
82 bool intersects(User& previous, User& current, analysis::AnalysisManager& analysis_manager);
83
84 bool closes(analysis::AnalysisManager& analysis_manager, User& previous, User& current, bool requires_dominance);
85
86 bool depends(analysis::AnalysisManager& analysis_manager, User& previous, User& current);
87
88 // True iff every read-subset of `current` is contained in some single
89 // open writer's subset (per-subset coverage). For scalars / undefined
90 // users / symbol uses this degrades to `depends`. Used to detect partial
91 // coverage that `depends` (intersect-any) would otherwise hide, which
92 // would cause upward-exposed reads to be silently swallowed.
93 bool fully_covered(
94 analysis::AnalysisManager& analysis_manager,
95 User& current,
96 const std::unordered_map<User*, std::unordered_set<User*>>* open_definitions
97 );
98
99 using Definitions = std::unordered_map<User*, std::unordered_set<User*>>;
100 // Open definitions grouped by container: every query only concerns writes to the same container.
101 using OpenDefinitions = std::unordered_map<std::string, Definitions>;
102
103 static OpenDefinitions group_by_container(const Definitions& definitions);
104 static Definitions flatten(const OpenDefinitions& definitions);
105
106 void visit_block_impl(
107 analysis::AnalysisManager& analysis_manager,
109 std::unordered_set<User*>& undefined,
110 OpenDefinitions& open_definitions,
111 Definitions& closed_definitions
112 );
113 void visit_assignment_block_impl(
114 analysis::AnalysisManager& analysis_manager,
116 std::unordered_set<User*>& undefined,
117 OpenDefinitions& open_definitions,
118 Definitions& closed_definitions
119 );
120 void visit_for_impl(
121 analysis::AnalysisManager& analysis_manager,
123 std::unordered_set<User*>& undefined,
124 OpenDefinitions& open_definitions,
125 Definitions& closed_definitions
126 );
127 void visit_if_else_impl(
128 analysis::AnalysisManager& analysis_manager,
130 std::unordered_set<User*>& undefined,
131 OpenDefinitions& open_definitions,
132 Definitions& closed_definitions
133 );
134 void visit_while_impl(
135 analysis::AnalysisManager& analysis_manager,
137 std::unordered_set<User*>& undefined,
138 OpenDefinitions& open_definitions,
139 Definitions& closed_definitions
140 );
141 void visit_return_impl(
142 analysis::AnalysisManager& analysis_manager,
143 structured_control_flow::Return& return_statement,
144 std::unordered_set<User*>& undefined,
145 OpenDefinitions& open_definitions,
146 Definitions& closed_definitions
147 );
148 void visit_sequence_impl(
149 analysis::AnalysisManager& analysis_manager,
151 std::unordered_set<User*>& undefined,
152 OpenDefinitions& open_definitions,
153 Definitions& closed_definitions
154 );
155
156public:
158
160
162
163 // Enable detailed symbolic subset/disjointness checks. Off by default;
164 // `LoopCarriedDependencyAnalysis` flips it on for its own manually
165 // constructed instance.
166 void set_detailed(bool detailed) {
167 detailed_ = detailed;
168 }
169
170 std::string name() const override {
171 return "DataDependencyAnalysis";
172 }
173
174 void run(analysis::AnalysisManager& analysis_manager) override;
175
176 /****** Visitor API ******/
177
179 analysis::AnalysisManager& analysis_manager,
181 std::unordered_set<User*>& undefined,
182 std::unordered_map<User*, std::unordered_set<User*>>& open_definitions,
183 std::unordered_map<User*, std::unordered_set<User*>>& closed_definitions
184 );
185
187 analysis::AnalysisManager& analysis_manager,
189 std::unordered_set<User*>& undefined,
190 std::unordered_map<User*, std::unordered_set<User*>>& open_definitions,
191 std::unordered_map<User*, std::unordered_set<User*>>& closed_definitions
192 );
193
195 analysis::AnalysisManager& analysis_manager,
197 std::unordered_set<User*>& undefined,
198 std::unordered_map<User*, std::unordered_set<User*>>& open_definitions,
199 std::unordered_map<User*, std::unordered_set<User*>>& closed_definitions
200 );
201
203 analysis::AnalysisManager& analysis_manager,
205 std::unordered_set<User*>& undefined,
206 std::unordered_map<User*, std::unordered_set<User*>>& open_definitions,
207 std::unordered_map<User*, std::unordered_set<User*>>& closed_definitions
208 );
209
211 analysis::AnalysisManager& analysis_manager,
213 std::unordered_set<User*>& undefined,
214 std::unordered_map<User*, std::unordered_set<User*>>& open_definitions,
215 std::unordered_map<User*, std::unordered_set<User*>>& closed_definitions
216 );
217
219 analysis::AnalysisManager& analysis_manager,
220 structured_control_flow::Return& return_statement,
221 std::unordered_set<User*>& undefined,
222 std::unordered_map<User*, std::unordered_set<User*>>& open_definitions,
223 std::unordered_map<User*, std::unordered_set<User*>>& closed_definitions
224 );
225
227 analysis::AnalysisManager& analysis_manager,
229 std::unordered_set<User*>& undefined,
230 std::unordered_map<User*, std::unordered_set<User*>>& open_definitions,
231 std::unordered_map<User*, std::unordered_set<User*>>& closed_definitions
232 );
233
234 /****** Defines & Use ******/
235
242 std::unordered_set<User*> defines(User& write);
243
250 std::unordered_map<User*, std::unordered_set<User*>> definitions(const std::string& container);
251
258 std::unordered_map<User*, std::unordered_set<User*>> defined_by(const std::string& container);
259
266 std::unordered_set<User*> defined_by(User& read);
267
268 bool is_undefined_user(User& user) const;
269
270 /****** Loop boundaries (consumed by LoopCarriedDependencyAnalysis) ******/
271
276
281 const std::unordered_set<User*>& upward_exposed_reads(structured_control_flow::StructuredLoop& loop) const;
282
287 const std::unordered_map<User*, std::unordered_set<User*>>&
289};
290
291} // namespace analysis
292} // namespace sdfg
Definition structured_sdfg.h:30
Definition analysis.h:53
Analysis(StructuredSDFG &sdfg)
Definition assumptions_analysis.h:15
DataDependencyAnalysis(StructuredSDFG &sdfg, structured_control_flow::Sequence &node)
void run(analysis::AnalysisManager &analysis_manager) override
DataDependencyAnalysis(StructuredSDFG &sdfg)
bool has_loop_boundary(structured_control_flow::StructuredLoop &loop) const
Whether boundary snapshots are available for the given loop.
void visit_sequence(analysis::AnalysisManager &analysis_manager, structured_control_flow::Sequence &sequence, std::unordered_set< User * > &undefined, std::unordered_map< User *, std::unordered_set< User * > > &open_definitions, std::unordered_map< User *, std::unordered_set< User * > > &closed_definitions)
std::unordered_set< User * > defines(User &write)
Get the users (reads) of a definition (write).
DataDependencyAnalysis(StructuredSDFG &sdfg, structured_control_flow::StructuredLoop &loop)
std::unordered_map< User *, std::unordered_set< User * > > defined_by(const std::string &container)
Get all definitions (writes) for each user (reads).
bool is_undefined_user(User &user) const
const std::unordered_set< User * > & upward_exposed_reads(structured_control_flow::StructuredLoop &loop) const
Reads inside loop's body that are upward-exposed at the loop boundary (i.e.
std::unordered_set< User * > defined_by(User &read)
Get all definitions (writes) for a user (read).
std::unordered_map< User *, std::unordered_set< User * > > definitions(const std::string &container)
Get all definitions (writes) and their users (reads).
const std::unordered_map< User *, std::unordered_set< User * > > & escaping_definitions(structured_control_flow::StructuredLoop &loop) const
Writes inside loop's body that escape the body (i.e.
void visit_return(analysis::AnalysisManager &analysis_manager, structured_control_flow::Return &return_statement, std::unordered_set< User * > &undefined, std::unordered_map< User *, std::unordered_set< User * > > &open_definitions, std::unordered_map< User *, std::unordered_set< User * > > &closed_definitions)
void visit_while(analysis::AnalysisManager &analysis_manager, structured_control_flow::While &while_loop, std::unordered_set< User * > &undefined, std::unordered_map< User *, std::unordered_set< User * > > &open_definitions, std::unordered_map< User *, std::unordered_set< User * > > &closed_definitions)
void visit_block(analysis::AnalysisManager &analysis_manager, structured_control_flow::Block &block, std::unordered_set< User * > &undefined, std::unordered_map< User *, std::unordered_set< User * > > &open_definitions, std::unordered_map< User *, std::unordered_set< User * > > &closed_definitions)
void visit_if_else(analysis::AnalysisManager &analysis_manager, structured_control_flow::IfElse &if_loop, std::unordered_set< User * > &undefined, std::unordered_map< User *, std::unordered_set< User * > > &open_definitions, std::unordered_map< User *, std::unordered_set< User * > > &closed_definitions)
void set_detailed(bool detailed)
Definition data_dependency_analysis.h:166
void visit_assignment_block(analysis::AnalysisManager &analysis_manager, structured_control_flow::AssignmentBlock &assignments, std::unordered_set< User * > &undefined, std::unordered_map< User *, std::unordered_set< User * > > &open_definitions, std::unordered_map< User *, std::unordered_set< User * > > &closed_definitions)
void visit_for(analysis::AnalysisManager &analysis_manager, structured_control_flow::StructuredLoop &for_loop, std::unordered_set< User * > &undefined, std::unordered_map< User *, std::unordered_set< User * > > &open_definitions, std::unordered_map< User *, std::unordered_set< User * > > &closed_definitions)
std::string name() const override
Definition data_dependency_analysis.h:170
friend class AnalysisManager
Definition data_dependency_analysis.h:28
A control flow node representing a basic block with dataflow computations.
Definition block.h:42
Represents a conditional if-else control flow node with multiple cases.
Definition if_else.h:47
Represents a return statement that exits the function with a value.
Definition return.h:32
A sequential container of control flow nodes.
Definition sequence.h:52
Base class for structured loop constructs.
Definition structured_loop.h:244
Represents a while-loop with condition-controlled iteration.
Definition while.h:37
Definition user.h:28
Definition analysis.h:8
Definition analysis.h:7