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

daisytuner / sdfglib / 15044057891

15 May 2025 11:42AM UTC coverage: 59.37% (+1.8%) from 57.525%
15044057891

push

github

web-flow
Merge pull request #14 from daisytuner/sanitizers

enables sanitizer on unit tests

63 of 67 new or added lines in 47 files covered. (94.03%)

570 existing lines in 62 files now uncovered.

7356 of 12390 relevant lines covered (59.37%)

505.93 hits per line

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

90.3
/src/analysis/assumptions_analysis.cpp
1
#include "sdfg/analysis/assumptions_analysis.h"
2

3
#include <utility>
4
#include <vector>
5

6
#include "sdfg/structured_control_flow/sequence.h"
7
#include "sdfg/symbolic/analysis.h"
8
#include "sdfg/symbolic/assumptions.h"
9
#include "sdfg/symbolic/symbolic.h"
10
#include "symengine/basic.h"
11
#include "symengine/symbol.h"
12

13
namespace sdfg {
14
namespace analysis {
15

16
void AssumptionsAnalysis::traverse(structured_control_flow::Sequence& root) {
132✔
17
    std::list<structured_control_flow::ControlFlowNode*> queue = {&root};
132✔
18
    while (!queue.empty()) {
1,608✔
19
        auto current = queue.front();
1,476✔
20
        queue.pop_front();
1,476✔
21

22
        if (auto block_stmt = dynamic_cast<structured_control_flow::Block*>(current)) {
1,476✔
23
            this->visit_block(block_stmt);
406✔
24
        } else if (auto sequence_stmt = dynamic_cast<structured_control_flow::Sequence*>(current)) {
1,476✔
25
            this->visit_sequence(sequence_stmt);
601✔
26
            for (size_t i = 0; i < sequence_stmt->size(); i++) {
1,476✔
27
                queue.push_back(&sequence_stmt->at(i).first);
875✔
28
            }
875✔
29
        } else if (auto if_else_stmt = dynamic_cast<structured_control_flow::IfElse*>(current)) {
1,070✔
30
            this->visit_if_else(if_else_stmt);
×
31
            for (size_t i = 0; i < if_else_stmt->size(); i++) {
×
32
                queue.push_back(&if_else_stmt->at(i).first);
×
UNCOV
33
            }
×
34
        } else if (auto while_stmt = dynamic_cast<structured_control_flow::While*>(current)) {
469✔
35
            this->visit_while(while_stmt);
×
36
            queue.push_back(&while_stmt->root());
×
37
        } else if (auto for_stmt = dynamic_cast<structured_control_flow::For*>(current)) {
469✔
38
            this->visit_for(for_stmt);
461✔
39
            queue.push_back(&for_stmt->root());
461✔
40
        } else if (auto kern_stmt = dynamic_cast<const structured_control_flow::Kernel*>(current)) {
469✔
41
            this->visit_kernel(kern_stmt);
8✔
42
            queue.push_back(&kern_stmt->root());
8✔
43
        }
8✔
44
    }
45
};
132✔
46

47
void AssumptionsAnalysis::visit_block(structured_control_flow::Block* block) { return; };
406✔
48

49
void AssumptionsAnalysis::visit_sequence(structured_control_flow::Sequence* sequence) { return; };
601✔
50

51
void AssumptionsAnalysis::visit_if_else(structured_control_flow::IfElse* if_else) { return; };
×
52

53
void AssumptionsAnalysis::visit_while(structured_control_flow::While* while_loop) { return; };
×
54

55
void AssumptionsAnalysis::visit_for(structured_control_flow::For* for_loop) {
461✔
56
    if (symbolic::strict_monotonicity(for_loop->update(), for_loop->indvar()) !=
461✔
57
        symbolic::Sign::POSITIVE) {
58
        return;
×
59
    }
60

61
    auto& body = for_loop->root();
461✔
62
    if (this->assumptions_.find(&body) == this->assumptions_.end()) {
461✔
63
        this->assumptions_.insert({&body, symbolic::Assumptions()});
461✔
64
    }
461✔
65
    auto& body_assumptions = this->assumptions_[&body];
461✔
66

67
    auto indvar = for_loop->indvar();
461✔
68
    this->iterators_.push_back(indvar->get_name());
461✔
69
    auto sym = indvar;
461✔
70

71
    auto update = for_loop->update();
461✔
72
    if (body_assumptions.find(sym) == body_assumptions.end()) {
461✔
73
        body_assumptions.insert({sym, symbolic::Assumption(sym)});
461✔
74
    }
461✔
75
    body_assumptions[sym].map(update);
461✔
76

77
    auto init = for_loop->init();
461✔
78
    body_assumptions[sym].lower_bound(init);
461✔
79

80
    auto condition = for_loop->condition();
461✔
81
    auto args = condition->get_args();
461✔
82
    if (SymEngine::is_a<SymEngine::StrictLessThan>(*condition)) {
461✔
83
        auto arg_0 = args[0];
424✔
84
        auto arg_1 = args[1];
424✔
85
        if (symbolic::eq(arg_0, indvar)) {
424✔
86
            body_assumptions[sym].upper_bound(symbolic::sub(arg_1, symbolic::integer(1)));
424✔
87
        }
424✔
88
    } else if (SymEngine::is_a<SymEngine::LessThan>(*condition)) {
461✔
89
        auto arg_0 = args[0];
16✔
90
        auto arg_1 = args[1];
16✔
91
        if (symbolic::eq(arg_0, indvar)) {
16✔
92
            body_assumptions[sym].upper_bound(arg_1);
16✔
93
        }
16✔
94
    } else if (SymEngine::is_a<SymEngine::And>(*condition)) {
37✔
95
        auto args = condition->get_args();
21✔
96
        body_assumptions[sym].upper_bound(symbolic::infty(1));
21✔
97
        for (auto arg : args) {
63✔
98
            if (SymEngine::is_a<SymEngine::StrictLessThan>(*arg)) {
42✔
99
                auto args = arg->get_args();
40✔
100
                auto arg_0 = args[0];
40✔
101
                auto arg_1 = args[1];
40✔
102
                if (symbolic::eq(arg_0, indvar)) {
40✔
103
                    auto old_ub = body_assumptions[sym].upper_bound();
40✔
104
                    auto new_ub = symbolic::min(old_ub, symbolic::sub(arg_1, symbolic::integer(1)));
40✔
105
                    body_assumptions[sym].upper_bound(new_ub);
40✔
106
                }
40✔
107
            } else if (SymEngine::is_a<SymEngine::LessThan>(*arg)) {
42✔
108
                auto args = arg->get_args();
2✔
109
                auto arg_0 = args[0];
2✔
110
                auto arg_1 = args[1];
2✔
111
                if (symbolic::eq(arg_0, indvar)) {
2✔
112
                    auto old_ub = body_assumptions[sym].upper_bound();
2✔
113
                    auto new_ub = symbolic::min(old_ub, arg_1);
2✔
114
                    body_assumptions[sym].upper_bound(new_ub);
2✔
115
                }
2✔
116
            }
2✔
117
        }
42✔
118
    }
21✔
119
};
461✔
120

121
void AssumptionsAnalysis::visit_kernel(const structured_control_flow::Kernel* kernel) {
8✔
122
    auto& body = kernel->root();
8✔
123
    if (this->assumptions_.find(&body) == this->assumptions_.end()) {
8✔
124
        this->assumptions_.insert({&body, symbolic::Assumptions()});
8✔
125
    }
8✔
126
    auto& body_assumptions = this->assumptions_[&body];
8✔
127

128
    auto global_assumptions = this->assumptions_[&sdfg_.root()];
8✔
129

130
    std::vector<std::pair<symbolic::Symbol, symbolic::Expression>> dimensions = {
56✔
131
        {kernel->blockDim_x(), kernel->blockDim_x_init()},
8✔
132
        {kernel->blockDim_y(), kernel->blockDim_y_init()},
8✔
133
        {kernel->blockDim_z(), kernel->blockDim_z_init()},
8✔
134
        {kernel->gridDim_x(), kernel->gridDim_x_init()},
8✔
135
        {kernel->gridDim_y(), kernel->gridDim_y_init()},
8✔
136
        {kernel->gridDim_z(), kernel->gridDim_z_init()},
8✔
137
    };
138

139
    // Augment body assumptions by global assumptions
140
    for (auto& entry : dimensions) {
56✔
141
        for (auto& atom : symbolic::atoms(entry.second)) {
72✔
142
            auto sym = SymEngine::rcp_static_cast<const SymEngine::Symbol>(atom);
24✔
143
            if (global_assumptions.find(sym) != global_assumptions.end()) {
24✔
144
                if (body_assumptions.find(sym) == body_assumptions.end()) {
×
145
                    body_assumptions.insert({sym, symbolic::Assumption(sym)});
×
146
                    body_assumptions[sym].lower_bound(global_assumptions[sym].lower_bound());
×
147
                    body_assumptions[sym].upper_bound(global_assumptions[sym].upper_bound());
×
UNCOV
148
                }
×
UNCOV
149
            }
×
150
        }
24✔
151
    }
152

153
    for (auto& entry : dimensions) {
56✔
154
        auto& dim = entry.first;
48✔
155
        auto& init = entry.second;
48✔
156
        body_assumptions[dim].lower_bound(symbolic::lower_bound_analysis(init, body_assumptions));
48✔
157
        body_assumptions[dim].upper_bound(symbolic::upper_bound_analysis(init, body_assumptions));
48✔
158
    }
159

160
    body_assumptions[kernel->blockIdx_x()].lower_bound(symbolic::zero());
8✔
161
    body_assumptions[kernel->blockIdx_y()].lower_bound(symbolic::zero());
8✔
162
    body_assumptions[kernel->blockIdx_z()].lower_bound(symbolic::zero());
8✔
163

164
    body_assumptions[kernel->blockIdx_x()].upper_bound(
16✔
165
        symbolic::sub(kernel->gridDim_x(), symbolic::integer(1)));
8✔
166
    body_assumptions[kernel->blockIdx_y()].upper_bound(
16✔
167
        symbolic::sub(kernel->gridDim_y(), symbolic::integer(1)));
8✔
168
    body_assumptions[kernel->blockIdx_z()].upper_bound(
16✔
169
        symbolic::sub(kernel->gridDim_z(), symbolic::integer(1)));
8✔
170

171
    body_assumptions[kernel->threadIdx_x()].lower_bound(symbolic::zero());
8✔
172
    body_assumptions[kernel->threadIdx_y()].lower_bound(symbolic::zero());
8✔
173
    body_assumptions[kernel->threadIdx_z()].lower_bound(symbolic::zero());
8✔
174

175
    body_assumptions[kernel->threadIdx_x()].upper_bound(
16✔
176
        symbolic::sub(kernel->blockDim_x(), symbolic::integer(1)));
8✔
177
    body_assumptions[kernel->threadIdx_y()].upper_bound(
16✔
178
        symbolic::sub(kernel->blockDim_y(), symbolic::integer(1)));
8✔
179
    body_assumptions[kernel->threadIdx_z()].upper_bound(
16✔
180
        symbolic::sub(kernel->blockDim_z(), symbolic::integer(1)));
8✔
181
}
8✔
182

183
void AssumptionsAnalysis::run(analysis::AnalysisManager& analysis_manager) {
132✔
184
    this->assumptions_.clear();
132✔
185

186
    this->assumptions_.insert({&sdfg_.root(), symbolic::Assumptions()});
132✔
187
    for (auto& entry : sdfg_.assumptions()) {
865✔
188
        this->assumptions_[&sdfg_.root()][entry.first] = entry.second;
733✔
189
    }
190
    for (auto& entry : this->additional_assumptions_) {
132✔
191
        this->assumptions_[&sdfg_.root()][entry.first] = entry.second;
×
192
    }
193

194
    this->traverse(sdfg_.root());
132✔
195
};
132✔
196

197
AssumptionsAnalysis::AssumptionsAnalysis(StructuredSDFG& sdfg)
264✔
198
    : Analysis(sdfg) {
132✔
199

200
      };
132✔
201

202
const symbolic::Assumptions AssumptionsAnalysis::get(
464✔
203
    structured_control_flow::ControlFlowNode& node) {
204
    // TODO: Proper inference based on scope nesting
205
    symbolic::Assumptions assums;
464✔
206
    for (auto& entry : this->assumptions_) {
3,114✔
207
        if (entry.first == &sdfg_.root()) {
2,650✔
208
            continue;
464✔
209
        }
210
        for (auto& entry_ : entry.second) {
4,548✔
211
            assums[entry_.first] = entry_.second;
2,362✔
212
        }
213
    }
214
    for (auto entry : this->assumptions_[&sdfg_.root()]) {
3,564✔
215
        if (assums.find(entry.first) != assums.end()) {
3,100✔
216
            continue;
2,266✔
217
        }
218
        assums[entry.first] = entry.second;
834✔
219
    }
3,100✔
220

221
    return assums;
464✔
222
};
464✔
223

224
}  // namespace analysis
225
}  // 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