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

daisytuner / sdfglib / 19162352523

07 Nov 2025 08:16AM UTC coverage: 61.556% (-0.4%) from 61.911%
19162352523

push

github

web-flow
rewrite of arg captures to work on a scope level (#319)

* rewrite of arg captures to work on a scope level

* adding first unit tests for arg capturing

* Fix scoped arg captures

* Fix debug output

* Only write capture fila name to index

* Switch to element-id based capture storage

* Reenable debug prints

* Fix serialization deserialization of arg capture index

* Use fake node ids in rtl test

* Add debug output for capture file creation

* Boost coverage

---------

Co-authored-by: Nora Hagmeyer <nora.hagmeyer@daisytuner.com>

171 of 320 new or added lines in 18 files covered. (53.44%)

17 existing lines in 5 files now uncovered.

10265 of 16676 relevant lines covered (61.56%)

100.85 hits per line

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

85.19
/src/analysis/mem_access_range_analysis.cpp
1

2
#include "sdfg/analysis/mem_access_range_analysis.h"
3

4
#include <stdbool.h>
5
#include <symengine/basic.h>
6
#include <symengine/functions.h>
7
#include <symengine/infinity.h>
8
#include <symengine/number.h>
9
#include <symengine/symengine_rcp.h>
10

11
#include <tuple>
12
#include <unordered_set>
13
#include <utility>
14
#include <vector>
15

16
#include "sdfg/analysis/analysis.h"
17
#include "sdfg/analysis/assumptions_analysis.h"
18
#include "sdfg/analysis/mem_access_range_analysis_internal.h"
19
#include "sdfg/analysis/users.h"
20
#include "sdfg/helpers/helpers.h"
21
#include "sdfg/symbolic/extreme_values.h"
22
#include "sdfg/symbolic/symbolic.h"
23

24
namespace sdfg {
25
namespace analysis {
26

27
MemAccessRanges::MemAccessRanges(StructuredSDFG& sdfg) : Analysis(sdfg), graph_() {}
9✔
28

29
void MemAccessRanges::
30
    run(structured_control_flow::ControlFlowNode& node, std::unordered_set<std::string> target_containers) {
13✔
31
    auto& users = analysis_manager_->get<Users>();
13✔
32
    auto& assumptions_analysis = analysis_manager_->get<AssumptionsAnalysis>();
13✔
33

34
    UsersView users_view(users, node);
13✔
35

36
    auto builder = MemAccessRangesBuilder(sdfg_, users_view, assumptions_analysis);
13✔
37

38
    auto& worklist = builder.worklist_;
13✔
39

40
    // Initialize worklist with containers
41
    for (const auto& container : target_containers) {
28✔
42
        worklist.push_back(new WorkItem{&container});
15✔
43
    }
44

45
    // Iterate over all variables and their users
46
    while (!worklist.empty()) {
28✔
47
        auto* workItem = worklist.front();
15✔
48
        builder.process_workItem(workItem);
15✔
49
        worklist.pop_front();
15✔
50
        delete workItem;
15✔
51
    }
52

53
    this->ranges_.insert_or_assign(&node, std::move(builder.ranges_));
13✔
54
}
13✔
55

56
void MemAccessRanges::run(analysis::AnalysisManager& analysis_manager) {
9✔
57
    this->analysis_manager_ = &analysis_manager;
9✔
58
    std::unordered_set<std::string> containers;
9✔
59

60
    // Collect argument names
61
    for (auto& arg : sdfg_.arguments()) {
28✔
62
        if (sdfg_.type(arg).type_id() != types::TypeID::Scalar) {
19✔
63
            containers.insert(arg);
11✔
64
        }
11✔
65
    }
66

67
    // Collect external names
68
    for (auto& ext : sdfg_.externals()) {
9✔
UNCOV
69
        if (sdfg_.type(ext).type_id() != types::TypeID::Scalar) {
×
UNCOV
70
            containers.insert(ext);
×
UNCOV
71
        }
×
72
    }
73

74
    this->run(sdfg_.root(), containers);
9✔
75
}
9✔
76

77
const MemAccessRange* MemAccessRanges::get(const std::string& varName) const {
11✔
78
    auto ranges = this->ranges_.find(&sdfg_.root());
11✔
79
    if (ranges == this->ranges_.end()) {
11✔
80
        return nullptr;
×
81
    }
82
    auto res = ranges->second.find(varName);
11✔
83
    if (res != ranges->second.end()) {
11✔
84
        return &res->second;
8✔
85
    } else {
86
        return nullptr;
3✔
87
    }
88
}
11✔
89

90
const MemAccessRange* MemAccessRanges::
91
    get(const std::string& varName,
4✔
92
        structured_control_flow::ControlFlowNode& node,
93
        std::unordered_set<std::string> target_nodes) {
94
    auto ranges = this->ranges_.find(&node);
4✔
95
    this->run(node, target_nodes);
4✔
96
    ranges = this->ranges_.find(&node);
4✔
97
    if (ranges == this->ranges_.end()) {
4✔
NEW
98
        return nullptr;
×
99
    }
100
    auto res = ranges->second.find(varName);
4✔
101
    if (res != ranges->second.end()) {
4✔
102
        return &res->second;
×
103
    } else {
104
        return nullptr;
4✔
105
    }
106
}
4✔
107

108
MemAccessRange::MemAccessRange(
11✔
109
    const std::string& name,
110
    bool saw_read,
111
    bool saw_write,
112
    bool undefined,
113
    const std::vector<std::pair<symbolic::Expression, symbolic::Expression>>&& dims
114
)
115
    : name_(name), saw_read_(saw_read), saw_write_(saw_write), undefined_(undefined), dims_(dims) {}
11✔
116

117
const std::string& MemAccessRange::get_name() const { return name_; }
8✔
118

119
bool MemAccessRange::saw_read() const { return saw_read_; }
8✔
120
bool MemAccessRange::saw_write() const { return saw_write_; }
8✔
121
bool MemAccessRange::is_undefined() const { return undefined_; }
8✔
122

123
const std::vector<std::pair<symbolic::Expression, symbolic::Expression>>& MemAccessRange::dims() const { return dims_; }
8✔
124

125
void MemAccessRangesBuilder::process_workItem(WorkItem* item) {
15✔
126
    const auto* varName = item->var_name;
15✔
127

128
    const auto& reads = users_.reads(*varName);
15✔
129
    process_direct_users(item, false, reads);
15✔
130

131
    const auto& writes = users_.writes(*varName);
15✔
132
    process_direct_users(item, true, writes);
15✔
133

134
    const auto& views = users_.views(*varName);
15✔
135
    if (!views.empty()) {
15✔
136
        DEBUG_PRINTLN("Found views for " << *varName << " => not rangeable!");
×
137
        item->undefined = true;
×
138
    }
×
139

140
    const auto& moves = users_.moves(*varName);
15✔
141
    if (!moves.empty()) {
15✔
142
        DEBUG_PRINTLN("Found moves for " << *varName << " => not rangeable!");
×
143
        item->undefined = true;
×
144
    }
×
145

146
    if (!item->dims.empty()) {
15✔
147
        std::vector<std::pair<symbolic::Expression, symbolic::Expression>> finalDims;
11✔
148
        finalDims.reserve(item->dims.size());
11✔
149

150
        for (auto& dim : item->dims) {
24✔
151
            auto& lowerExprs = std::get<0>(dim);
13✔
152
            bool isLowerUndefined = std::get<1>(dim);
13✔
153
            symbolic::Expression lb = (!lowerExprs.empty() && !isLowerUndefined)
26✔
154
                                          ? SymEngine::min(lowerExprs)
13✔
155
                                          : SymEngine::RCP<const SymEngine::Basic>();
×
156
            auto& upperExprs = std::get<2>(dim);
13✔
157
            bool isUpperUndefined = std::get<3>(dim);
13✔
158
            symbolic::Expression ub = (!upperExprs.empty() && !isUpperUndefined)
26✔
159
                                          ? SymEngine::max(upperExprs)
13✔
160
                                          : SymEngine::RCP<const SymEngine::Basic>();
×
161

162
            if (lb.is_null() || ub.is_null()) {
13✔
163
                item->undefined = true;
×
164
            }
×
165
            if (!lb.is_null() && SymEngine::is_a<SymEngine::Infty>(*lb)) {
13✔
166
                lb = SymEngine::null;
1✔
167
                item->undefined = true;
1✔
168
            }
1✔
169
            if (!ub.is_null() && SymEngine::is_a<SymEngine::Infty>(*ub)) {
13✔
170
                ub = SymEngine::null;
1✔
171
                item->undefined = true;
1✔
172
            }
1✔
173

174
            finalDims.emplace_back(std::move(lb), std::move(ub));
13✔
175
        }
13✔
176

177
        this->ranges_.emplace(
22✔
178
            std::piecewise_construct,
179
            std::forward_as_tuple(*varName),
11✔
180
            std::forward_as_tuple(*varName, item->saw_read, item->saw_write, item->undefined, std::move(finalDims))
11✔
181
        );
182
    }
11✔
183
}
15✔
184

185
void MemAccessRangesBuilder::process_direct_users(WorkItem* item, bool is_write, std::vector<User*> accesses) {
30✔
186
    for (auto& access : accesses) {
47✔
187
        auto subsets = access->subsets();
17✔
188
        const auto& user_scope = analysis::Users::scope(access);
17✔
189
        auto assums = assumptions_analysis_.get(*user_scope, false);
17✔
190
        auto params = this->sdfg_.parameters();
17✔
191

192
        item->saw_read |= !is_write;
17✔
193
        item->saw_write |= is_write;
17✔
194

195
        for (const auto& subset : subsets) {
34✔
196
            auto subsetDims = subset.size();
17✔
197
            item->dims.reserve(subsetDims);
17✔
198
            for (size_t i = item->dims.size(); i < subsetDims; ++i) {
30✔
199
                item->dims.emplace_back(std::make_tuple<
26✔
200
                                        std::vector<symbolic::Expression>,
201
                                        bool,
202
                                        std::vector<symbolic::Expression>,
203
                                        bool>({}, false, {}, false));
13✔
204
            }
13✔
205
            int dimIdx = 0;
17✔
206
            for (auto& dim : subset) {
30✔
207
                auto lb = symbolic::minimum(dim, params, assums);
13✔
208
                auto ub = symbolic::maximum(dim, params, assums);
13✔
209

210
                if (lb.is_null()) {
13✔
211
                    std::get<1>(item->dims[dimIdx]) = true;
×
212
                } else {
×
213
                    std::get<0>(item->dims[dimIdx]).push_back(lb);
13✔
214
                }
215
                if (ub.is_null()) {
13✔
216
                    std::get<3>(item->dims[dimIdx]) = true;
×
217
                } else {
×
218
                    std::get<2>(item->dims[dimIdx]).push_back(ub);
13✔
219
                }
220

221
                ++dimIdx;
13✔
222
            }
13✔
223
        }
224
    }
17✔
225
}
30✔
226

227
} // namespace analysis
228
} // 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

© 2025 Coveralls, Inc