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

daisytuner / sdfglib / 17368505925

01 Sep 2025 05:29AM UTC coverage: 58.982% (-0.8%) from 59.781%
17368505925

push

github

web-flow
Merge pull request #216 from daisytuner/transitions-bug

Updates API for Sequence transitions to prevent leakage of assignments

239 of 547 new or added lines in 25 files covered. (43.69%)

75 existing lines in 12 files now uncovered.

9190 of 15581 relevant lines covered (58.98%)

115.89 hits per line

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

43.7
/src/data_flow/library_nodes/math/ml/element_wise.cpp
1
#include "sdfg/data_flow/library_nodes/math/ml/relu.h"
2

3
#include "sdfg/analysis/analysis.h"
4
#include "sdfg/builder/structured_sdfg_builder.h"
5

6
#include "sdfg/analysis/scope_analysis.h"
7

8
namespace sdfg {
9
namespace math {
10
namespace ml {
11

12
ElementWiseUnaryNode::ElementWiseUnaryNode(
5✔
13
    size_t element_id,
14
    const DebugInfo& debug_info,
15
    const graph::Vertex vertex,
16
    data_flow::DataFlowGraph& parent,
17
    const data_flow::LibraryNodeCode& code,
18
    const std::unordered_map<std::string, std::string>& attributes
19
)
20
    : MathNode(element_id, debug_info, vertex, parent, code, {"Y"}, {"X"}, data_flow::ImplementationType_NONE),
5✔
21
      attributes_(attributes) {}
5✔
22

23
void ElementWiseUnaryNode::validate(const Function& function) const {
6✔
24
    // TODO: Implement
25
}
6✔
26

27
bool ElementWiseUnaryNode::expand(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
2✔
28
    auto& dataflow = this->get_parent();
2✔
29
    auto& block = static_cast<structured_control_flow::Block&>(*dataflow.get_parent());
2✔
30
    if (dataflow.in_degree(*this) != 1 || dataflow.out_degree(*this) != 1) {
2✔
31
        return false;
×
32
    }
33

34
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
2✔
35
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
2✔
36
    int index = parent.index(block);
2✔
37
    auto& transition = parent.at(index).second;
2✔
38

39
    auto& input = this->inputs_.at(0);
2✔
40
    auto& output = this->outputs_.at(0);
2✔
41

42
    auto& iedge = *dataflow.in_edges(*this).begin();
2✔
43
    auto& oedge = *dataflow.out_edges(*this).begin();
2✔
44

45
    // Checks if legal
46
    auto& input_node = static_cast<data_flow::AccessNode&>(iedge.src());
2✔
47
    auto& output_node = static_cast<data_flow::AccessNode&>(oedge.dst());
2✔
48
    if (dataflow.in_degree(input_node) != 0 || dataflow.out_degree(output_node) != 0) {
2✔
49
        return false;
×
50
    }
51

52
    // Add new graph after the current block
53
    auto& new_sequence = builder.add_sequence_before(parent, block, transition.assignments(), block.debug_info());
2✔
54

55
    // Add maps
56
    auto& begin_subsets_out = oedge.begin_subset();
2✔
57
    auto& end_subsets_out = oedge.end_subset();
2✔
58
    data_flow::Subset new_subset;
2✔
59
    structured_control_flow::Sequence* last_scope = &new_sequence;
2✔
60
    structured_control_flow::Map* last_map = nullptr;
2✔
61
    for (size_t i = 0; i < begin_subsets_out.size(); i++) {
6✔
62
        auto& dim_begin = begin_subsets_out[i];
4✔
63
        auto& dim_end = end_subsets_out[i];
4✔
64

65
        std::string indvar_str = builder.find_new_name("_i");
4✔
66
        builder.add_container(indvar_str, types::Scalar(types::PrimitiveType::UInt64));
4✔
67

68
        auto indvar = symbolic::symbol(indvar_str);
4✔
69
        auto init = dim_begin;
4✔
70
        auto update = symbolic::add(indvar, symbolic::one());
4✔
71
        auto condition = symbolic::Lt(indvar, symbolic::add(dim_end, symbolic::one()));
4✔
72
        last_map = &builder.add_map(
4✔
73
            *last_scope,
4✔
74
            indvar,
75
            condition,
76
            init,
77
            update,
78
            structured_control_flow::ScheduleType_Sequential,
79
            {},
4✔
80
            block.debug_info()
4✔
81
        );
82
        last_scope = &last_map->root();
4✔
83

84
        new_subset.push_back(indvar);
4✔
85
    }
4✔
86

87
    bool success = this->expand_operation(
2✔
88
        builder,
2✔
89
        analysis_manager,
2✔
90
        *last_scope,
2✔
91
        input_node.data(),
2✔
92
        output_node.data(),
2✔
93
        iedge.base_type(),
2✔
94
        oedge.base_type(),
2✔
95
        new_subset
96
    );
97
    if (!success) {
2✔
98
        return false;
×
99
    }
100

101
    // Clean up block
102
    builder.remove_memlet(block, iedge);
2✔
103
    builder.remove_memlet(block, oedge);
2✔
104
    builder.remove_node(block, input_node);
2✔
105
    builder.remove_node(block, output_node);
2✔
106
    builder.remove_node(block, *this);
2✔
107
    builder.remove_child(parent, index + 1);
2✔
108

109
    return true;
2✔
110
}
2✔
111

112
ElementWiseBinaryNode::ElementWiseBinaryNode(
×
113
    size_t element_id,
114
    const DebugInfo& debug_info,
115
    const graph::Vertex vertex,
116
    data_flow::DataFlowGraph& parent,
117
    const data_flow::LibraryNodeCode& code,
118
    const std::unordered_map<std::string, std::string>& attributes
119
)
120
    : MathNode(element_id, debug_info, vertex, parent, code, {"C"}, {"A", "B"}, data_flow::ImplementationType_NONE),
×
121
      attributes_(attributes) {}
×
122

123
void ElementWiseBinaryNode::validate(const Function& function) const {
×
124
    // TODO: Implement
125
}
×
126

127
bool ElementWiseBinaryNode::expand(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
×
128
    auto& dataflow = this->get_parent();
×
129
    auto& block = static_cast<structured_control_flow::Block&>(*dataflow.get_parent());
×
130
    if (dataflow.in_degree(*this) != 1 || dataflow.out_degree(*this) != 1) {
×
131
        return false;
×
132
    }
133
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
×
134
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
×
NEW
135
    int index = parent.index(block);
×
NEW
136
    auto& transition = parent.at(index).second;
×
137

138
    auto& input_a = this->inputs_.at(0);
×
139
    auto& input_b = this->inputs_.at(1);
×
140
    auto& output = this->outputs_.at(0);
×
141

142
    auto iedge_a = &(*dataflow.in_edges(*this).begin());
×
143
    auto iedge_b = &(*(++dataflow.in_edges(*this).begin()));
×
144
    if (iedge_a->dst_conn() != "A") {
×
145
        std::swap(iedge_a, iedge_b);
×
146
    }
×
147
    auto& oedge = *dataflow.out_edges(*this).begin();
×
148

149
    // Checks if legal
150
    auto& input_node_a = static_cast<data_flow::AccessNode&>(iedge_a->src());
×
151
    auto& input_node_b = static_cast<data_flow::AccessNode&>(iedge_b->src());
×
152
    auto& output_node = static_cast<data_flow::AccessNode&>(oedge.dst());
×
153
    if (dataflow.in_degree(input_node_a) != 0 || dataflow.in_degree(input_node_b) != 0 ||
×
154
        dataflow.out_degree(output_node) != 0) {
×
155
        return false;
×
156
    }
157

158
    // Add new graph after the current block
NEW
159
    auto& new_sequence = builder.add_sequence_before(parent, block, transition.assignments(), block.debug_info());
×
160

161
    // Add maps
162
    auto& begin_subsets_out = oedge.begin_subset();
×
163
    auto& end_subsets_out = oedge.end_subset();
×
164
    data_flow::Subset new_subset;
×
165
    structured_control_flow::Sequence* last_scope = &new_sequence;
×
166
    structured_control_flow::Map* last_map = nullptr;
×
167
    for (size_t i = 0; i < begin_subsets_out.size(); i++) {
×
168
        auto& dim_begin = begin_subsets_out[i];
×
169
        auto& dim_end = end_subsets_out[i];
×
170

171
        std::string indvar_str = builder.find_new_name("_i");
×
172
        builder.add_container(indvar_str, types::Scalar(types::PrimitiveType::UInt64));
×
173

174
        auto indvar = symbolic::symbol(indvar_str);
×
175
        auto init = dim_begin;
×
176
        auto update = symbolic::add(indvar, symbolic::one());
×
177
        auto condition = symbolic::Lt(indvar, symbolic::add(dim_end, symbolic::one()));
×
178
        last_map = &builder.add_map(
×
179
            *last_scope,
×
180
            indvar,
181
            condition,
182
            init,
183
            update,
184
            structured_control_flow::ScheduleType_Sequential,
185
            {},
×
186
            block.debug_info()
×
187
        );
188
        last_scope = &last_map->root();
×
189

190
        new_subset.push_back(indvar);
×
191
    }
×
192

193
    bool success = this->expand_operation(
×
194
        builder,
×
195
        analysis_manager,
×
196
        *last_scope,
×
197
        input_node_a.data(),
×
198
        input_node_b.data(),
×
199
        output_node.data(),
×
200
        iedge_a->base_type(),
×
201
        iedge_b->base_type(),
×
202
        oedge.base_type(),
×
203
        new_subset
204
    );
205
    if (!success) {
×
206
        return false;
×
207
    }
208

209
    // Clean up block
210
    builder.remove_memlet(block, *iedge_a);
×
211
    builder.remove_memlet(block, *iedge_b);
×
212
    builder.remove_memlet(block, oedge);
×
213
    builder.remove_node(block, input_node_a);
×
214
    builder.remove_node(block, input_node_b);
×
215
    builder.remove_node(block, output_node);
×
216
    builder.remove_node(block, *this);
×
NEW
217
    builder.remove_child(parent, index + 1);
×
218

219
    return true;
×
220
}
×
221

222
} // namespace ml
223
} // namespace math
224
} // 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