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

daisytuner / sdfglib / 17651658650

11 Sep 2025 04:58PM UTC coverage: 61.012% (+1.3%) from 59.755%
17651658650

Pull #219

github

web-flow
Merge 742a12367 into f744ac9f5
Pull Request #219: stdlib Library Nodes and ConstantNodes

499 of 1681 new or added lines in 81 files covered. (29.68%)

95 existing lines in 36 files now uncovered.

9718 of 15928 relevant lines covered (61.01%)

108.0 hits per line

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

37.25
/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 DebugInfoRegion& debug_info,
15
    const graph::Vertex vertex,
16
    data_flow::DataFlowGraph& parent,
17
    const data_flow::LibraryNodeCode& code,
18
    const std::vector<symbolic::Expression>& shape,
19
    const std::unordered_map<std::string, std::string>& attributes
20
)
21
    : MathNode(element_id, debug_info, vertex, parent, code, {"Y"}, {"X"}, data_flow::ImplementationType_NONE),
5✔
22
      shape_(shape), attributes_(attributes) {}
5✔
23

NEW
24
symbolic::SymbolSet ElementWiseUnaryNode::symbols() const {
×
NEW
25
    symbolic::SymbolSet syms;
×
NEW
26
    for (const auto& dim : shape_) {
×
NEW
27
        for (auto& atom : symbolic::atoms(dim)) {
×
NEW
28
            syms.insert(atom);
×
29
        }
30
    }
NEW
31
    return syms;
×
NEW
32
}
×
33

NEW
34
void ElementWiseUnaryNode::replace(const symbolic::Expression& old_expression, const symbolic::Expression& new_expression) {
×
NEW
35
    for (auto& dim : shape_) {
×
NEW
36
        dim = symbolic::subs(dim, old_expression, new_expression);
×
37
    }
UNCOV
38
}
×
39

40
void ElementWiseUnaryNode::validate(const Function& function) const {}
6✔
41

42
bool ElementWiseUnaryNode::expand(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
2✔
43
    auto& dataflow = this->get_parent();
2✔
44
    auto& block = static_cast<structured_control_flow::Block&>(*dataflow.get_parent());
2✔
45
    if (dataflow.in_degree(*this) != 1 || dataflow.out_degree(*this) != 1) {
2✔
46
        return false;
×
47
    }
48

49
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
2✔
50
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
2✔
51
    int index = parent.index(block);
2✔
52
    auto& transition = parent.at(index).second;
2✔
53

54
    auto& input = this->inputs_.at(0);
2✔
55
    auto& output = this->outputs_.at(0);
2✔
56

57
    auto& iedge = *dataflow.in_edges(*this).begin();
2✔
58
    auto& oedge = *dataflow.out_edges(*this).begin();
2✔
59

60
    // Checks if legal
61
    auto& input_node = static_cast<data_flow::AccessNode&>(iedge.src());
2✔
62
    auto& output_node = static_cast<data_flow::AccessNode&>(oedge.dst());
2✔
63
    if (dataflow.in_degree(input_node) != 0 || dataflow.out_degree(output_node) != 0) {
2✔
64
        return false;
×
65
    }
66

67
    // Add new graph after the current block
68
    auto& new_sequence = builder.add_sequence_before(
2✔
69
        parent, block, transition.assignments(), builder.debug_info().get_region(block.debug_info().indices())
2✔
70
    );
71

72
    // Add maps
73
    data_flow::Subset new_subset;
2✔
74
    structured_control_flow::Sequence* last_scope = &new_sequence;
2✔
75
    structured_control_flow::Map* last_map = nullptr;
2✔
76
    for (size_t i = 0; i < this->shape_.size(); i++) {
6✔
77
        std::string indvar_str = builder.find_new_name("_i");
4✔
78
        builder.add_container(indvar_str, types::Scalar(types::PrimitiveType::UInt64));
4✔
79

80
        auto indvar = symbolic::symbol(indvar_str);
4✔
81
        auto init = symbolic::zero();
4✔
82
        auto update = symbolic::add(indvar, symbolic::one());
4✔
83
        auto condition = symbolic::Lt(indvar, this->shape_[i]);
4✔
84
        last_map = &builder.add_map(
8✔
85
            *last_scope,
4✔
86
            indvar,
87
            condition,
88
            init,
4✔
89
            update,
90
            structured_control_flow::ScheduleType_Sequential::create(),
4✔
91
            {},
4✔
92
            builder.debug_info().get_region(block.debug_info().indices())
4✔
93
        );
94
        last_scope = &last_map->root();
4✔
95

96
        new_subset.push_back(indvar);
4✔
97
    }
4✔
98

99
    bool success = this->expand_operation(
2✔
100
        builder,
2✔
101
        analysis_manager,
2✔
102
        *last_scope,
2✔
103
        input_node.data(),
2✔
104
        output_node.data(),
2✔
105
        iedge.base_type(),
2✔
106
        oedge.base_type(),
2✔
107
        new_subset
108
    );
109
    if (!success) {
2✔
110
        return false;
×
111
    }
112

113
    // Clean up block
114
    builder.remove_memlet(block, iedge);
2✔
115
    builder.remove_memlet(block, oedge);
2✔
116
    builder.remove_node(block, input_node);
2✔
117
    builder.remove_node(block, output_node);
2✔
118
    builder.remove_node(block, *this);
2✔
119
    builder.remove_child(parent, index + 1);
2✔
120

121
    return true;
2✔
122
}
2✔
123

