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

daisytuner / sdfglib / 16525628849

25 Jul 2025 03:25PM UTC coverage: 65.266% (-0.05%) from 65.32%
16525628849

push

github

web-flow
Merge pull request #162 from daisytuner/transfer-tuning

Transfer tuning

25 of 53 new or added lines in 6 files covered. (47.17%)

1 existing line in 1 file now uncovered.

8976 of 13753 relevant lines covered (65.27%)

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

16
      };
6✔
17

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

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

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

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

49
    return false;
×
50
};
6✔
51

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

57
    // Add new outer loop behind current outer loop
58
    structured_control_flow::StructuredLoop* new_outer_loop = nullptr;
4✔
59
    if (auto inner_map = dynamic_cast<structured_control_flow::Map*>(&inner_loop_)) {
4✔
60
        new_outer_loop = &builder
8✔
61
                              .add_map_after(
4✔
62
                                  outer_scope,
4✔
63
                                  this->outer_loop_,
4✔
64
                                  inner_map->indvar(),
4✔
65
                                  inner_map->condition(),
4✔
66
                                  inner_map->init(),
4✔
67
                                  inner_map->update(),
4✔
68
                                  inner_map->schedule_type()
4✔
69
                              )
70
                              .first;
4✔
71
    } else {
4✔
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;
4✔
86
    if (auto outer_map = dynamic_cast<structured_control_flow::Map*>(&outer_loop_)) {
4✔
87
        new_inner_loop = &builder
8✔
88
                              .add_map_after(
4✔
89
                                  inner_scope,
4✔
90
                                  this->inner_loop_,
4✔
91
                                  outer_map->indvar(),
4✔
92
                                  outer_map->condition(),
4✔
93
                                  outer_map->init(),
4✔
94
                                  outer_map->update(),
4✔
95
                                  outer_map->schedule_type()
4✔
96
                              )
97
                              .first;
4✔
98
    } else {
4✔
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();
4✔
113
    builder.insert_children(new_inner_loop->root(), inner_body, 0);
4✔
114

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

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

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

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

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

164
    return LoopInterchange(*outer_loop, *inner_loop);
1✔
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