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

daisytuner / sdfglib / 17075880734

19 Aug 2025 04:32PM UTC coverage: 63.863% (-1.7%) from 65.547%
17075880734

push

github

web-flow
Merge pull request #202 from daisytuner/ml-nodes

adds element-wise ml nodes

94 of 506 new or added lines in 22 files covered. (18.58%)

2 existing lines in 1 file now uncovered.

9239 of 14467 relevant lines covered (63.86%)

124.6 hits per line

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

43.51
/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✔
NEW
31
        return false;
×
32
    }
33
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
2✔
34
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
2✔
35

36
    auto& input = this->inputs_.at(0);
2✔
37
    auto& output = this->outputs_.at(0);
2✔
38

39
    auto& iedge = *dataflow.in_edges(*this).begin();
2✔
40
    auto& oedge = *dataflow.out_edges(*this).begin();
2✔
41

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

49
    // Add new graph after the current block
50
    auto& new_sequence = builder.add_sequence_before(parent, block, block.debug_info()).first;
2✔
51

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

62
        std::string indvar_str = builder.find_new_name("_i");
4✔
63
        builder.add_container(indvar_str, types::Scalar(types::PrimitiveType::UInt64));
4✔
64

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

81
        new_subset.push_back(indvar);
4✔
82
    }
4✔
83

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

98
    // Clean up block
99
    builder.remove_memlet(block, iedge);
2✔
100
    builder.remove_memlet(block, oedge);
2✔
101
    builder.remove_node(block, input_node);
2✔
102
    builder.remove_node(block, output_node);
2✔
103
    builder.remove_node(block, *this);
2✔
104
    builder.remove_child(parent, block);
2✔
105

106
    return true;
2✔
107
}
2✔
108

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

NEW
120
void ElementWiseBinaryNode::validate(const Function& function) const {
×
121
    // TODO: Implement
NEW
122
}
×
123

NEW
124
bool ElementWiseBinaryNode::expand(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
×
NEW
125
    auto& dataflow = this->get_parent();
×
NEW
126
    auto& block = static_cast<structured_control_flow::Block&>(*dataflow.get_parent());
×
NEW
127
    if (dataflow.in_degree(*this) != 1 || dataflow.out_degree(*this) != 1) {
×
NEW
128
        return false;
×
129
    }
NEW
130
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
×
NEW
131
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
×
NEW
132
    auto& input_a = this->inputs_.at(0);
×
NEW
133
    auto& input_b = this->inputs_.at(1);
×
NEW
134
    auto& output = this->outputs_.at(0);
×
135

NEW
136
    auto iedge_a = &(*dataflow.in_edges(*this).begin());
×
NEW
137
    auto iedge_b = &(*(++dataflow.in_edges(*this).begin()));
×
NEW
138
    if (iedge_a->dst_conn() != "A") {
×
NEW
139
        std::swap(iedge_a, iedge_b);
×
NEW
140
    }
×
NEW
141
    auto& oedge = *dataflow.out_edges(*this).begin();
×
142

143
    // Checks if legal
NEW
144
    auto& input_node_a = static_cast<data_flow::AccessNode&>(iedge_a->src());
×
NEW
145
    auto& input_node_b = static_cast<data_flow::AccessNode&>(iedge_b->src());
×
NEW
146
    auto& output_node = static_cast<data_flow::AccessNode&>(oedge.dst());
×
NEW
147
    if (dataflow.in_degree(input_node_a) != 0 || dataflow.in_degree(input_node_b) != 0 ||
×
NEW
148
        dataflow.out_degree(output_node) != 0) {
×
NEW
149
        return false;
×
150
    }
151

152
    // Add new graph after the current block
NEW
153
    auto& new_sequence = builder.add_sequence_before(parent, block, block.debug_info()).first;
×
154

155
    // Add maps
NEW
156
    auto& begin_subsets_out = oedge.begin_subset();
×
NEW
157
    auto& end_subsets_out = oedge.end_subset();
×
NEW
158
    data_flow::Subset new_subset;
×
NEW
159
    structured_control_flow::Sequence* last_scope = &new_sequence;
×
NEW
160
    structured_control_flow::Map* last_map = nullptr;
×
NEW
161
    for (size_t i = 0; i < begin_subsets_out.size(); i++) {
×
NEW
162
        auto& dim_begin = begin_subsets_out[i];
×
NEW
163
        auto& dim_end = end_subsets_out[i];
×
164

NEW
165
        std::string indvar_str = builder.find_new_name("_i");
×
NEW
166
        builder.add_container(indvar_str, types::Scalar(types::PrimitiveType::UInt64));
×
167

NEW
168
        auto indvar = symbolic::symbol(indvar_str);
×
NEW
169
        auto init = dim_begin;
×
NEW
170
        auto update = symbolic::add(indvar, symbolic::one());
×
NEW
171
        auto condition = symbolic::Lt(indvar, symbolic::add(dim_end, symbolic::one()));
×
NEW
172
        last_map = &builder.add_map(
×
NEW
173
            *last_scope,
×
174
            indvar,
175
            condition,
176
            init,
177
            update,
178
            structured_control_flow::ScheduleType_Sequential,
NEW
179
            {},
×
NEW
180
            block.debug_info()
×
181
        );
NEW
182
        last_scope = &last_map->root();
×
183

NEW
184
        new_subset.push_back(indvar);
×
NEW
185
    }
×
186

NEW
187
    bool success = this->expand_operation(
×
NEW
188
        builder,
×
NEW
189
        analysis_manager,
×
NEW
190
        *last_scope,
×
NEW
191
        input_node_a.data(),
×
NEW
192
        input_node_b.data(),
×
NEW
193
        output_node.data(),
×
NEW
194
        iedge_a->base_type(),
×
NEW
195
        iedge_b->base_type(),
×
NEW
196
        oedge.base_type(),
×
197
        new_subset
198
    );
NEW
199
    if (!success) {
×
NEW
200
        return false;
×
201
    }
202

203
    // Clean up block
NEW
204
    builder.remove_memlet(block, *iedge_a);
×
NEW
205
    builder.remove_memlet(block, *iedge_b);
×
NEW
206
    builder.remove_memlet(block, oedge);
×
NEW
207
    builder.remove_node(block, input_node_a);
×
NEW
208
    builder.remove_node(block, input_node_b);
×
NEW
209
    builder.remove_node(block, output_node);
×
NEW
210
    builder.remove_node(block, *this);
×
NEW
211
    builder.remove_child(parent, block);
×
212

NEW
213
    return true;
×
NEW
214
}
×
215

216
} // namespace ml
217
} // namespace math
218
} // 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