124
ElementWiseBinaryNode::ElementWiseBinaryNode(
×
125
    size_t element_id,
126
    const DebugInfoRegion& debug_info,
127
    const graph::Vertex vertex,
128
    data_flow::DataFlowGraph& parent,
129
    const data_flow::LibraryNodeCode& code,
130
    const std::vector<symbolic::Expression>& shape,
131
    const std::unordered_map<std::string, std::string>& attributes
132
)
133
    : MathNode(element_id, debug_info, vertex, parent, code, {"C"}, {"A", "B"}, data_flow::ImplementationType_NONE),
×
NEW
134
      shape_(shape), attributes_(attributes) {}
×
135

NEW
136
symbolic::SymbolSet ElementWiseBinaryNode::symbols() const {
×
NEW
137
    symbolic::SymbolSet syms;
×
NEW
138
    for (const auto& dim : shape_) {
×
NEW
139
        for (auto& atom : symbolic::atoms(dim)) {
×
NEW
140
            syms.insert(atom);
×
141
        }
142
    }
NEW
143
    return syms;
×
NEW
144
}
×
145

NEW
146
void ElementWiseBinaryNode::replace(const symbolic::Expression& old_expression, const symbolic::Expression& new_expression) {
×
NEW
147
    for (auto& dim : shape_) {
×
NEW
148
        dim = symbolic::subs(dim, old_expression, new_expression);
×
149
    }
UNCOV
150
}
×
151

NEW
152
void ElementWiseBinaryNode::validate(const Function& function) const {}
×
153

154
bool ElementWiseBinaryNode::expand(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
×
155
    auto& dataflow = this->get_parent();
×
156
    auto& block = static_cast<structured_control_flow::Block&>(*dataflow.get_parent());
×
157
    if (dataflow.in_degree(*this) != 1 || dataflow.out_degree(*this) != 1) {
×
158
        return false;
×
159
    }
160
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
×
161
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
×
162
    int index = parent.index(block);
×
163
    auto& transition = parent.at(index).second;
×
164

165
    auto& input_a = this->inputs_.at(0);
×
166
    auto& input_b = this->inputs_.at(1);
×
167
    auto& output = this->outputs_.at(0);
×
168

169
    auto iedge_a = &(*dataflow.in_edges(*this).begin());
×
170
    auto iedge_b = &(*(++dataflow.in_edges(*this).begin()));
×
171
    if (iedge_a->dst_conn() != "A") {
×
172
        std::swap(iedge_a, iedge_b);
×
173
    }
×
174
    auto& oedge = *dataflow.out_edges(*this).begin();
×
175

176
    // Checks if legal
177
    auto& input_node_a = static_cast<data_flow::AccessNode&>(iedge_a->src());
×
178
    auto& input_node_b = static_cast<data_flow::AccessNode&>(iedge_b->src());
×
179
    auto& output_node = static_cast<data_flow::AccessNode&>(oedge.dst());
×
180
    if (dataflow.in_degree(input_node_a) != 0 || dataflow.in_degree(input_node_b) != 0 ||
×
181
        dataflow.out_degree(output_node) != 0) {
×
182
        return false;
×
183
    }
184

185
    // Add new graph after the current block
186
    auto& new_sequence = builder.add_sequence_before(
×
187
        parent, block, transition.assignments(), builder.debug_info().get_region(block.debug_info().indices())
×
188
    );
189

190
    // Add maps
191
    data_flow::Subset new_subset;
×
192
    structured_control_flow::Sequence* last_scope = &new_sequence;
×
193
    structured_control_flow::Map* last_map = nullptr;
×
NEW
194
    for (size_t i = 0; i < this->shape_.size(); i++) {
×
195
        std::string indvar_str = builder.find_new_name("_i");
×
196
        builder.add_container(indvar_str, types::Scalar(types::PrimitiveType::UInt64));
×
197

198
        auto indvar = symbolic::symbol(indvar_str);
×
NEW
199
        auto init = symbolic::zero();
×
200
        auto update = symbolic::add(indvar, symbolic::one());
×
NEW
201
        auto condition = symbolic::Lt(indvar, this->shape_[i]);
×
202
        last_map = &builder.add_map(
×
203
            *last_scope,
×
204
            indvar,
205
            condition,
UNCOV
206
            init,
×
207
            update,
208
            structured_control_flow::ScheduleType_Sequential::create(),
×
209
            {},
×
210
            builder.debug_info().get_region(block.debug_info().indices())
×
211
        );
212
        last_scope = &last_map->root();
×
213

214
        new_subset.push_back(indvar);
×
215
    }
×
216

217
    bool success = this->expand_operation(
×
218
        builder,
×
219
        analysis_manager,
×
220
        *last_scope,
×
221
        input_node_a.data(),
×
222
        input_node_b.data(),
×
223
        output_node.data(),
×
224
        iedge_a->base_type(),
×
225
        iedge_b->base_type(),
×
226
        oedge.base_type(),
×
227
        new_subset
228
    );
229
    if (!success) {
×
230
        return false;
×
231
    }
232

233
    // Clean up block
234
    builder.remove_memlet(block, *iedge_a);
×
235
    builder.remove_memlet(block, *iedge_b);
×
236
    builder.remove_memlet(block, oedge);
×
237
    builder.remove_node(block, input_node_a);
×
238
    builder.remove_node(block, input_node_b);
×
239
    builder.remove_node(block, output_node);
×
240
    builder.remove_node(block, *this);
×
241
    builder.remove_child(parent, index + 1);
×
242

243
    return true;
×
244
}
×
245

246
} // namespace ml
247
} // namespace math
248
} // 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