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

daisytuner / sdfglib / 20764569418

06 Jan 2026 10:50PM UTC coverage: 62.168% (+21.4%) from 40.764%
20764569418

push

github

web-flow
Merge pull request #433 from daisytuner/clang-coverage

updates clang coverage flags

14988 of 24109 relevant lines covered (62.17%)

88.57 hits per line

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

83.13
/src/analysis/control_flow_analysis.cpp
1
#include "sdfg/analysis/control_flow_analysis.h"
2

3
#include <cassert>
4
#include <list>
5
#include <memory>
6
#include <string>
7
#include <unordered_map>
8
#include <unordered_set>
9
#include <vector>
10

11
#include "sdfg/data_flow/memlet.h"
12
#include "sdfg/element.h"
13
#include "sdfg/graph/graph.h"
14
#include "sdfg/structured_control_flow/for.h"
15
#include "sdfg/structured_control_flow/map.h"
16
#include "sdfg/structured_control_flow/sequence.h"
17
#include "sdfg/structured_sdfg.h"
18
#include "sdfg/symbolic/sets.h"
19
#include "sdfg/symbolic/symbolic.h"
20

21
namespace sdfg {
22
namespace analysis {
23
ControlFlowAnalysis::ControlFlowAnalysis(StructuredSDFG& sdfg)
24
    : Analysis(sdfg) {
4✔
25

26
      };
4✔
27

28
std::pair<graph::Vertex, graph::Vertex> ControlFlowAnalysis::traverse(structured_control_flow::ControlFlowNode& current
29
) {
23✔
30
    // Leaf nodes
31
    if (auto block_node = dynamic_cast<structured_control_flow::Block*>(&current)) {
23✔
32
        auto v = boost::add_vertex(graph_);
12✔
33
        nodes_[v] = &current;
12✔
34
        return {v, v};
12✔
35
    } else if (auto return_node = dynamic_cast<structured_control_flow::Return*>(&current)) {
12✔
36
        auto v = boost::add_vertex(graph_);
×
37
        nodes_[v] = &current;
×
38
        return {v, boost::graph_traits<graph::Graph>::null_vertex()};
×
39
    } else if (auto continue_node = dynamic_cast<structured_control_flow::Continue*>(&current)) {
11✔
40
        auto v = boost::add_vertex(graph_);
×
41
        nodes_[v] = &current;
×
42
        boost::add_edge(v, last_loop_, graph_);
×
43
        return {v, boost::graph_traits<graph::Graph>::null_vertex()};
×
44
    } else if (auto break_node = dynamic_cast<structured_control_flow::Break*>(&current)) {
11✔
45
        auto v = boost::add_vertex(graph_);
×
46
        nodes_[v] = &current;
×
47
        boost::add_edge(v, last_loop_, graph_);
×
48
        return {v, boost::graph_traits<graph::Graph>::null_vertex()};
×
49
    } else if (auto if_else_node = dynamic_cast<structured_control_flow::IfElse*>(&current)) {
11✔
50
        auto start_v = boost::add_vertex(graph_);
1✔
51
        nodes_[start_v] = &current;
1✔
52

53
        graph::Vertex end_v = boost::graph_traits<graph::Graph>::null_vertex();
1✔
54
        for (size_t i = 0; i < if_else_node->size(); i++) {
3✔
55
            auto [case_start, case_end] = this->traverse(if_else_node->at(i).first);
2✔
56
            if (case_start != boost::graph_traits<graph::Graph>::null_vertex()) {
2✔
57
                boost::add_edge(start_v, case_start, graph_);
2✔
58
            }
2✔
59
            if (case_end != boost::graph_traits<graph::Graph>::null_vertex()) {
2✔
60
                if (end_v == boost::graph_traits<graph::Graph>::null_vertex()) {
2✔
61
                    end_v = boost::add_vertex(graph_);
1✔
62
                    nodes_[end_v] = nullptr;
1✔
63
                }
1✔
64
                boost::add_edge(case_end, end_v, graph_);
2✔
65
            }
2✔
66
        }
2✔
67

68
        if (!if_else_node->is_complete()) {
1✔
69
            if (end_v == boost::graph_traits<graph::Graph>::null_vertex()) {
×
70
                end_v = boost::add_vertex(graph_);
×
71
                nodes_[end_v] = nullptr;
×
72
            }
×
73
            boost::add_edge(start_v, end_v, graph_);
×
74
        }
×
75

76
        return {start_v, end_v};
1✔
77
    } else if (auto while_loop = dynamic_cast<structured_control_flow::While*>(&current)) {
10✔
78
        auto header_v = boost::add_vertex(graph_);
1✔
79
        nodes_[header_v] = &current;
1✔
80

81
        auto previous_loop_ = last_loop_;
1✔
82
        last_loop_ = header_v;
1✔
83

84
        auto [body_start, body_end] = this->traverse(while_loop->root());
1✔
85
        if (body_start != boost::graph_traits<graph::Graph>::null_vertex()) {
1✔
86
            boost::add_edge(header_v, body_start, graph_);
1✔
87
        }
1✔
88
        if (body_end != boost::graph_traits<graph::Graph>::null_vertex()) {
1✔
89
            boost::add_edge(body_end, header_v, graph_);
1✔
90
        }
1✔
91

92
        last_loop_ = previous_loop_;
1✔
93

94
        return {header_v, header_v};
1✔
95
    } else if (auto structured_loop = dynamic_cast<structured_control_flow::StructuredLoop*>(&current)) {
9✔
96
        auto header_v = boost::add_vertex(graph_);
1✔
97
        nodes_[header_v] = &current;
1✔
98

99
        auto previous_loop_ = last_loop_;
1✔
100
        last_loop_ = header_v;
1✔
101

102
        auto [body_start, body_end] = this->traverse(structured_loop->root());
1✔
103
        if (body_start != boost::graph_traits<graph::Graph>::null_vertex()) {
1✔
104
            boost::add_edge(header_v, body_start, graph_);
1✔
105
        }
1✔
106
        if (body_end != boost::graph_traits<graph::Graph>::null_vertex()) {
1✔
107
            boost::add_edge(body_end, header_v, graph_);
1✔
108
        }
1✔
109

110
        last_loop_ = previous_loop_;
1✔
111

112
        return {header_v, header_v};
1✔
113
    } else if (auto sequence_node = dynamic_cast<structured_control_flow::Sequence*>(&current)) {
8✔
114
        graph::Vertex seq_start = boost::graph_traits<graph::Graph>::null_vertex();
8✔
115
        graph::Vertex seq_end = boost::graph_traits<graph::Graph>::null_vertex();
8✔
116

117
        for (size_t i = 0; i < sequence_node->size(); i++) {
23✔
118
            auto& child = sequence_node->at(i).first;
15✔
119
            auto [child_start, child_end] = this->traverse(child);
15✔
120
            if (child_start != boost::graph_traits<graph::Graph>::null_vertex()) {
15✔
121
                if (seq_start == boost::graph_traits<graph::Graph>::null_vertex()) {
15✔
122
                    seq_start = child_start;
8✔
123
                }
8✔
124
                if (seq_end != boost::graph_traits<graph::Graph>::null_vertex()) {
15✔
125
                    boost::add_edge(seq_end, child_start, graph_);
7✔
126
                }
7✔
127
            }
15✔
128

129
            seq_end = child_end;
15✔
130
            if (seq_end == boost::graph_traits<graph::Graph>::null_vertex()) {
15✔
131
                break;
×
132
            }
×
133
        }
15✔
134

135
        return {seq_start, seq_end};
8✔
136
    } else {
8✔
137
        throw InvalidSDFGException("Unknown control flow node type encountered during control flow analysis.");
×
138
    }
×
139
};
23✔
140

141
void ControlFlowAnalysis::run(analysis::AnalysisManager& analysis_manager) {
4✔
142
    nodes_.clear();
4✔
143
    graph_.clear();
4✔
144
    dom_tree_.clear();
4✔
145
    pdom_tree_.clear();
4✔
146

147
    this->traverse(sdfg_.root());
4✔
148

149
    graph::Vertex entry_vertex = boost::graph_traits<graph::Graph>::null_vertex();
4✔
150
    for (auto v : boost::make_iterator_range(boost::vertices(graph_))) {
16✔
151
        if (boost::in_degree(v, graph_) == 0) {
16✔
152
            assert(entry_vertex == boost::graph_traits<graph::Graph>::null_vertex());
4✔
153
            entry_vertex = v;
4✔
154
        }
4✔
155
    }
16✔
156

157
    auto dom_tree = graph::dominator_tree(graph_, entry_vertex);
4✔
158
    for (const auto& [node, dom_node] : dom_tree) {
16✔
159
        if (nodes_.find(node) != nodes_.end() && nodes_.find(dom_node) != nodes_.end()) {
16✔
160
            dom_tree_[nodes_.at(node)] = nodes_.at(dom_node);
12✔
161
        }
12✔
162
    }
16✔
163

164
    auto pdom_tree = graph::post_dominator_tree(graph_);
4✔
165
    for (const auto& [node, pdom_node] : pdom_tree) {
16✔
166
        if (nodes_.find(node) != nodes_.end() && nodes_.find(pdom_node) != nodes_.end()) {
16✔
167
            pdom_tree_[nodes_.at(node)] = nodes_.at(pdom_node);
12✔
168
        }
12✔
169
    }
16✔
170
};
4✔
171

172
std::unordered_set<structured_control_flow::ControlFlowNode*> ControlFlowAnalysis::exits() const {
12✔
173
    std::unordered_set<structured_control_flow::ControlFlowNode*> exit_nodes;
12✔
174

175
    for (auto v : boost::make_iterator_range(boost::vertices(graph_))) {
48✔
176
        if (boost::out_degree(v, graph_) == 0) {
48✔
177
            assert(nodes_.find(v) != nodes_.end());
12✔
178
            exit_nodes.insert(nodes_.at(v));
12✔
179
        }
12✔
180
    }
48✔
181

182
    return exit_nodes;
12✔
183
}
12✔
184

185
const std::unordered_map<structured_control_flow::ControlFlowNode*, structured_control_flow::ControlFlowNode*>&
186
ControlFlowAnalysis::dom_tree() const {
×
187
    return dom_tree_;
×
188
}
×
189

190
const std::unordered_map<structured_control_flow::ControlFlowNode*, structured_control_flow::ControlFlowNode*>&
191
ControlFlowAnalysis::pdom_tree() const {
×
192
    return pdom_tree_;
×
193
}
×
194

195
bool ControlFlowAnalysis::
196
    dominates(structured_control_flow::ControlFlowNode& a, structured_control_flow::ControlFlowNode& b) const {
13✔
197
    auto it = dom_tree_.find(&b);
13✔
198
    while (it != dom_tree_.end()) {
31✔
199
        if (it->second == &a) {
26✔
200
            return true;
8✔
201
        }
8✔
202
        it = dom_tree_.find(it->second);
18✔
203
    }
18✔
204
    return false;
5✔
205
}
13✔
206

207
bool ControlFlowAnalysis::
208
    post_dominates(structured_control_flow::ControlFlowNode& a, structured_control_flow::ControlFlowNode& b) const {
13✔
209
    auto it = pdom_tree_.find(&b);
13✔
210
    while (it != pdom_tree_.end()) {
31✔
211
        if (it->second == &a) {
26✔
212
            return true;
8✔
213
        }
8✔
214
        it = pdom_tree_.find(it->second);
18✔
215
    }
18✔
216
    return false;
5✔
217
}
13✔
218

219
} // namespace analysis
220
} // 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