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

daisytuner / sdfglib / 16069945621

04 Jul 2025 08:56AM UTC coverage: 64.375% (-0.2%) from 64.606%
16069945621

push

github

web-flow
Merge pull request #137 from daisytuner/clang-format

runs clang-format on codebase

609 of 827 new or added lines in 63 files covered. (73.64%)

46 existing lines in 30 files now uncovered.

8578 of 13325 relevant lines covered (64.38%)

177.24 hits per line

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

64.29
/src/analysis/loop_analysis.cpp
1
#include "sdfg/analysis/loop_analysis.h"
2

3
#include "sdfg/analysis/assumptions_analysis.h"
4
#include "sdfg/structured_control_flow/structured_loop.h"
5
#include "sdfg/symbolic/conjunctive_normal_form.h"
6
#include "sdfg/symbolic/series.h"
7

8
namespace sdfg {
9
namespace analysis {
10

11
LoopAnalysis::LoopAnalysis(StructuredSDFG& sdfg) : Analysis(sdfg) {}
35✔
12

13
void LoopAnalysis::
14
    run(structured_control_flow::ControlFlowNode& scope, structured_control_flow::ControlFlowNode* parent_loop) {
86✔
15
    std::list<structured_control_flow::ControlFlowNode*> queue = {&scope};
86✔
16
    while (!queue.empty()) {
281✔
17
        auto current = queue.front();
195✔
18
        queue.pop_front();
195✔
19

20
        // Loop detected
21
        if (auto while_stmt = dynamic_cast<structured_control_flow::While*>(current)) {
195✔
22
            this->loops_.insert(while_stmt);
×
23
            this->loop_tree_[while_stmt] = parent_loop;
×
24
        } else if (auto loop_stmt = dynamic_cast<structured_control_flow::StructuredLoop*>(current)) {
195✔
25
            this->loops_.insert(loop_stmt);
51✔
26
            this->loop_tree_[loop_stmt] = parent_loop;
51✔
27
        }
51✔
28

29
        if (dynamic_cast<structured_control_flow::Block*>(current)) {
195✔
30
            continue;
58✔
31
        } else if (auto sequence_stmt = dynamic_cast<structured_control_flow::Sequence*>(current)) {
137✔
32
            for (size_t i = 0; i < sequence_stmt->size(); i++) {
195✔
33
                queue.push_back(&sequence_stmt->at(i).first);
109✔
34
            }
109✔
35
        } else if (auto if_else_stmt = dynamic_cast<structured_control_flow::IfElse*>(current)) {
137✔
36
            for (size_t i = 0; i < if_else_stmt->size(); i++) {
×
37
                queue.push_back(&if_else_stmt->at(i).first);
×
38
            }
×
39
        } else if (auto while_stmt = dynamic_cast<structured_control_flow::While*>(current)) {
51✔
40
            this->run(while_stmt->root(), while_stmt);
×
41
        } else if (auto for_stmt = dynamic_cast<structured_control_flow::StructuredLoop*>(current)) {
51✔
42
            this->run(for_stmt->root(), for_stmt);
51✔
43
        } else if (dynamic_cast<structured_control_flow::Break*>(current)) {
51✔
44
            continue;
×
45
        } else if (dynamic_cast<structured_control_flow::Continue*>(current)) {
×
46
            continue;
×
47
        } else if (dynamic_cast<structured_control_flow::Return*>(current)) {
×
48
            continue;
×
49
        } else {
50
            throw std::runtime_error("Unsupported control flow node type");
×
51
        }
52
    }
53
}
86✔
54

55
void LoopAnalysis::run(AnalysisManager& analysis_manager) {
35✔
56
    this->loops_.clear();
35✔
57
    this->loop_tree_.clear();
35✔
58
    this->run(this->sdfg_.root(), nullptr);
35✔
59
}
35✔
60

61
const std::unordered_set<structured_control_flow::ControlFlowNode*> LoopAnalysis::loops() const { return this->loops_; }
34✔
62

63
bool LoopAnalysis::is_monotonic(structured_control_flow::StructuredLoop* loop, AssumptionsAnalysis& assumptions_analysis) {
103✔
64
    auto assums = assumptions_analysis.get(*loop, true);
103✔
65

66
    return symbolic::series::is_monotonic(loop->update(), loop->indvar(), assums);
103✔
67
}
103✔
68

69
bool LoopAnalysis::is_contiguous(structured_control_flow::StructuredLoop* loop, AssumptionsAnalysis& assumptions_analysis) {
17✔
70
    auto assums = assumptions_analysis.get(*loop, true);
17✔
71

72
    return symbolic::series::is_contiguous(loop->update(), loop->indvar(), assums);
17✔
73
}
17✔
74

75
symbolic::Expression LoopAnalysis::
76
    canonical_bound(structured_control_flow::StructuredLoop* loop, AssumptionsAnalysis& assumptions_analysis) {
3✔
77
    if (!LoopAnalysis::is_monotonic(loop, assumptions_analysis)) {
3✔
78
        return SymEngine::null;
×
79
    }
80

81
    symbolic::CNF cnf;
3✔
82
    try {
83
        cnf = symbolic::conjunctive_normal_form(loop->condition());
3✔
84
    } catch (const std::runtime_error& e) {
3✔
85
        return SymEngine::null;
×
86
    }
×
87

88
    bool has_complex_clauses = false;
3✔
89
    for (auto& clause : cnf) {
8✔
90
        if (clause.size() > 1) {
5✔
91
            has_complex_clauses = true;
×
92
            break;
×
93
        }
94
    }
95
    if (has_complex_clauses) {
3✔
96
        return SymEngine::null;
×
97
    }
98

99
    auto indvar = loop->indvar();
3✔
100
    symbolic::Expression bound = SymEngine::null;
3✔
101
    for (auto& clause : cnf) {
8✔
102
        for (auto& literal : clause) {
10✔
103
            if (SymEngine::is_a<SymEngine::StrictLessThan>(*literal)) {
5✔
104
                auto lt = SymEngine::rcp_dynamic_cast<const SymEngine::StrictLessThan>(literal);
3✔
105
                auto lhs = lt->get_args()[0];
3✔
106
                auto rhs = lt->get_args()[1];
3✔
107
                if (SymEngine::eq(*lhs, *indvar)) {
3✔
108
                    if (bound == SymEngine::null) {
3✔
109
                        bound = rhs;
2✔
110
                    } else {
2✔
111
                        bound = symbolic::min(bound, rhs);
1✔
112
                    }
113
                } else {
3✔
114
                    return SymEngine::null;
×
115
                }
116
            } else if (SymEngine::is_a<SymEngine::LessThan>(*literal)) {
5✔
117
                auto le = SymEngine::rcp_dynamic_cast<const SymEngine::LessThan>(literal);
2✔
118
                auto lhs = le->get_args()[0];
2✔
119
                auto rhs = le->get_args()[1];
2✔
120
                if (SymEngine::eq(*lhs, *indvar)) {
2✔
121
                    if (bound == SymEngine::null) {
2✔
122
                        bound = symbolic::add(rhs, symbolic::one());
1✔
123
                    } else {
1✔
124
                        bound = symbolic::min(bound, symbolic::add(rhs, symbolic::one()));
1✔
125
                    }
126
                } else {
2✔
127
                    return SymEngine::null;
×
128
                }
129
            } else {
2✔
130
                return SymEngine::null;
×
131
            }
132
        }
133
    }
134

135
    return bound;
3✔
136
}
3✔
137

138
symbolic::Integer LoopAnalysis::stride(structured_control_flow::StructuredLoop* loop) {
×
139
    auto expr = loop->update();
×
140
    auto indvar = loop->indvar();
×
141

142
    if (SymEngine::is_a<SymEngine::Add>(*expr)) {
×
143
        auto add_expr = SymEngine::rcp_static_cast<const SymEngine::Add>(expr);
×
144
        if (add_expr->get_args().size() != 2) {
×
145
            return SymEngine::null;
×
146
        }
147
        auto arg1 = add_expr->get_args()[0];
×
148
        auto arg2 = add_expr->get_args()[1];
×
149
        if (symbolic::eq(arg1, indvar)) {
×
150
            if (SymEngine::is_a<SymEngine::Integer>(*arg2)) {
×
151
                return SymEngine::rcp_static_cast<const SymEngine::Integer>(arg2);
×
152
            }
153
        }
×
154
        if (symbolic::eq(arg2, indvar)) {
×
155
            if (SymEngine::is_a<SymEngine::Integer>(*arg1)) {
×
156
                return SymEngine::rcp_static_cast<const SymEngine::Integer>(arg1);
×
157
            }
158
        }
×
159
    }
×
160
    return SymEngine::null;
×
161
}
×
162

163
const std::unordered_map<structured_control_flow::ControlFlowNode*, structured_control_flow::ControlFlowNode*>&
UNCOV
164
LoopAnalysis::loop_tree() const {
×
165
    return this->loop_tree_;
×
166
}
167

NEW
168
structured_control_flow::ControlFlowNode* LoopAnalysis::parent_loop(structured_control_flow::ControlFlowNode* loop
×
169
) const {
UNCOV
170
    return this->loop_tree_.at(loop);
×
171
}
172

173
const std::vector<structured_control_flow::ControlFlowNode*> LoopAnalysis::outermost_loops() const {
1✔
174
    std::vector<structured_control_flow::ControlFlowNode*> outermost_loops_;
1✔
175
    for (const auto& [loop, parent] : this->loop_tree_) {
3✔
176
        if (parent == nullptr) {
2✔
177
            outermost_loops_.push_back(loop);
1✔
178
        }
1✔
179
    }
180
    return outermost_loops_;
1✔
181
}
1✔
182

183
} // namespace analysis
184
} // 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