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

daisytuner / sdfglib / 16779684622

06 Aug 2025 02:21PM UTC coverage: 64.3% (-1.0%) from 65.266%
16779684622

push

github

web-flow
Merge pull request #172 from daisytuner/opaque-pointers

Opaque pointers, typed memlets, untyped tasklet connectors

330 of 462 new or added lines in 38 files covered. (71.43%)

382 existing lines in 30 files now uncovered.

8865 of 13787 relevant lines covered (64.3%)

116.73 hits per line

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

51.35
/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(
3✔
12
    structured_control_flow::StructuredLoop& outer_loop, structured_control_flow::StructuredLoop& inner_loop
13
)
14
    : outer_loop_(outer_loop), inner_loop_(inner_loop) {
3✔
15

16
      };
3✔
17

UNCOV
18
std::string LoopInterchange::name() const { return "LoopInterchange"; };
×
19

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

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

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

49
    return false;
×
50
};
3✔
51

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

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

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

111
    // Insert inner loop body into new inner loop
112
    auto& inner_body = this->inner_loop_.root();
1✔
113
    builder.insert_children(new_inner_loop->root(), inner_body, 0);
1✔
114

115
    // Insert outer loop body into new outer loop
116
    auto& outer_body = this->outer_loop_.root();
1✔
117
    builder.insert_children(new_outer_loop->root(), outer_body, 0);
1✔
118

119
    // Remove old loops
120
    builder.remove_child(new_outer_loop->root(), this->inner_loop_);
1✔
121
    builder.remove_child(outer_scope, this->outer_loop_);
1✔
122

123
    analysis_manager.invalidate_all();
1✔
124
};
1✔
125

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

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

UNCOV
164
    return LoopInterchange(*outer_loop, *inner_loop);
×
165
};
×
166

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