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

daisytuner / sdfglib / 20621841097

31 Dec 2025 03:18PM UTC coverage: 39.655% (-0.06%) from 39.712%
20621841097

Pull #421

github

web-flow
Merge 7662c1b88 into 3b72c335e
Pull Request #421: Extend tensor library nodes with primitive type support and refactor CMathNode to use enums

14996 of 49220 branches covered (30.47%)

Branch coverage included in aggregate %.

247 of 608 new or added lines in 52 files covered. (40.63%)

38 existing lines in 5 files now uncovered.

12874 of 21062 relevant lines covered (61.12%)

89.39 hits per line

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

0.0
/src/data_flow/library_nodes/math/tensor/broadcast_node.cpp
1
#include "sdfg/data_flow/library_nodes/math/tensor/broadcast_node.h"
2
#include "sdfg/analysis/scope_analysis.h"
3
#include "sdfg/builder/structured_sdfg_builder.h"
4
#include "sdfg/structured_control_flow/for.h"
5

6
namespace sdfg {
7
namespace math {
8
namespace tensor {
9

10
BroadcastNode::BroadcastNode(
×
11
    size_t element_id,
12
    const DebugInfo& debug_info,
13
    const graph::Vertex vertex,
14
    data_flow::DataFlowGraph& parent,
15
    const std::vector<symbolic::Expression>& input_shape,
16
    const std::vector<symbolic::Expression>& output_shape
17
)
NEW
18
    : TensorNode(
×
19
          element_id,
×
20
          debug_info,
×
21
          vertex,
×
22
          parent,
×
23
          LibraryNodeType_Broadcast,
24
          {"Y"},
×
25
          {"X"},
×
UNCOV
26
          data_flow::ImplementationType_NONE
×
27
      ),
28
      input_shape_(input_shape), output_shape_(output_shape) {}
×
29

30
symbolic::SymbolSet BroadcastNode::symbols() const {
×
31
    symbolic::SymbolSet syms;
×
32
    for (const auto& dim : input_shape_) {
×
33
        for (auto& atom : symbolic::atoms(dim)) {
×
34
            syms.insert(atom);
×
35
        }
36
    }
37
    for (const auto& dim : output_shape_) {
×
38
        for (auto& atom : symbolic::atoms(dim)) {
×
39
            syms.insert(atom);
×
40
        }
41
    }
42
    return syms;
×
43
}
×
44

45
void BroadcastNode::replace(const symbolic::Expression old_expression, const symbolic::Expression new_expression) {
×
46
    for (auto& dim : input_shape_) {
×
47
        dim = symbolic::subs(dim, old_expression, new_expression);
×
48
    }
49
    for (auto& dim : output_shape_) {
×
50
        dim = symbolic::subs(dim, old_expression, new_expression);
×
51
    }
52
}
×
53

54
bool BroadcastNode::expand(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
×
UNCOV
55
    auto& dataflow = this->get_parent();
×
56
    auto& block = static_cast<structured_control_flow::Block&>(*dataflow.get_parent());
×
57

58
    if (dataflow.in_degree(*this) != 1 || dataflow.out_degree(*this) != 1) {
×
59
        return false;
×
60
    }
61

62
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
×
63
    auto& parent = static_cast<structured_control_flow::Sequence&>(*scope_analysis.parent_scope(&block));
×
64

65
    auto& in_edge = *dataflow.in_edges(*this).begin();
×
66
    auto& out_edge = *dataflow.out_edges(*this).begin();
×
67
    auto& in_node = static_cast<data_flow::AccessNode&>(in_edge.src());
×
68
    auto& out_node = static_cast<data_flow::AccessNode&>(out_edge.dst());
×
69

70
    symbolic::SymbolVec loop_vars;
×
71
    structured_control_flow::Sequence* inner_scope = nullptr;
×
72

73
    for (size_t i = 0; i < output_shape_.size(); ++i) {
×
74
        std::string var_name = builder.find_new_name("_i" + std::to_string(i));
×
75
        builder.add_container(var_name, types::Scalar(types::PrimitiveType::Int64));
×
76

77
        auto sym_var = symbolic::symbol(var_name);
×
78
        auto condition = symbolic::Lt(sym_var, output_shape_[i]);
×
79
        auto init = symbolic::zero();
×
80
        auto update = symbolic::add(sym_var, symbolic::one());
×
81

82
        if (i == 0) {
×
83
            auto& loop = builder.add_map_before(
×
84
                parent,
×
85
                block,
×
86
                sym_var,
×
87
                condition,
×
88
                init,
×
89
                update,
×
90
                structured_control_flow::ScheduleType_Sequential::create(),
×
91
                {},
×
92
                this->debug_info()
×
93
            );
94
            inner_scope = &loop.root();
×
95
        } else {
×
96
            auto& loop = builder.add_map(
×
97
                *inner_scope,
×
98
                sym_var,
×
99
                condition,
×
100
                init,
×
101
                update,
×
102
                structured_control_flow::ScheduleType_Sequential::create(),
×
103
                {},
×
104
                this->debug_info()
×
105
            );
106
            inner_scope = &loop.root();
×
107
        }
108
        loop_vars.push_back(sym_var);
×
109
    }
×
110

111
    auto& tasklet_block = builder.add_block(*inner_scope, {}, this->debug_info());
×
112

113
    auto& in_acc = builder.add_access(tasklet_block, in_node.data());
×
114
    auto& out_acc = builder.add_access(tasklet_block, out_node.data());
×
115

116
    auto& tasklet =
×
117
        builder.add_tasklet(tasklet_block, data_flow::TaskletCode::assign, "_out", {"_in"}, this->debug_info());
×
118

119
    symbolic::Expression input_linear_index = symbolic::zero();
×
120
    for (size_t i = 0; i < input_shape_.size(); ++i) {
×
121
        if (!symbolic::eq(input_shape_[i], symbolic::one())) {
×
122
            input_linear_index = symbolic::add(symbolic::mul(input_linear_index, input_shape_[i]), loop_vars[i]);
×
123
        }
×
124
    }
×
125

126
    symbolic::Expression output_linear_index = symbolic::zero();
×
127
    for (size_t i = 0; i < output_shape_.size(); ++i) {
×
128
        output_linear_index = symbolic::add(symbolic::mul(output_linear_index, output_shape_[i]), loop_vars[i]);
×
129
    }
×
130

131
    data_flow::Subset input_subset;
×
132
    if (in_edge.base_type().type_id() != types::TypeID::Scalar) {
×
133
        input_subset = {input_linear_index};
×
134
    }
×
135
    data_flow::Subset output_subset;
×
136
    if (out_edge.base_type().type_id() != types::TypeID::Scalar) {
×
137
        output_subset = {output_linear_index};
×
138
    }
×
139
    builder.add_computational_memlet(
×
140
        tasklet_block, in_acc, tasklet, "_in", input_subset, in_edge.base_type(), this->debug_info()
×
141
    );
142
    builder.add_computational_memlet(
×
143
        tasklet_block, tasklet, "_out", out_acc, output_subset, out_edge.base_type(), this->debug_info()
×
144
    );
145

146
    builder.remove_memlet(block, in_edge);
×
147
    builder.remove_memlet(block, out_edge);
×
148
    builder.remove_node(block, in_node);
×
149
    builder.remove_node(block, out_node);
×
150
    builder.remove_node(block, *this);
×
151

152
    int index = parent.index(block);
×
153
    builder.remove_child(parent, index);
×
154

155
    return true;
×
156
}
×
157

158
std::unique_ptr<data_flow::DataFlowNode> BroadcastNode::
159
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph& parent) const {
×
160
    return std::unique_ptr<data_flow::DataFlowNode>(
×
161
        new BroadcastNode(element_id, this->debug_info(), vertex, parent, input_shape_, output_shape_)
×
162
    );
163
}
×
164

165
} // namespace tensor
166
} // namespace math
167
} // 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