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

daisytuner / docc / 28101952530

24 Jun 2026 01:27PM UTC coverage: 61.988% (+0.1%) from 61.844%
28101952530

Pull #802

github

web-flow
Merge 54d7d8794 into 57cc1db99
Pull Request #802: adds reduce as new structured loop type

604 of 780 new or added lines in 24 files covered. (77.44%)

96 existing lines in 11 files now uncovered.

38005 of 61310 relevant lines covered (61.99%)

1006.39 hits per line

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

80.3
/opt/src/transformations/loop_split.cpp
1
#include "sdfg/transformations/loop_split.h"
2

3
#include "sdfg/analysis/scope_analysis.h"
4
#include "sdfg/builder/structured_sdfg_builder.h"
5
#include "sdfg/deepcopy/structured_sdfg_deep_copy.h"
6
#include "sdfg/structured_control_flow/for.h"
7
#include "sdfg/structured_control_flow/map.h"
8
#include "sdfg/structured_control_flow/sequence.h"
9
#include "sdfg/symbolic/symbolic.h"
10

11
namespace sdfg {
12
namespace transformations {
13

14
LoopSplit::LoopSplit(structured_control_flow::StructuredLoop& loop, const symbolic::Expression& split_point)
15
    : loop_(loop), split_point_(split_point) {};
9✔
16

17
std::string LoopSplit::name() const { return "LoopSplit"; };
3✔
18

19
bool LoopSplit::can_be_applied(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
7✔
20
    // Loop must be contiguous (unit stride)
21
    if (!loop_.is_contiguous()) {
7✔
22
        return false;
1✔
23
    }
1✔
24

25
    // Loop must have a canonical bound (well-formed upper bound)
26
    auto bound = loop_.canonical_bound();
6✔
27
    if (bound == SymEngine::null) {
6✔
28
        return false;
×
29
    }
×
30

31
    // split_point must not be null
32
    if (split_point_ == SymEngine::null) {
6✔
33
        return false;
×
34
    }
×
35

36
    return true;
6✔
37
};
6✔
38

39
void LoopSplit::apply(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
5✔
40
    auto& sdfg = builder.subject();
5✔
41

42
    auto indvar = loop_.indvar();
5✔
43
    auto condition = loop_.condition();
5✔
44
    auto init = loop_.init();
5✔
45
    auto update = loop_.update();
5✔
46
    auto bound = loop_.canonical_bound();
5✔
47

48
    // Get parent scope
49
    auto parent = static_cast<structured_control_flow::Sequence*>(loop_.get_parent());
5✔
50

51
    // Create the first loop (before the original): for (i = init; i < split_point && original_cond; i++)
52
    //
53
    // We conjoin the original loop condition so that downstream symbolic
54
    // analysis (assumptions, MLA delinearization) sees the FULL bound on the
55
    // in-panel iteration space, not just the split point. Without this, when
56
    // `split_point` may exceed the original upper bound (a runtime-dependent
57
    // case), the in-panel loop's effective range would be unrepresentable in
58
    // the symbolic model.
59
    auto first_condition = symbolic::And(symbolic::Lt(indvar, split_point_), condition);
5✔
60

61
    structured_control_flow::StructuredLoop* first_loop = nullptr;
5✔
62
    if (auto map = dynamic_cast<structured_control_flow::Map*>(&loop_)) {
5✔
63
        first_loop = &builder.add_map_before(
×
64
            *parent, loop_, indvar, first_condition, init, update, map->schedule_type(), {}, loop_.debug_info()
×
65
        );
×
66
    } else {
5✔
67
        first_loop =
5✔
68
            &builder.add_for_before(*parent, loop_, indvar, first_condition, init, update, {}, loop_.debug_info());
5✔
69
    }
5✔
70

71
    // Deep copy the original loop body into the first loop
72
    deepcopy::StructuredSDFGDeepCopy deep_copy(builder, first_loop->root(), loop_.root());
5✔
73
    deep_copy.insert();
5✔
74

75
    // Give the first loop a fresh induction variable (to avoid name collision)
76
    std::string new_indvar_name = builder.find_new_name(indvar->get_name());
5✔
77
    builder.add_container(new_indvar_name, sdfg.type(indvar->get_name()));
5✔
78
    first_loop->replace(indvar, symbolic::symbol(new_indvar_name));
5✔
79

80
    // Update the original loop to start at split_point: for (i = split_point; i < bound; i++)
81
    builder.update_loop(loop_, indvar, condition, split_point_, update);
5✔
82

83
    analysis_manager.invalidate_all();
5✔
84
};
5✔
85

86
void LoopSplit::to_json(nlohmann::json& j) const {
2✔
87
    j["transformation_type"] = this->name();
2✔
88
    j["parameters"] = nlohmann::json::object();
2✔
89
    j["parameters"] = {{"split_point", split_point_->__str__()}};
2✔
90

91
    serializer::JSONSerializer ser_flat(false);
2✔
92
    j["subgraph"] = nlohmann::json::object();
2✔
93
    j["subgraph"]["0"] = nlohmann::json::object();
2✔
94
    ser_flat.serialize_node(j["subgraph"]["0"], loop_);
2✔
95
};
2✔
96

97
LoopSplit LoopSplit::from_json(builder::StructuredSDFGBuilder& builder, const nlohmann::json& desc) {
1✔
98
    auto loop_id = desc["subgraph"]["0"]["element_id"].get<size_t>();
1✔
99
    auto split_point_str = desc["parameters"]["split_point"].get<std::string>();
1✔
100

101
    auto element = builder.find_element_by_id(loop_id);
1✔
102
    if (element == nullptr) {
1✔
UNCOV
103
        throw InvalidTransformationDescriptionException("Element with ID " + std::to_string(loop_id) + " not found.");
×
UNCOV
104
    }
×
105

106
    auto loop = dynamic_cast<structured_control_flow::StructuredLoop*>(element);
1✔
107
    if (loop == nullptr) {
1✔
UNCOV
108
        throw InvalidTransformationDescriptionException(
×
UNCOV
109
            "Element with ID " + std::to_string(loop_id) + " is not a StructuredLoop."
×
UNCOV
110
        );
×
UNCOV
111
    }
×
112

113
    auto split_point = symbolic::parse(split_point_str);
1✔
114
    return LoopSplit(*loop, split_point);
1✔
115
};
1✔
116

117
} // namespace transformations
118
} // 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