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

daisytuner / sdfglib / 20781520363

07 Jan 2026 10:50AM UTC coverage: 61.994% (-0.2%) from 62.168%
20781520363

Pull #438

github

web-flow
Merge af6583671 into 0c34ccd02
Pull Request #438: Cuda tiling

8 of 51 new or added lines in 6 files covered. (15.69%)

2 existing lines in 1 file now uncovered.

14904 of 24041 relevant lines covered (61.99%)

88.13 hits per line

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

65.03
/src/transformations/loop_interchange.cpp
1
#include "sdfg/transformations/loop_interchange.h"
2

3
#include "sdfg/analysis/scope_analysis.h"
4
#include "sdfg/exceptions.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(
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()) ||
8✔
28
        symbolic::uses(inner_loop_condition, outer_indvar->get_name()) ||
8✔
29
        symbolic::uses(inner_loop_update, outer_indvar->get_name())) {
8✔
30
        return false;
1✔
31
    }
1✔
32

33
    // Criterion: Outer loop must not have any outer blocks
34
    if (outer_loop_.root().size() > 1) {
7✔
35
        return false;
1✔
36
    }
1✔
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_)) {
6✔
46
        return true;
6✔
47
    }
6✔
48

49
    return false;
×
50
};
6✔
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
            this->inner_loop_.debug_info()
6✔
73
        );
6✔
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(),
×
83
            this->inner_loop_.debug_info()
×
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(
6✔
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
            this->outer_loop_.debug_info()
6✔
100
        );
6✔
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
            {},
×
110
            this->outer_loop_.debug_info()
×
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
    applied_ = true;
6✔
126
    new_outer_loop_ = new_outer_loop;
6✔
127
    new_inner_loop_ = new_inner_loop;
6✔
128
};
6✔
129

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

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

168
    return LoopInterchange(*outer_loop, *inner_loop);
2✔
169
};
2✔
170

NEW
171
structured_control_flow::StructuredLoop* LoopInterchange::new_outer_loop() const {
×
NEW
172
    if (!applied_) {
×
NEW
173
        throw InvalidSDFGException("Transformation has not been applied yet.");
×
NEW
174
    }
×
NEW
175
    return new_outer_loop_;
×
NEW
176
};
×
177

NEW
178
structured_control_flow::StructuredLoop* LoopInterchange::new_inner_loop() const {
×
NEW
179
    if (!applied_) {
×
NEW
180
        throw InvalidSDFGException("Transformation has not been applied yet.");
×
NEW
181
    }
×
NEW
182
    return new_inner_loop_;
×
NEW
183
};
×
184

185
} // namespace transformations
186
} // 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