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

daisytuner / sdfglib / 15710378262

17 Jun 2025 02:40PM UTC coverage: 63.835% (-0.7%) from 64.576%
15710378262

Pull #86

github

web-flow
Merge 33788b6e3 into 37980e90f
Pull Request #86: Add optimizer functionality

37 of 215 new or added lines in 9 files covered. (17.21%)

12 existing lines in 5 files now uncovered.

8063 of 12631 relevant lines covered (63.84%)

115.87 hits per line

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

46.99
/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,
2✔
10
                                 structured_control_flow::StructuredLoop& inner_loop)
11
    : outer_loop_(outer_loop), inner_loop_(inner_loop) {
2✔
12

13
      };
2✔
14

NEW
15
std::string LoopInterchange::name() const { return "LoopInterchange"; };
×
16

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

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

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

44
    auto& outer_dependencies = analysis.get(this->outer_loop_);
2✔
45
    if (outer_dependencies.size() > 0) {
2✔
46
        bool is_map = true;
2✔
47
        for (auto& dep : outer_dependencies) {
10✔
48
            auto& dep_type = dep.second;
8✔
49
            if (dep_type < analysis::Parallelism::PARALLEL) {
8✔
50
                is_map = false;
×
51
                break;
×
52
            }
53
        }
54
        if (is_map) {
2✔
55
            return true;
2✔
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
};
2✔
75

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

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

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

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

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

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

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

NEW
UNCOV
124
    return LoopInterchange(*outer_loop, *inner_loop);
×
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