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

daisytuner / docc / 28851442347

07 Jul 2026 08:09AM UTC coverage: 62.959% (+1.3%) from 61.644%
28851442347

Pull #810

github

web-flow
Merge 768a26f80 into e7f8bfb2e
Pull Request #810: Add DOCC_REUSE_SOURCES envar to recompile the shared library from locally edited sources

37 of 46 new or added lines in 1 file covered. (80.43%)

3687 existing lines in 112 files now uncovered.

40560 of 64423 relevant lines covered (62.96%)

963.15 hits per line

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

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

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

10
namespace sdfg {
11
namespace transformations {
12

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

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

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

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

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

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

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

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

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

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

60
    structured_control_flow::StructuredLoop* first_loop = nullptr;
5✔
61
    if (auto map = dynamic_cast<structured_control_flow::Map*>(&loop_)) {
5✔
UNCOV
62
        first_loop = &builder.add_map_before(
×
63
            *parent, loop_, indvar, first_condition, init, update, map->schedule_type(), {}, loop_.debug_info()
×
64
        );
×
65
    } else if (auto reduce = dynamic_cast<structured_control_flow::Reduce*>(&loop_)) {
5✔
UNCOV
66
        first_loop = &builder.add_reduce_before(
×
UNCOV
67
            *parent,
×
UNCOV
68
            loop_,
×
UNCOV
69
            indvar,
×
UNCOV
70
            first_condition,
×
UNCOV
71
            init,
×
UNCOV
72
            update,
×
UNCOV
73
            reduce->reductions(),
×
UNCOV
74
            reduce->schedule_type(),
×
UNCOV
75
            {},
×
UNCOV
76
            loop_.debug_info()
×
UNCOV
77
        );
×
78
    } else {
5✔
79
        first_loop =
5✔
80
            &builder.add_for_before(*parent, loop_, indvar, first_condition, init, update, {}, loop_.debug_info());
5✔
81
    }
5✔
82

83
    // Deep copy the original loop body into the first loop
84
    deepcopy::StructuredSDFGDeepCopy deep_copy(builder, first_loop->root(), loop_.root());
5✔
85
    deep_copy.insert();
5✔
86

87
    // Give the first loop a fresh induction variable (to avoid name collision)
88
    std::string new_indvar_name = builder.find_new_name(indvar->get_name());
5✔
89
    builder.add_container(new_indvar_name, sdfg.type(indvar->get_name()));
5✔
90
    first_loop->replace(indvar, symbolic::symbol(new_indvar_name));
5✔
91

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

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

98
void LoopSplit::to_json(nlohmann::json& j) const {
2✔
99
    j["transformation_type"] = this->name();
2✔
100
    j["parameters"] = nlohmann::json::object();
2✔
101
    j["parameters"] = {{"split_point", split_point_->__str__()}};
2✔
102

103
    serializer::JSONSerializer ser_flat(false);
2✔
104
    j["subgraph"] = nlohmann::json::object();
2✔
105
    j["subgraph"]["0"] = nlohmann::json::object();
2✔
106
    ser_flat.serialize_node(j["subgraph"]["0"], loop_);
2✔
107
};
2✔
108

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

113
    auto element = builder.find_element_by_id(loop_id);
1✔
114
    if (element == nullptr) {
1✔
UNCOV
115
        throw InvalidTransformationDescriptionException("Element with ID " + std::to_string(loop_id) + " not found.");
×
UNCOV
116
    }
×
117

118
    auto loop = dynamic_cast<structured_control_flow::StructuredLoop*>(element);
1✔
119
    if (loop == nullptr) {
1✔
UNCOV
120
        throw InvalidTransformationDescriptionException(
×
UNCOV
121
            "Element with ID " + std::to_string(loop_id) + " is not a StructuredLoop."
×
UNCOV
122
        );
×
UNCOV
123
    }
×
124

125
    auto split_point = symbolic::parse(split_point_str);
1✔
126
    return LoopSplit(*loop, split_point);
1✔
127
};
1✔
128

129
} // namespace transformations
130
} // namespace sdfg
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc