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

daisytuner / sdfglib / 15206954197

23 May 2025 09:24AM UTC coverage: 60.604% (+0.1%) from 60.482%
15206954197

Pull #26

github

web-flow
Merge 14900737f into aa7d2127d
Pull Request #26: Develop Map node

254 of 387 new or added lines in 26 files covered. (65.63%)

17 existing lines in 14 files now uncovered.

8264 of 13636 relevant lines covered (60.6%)

101.91 hits per line

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

78.95
/src/passes/structured_control_flow/for2map.cpp
1
#include "sdfg/passes/structured_control_flow/for2map.h"
2

3
#include "sdfg/analysis/data_parallelism_analysis.h"
4
#include "sdfg/structured_control_flow/for.h"
5
#include "sdfg/structured_control_flow/map.h"
6
#include "sdfg/structured_control_flow/sequence.h"
7
#include "sdfg/symbolic/symbolic.h"
8
#include "symengine/basic.h"
9
#include "symengine/logic.h"
10
#include "symengine/symengine_rcp.h"
11

12
namespace sdfg {
13
namespace passes {
14

15
For2Map::For2Map()
6✔
16
    : Pass() {
6✔
17

18
      };
6✔
19

NEW
20
std::string For2Map::name() { return "For2Map"; };
×
21

22
symbolic::Expression For2Map::num_iterations(const structured_control_flow::For& for_stmt,
6✔
23
                                             analysis::AnalysisManager& analysis_manager) const {
24
    // Criterion: loop must be data-parallel w.r.t containers
25
    auto& analysis = analysis_manager.get<analysis::DataParallelismAnalysis>();
6✔
26
    auto& dependencies = analysis.get(for_stmt);
6✔
27
    if (dependencies.size() == 0) {
6✔
NEW
28
        return symbolic::zero();
×
29
    }
30

31
    // Criterion: update must be normalizable (i.e., it may not be involved in anything but an
32
    // addition during the update)
33
    auto& index_var = for_stmt.indvar();
6✔
34
    auto& update = for_stmt.update();
6✔
35
    auto& init = for_stmt.init();
6✔
36

37
    bool normalizable_update = symbolic::eq(
6✔
38
        symbolic::subs(update, index_var, symbolic::one()),
6✔
39
        symbolic::add(symbolic::subs(update, index_var, symbolic::zero()), symbolic::one()));
6✔
40

41
    if (!normalizable_update) {
6✔
42
        return symbolic::zero();
1✔
43
    }
44

45
    auto stride = symbolic::subs(update, index_var, symbolic::zero());
5✔
46

47
    // Criterion: loop bound must be simple, less than or equal statement (e.g., i < N)
48

49
    auto condition = symbolic::rearrange_simple_condition(for_stmt.condition(), index_var);
5✔
50

51
    symbolic::Expression bound;
5✔
52
    bool is_strict = false;
5✔
53
    symbolic::Expression lhs;
5✔
54
    symbolic::Expression rhs;
5✔
55
    if (SymEngine::is_a<SymEngine::LessThan>(*condition)) {
5✔
NEW
56
        auto condition_LE = SymEngine::rcp_dynamic_cast<const SymEngine::LessThan>(condition);
×
NEW
57
        lhs = condition_LE->get_arg1();
×
NEW
58
        rhs = condition_LE->get_arg2();
×
59
    } else if (SymEngine::is_a<SymEngine::StrictLessThan>(*condition)) {
5✔
60
        auto condition_LT = SymEngine::rcp_dynamic_cast<const SymEngine::StrictLessThan>(condition);
5✔
61
        lhs = condition_LT->get_arg1();
5✔
62
        rhs = condition_LT->get_arg2();
5✔
63
        is_strict = true;
5✔
64
    } else {
5✔
NEW
65
        return symbolic::zero();
×
66
    }
67

68
    if (symbolic::eq(lhs, index_var)) {
5✔
69
        bound = rhs;
4✔
70
    } else {
4✔
71
        return symbolic::zero();
1✔
72
    }
73

74
    if (!is_strict) {
4✔
NEW
75
        bound = symbolic::add(bound, symbolic::one());
×
NEW
76
    }
×
77

78
    // subtract the init value from the bound
79
    bound = symbolic::sub(bound, init);
4✔
80

81
    symbolic::Expression num_iterations;
4✔
82

83
    if (symbolic::eq(stride, symbolic::one())) {
4✔
84
        num_iterations = bound;
3✔
85
    } else if (symbolic::eq(stride, symbolic::zero())) {
4✔
NEW
86
        throw std::runtime_error("Stride is zero");
×
87
    } else {
88
        num_iterations = symbolic::ceil(symbolic::div(bound, stride));
1✔
89
    }
90

91
    return num_iterations;
4✔
92
}
10✔
93

94
bool For2Map::run_pass(builder::StructuredSDFGBuilder& builder,
6✔
95
                       analysis::AnalysisManager& analysis_manager) {
96
    bool applied = false;
6✔
97

98
    auto& sdfg = builder.subject();
6✔
99

100
    auto& root = sdfg.root();
6✔
101
    if (root.size() == 0) {
6✔
NEW
102
        return false;
×
103
    }
104

105
    std::list<structured_control_flow::Sequence*> queue = {&sdfg.root()};
6✔
106
    while (!queue.empty()) {
18✔
107
        auto curr = queue.front();
12✔
108
        queue.pop_front();
12✔
109

110
        for (size_t i = 0; i < curr->size(); i++) {
24✔
111
            auto& child = curr->at(i).first;
12✔
112

113
            if (auto if_else_stmt = dynamic_cast<structured_control_flow::IfElse*>(&child)) {
12✔
114
                // Add to queue
NEW
115
                for (size_t j = 0; j < if_else_stmt->size(); j++) {
×
NEW
116
                    queue.push_back(&if_else_stmt->at(j).first);
×
NEW
117
                }
×
118
            } else if (auto loop_stmt = dynamic_cast<structured_control_flow::While*>(&child)) {
12✔
NEW
119
                auto& root = loop_stmt->root();
×
NEW
120
                queue.push_back(&root);
×
121
            } else if (auto for_stmt = dynamic_cast<structured_control_flow::For*>(&child)) {
12✔
122
                auto num_iterations = this->num_iterations(*for_stmt, analysis_manager);
6✔
123
                if (symbolic::eq(num_iterations, symbolic::zero())) {
6✔
124
                    auto& root = for_stmt->root();
2✔
125
                    queue.push_back(&root);
2✔
126
                    continue;
2✔
127
                }
128

129
                auto init = for_stmt->init();
4✔
130
                auto indvar = for_stmt->indvar();
4✔
131
                auto update = for_stmt->update();
4✔
132

133
                // Create map
134
                auto& map = builder.convert_for(*curr, *for_stmt, num_iterations);
4✔
135
                auto& root = map.root();
4✔
136
                auto stride = symbolic::subs(update, indvar, symbolic::zero());
4✔
137

138
                auto replacement = symbolic::add(symbolic::mul(map.indvar(), stride), init);
4✔
139
                root.replace(map.indvar(), replacement);
4✔
140

141
                queue.push_back(&root);
4✔
142
                applied = true;
4✔
143

144
            } else if (auto kernel_stmt = dynamic_cast<structured_control_flow::Kernel*>(&child)) {
12✔
NEW
145
                auto& root = kernel_stmt->root();
×
NEW
146
                queue.push_back(&root);
×
147
            } else if (auto map_stmt = dynamic_cast<structured_control_flow::Map*>(&child)) {
6✔
NEW
148
                auto& root = map_stmt->root();
×
NEW
149
                queue.push_back(&root);
×
NEW
150
            }
×
151
        }
10✔
152
    }
153

154
    return applied;
6✔
155
}
6✔
156

157
}  // namespace passes
158
}  // 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