• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daisytuner / sdfglib / 15656007340

14 Jun 2025 08:51PM UTC coverage: 13.234% (-49.9%) from 63.144%
15656007340

Pull #76

github

web-flow
Merge 9586c8161 into 413c53212
Pull Request #76: New Loop Dependency Analysis

361 of 465 new or added lines in 7 files covered. (77.63%)

6215 existing lines in 110 files now uncovered.

1612 of 12181 relevant lines covered (13.23%)

13.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/analysis/happens_before_analysis.cpp
1
#include "sdfg/analysis/happens_before_analysis.h"
2

3
#include <cassert>
4
#include <string>
5
#include <unordered_map>
6
#include <unordered_set>
7
#include <vector>
8

9
#include "sdfg/analysis/analysis.h"
10
#include "sdfg/data_flow/memlet.h"
11
#include "sdfg/structured_control_flow/for.h"
12
#include "sdfg/structured_control_flow/sequence.h"
13
#include "sdfg/structured_sdfg.h"
14
#include "sdfg/symbolic/symbolic.h"
15

16
namespace sdfg {
17
namespace analysis {
18

UNCOV
19
HappensBeforeAnalysis::HappensBeforeAnalysis(StructuredSDFG& sdfg)
×
UNCOV
20
    : Analysis(sdfg), node_(sdfg.root()) {
×
21

UNCOV
22
      };
×
23

24
HappensBeforeAnalysis::HappensBeforeAnalysis(StructuredSDFG& sdfg,
×
25
                                             structured_control_flow::Sequence& node)
26
    : Analysis(sdfg), node_(node) {
×
27

28
      };
×
29

UNCOV
30
void HappensBeforeAnalysis::run(analysis::AnalysisManager& analysis_manager) {
×
UNCOV
31
    results_.clear();
×
32

UNCOV
33
    std::unordered_set<User*> open_reads;
×
UNCOV
34
    std::unordered_map<User*, std::unordered_set<User*>> open_reads_after_writes;
×
UNCOV
35
    std::unordered_map<User*, std::unordered_set<User*>> closed_reads_after_write;
×
36

UNCOV
37
    auto& users = analysis_manager.get<Users>();
×
UNCOV
38
    visit_sequence(users, node_, open_reads, open_reads_after_writes, closed_reads_after_write);
×
39

UNCOV
40
    for (auto& entry : open_reads_after_writes) {
×
UNCOV
41
        closed_reads_after_write.insert(entry);
×
42
    }
43

UNCOV
44
    for (auto& entry : closed_reads_after_write) {
×
UNCOV
45
        if (results_.find(entry.first->container()) == results_.end()) {
×
UNCOV
46
            results_.insert({entry.first->container(), {}});
×
UNCOV
47
        }
×
UNCOV
48
        results_.at(entry.first->container()).insert(entry);
×
49
    }
UNCOV
50
};
×
51

52
/****** Visitor API ******/
53

UNCOV
54
void HappensBeforeAnalysis::visit_block(
×
55
    analysis::Users& users, structured_control_flow::Block& block,
56
    std::unordered_set<User*>& open_reads,
57
    std::unordered_map<User*, std::unordered_set<User*>>& open_reads_after_writes,
58
    std::unordered_map<User*, std::unordered_set<User*>>& closed_reads_after_write) {
UNCOV
59
    auto& dataflow = block.dataflow();
×
60

UNCOV
61
    for (auto node : dataflow.topological_sort()) {
×
UNCOV
62
        if (auto access_node = dynamic_cast<data_flow::AccessNode*>(node)) {
×
UNCOV
63
            if (!symbolic::is_pointer(symbolic::symbol(access_node->data()))) {
×
UNCOV
64
                if (dataflow.in_degree(*node) > 0) {
×
UNCOV
65
                    Use use = Use::WRITE;
×
UNCOV
66
                    for (auto& iedge : dataflow.in_edges(*access_node)) {
×
UNCOV
67
                        if (iedge.src_conn() == "refs" || iedge.dst_conn() == "refs") {
×
UNCOV
68
                            use = Use::MOVE;
×
UNCOV
69
                            break;
×
70
                        }
71
                    }
72

UNCOV
73
                    auto current_user = users.get_user(access_node->data(), access_node, use);
×
74

UNCOV
75
                    if (use == Use::WRITE) {
×
UNCOV
76
                        std::unordered_map<User*, std::unordered_set<User*>> to_close;
×
UNCOV
77
                        for (auto& user : open_reads_after_writes) {
×
UNCOV
78
                            if (user.first->container() == access_node->data()) {
×
UNCOV
79
                                to_close.insert(user);
×
UNCOV
80
                            }
×
81
                        }
UNCOV
82
                        for (auto& user : to_close) {
×
UNCOV
83
                            open_reads_after_writes.erase(user.first);
×
UNCOV
84
                            closed_reads_after_write.insert(user);
×
85
                        }
UNCOV
86
                        open_reads_after_writes.insert({current_user, {}});
×
UNCOV
87
                    }
×
UNCOV
88
                }
×
UNCOV
89
                if (dataflow.out_degree(*access_node) > 0) {
×
UNCOV
90
                    Use use = Use::READ;
×
UNCOV
91
                    for (auto& oedge : dataflow.out_edges(*access_node)) {
×
UNCOV
92
                        if (oedge.src_conn() == "refs" || oedge.dst_conn() == "refs") {
×
UNCOV
93
                            use = Use::VIEW;
×
UNCOV
94
                            break;
×
95
                        }
96
                    }
97

UNCOV
98
                    auto current_user = users.get_user(access_node->data(), access_node, use);
×
99

UNCOV
100
                    if (use == Use::READ) {
×
UNCOV
101
                        bool found = false;
×
UNCOV
102
                        for (auto& user : open_reads_after_writes) {
×
UNCOV
103
                            if (user.first->container() == access_node->data()) {
×
UNCOV
104
                                user.second.insert(current_user);
×
UNCOV
105
                                found = true;
×
UNCOV
106
                            }
×
107
                        }
UNCOV
108
                        if (!found) {
×
UNCOV
109
                            open_reads.insert(current_user);
×
UNCOV
110
                        }
×
UNCOV
111
                    }
×
UNCOV
112
                }
×
UNCOV
113
            }
×
UNCOV
114
        } else if (auto tasklet = dynamic_cast<data_flow::Tasklet*>(node)) {
×
UNCOV
115
            if (tasklet->is_conditional()) {
×
116
                auto& condition = tasklet->condition();
×
117
                for (auto& atom : symbolic::atoms(condition)) {
×
118
                    auto current_user = users.get_user(atom->get_name(), tasklet, Use::READ);
×
119
                    {
120
                        bool found = false;
×
121
                        for (auto& user : open_reads_after_writes) {
×
122
                            if (user.first->container() == atom->get_name()) {
×
123
                                user.second.insert(current_user);
×
124
                                found = true;
×
125
                            }
×
126
                        }
127
                        if (!found) {
×
128
                            open_reads.insert(current_user);
×
129
                        }
×
130
                    }
131
                }
132
            }
×
UNCOV
133
        }
×
134

UNCOV
135
        for (auto& oedge : dataflow.out_edges(*node)) {
×
UNCOV
136
            std::unordered_set<std::string> used;
×
UNCOV
137
            for (auto& dim : oedge.subset()) {
×
UNCOV
138
                for (auto atom : symbolic::atoms(dim)) {
×
UNCOV
139
                    used.insert(atom->get_name());
×
UNCOV
140
                }
×
141
            }
UNCOV
142
            for (auto& atom : used) {
×
UNCOV
143
                auto current_user = users.get_user(atom, &oedge, Use::READ);
×
144

145
                {
UNCOV
146
                    bool found = false;
×
UNCOV
147
                    for (auto& user : open_reads_after_writes) {
×
UNCOV
148
                        if (user.first->container() == atom) {
×
UNCOV
149
                            user.second.insert(current_user);
×
UNCOV
150
                            found = true;
×
UNCOV
151
                        }
×
152
                    }
UNCOV
153
                    if (!found) {
×
UNCOV
154
                        open_reads.insert(current_user);
×
UNCOV
155
                    }
×
156
                }
157
            }
UNCOV
158
        }
×
159
    }
UNCOV
160
}
×
161

UNCOV
162
void HappensBeforeAnalysis::visit_for(
×
163
    analysis::Users& users, structured_control_flow::For& for_loop,
164
    std::unordered_set<User*>& open_reads,
165
    std::unordered_map<User*, std::unordered_set<User*>>& open_reads_after_writes,
166
    std::unordered_map<User*, std::unordered_set<User*>>& closed_reads_after_write) {
167
    // Read Init
UNCOV
168
    for (auto atom : symbolic::atoms(for_loop.init())) {
×
UNCOV
169
        auto current_user = users.get_user(atom->get_name(), &for_loop, Use::READ, true);
×
170

UNCOV
171
        bool found = false;
×
UNCOV
172
        for (auto& user : open_reads_after_writes) {
×
UNCOV
173
            if (user.first->container() == atom->get_name()) {
×
UNCOV
174
                user.second.insert(current_user);
×
UNCOV
175
                found = true;
×
UNCOV
176
            }
×
177
        }
UNCOV
178
        if (!found) {
×
179
            open_reads.insert(current_user);
×
180
        }
×
UNCOV
181
    }
×
182

183
    {
184
        // Write Induction Variable
UNCOV
185
        auto current_user =
×
UNCOV
186
            users.get_user(for_loop.indvar()->get_name(), &for_loop, Use::WRITE, true);
×
187

UNCOV
188
        std::unordered_set<User*> to_close;
×
UNCOV
189
        for (auto& user : open_reads_after_writes) {
×
UNCOV
190
            if (user.first->container() == for_loop.indvar()->get_name()) {
×
UNCOV
191
                to_close.insert(user.first);
×
UNCOV
192
            }
×
193
        }
UNCOV
194
        for (auto& user : to_close) {
×
UNCOV
195
            closed_reads_after_write.insert({user, open_reads_after_writes.at(user)});
×
UNCOV
196
            open_reads_after_writes.erase(user);
×
197
        }
UNCOV
198
        open_reads_after_writes.insert({current_user, {}});
×
UNCOV
199
    }
×
200
    {
201
        // Write Update
UNCOV
202
        auto current_user = users.get_user(for_loop.indvar()->get_name(), &for_loop, Use::WRITE,
×
203
                                           false, false, true);
UNCOV
204
        open_reads_after_writes.insert({current_user, {}});
×
205
    }
206

207
    // Read Condition - Never written in body
UNCOV
208
    for (auto atom : symbolic::atoms(for_loop.condition())) {
×
UNCOV
209
        auto current_user = users.get_user(atom->get_name(), &for_loop, Use::READ, false, true);
×
210

UNCOV
211
        bool found = false;
×
UNCOV
212
        for (auto& user : open_reads_after_writes) {
×
UNCOV
213
            if (user.first->container() == atom->get_name()) {
×
UNCOV
214
                user.second.insert(current_user);
×
UNCOV
215
                found = true;
×
UNCOV
216
            }
×
217
        }
UNCOV
218
        if (!found) {
×
219
            open_reads.insert(current_user);
×
220
        }
×
UNCOV
221
    }
×
222

UNCOV
223
    std::unordered_map<User*, std::unordered_set<User*>> open_reads_after_writes_for;
×
UNCOV
224
    std::unordered_map<User*, std::unordered_set<User*>> closed_reads_after_writes_for;
×
UNCOV
225
    std::unordered_set<User*> open_reads_for;
×
226

UNCOV
227
    visit_sequence(users, for_loop.root(), open_reads_for, open_reads_after_writes_for,
×
228
                   closed_reads_after_writes_for);
229

UNCOV
230
    for (auto& entry : closed_reads_after_writes_for) {
×
231
        closed_reads_after_write.insert(entry);
×
232
    }
233

234
    // Read Update
UNCOV
235
    for (auto atom : symbolic::atoms(for_loop.update())) {
×
UNCOV
236
        auto current_user =
×
UNCOV
237
            users.get_user(atom->get_name(), &for_loop, Use::READ, false, false, true);
×
238

239
        // Add for body
UNCOV
240
        for (auto& user : open_reads_after_writes_for) {
×
UNCOV
241
            if (user.first->container() == atom->get_name()) {
×
UNCOV
242
                user.second.insert(current_user);
×
UNCOV
243
            }
×
244
        }
245

246
        // Add to outside
UNCOV
247
        bool found = false;
×
UNCOV
248
        for (auto& user : open_reads_after_writes) {
×
UNCOV
249
            if (user.first->container() == atom->get_name()) {
×
UNCOV
250
                user.second.insert(current_user);
×
UNCOV
251
                found = true;
×
UNCOV
252
            }
×
253
        }
UNCOV
254
        if (!found) {
×
UNCOV
255
            open_reads.insert(current_user);
×
UNCOV
256
        }
×
UNCOV
257
    }
×
258

259
    // Handle open reads of for
UNCOV
260
    for (auto open_read : open_reads_for) {
×
261
        // Add recursive
UNCOV
262
        for (auto& user : open_reads_after_writes_for) {
×
UNCOV
263
            if (user.first->container() == open_read->container()) {
×
264
                user.second.insert(open_read);
×
265
            }
×
266
        }
267

UNCOV
268
        bool found = false;
×
UNCOV
269
        for (auto& entry : open_reads_after_writes) {
×
UNCOV
270
            if (entry.first->container() == open_read->container()) {
×
UNCOV
271
                entry.second.insert(open_read);
×
UNCOV
272
                found = true;
×
UNCOV
273
            }
×
274
        }
UNCOV
275
        if (!found) {
×
276
            open_reads.insert(open_read);
×
277
        }
×
278
    }
279

280
    // Merge open reads_after_writes
UNCOV
281
    for (auto& entry : open_reads_after_writes_for) {
×
UNCOV
282
        open_reads_after_writes.insert(entry);
×
283
    }
UNCOV
284
}
×
285

UNCOV
286
void HappensBeforeAnalysis::visit_if_else(
×
287
    analysis::Users& users, structured_control_flow::IfElse& if_else,
288
    std::unordered_set<User*>& open_reads,
289
    std::unordered_map<User*, std::unordered_set<User*>>& open_reads_after_writes,
290
    std::unordered_map<User*, std::unordered_set<User*>>& closed_reads_after_write) {
291
    // Read Conditions
UNCOV
292
    for (size_t i = 0; i < if_else.size(); i++) {
×
UNCOV
293
        auto child = if_else.at(i).second;
×
UNCOV
294
        for (auto atom : symbolic::atoms(child)) {
×
UNCOV
295
            auto current_user = users.get_user(atom->get_name(), &if_else, Use::READ);
×
296

UNCOV
297
            bool found = false;
×
UNCOV
298
            for (auto& user : open_reads_after_writes) {
×
UNCOV
299
                if (user.first->container() == atom->get_name()) {
×
UNCOV
300
                    user.second.insert(current_user);
×
UNCOV
301
                    found = true;
×
UNCOV
302
                }
×
303
            }
UNCOV
304
            if (!found) {
×
UNCOV
305
                open_reads.insert(current_user);
×
UNCOV
306
            }
×
UNCOV
307
        }
×
UNCOV
308
    }
×
309

UNCOV
310
    std::vector<std::unordered_set<User*>> open_reads_branches(if_else.size());
×
311
    std::vector<std::unordered_map<User*, std::unordered_set<User*>>>
UNCOV
312
        open_reads_after_writes_branches(if_else.size());
×
313
    std::vector<std::unordered_map<User*, std::unordered_set<User*>>>
UNCOV
314
        closed_reads_after_writes_branches(if_else.size());
×
UNCOV
315
    for (size_t i = 0; i < if_else.size(); i++) {
×
UNCOV
316
        auto& child = if_else.at(i).first;
×
UNCOV
317
        visit_sequence(users, child, open_reads_branches.at(i),
×
UNCOV
318
                       open_reads_after_writes_branches.at(i),
×
UNCOV
319
                       closed_reads_after_writes_branches.at(i));
×
UNCOV
320
    }
×
321

322
    // merge partial open reads
UNCOV
323
    for (size_t i = 0; i < if_else.size(); i++) {
×
UNCOV
324
        for (auto& entry : open_reads_branches.at(i)) {
×
UNCOV
325
            bool found = false;
×
UNCOV
326
            for (auto& entry2 : open_reads_after_writes) {
×
UNCOV
327
                if (entry2.first->container() == entry->container()) {
×
UNCOV
328
                    entry2.second.insert(entry);
×
UNCOV
329
                    found = true;
×
UNCOV
330
                }
×
331
            }
UNCOV
332
            if (!found) {
×
UNCOV
333
                open_reads.insert(entry);
×
UNCOV
334
            }
×
335
        }
UNCOV
336
    }
×
337

338
    // merge closed writes
UNCOV
339
    for (auto& closing : closed_reads_after_writes_branches) {
×
UNCOV
340
        for (auto& entry : closing) {
×
341
            closed_reads_after_write.insert(entry);
×
342
        }
343
    }
344

345
    // Close open reads_after_writes for complete branches
UNCOV
346
    if (if_else.is_complete()) {
×
UNCOV
347
        std::unordered_map<User*, std::unordered_set<User*>> to_close;
×
UNCOV
348
        std::unordered_set<std::string> candidates;
×
UNCOV
349
        std::unordered_set<std::string> candidates_tmp;
×
350

351
        /* Complete close open reads_after_writes
352
        1. get candidates from first iteration
353
        2. iterate over all branches and prune candidates
354
        3. find prior writes for remaining candidates
355
        4. close open reads_after_writes for all candidates
356
        */
UNCOV
357
        for (auto& entry : open_reads_after_writes_branches.at(0)) {
×
UNCOV
358
            candidates.insert(entry.first->container());
×
359
        }
UNCOV
360
        for (auto& entry : closed_reads_after_writes_branches.at(0)) {
×
361
            candidates.insert(entry.first->container());
×
362
        }
363

UNCOV
364
        for (size_t i = 1; i < if_else.size(); i++) {
×
UNCOV
365
            for (auto& entry : open_reads_after_writes_branches.at(i)) {
×
UNCOV
366
                if (candidates.find(entry.first->container()) != candidates.end()) {
×
UNCOV
367
                    candidates_tmp.insert(entry.first->container());
×
UNCOV
368
                }
×
369
            }
UNCOV
370
            candidates.swap(candidates_tmp);
×
UNCOV
371
            candidates_tmp.clear();
×
UNCOV
372
        }
×
373

UNCOV
374
        for (auto& entry : open_reads_after_writes) {
×
UNCOV
375
            if (candidates.find(entry.first->container()) != candidates.end()) {
×
UNCOV
376
                to_close.insert(entry);
×
UNCOV
377
            }
×
378
        }
379

UNCOV
380
        for (auto& entry : to_close) {
×
UNCOV
381
            open_reads_after_writes.erase(entry.first);
×
UNCOV
382
            closed_reads_after_write.insert(entry);
×
383
        }
UNCOV
384
    }
×
385

386
    // merge open reads_after_writes
UNCOV
387
    for (auto& branch : open_reads_after_writes_branches) {
×
UNCOV
388
        for (auto& entry : branch) {
×
UNCOV
389
            open_reads_after_writes.insert(entry);
×
390
        }
391
    }
UNCOV
392
}
×
393

UNCOV
394
void HappensBeforeAnalysis::visit_while(
×
395
    analysis::Users& users, structured_control_flow::While& while_loop,
396
    std::unordered_set<User*>& open_reads,
397
    std::unordered_map<User*, std::unordered_set<User*>>& open_reads_after_writes,
398
    std::unordered_map<User*, std::unordered_set<User*>>& closed_reads_after_write) {
UNCOV
399
    std::unordered_map<User*, std::unordered_set<User*>> open_reads_after_writes_while;
×
UNCOV
400
    std::unordered_map<User*, std::unordered_set<User*>> closed_reads_after_writes_while;
×
UNCOV
401
    std::unordered_set<User*> open_reads_while;
×
402

UNCOV
403
    visit_sequence(users, while_loop.root(), open_reads_while, open_reads_after_writes_while,
×
404
                   closed_reads_after_writes_while);
405

UNCOV
406
    for (auto& entry : closed_reads_after_writes_while) {
×
UNCOV
407
        closed_reads_after_write.insert(entry);
×
408
    }
409

UNCOV
410
    for (auto open_read : open_reads_while) {
×
411
        // Add recursively to loop
UNCOV
412
        for (auto& entry : open_reads_after_writes_while) {
×
UNCOV
413
            if (entry.first->container() == open_read->container()) {
×
UNCOV
414
                entry.second.insert(open_read);
×
UNCOV
415
            }
×
416
        }
417

418
        // Add to outside
UNCOV
419
        bool found = false;
×
UNCOV
420
        for (auto& entry : open_reads_after_writes) {
×
UNCOV
421
            if (entry.first->container() == open_read->container()) {
×
UNCOV
422
                entry.second.insert(open_read);
×
UNCOV
423
                found = true;
×
UNCOV
424
            }
×
425
        }
UNCOV
426
        if (!found) {
×
UNCOV
427
            open_reads.insert(open_read);
×
UNCOV
428
        }
×
429
    }
430

431
    // Keep open reads_after_writes open after loop
UNCOV
432
    for (auto& entry : open_reads_after_writes_while) {
×
UNCOV
433
        open_reads_after_writes.insert(entry);
×
434
    }
UNCOV
435
}
×
436

437
void HappensBeforeAnalysis::visit_return(
×
438
    analysis::Users& users, structured_control_flow::Return& return_statement,
439
    std::unordered_set<User*>& open_reads,
440
    std::unordered_map<User*, std::unordered_set<User*>>& open_reads_after_writes,
441
    std::unordered_map<User*, std::unordered_set<User*>>& closed_reads_after_write) {
442
    // close all open reads_after_writes
443
    for (auto& entry : open_reads_after_writes) {
×
444
        closed_reads_after_write.insert(entry);
×
445
    }
446
    open_reads_after_writes.clear();
×
447
}
×
448

UNCOV
449
void HappensBeforeAnalysis::visit_map(
×
450
    analysis::Users& users, structured_control_flow::Map& map,
451
    std::unordered_set<User*>& open_reads,
452
    std::unordered_map<User*, std::unordered_set<User*>>& open_reads_after_writes,
453
    std::unordered_map<User*, std::unordered_set<User*>>& closed_reads_after_write) {
454
    // write Init
UNCOV
455
    auto current_user = users.get_user(map.indvar()->get_name(), &map, Use::WRITE);
×
456

UNCOV
457
    open_reads_after_writes.insert({current_user, {}});
×
458

UNCOV
459
    std::unordered_map<User*, std::unordered_set<User*>> open_reads_after_writes_map;
×
UNCOV
460
    std::unordered_map<User*, std::unordered_set<User*>> closed_reads_after_writes_map;
×
UNCOV
461
    std::unordered_set<User*> open_reads_map;
×
462

UNCOV
463
    visit_sequence(users, map.root(), open_reads_map, open_reads_after_writes_map,
×
464
                   closed_reads_after_writes_map);
465

UNCOV
466
    for (auto& entry : closed_reads_after_writes_map) {
×
467
        closed_reads_after_write.insert(entry);
×
468
    }
469

470
    // Handle open reads of for
UNCOV
471
    for (auto open_read : open_reads_map) {
×
472
        // Add recursive
UNCOV
473
        for (auto& user : open_reads_after_writes_map) {
×
UNCOV
474
            if (user.first->container() == open_read->container()) {
×
475
                user.second.insert(open_read);
×
476
            }
×
477
        }
478

UNCOV
479
        bool found = false;
×
UNCOV
480
        for (auto& entry : open_reads_after_writes) {
×
UNCOV
481
            if (entry.first->container() == open_read->container()) {
×
UNCOV
482
                entry.second.insert(open_read);
×
UNCOV
483
                found = true;
×
UNCOV
484
            }
×
485
        }
UNCOV
486
        if (!found) {
×
487
            open_reads.insert(open_read);
×
488
        }
×
489
    }
490

491
    // Merge open reads_after_writes
UNCOV
492
    for (auto& entry : open_reads_after_writes_map) {
×
UNCOV
493
        open_reads_after_writes.insert(entry);
×
494
    }
UNCOV
495
}
×
496

UNCOV
497
void HappensBeforeAnalysis::visit_sequence(
×
498
    analysis::Users& users, structured_control_flow::Sequence& sequence,
499
    std::unordered_set<User*>& open_reads,
500
    std::unordered_map<User*, std::unordered_set<User*>>& open_reads_after_writes,
501
    std::unordered_map<User*, std::unordered_set<User*>>& closed_reads_after_write) {
UNCOV
502
    for (size_t i = 0; i < sequence.size(); i++) {
×
UNCOV
503
        auto child = sequence.at(i);
×
UNCOV
504
        if (auto block = dynamic_cast<structured_control_flow::Block*>(&child.first)) {
×
UNCOV
505
            visit_block(users, *block, open_reads, open_reads_after_writes,
×
UNCOV
506
                        closed_reads_after_write);
×
UNCOV
507
        } else if (auto for_loop = dynamic_cast<structured_control_flow::For*>(&child.first)) {
×
UNCOV
508
            visit_for(users, *for_loop, open_reads, open_reads_after_writes,
×
UNCOV
509
                      closed_reads_after_write);
×
UNCOV
510
        } else if (auto if_else = dynamic_cast<structured_control_flow::IfElse*>(&child.first)) {
×
UNCOV
511
            visit_if_else(users, *if_else, open_reads, open_reads_after_writes,
×
UNCOV
512
                          closed_reads_after_write);
×
UNCOV
513
        } else if (auto while_loop = dynamic_cast<structured_control_flow::While*>(&child.first)) {
×
UNCOV
514
            visit_while(users, *while_loop, open_reads, open_reads_after_writes,
×
UNCOV
515
                        closed_reads_after_write);
×
UNCOV
516
        } else if (auto return_statement =
×
UNCOV
517
                       dynamic_cast<structured_control_flow::Return*>(&child.first)) {
×
518
            visit_return(users, *return_statement, open_reads, open_reads_after_writes,
×
519
                         closed_reads_after_write);
×
UNCOV
520
        } else if (auto sequence = dynamic_cast<structured_control_flow::Sequence*>(&child.first)) {
×
521
            visit_sequence(users, *sequence, open_reads, open_reads_after_writes,
×
522
                           closed_reads_after_write);
×
UNCOV
523
        } else if (auto map = dynamic_cast<structured_control_flow::Map*>(&child.first)) {
×
UNCOV
524
            visit_map(users, *map, open_reads, open_reads_after_writes, closed_reads_after_write);
×
UNCOV
525
        }
×
526

527
        // handle transitions read
UNCOV
528
        for (auto& entry : child.second.assignments()) {
×
UNCOV
529
            for (auto& atom : symbolic::atoms(entry.second)) {
×
UNCOV
530
                if (symbolic::is_pointer(atom)) {
×
531
                    continue;
×
532
                }
UNCOV
533
                auto current_user = users.get_user(atom->get_name(), &child.second, Use::READ);
×
534

UNCOV
535
                bool found = false;
×
UNCOV
536
                for (auto& user : open_reads_after_writes) {
×
UNCOV
537
                    if (user.first->container() == atom->get_name()) {
×
UNCOV
538
                        user.second.insert(current_user);
×
UNCOV
539
                        found = true;
×
UNCOV
540
                    }
×
541
                }
UNCOV
542
                if (!found) {
×
UNCOV
543
                    open_reads.insert(current_user);
×
UNCOV
544
                }
×
545
            }
546
        }
547

548
        // handle transitions write
UNCOV
549
        for (auto& entry : child.second.assignments()) {
×
UNCOV
550
            auto current_user = users.get_user(entry.first->get_name(), &child.second, Use::WRITE);
×
551

UNCOV
552
            std::unordered_set<User*> to_close;
×
UNCOV
553
            for (auto& user : open_reads_after_writes) {
×
UNCOV
554
                if (user.first->container() == entry.first->get_name()) {
×
555
                    to_close.insert(user.first);
×
556
                }
×
557
            }
UNCOV
558
            for (auto& user : to_close) {
×
559
                closed_reads_after_write.insert({user, open_reads_after_writes.at(user)});
×
560
                open_reads_after_writes.erase(user);
×
561
            }
UNCOV
562
            open_reads_after_writes.insert({current_user, {}});
×
UNCOV
563
        }
×
UNCOV
564
    }
×
UNCOV
565
}
×
566

567
std::unordered_set<User*> HappensBeforeAnalysis::reads_after_write(User& write) {
×
568
    assert(write.use() == Use::WRITE);
×
569
    if (results_.find(write.container()) == results_.end()) {
×
570
        return {};
×
571
    }
572
    auto& raws = results_.at(write.container());
×
573
    assert(raws.find(&write) != raws.end());
×
574

575
    auto& reads_for_write = raws.at(&write);
×
576

577
    std::unordered_set<User*> reads;
×
578
    for (auto& entry : reads_for_write) {
×
579
        reads.insert(entry);
×
580
    }
581

582
    return reads;
×
583
};
×
584

UNCOV
585
std::unordered_map<User*, std::unordered_set<User*>> HappensBeforeAnalysis::reads_after_writes(
×
586
    const std::string& container) {
UNCOV
587
    if (results_.find(container) == results_.end()) {
×
UNCOV
588
        return {};
×
589
    }
UNCOV
590
    return results_.at(container);
×
UNCOV
591
};
×
592

593
std::unordered_map<User*, std::unordered_set<User*>>
UNCOV
594
HappensBeforeAnalysis::reads_after_write_groups(const std::string& container) {
×
UNCOV
595
    auto reads = this->reads_after_writes(container);
×
596

UNCOV
597
    std::unordered_map<User*, std::unordered_set<User*>> read_to_writes_map;
×
UNCOV
598
    for (auto& entry : reads) {
×
UNCOV
599
        for (auto& read : entry.second) {
×
UNCOV
600
            if (read_to_writes_map.find(read) == read_to_writes_map.end()) {
×
UNCOV
601
                read_to_writes_map[read] = {};
×
UNCOV
602
            }
×
UNCOV
603
            read_to_writes_map[read].insert(entry.first);
×
604
        }
605
    }
UNCOV
606
    return read_to_writes_map;
×
UNCOV
607
};
×
608

609
}  // namespace analysis
610
}  // namespace sdfg
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc