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

daisytuner / sdfglib / 15732162024

18 Jun 2025 11:57AM UTC coverage: 64.351% (+0.03%) from 64.317%
15732162024

Pull #86

github

web-flow
Merge 742edbbbe into 32b5d7ae4
Pull Request #86: Add optimizer functionality

144 of 230 new or added lines in 9 files covered. (62.61%)

9 existing lines in 6 files now uncovered.

8125 of 12626 relevant lines covered (64.35%)

153.57 hits per line

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

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

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

6
namespace sdfg {
7
namespace transformations {
8

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

13
      };
5✔
14

15
std::string LoopInterchange::name() const { return "LoopInterchange"; };
10✔
16

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

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

31
    // Criterion: Outer loop must not have any outer blocks
32
    if (outer_loop_.root().size() > 1) {
5✔
33
        return false;
×
34
    }
35
    if (outer_loop_.root().at(0).second.assignments().size() > 0) {
5✔
36
        return false;
×
37
    }
38
    if (&outer_loop_.root().at(0).first != &inner_loop_) {
5✔
39
        return false;
×
40
    }
41
    // Criterion: Any of both loops is a map
42
    auto& analysis = analysis_manager.get<analysis::DataParallelismAnalysis>();
5✔
43

44
    auto& outer_dependencies = analysis.get(this->outer_loop_);
5✔
45
    if (outer_dependencies.size() > 0) {
5✔
46
        bool is_map = true;
5✔
47
        for (auto& dep : outer_dependencies) {
24✔
48
            auto& dep_type = dep.second;
19✔
49
            if (dep_type < analysis::Parallelism::PARALLEL) {
19✔
50
                is_map = false;
×
51
                break;
×
52
            }
53
        }
54
        if (is_map) {
5✔
55
            return true;
5✔
56
        }
57
    }
×
58
    auto& inner_dependencies = analysis.get(this->inner_loop_);
×
59
    if (inner_dependencies.size() > 0) {
×
60
        bool is_map = true;
×
61
        for (auto& dep : inner_dependencies) {
×
62
            auto& dep_type = dep.second;
×
63
            if (dep_type < analysis::Parallelism::PARALLEL) {
×
64
                is_map = false;
×
65
                break;
×
66
            }
67
        }
68
        if (is_map) {
×
69
            return true;
×
70
        }
71
    }
×
72

73
    return false;
×
74
};
5✔
75

76
void LoopInterchange::apply(builder::StructuredSDFGBuilder& builder,
5✔
77
                            analysis::AnalysisManager& analysis_manager) {
78
    auto new_inner_loop = builder.add_for_after(
10✔
79
        builder.parent(inner_loop_), this->inner_loop_, this->outer_loop_.indvar(),
5✔
80
        this->outer_loop_.condition(), this->outer_loop_.init(), this->outer_loop_.update());
5✔
81
    auto& inner_body = this->inner_loop_.root();
5✔
82

83
    builder.insert_children(new_inner_loop.first.root(), inner_body, 0);
5✔
84

85
    auto new_outer_loop = builder.add_for_after(
10✔
86
        builder.parent(outer_loop_), this->outer_loop_, this->inner_loop_.indvar(),
5✔
87
        this->inner_loop_.condition(), this->inner_loop_.init(), this->inner_loop_.update());
5✔
88

89
    auto& outer_body = this->outer_loop_.root();
5✔
90
    builder.insert_children(new_outer_loop.first.root(), outer_body, 0);
5✔
91
    builder.remove_child(builder.parent(inner_loop_), this->inner_loop_);
5✔
92
    builder.remove_child(builder.parent(outer_loop_), this->outer_loop_);
5✔
93

94
    analysis_manager.invalidate_all();
5✔
95
};
5✔
96

97
void LoopInterchange::to_json(nlohmann::json& j) const {
2✔
98
    std::cout << "Serializing LoopTiling transformation to JSON" << std::endl;
2✔
99
    std::cout << "Writing transformation type: " << this->name() << std::endl;
2✔
100
    j["transformation_type"] = this->name();
2✔
101
    std::cout << "Writing parent element ID " << std::endl;
2✔
102
    j["outer_loop_element_id"] = this->outer_loop_.element_id();
2✔
103
    std::cout << "Writing loop element ID " << std::endl;
2✔
104
    j["inner_loop_element_id"] = this->inner_loop_.element_id();
2✔
105
};
2✔
106

107
LoopInterchange LoopInterchange::from_json(builder::StructuredSDFGBuilder& builder,
1✔
108
                                           const nlohmann::json& desc) {
109
    auto outer_loop_id = desc["outer_loop_element_id"].get<size_t>();
1✔
110
    auto inner_loop_id = desc["inner_loop_element_id"].get<size_t>();
1✔
111
    auto outer_element = builder.find_element_by_id(outer_loop_id);
1✔
112
    auto inner_element = builder.find_element_by_id(inner_loop_id);
1✔
113
    if (!outer_element) {
1✔
NEW
114
        throw InvalidTransformationDescriptionException(
×
NEW
115
            "Element with ID " + std::to_string(outer_loop_id) + " not found.");
×
116
    }
117
    if (!inner_element) {
1✔
NEW
118
        throw InvalidTransformationDescriptionException(
×
NEW
119
            "Element with ID " + std::to_string(inner_loop_id) + " not found.");
×
120
    }
121
    auto outer_loop = dynamic_cast<structured_control_flow::For*>(outer_element);
1✔
122
    auto inner_loop = dynamic_cast<structured_control_flow::For*>(inner_element);
1✔
123

124
    return LoopInterchange(*outer_loop, *inner_loop);
1✔
NEW
UNCOV
125
};
×
126

127
}  // namespace transformations
128
}  // 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