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

daisytuner / sdfglib / 18186882603

02 Oct 2025 07:52AM UTC coverage: 61.116% (+0.05%) from 61.068%
18186882603

Pull #258

github

web-flow
Merge 0fbf718f8 into a12f62888
Pull Request #258: adds macro for debug prints

0 of 16 new or added lines in 5 files covered. (0.0%)

10 existing lines in 2 files now uncovered.

9569 of 15657 relevant lines covered (61.12%)

111.31 hits per line

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

81.02
/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_() {}
8✔
28

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

121
bool MemAccessRange::saw_read() const { return saw_read_; }
10✔
122
bool MemAccessRange::saw_write() const { return saw_write_; }
10✔
123
bool MemAccessRange::is_undefined() const { return undefined_; }
9✔
124

125
const std::vector<std::pair<symbolic::Expression, symbolic::Expression>>& MemAccessRange::dims() const { return dims_; }
10✔
126

127
void MemAccessRangesBuilder::process_workItem(WorkItem* item) {
13✔
128
    const auto* varName = item->var_name;
13✔
129

130
    const auto& reads = users_.reads(*varName);
13✔
131
    process_direct_users(item, false, reads);
13✔
132

133
    const auto& writes = users_.writes(*varName);
13✔
134
    process_direct_users(item, true, writes);
13✔
135

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

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

148
    if (!item->dims.empty()) {
13✔
149
        std::vector<std::pair<symbolic::Expression, symbolic::Expression>> finalDims;
13✔
150
        finalDims.reserve(item->dims.size());
13✔
151

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

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

176
            finalDims.emplace_back(std::move(lb), std::move(ub));
16✔
177
        }
16✔
178

179
        this->ranges_.emplace(
26✔
180
            std::piecewise_construct,
181
            std::forward_as_tuple(*varName),
13✔
182
            std::forward_as_tuple(*varName, item->saw_read, item->saw_write, item->undefined, std::move(finalDims))
13✔
183
        );
184
    }
13✔
185
}
13✔
186

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

194
        item->saw_read |= !is_write;
14✔
195
        item->saw_write |= is_write;
14✔
196

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

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

223
                ++dimIdx;
18✔
224
            }
18✔
225
        }
226
    }
14✔
227
}
26✔
228

229
} // namespace analysis
230
} // 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