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

daisytuner / docc / 30543265435

30 Jul 2026 12:36PM UTC coverage: 64.549% (-0.2%) from 64.738%
30543265435

Pull #913

github

web-flow
Merge 6970d8cbe into 4a519a416
Pull Request #913: delegates instrumentation event type decision to specific node dispat…

17 of 236 new or added lines in 25 files covered. (7.2%)

7 existing lines in 7 files now uncovered.

44347 of 68703 relevant lines covered (64.55%)

714.95 hits per line

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

37.56
/sdfg/src/data_flow/library_nodes/math/blas/dot_node.cpp
1
#include "sdfg/data_flow/library_nodes/math/blas/dot_node.h"
2
#include <stdexcept>
3
#include <string>
4

5
#include "sdfg/analysis/analysis.h"
6
#include "sdfg/builder/structured_sdfg_builder.h"
7

8
#include "sdfg/symbolic/symbolic.h"
9

10
namespace sdfg {
11
namespace math {
12
namespace blas {
13

14
DotNode::DotNode(
15
    size_t element_id,
16
    const DebugInfo& debug_info,
17
    const graph::Vertex vertex,
18
    data_flow::DataFlowGraph& parent,
19
    const data_flow::ImplementationType& implementation_type,
20
    const BLAS_Precision& precision,
21
    symbolic::Expression n,
22
    symbolic::Expression incx,
23
    symbolic::Expression incy
24
)
25
    : BLASNode(
13✔
26
          element_id,
13✔
27
          debug_info,
13✔
28
          vertex,
13✔
29
          parent,
13✔
30
          LibraryNodeType_DOT,
13✔
31
          {"__out"},
13✔
32
          {"__x", "__y"},
13✔
33
          implementation_type,
13✔
34
          precision
13✔
35
      ),
13✔
36
      n_(n), incx_(incx), incy_(incy) {}
13✔
37

38
symbolic::Expression DotNode::n() const { return this->n_; };
4✔
39

40
symbolic::Expression DotNode::incx() const { return this->incx_; };
2✔
41

42
symbolic::Expression DotNode::incy() const { return this->incy_; };
2✔
43

44
symbolic::SymbolSet DotNode::symbols() const {
×
45
    symbolic::SymbolSet syms;
×
46

47
    for (auto& atom : symbolic::atoms(this->n_)) {
×
48
        syms.insert(atom);
×
49
    }
×
50
    for (auto& atom : symbolic::atoms(this->incx_)) {
×
51
        syms.insert(atom);
×
52
    }
×
53
    for (auto& atom : symbolic::atoms(this->incy_)) {
×
54
        syms.insert(atom);
×
55
    }
×
56

57
    return syms;
×
58
};
×
59

60
void DotNode::replace(const symbolic::Expression old_expression, const symbolic::Expression new_expression) {
×
61
    this->n_ = symbolic::subs(this->n_, old_expression, new_expression);
×
62
    this->incx_ = symbolic::subs(this->incx_, old_expression, new_expression);
×
63
    this->incy_ = symbolic::subs(this->incy_, old_expression, new_expression);
×
64
};
×
65

66
void DotNode::replace(const symbolic::ExpressionMapping& replacements) {
×
67
    this->n_ = symbolic::subs(this->n_, replacements);
×
68
    this->incx_ = symbolic::subs(this->incx_, replacements);
×
69
    this->incy_ = symbolic::subs(this->incy_, replacements);
×
70
};
×
71

72
void DotNode::validate(const Function& function) const { BLASNode::validate(function); }
×
73

74
passes::LibNodeExpander::ExpandOutcome DotNode::
75
    expand(passes::LibNodeExpander::ExpandContext& context, structured_control_flow::Block& block) {
5✔
76
    auto& dataflow = this->get_parent();
5✔
77

78
    const data_flow::Memlet* iedge_x = nullptr;
5✔
79
    const data_flow::Memlet* iedge_y = nullptr;
5✔
80
    for (const auto& iedge : dataflow.in_edges(*this)) {
10✔
81
        if (iedge.dst_conn() == "__x") {
10✔
82
            iedge_x = &iedge;
5✔
83
        } else if (iedge.dst_conn() == "__y") {
5✔
84
            iedge_y = &iedge;
5✔
85
        }
5✔
86
    }
10✔
87

88
    const data_flow::Memlet* oedge_res = nullptr;
5✔
89
    for (const auto& oedge : dataflow.out_edges(*this)) {
5✔
90
        if (oedge.src_conn() == "__out") {
5✔
91
            oedge_res = &oedge;
5✔
92
            break;
5✔
93
        }
5✔
94
    }
5✔
95

96
    using Use = passes::LibNodeExpander::InputUse;
5✔
97
    auto standalone = context.replacement_requires_access_nodes({Use::IndirectRead, Use::IndirectRead});
5✔
98
    if (!standalone) {
5✔
99
        return context.unable();
×
100
    }
×
101

102
    auto& builder = standalone->builder();
5✔
103
    auto& new_sequence = standalone->replace_with_sequence();
5✔
104

105
    std::string loop_var = builder.find_new_name("_i");
5✔
106
    builder.add_container(loop_var, types::Scalar(types::PrimitiveType::UInt64));
5✔
107

108
    auto loop_indvar = symbolic::symbol(loop_var);
5✔
109
    auto loop_init = symbolic::integer(0);
5✔
110
    auto loop_condition = symbolic::Lt(loop_indvar, this->n_);
5✔
111
    auto loop_update = symbolic::add(loop_indvar, symbolic::integer(1));
5✔
112

113
    auto& loop = builder.add_for(new_sequence, loop_indvar, loop_condition, loop_init, loop_update, block.debug_info());
5✔
114
    auto& body = loop.root();
5✔
115

116
    auto& new_block = builder.add_block(body);
5✔
117

118
    auto& res_out = standalone->add_output_access(new_block, 0);
5✔
119
    auto& res_in = builder.add_access(new_block, res_out.data());
5✔
120
    // absolute hack to read sth. that is supposed to be an output.
121
    // This will definitely break SSA when we switch and should use a temporary scoped to the loop instead
122

123
    auto& x = standalone->add_indirect_read_access(new_block, 0);
5✔
124
    auto& y = standalone->add_indirect_read_access(new_block, 1);
5✔
125

126
    auto& tasklet = builder.add_tasklet(new_block, data_flow::TaskletCode::fp_fma, "__out", {"_in1", "_in2", "_in3"});
5✔
127

128
    builder.add_computational_memlet(
5✔
129
        new_block,
5✔
130
        x,
5✔
131
        tasklet,
5✔
132
        "_in1",
5✔
133
        {symbolic::mul(loop_indvar, this->incx_)},
5✔
134
        iedge_x->base_type(),
5✔
135
        iedge_x->debug_info()
5✔
136
    );
5✔
137
    builder.add_computational_memlet(
5✔
138
        new_block,
5✔
139
        y,
5✔
140
        tasklet,
5✔
141
        "_in2",
5✔
142
        {symbolic::mul(loop_indvar, this->incy_)},
5✔
143
        iedge_y->base_type(),
5✔
144
        iedge_y->debug_info()
5✔
145
    );
5✔
146
    builder
5✔
147
        .add_computational_memlet(new_block, res_in, tasklet, "_in3", {}, oedge_res->base_type(), oedge_res->debug_info());
5✔
148
    builder.add_computational_memlet(
5✔
149
        new_block, tasklet, "__out", res_out, {}, oedge_res->base_type(), oedge_res->debug_info()
5✔
150
    );
5✔
151

152
    return context.unable();
5✔
153
}
5✔
154

155
symbolic::Expression DotNode::flop() const {
×
156
    auto muls = this->n_;
×
157
    auto adds = symbolic::sub(this->n_, symbolic::one());
×
158
    return symbolic::add(muls, adds);
×
159
}
×
160

161
std::unique_ptr<data_flow::DataFlowNode> DotNode::
162
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph& parent) const {
×
163
    auto node_clone = std::unique_ptr<DotNode>(new DotNode(
×
164
        element_id,
×
165
        this->debug_info(),
×
166
        vertex,
×
167
        parent,
×
168
        this->implementation_type_,
×
169
        this->precision_,
×
170
        this->n_,
×
171
        this->incx_,
×
172
        this->incy_
×
173
    ));
×
174
    return std::move(node_clone);
×
175
}
×
176

177
data_flow::PointerAccessType DotNode::pointer_access_type(int input_idx) const {
×
178
    if (input_idx == 0) {
×
179
        return data_flow::PointerAccessMeta::create_read_only(symbolic::mul(n_, incx_), true);
×
180
    } else if (input_idx == 1) {
×
181
        return data_flow::PointerAccessMeta::create_read_only(symbolic::mul(n_, incy_), true);
×
182
    } else {
×
183
        return BLASNode::pointer_access_type(input_idx);
×
184
    }
×
185
}
×
186

187
nlohmann::json DotNodeSerializer::serialize(const data_flow::LibraryNode& library_node) {
×
188
    const DotNode& gemm_node = static_cast<const DotNode&>(library_node);
×
189
    nlohmann::json j;
×
190

191
    serializer::JSONSerializer serializer;
×
192
    j["code"] = gemm_node.code().value();
×
193
    j["precision"] = gemm_node.precision();
×
194
    j["n"] = serializer.expression(gemm_node.n());
×
195
    j["incx"] = serializer.expression(gemm_node.incx());
×
196
    j["incy"] = serializer.expression(gemm_node.incy());
×
197

198
    return j;
×
199
}
×
200

201
data_flow::LibraryNode& DotNodeSerializer::deserialize(
202
    const nlohmann::json& j, builder::StructuredSDFGBuilder& builder, structured_control_flow::Block& parent
203
) {
×
204
    // Assertions for required fields
205
    assert(j.contains("element_id"));
×
206
    assert(j.contains("code"));
×
207
    assert(j.contains("debug_info"));
×
208

209
    auto code = j["code"].get<std::string>();
×
210
    if (code != LibraryNodeType_DOT.value()) {
×
211
        throw std::runtime_error("Invalid library node code");
×
212
    }
×
213

214
    // Extract debug info using JSONSerializer
215
    sdfg::serializer::JSONSerializer serializer;
×
216
    DebugInfo debug_info = serializer.json_to_debug_info(j["debug_info"]);
×
217

218
    auto precision = j.at("precision").get<BLAS_Precision>();
×
219
    auto n = symbolic::parse(j.at("n"));
×
220
    auto incx = symbolic::parse(j.at("incx"));
×
221
    auto incy = symbolic::parse(j.at("incy"));
×
222

223
    auto implementation_type = j.at("implementation_type").get<std::string>();
×
224

225
    return builder.add_library_node<DotNode>(parent, debug_info, implementation_type, precision, n, incx, incy);
×
226
}
×
227

228
DotNodeDispatcher_BLAS::DotNodeDispatcher_BLAS(
229
    codegen::LanguageExtension& language_extension,
230
    const Function& function,
231
    const data_flow::DataFlowGraph& data_flow_graph,
232
    const DotNode& node
233
)
234
    : codegen::LibraryNodeDispatcher(language_extension, function, data_flow_graph, node) {}
×
235

236
void DotNodeDispatcher_BLAS::dispatch_code_with_edges(
237
    codegen::CodegenOutput& out,
238
    std::vector<codegen::DispatchInput>& inputs,
239
    std::vector<codegen::DispatchOutput>& outputs
240
) {
×
241
    auto& dot_node = static_cast<const DotNode&>(this->node_);
×
242

243
    sdfg::types::Scalar base_type(types::PrimitiveType::Void);
×
244
    BLAS_Precision precision = dot_node.precision();
×
245
    switch (precision) {
×
246
        case BLAS_Precision::h:
×
247
            base_type = types::Scalar(types::PrimitiveType::Half);
×
248
            break;
×
249
        case BLAS_Precision::s:
×
250
            base_type = types::Scalar(types::PrimitiveType::Float);
×
251
            break;
×
252
        case BLAS_Precision::d:
×
253
            base_type = types::Scalar(types::PrimitiveType::Double);
×
254
            break;
×
255
        default:
×
256
            throw std::runtime_error("Invalid BLAS_Precision value");
×
257
    }
×
258

259
    out.library_snippet_factory.require_dependency(BLASLibDependency::instance());
×
260

261
    auto& output = outputs.at(0);
×
262
    pre_allocate_output(out, output, dot_node.output(0));
×
263

264
    out.stream << *output.local_name << " = ";
×
265
    out.stream << "cblas_" << BLAS_Precision_to_string(precision) << "dot(";
×
266
    out.stream.changeIndent(+4);
×
267
    out.stream << this->language_extension_.expression(dot_node.n());
×
268
    out.stream << ", ";
×
269
    out.stream << inputs.at(0).expr;
×
270
    out.stream << ", ";
×
271
    out.stream << this->language_extension_.expression(dot_node.incx());
×
272
    out.stream << ", ";
×
273
    out.stream << inputs.at(1).expr;
×
274
    out.stream << ", ";
×
275
    out.stream << this->language_extension_.expression(dot_node.incy());
×
276
    out.stream.changeIndent(-4);
×
277
    out.stream << ");" << std::endl;
×
278
}
×
279

NEW
280
codegen::InstrumentationInfo DotNodeDispatcher_BLAS::instrumentation_info() const {
×
NEW
281
    return {
×
NEW
282
        node_.element_id(),
×
NEW
283
        std::string(node_.element_type()) + ":::" + node_.code().value(),
×
NEW
284
        codegen::TargetType_CPU_PARALLEL,
×
NEW
285
        codegen::InstrumentationEventType::CPU,
×
NEW
286
        analysis::LoopInfo{},
×
NEW
287
        {}
×
NEW
288
    };
×
NEW
289
}
×
290

291

292
} // namespace blas
293
} // namespace math
294
} // namespace sdfg
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc