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

daisytuner / sdfglib / 16069945621

04 Jul 2025 08:56AM UTC coverage: 64.375% (-0.2%) from 64.606%
16069945621

push

github

web-flow
Merge pull request #137 from daisytuner/clang-format

runs clang-format on codebase

609 of 827 new or added lines in 63 files covered. (73.64%)

46 existing lines in 30 files now uncovered.

8578 of 13325 relevant lines covered (64.38%)

177.24 hits per line

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

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

3
#include "sdfg/analysis/scope_analysis.h"
4
#include "sdfg/structured_control_flow/structured_loop.h"
5

6
namespace sdfg {
7
namespace transformations {
8

9
LoopInterchange::LoopInterchange(
6✔
10
    structured_control_flow::StructuredLoop& outer_loop, structured_control_flow::StructuredLoop& inner_loop
11
)
12
    : outer_loop_(outer_loop), inner_loop_(inner_loop) {
6✔
13

14
      };
6✔
15

16
std::string LoopInterchange::name() const { return "LoopInterchange"; };
2✔
17

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

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

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

47
    return false;
×
48
};
6✔
49

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

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

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

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

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

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

121
    analysis_manager.invalidate_all();
4✔
122
};
4✔
123

124
void LoopInterchange::to_json(nlohmann::json& j) const {
2✔
125
    j["transformation_type"] = this->name();
2✔
126
    j["outer_loop_element_id"] = this->outer_loop_.element_id();
2✔
127
    j["inner_loop_element_id"] = this->inner_loop_.element_id();
2✔
128
};
2✔
129

130
LoopInterchange LoopInterchange::from_json(builder::StructuredSDFGBuilder& builder, const nlohmann::json& desc) {
1✔
131
    auto outer_loop_id = desc["outer_loop_element_id"].get<size_t>();
1✔
132
    auto inner_loop_id = desc["inner_loop_element_id"].get<size_t>();
1✔
133
    auto outer_element = builder.find_element_by_id(outer_loop_id);
1✔
134
    auto inner_element = builder.find_element_by_id(inner_loop_id);
1✔
135
    if (!outer_element) {
1✔
136
        throw InvalidTransformationDescriptionException(
×
NEW
137
            "Element with ID " + std::to_string(outer_loop_id) + " not found."
×
138
        );
139
    }
140
    if (!inner_element) {
1✔
141
        throw InvalidTransformationDescriptionException(
×
NEW
142
            "Element with ID " + std::to_string(inner_loop_id) + " not found."
×
143
        );
144
    }
145
    auto outer_loop = dynamic_cast<structured_control_flow::StructuredLoop*>(outer_element);
1✔
146
    auto inner_loop = dynamic_cast<structured_control_flow::StructuredLoop*>(inner_element);
1✔
147

148
    return LoopInterchange(*outer_loop, *inner_loop);
1✔
149
};
×
150

151
} // namespace transformations
152
} // 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

© 2025 Coveralls, Inc