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

daisytuner / sdfglib / 17637380013

11 Sep 2025 07:29AM UTC coverage: 59.755% (+0.6%) from 59.145%
17637380013

push

github

web-flow
New debug info (#210)

* initial draft

* update data structure and construction logic

* finalize DebugInfo draft

* fix tests

* Update serializer and fix tests

* fix append bug

* update data structure

* sdfg builder update

* const ref vectors

* update implementation and partial tests

* compiling state

* update serializer interface

* update dot test

* reset interface to debug_info in json to maintain compatibility with tools

* first review batch

* second batch of changes

* merge fixes

777 of 1111 new or added lines in 46 files covered. (69.94%)

11 existing lines in 11 files now uncovered.

9755 of 16325 relevant lines covered (59.75%)

115.06 hits per line

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

73.87
/src/transformations/loop_interchange.cpp
1
#include "sdfg/transformations/loop_interchange.h"
2
#include <stdexcept>
3

4
#include "sdfg/analysis/scope_analysis.h"
5
#include "sdfg/structured_control_flow/for.h"
6
#include "sdfg/structured_control_flow/structured_loop.h"
7

8
namespace sdfg {
9
namespace transformations {
10

11
LoopInterchange::LoopInterchange(
8✔
12
    structured_control_flow::StructuredLoop& outer_loop, structured_control_flow::StructuredLoop& inner_loop
13
)
14
    : outer_loop_(outer_loop), inner_loop_(inner_loop) {
8✔
15

16
      };
8✔
17

18
std::string LoopInterchange::name() const { return "LoopInterchange"; };
2✔
19

20
bool LoopInterchange::can_be_applied(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
8✔
21
    auto& outer_indvar = this->outer_loop_.indvar();
8✔
22

23
    // Criterion: Inner loop must not depend on outer loop
24
    auto& inner_loop_init = this->inner_loop_.init();
8✔
25
    auto& inner_loop_condition = this->inner_loop_.condition();
8✔
26
    auto& inner_loop_update = this->inner_loop_.update();
8✔
27
    if (symbolic::uses(inner_loop_init, outer_indvar->get_name()) ||
16✔
28
        symbolic::uses(inner_loop_condition, outer_indvar->get_name()) ||
15✔
29
        symbolic::uses(inner_loop_update, outer_indvar->get_name())) {
7✔
30
        return false;
1✔
31
    }
32

33
    // Criterion: Outer loop must not have any outer blocks
34
    if (outer_loop_.root().size() > 1) {
7✔
35
        return false;
1✔
36
    }
37
    if (outer_loop_.root().at(0).second.assignments().size() > 0) {
6✔
38
        return false;
×
39
    }
40
    if (&outer_loop_.root().at(0).first != &inner_loop_) {
6✔
41
        return false;
×
42
    }
43
    // Criterion: Any of both loops is a map
44
    if (dynamic_cast<structured_control_flow::Map*>(&outer_loop_) ||
6✔
45
        dynamic_cast<structured_control_flow::Map*>(&inner_loop_)) {
×
46
        return true;
6✔
47
    }
48

49
    return false;
×
50
};
8✔
51

52
void LoopInterchange::apply(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
6✔
53
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
6✔
54
    auto& outer_scope = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&outer_loop_));
6✔
55
    auto& inner_scope = outer_loop_.root();
6✔
56

57
    int index = outer_scope.index(this->outer_loop_);
6✔
58
    auto& outer_transition = outer_scope.at(index).second;
6✔
59

60
    // Add new outer loop behind current outer loop
61
    structured_control_flow::StructuredLoop* new_outer_loop = nullptr;
6✔
62
    if (auto inner_map = dynamic_cast<structured_control_flow::Map*>(&inner_loop_)) {
6✔
63
        new_outer_loop = &builder.add_map_after(
6✔
64
            outer_scope,
6✔
65
            this->outer_loop_,
6✔
66
            inner_map->indvar(),
6✔
67
            inner_map->condition(),
6✔
68
            inner_map->init(),
6✔
69
            inner_map->update(),
6✔
70
            inner_map->schedule_type(),
6✔
71
            outer_transition.assignments(),
6✔
72
            builder.debug_info().get_region(inner_map->debug_info().indices())
6✔
73
        );
74
    } else {
6✔
75
        new_outer_loop = &builder.add_for_after(
×
76
            outer_scope,
×
77
            this->outer_loop_,
×
78
            this->inner_loop_.indvar(),
×
79
            this->inner_loop_.condition(),
×
80
            this->inner_loop_.init(),
×
81
            this->inner_loop_.update(),
×
82
            outer_transition.assignments(),
×
NEW
83
            builder.debug_info().get_region(this->inner_loop_.debug_info().indices())
×
84
        );
85
    }
86

87
    // Add new inner loop behind current inner loop
88
    structured_control_flow::StructuredLoop* new_inner_loop = nullptr;
6✔
89
    if (auto outer_map = dynamic_cast<structured_control_flow::Map*>(&outer_loop_)) {
6✔
90
        new_inner_loop = &builder.add_map_after(
12✔
91
            inner_scope,
6✔
92
            this->inner_loop_,
6✔
93
            outer_map->indvar(),
6✔
94
            outer_map->condition(),
6✔
95
            outer_map->init(),
6✔
96
            outer_map->update(),
6✔
97
            outer_map->schedule_type(),
6✔
98
            {},
6✔
99
            builder.debug_info().get_region(outer_map->debug_info().indices())
6✔
100
        );
101
    } else {
6✔
102
        new_inner_loop = &builder.add_for_after(
×
103
            inner_scope,
×
104
            this->inner_loop_,
×
105
            this->outer_loop_.indvar(),
×
106
            this->outer_loop_.condition(),
×
107
            this->outer_loop_.init(),
×
108
            this->outer_loop_.update(),
×
109
            {},
×
NEW
110
            builder.debug_info().get_region(this->outer_loop_.debug_info().indices())
×
111
        );
112
    }
113

114
    // Insert inner loop body into new inner loop
115
    builder.move_children(this->inner_loop_.root(), new_inner_loop->root());
6✔
116

117
    // Insert outer loop body into new outer loop
118
    builder.move_children(this->outer_loop_.root(), new_outer_loop->root());
6✔
119

120
    // Remove old loops
121
    builder.remove_child(new_outer_loop->root(), 0);
6✔
122
    builder.remove_child(outer_scope, index);
6✔
123

124
    analysis_manager.invalidate_all();
6✔
125
};
6✔
126

127
void LoopInterchange::to_json(nlohmann::json& j) const {
2✔
128
    std::vector<std::string> loop_types;
2✔
129
    for (auto* loop : {&(this->outer_loop_), &(this->inner_loop_)}) {
6✔
130
        if (dynamic_cast<structured_control_flow::For*>(loop)) {
4✔
131
            loop_types.push_back("for");
×
132
        } else if (dynamic_cast<structured_control_flow::Map*>(loop)) {
4✔
133
            loop_types.push_back("map");
4✔
134
        } else {
4✔
135
            throw std::runtime_error("Unsupported loop type for serialization of loop: " + loop->indvar()->get_name());
×
136
        }
137
    }
138
    j["transformation_type"] = this->name();
2✔
139
    j["subgraph"] = {
6✔
140
        {"0", {{"element_id", this->outer_loop_.element_id()}, {"type", loop_types[0]}}},
2✔
141
        {"1", {{"element_id", this->inner_loop_.element_id()}, {"type", loop_types[1]}}}
2✔
142
    };
143
};
2✔
144

145
LoopInterchange LoopInterchange::from_json(builder::StructuredSDFGBuilder& builder, const nlohmann::json& desc) {
2✔
146
    auto outer_loop_id = desc["subgraph"]["0"]["element_id"].get<size_t>();
2✔
147
    auto inner_loop_id = desc["subgraph"]["1"]["element_id"].get<size_t>();
2✔
148
    auto outer_element = builder.find_element_by_id(outer_loop_id);
2✔
149
    auto inner_element = builder.find_element_by_id(inner_loop_id);
2✔
150
    if (outer_element == nullptr) {
2✔
151
        throw std::runtime_error("Element with ID " + std::to_string(outer_loop_id) + " not found.");
×
152
    }
153
    if (inner_element == nullptr) {
2✔
154
        throw std::runtime_error("Element with ID " + std::to_string(inner_loop_id) + " not found.");
×
155
    }
156
    auto outer_loop = dynamic_cast<structured_control_flow::StructuredLoop*>(outer_element);
2✔
157
    if (outer_loop == nullptr) {
2✔
158
        throw std::runtime_error("Element with ID " + std::to_string(outer_loop_id) + " is not a StructuredLoop.");
×
159
    }
160
    auto inner_loop = dynamic_cast<structured_control_flow::StructuredLoop*>(inner_element);
2✔
161
    if (inner_loop == nullptr) {
2✔
162
        throw std::runtime_error("Element with ID " + std::to_string(inner_loop_id) + " is not a StructuredLoop.");
×
163
    }
164

165
    return LoopInterchange(*outer_loop, *inner_loop);
2✔
166
};
×
167

168
} // namespace transformations
169
} // 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