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

daisytuner / docc / 24517813654

16 Apr 2026 03:05PM UTC coverage: 64.286% (-0.2%) from 64.503%
24517813654

Pull #683

github

web-flow
Merge 3803436ab into e165e5156
Pull Request #683: Tuned ROCM Gemm

7 of 174 new or added lines in 3 files covered. (4.02%)

129 existing lines in 6 files now uncovered.

30845 of 47981 relevant lines covered (64.29%)

578.73 hits per line

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

46.58
/sdfg/src/offloading/data_offloading_node.cpp
1
#include "sdfg/targets/offloading/data_offloading_node.h"
2

3
#include <cstddef>
4
#include <string>
5
#include <vector>
6

7
#include "sdfg/data_flow/data_flow_graph.h"
8
#include "sdfg/data_flow/library_node.h"
9
#include "sdfg/element.h"
10
#include "sdfg/exceptions.h"
11
#include "sdfg/graph/graph.h"
12
#include "sdfg/symbolic/symbolic.h"
13

14
namespace sdfg {
15
namespace offloading {
16

17
constexpr bool dump_offload_node_ids = false;
18

19
DataOffloadingNode::DataOffloadingNode(
20
    size_t element_id,
21
    const DebugInfo& debug_info,
22
    const graph::Vertex vertex,
23
    data_flow::DataFlowGraph& parent,
24
    const data_flow::LibraryNodeCode code,
25
    const std::vector<std::string>& outputs,
26
    const std::vector<std::string>& inputs,
27
    DataTransferDirection transfer_direction,
28
    BufferLifecycle buffer_lifecycle,
29
    symbolic::Expression size
30
)
31
    : data_flow::LibraryNode(
105✔
32
          element_id, debug_info, vertex, parent, code, outputs, inputs, true, data_flow::ImplementationType_NONE
105✔
33
      ),
105✔
34
      transfer_direction_(transfer_direction), buffer_lifecycle_(buffer_lifecycle), size_(std::move(size)) {}
105✔
35

36
DataTransferDirection DataOffloadingNode::transfer_direction() const { return this->transfer_direction_; }
313✔
37

38
BufferLifecycle DataOffloadingNode::buffer_lifecycle() const { return this->buffer_lifecycle_; }
166✔
39

40
const symbolic::Expression DataOffloadingNode::size() const { return this->size_; }
195✔
41

42
const symbolic::Expression DataOffloadingNode::alloc_size() const { return this->size(); }
×
43

44
symbolic::SymbolSet DataOffloadingNode::symbols() const {
61✔
45
    if (this->size().is_null()) {
61✔
46
        return {};
×
47
    } else {
61✔
48
        return symbolic::atoms(this->size());
61✔
49
    }
61✔
50
}
61✔
51

52
void DataOffloadingNode::replace(const symbolic::Expression old_expression, const symbolic::Expression new_expression) {
15✔
53
    if (!this->size_.is_null()) {
15✔
54
        this->size_ = symbolic::subs(this->size_, old_expression, new_expression);
15✔
55
    }
15✔
56
}
15✔
57

58
std::string DataOffloadingNode::toStr() const {
×
59
    std::string direction, lifecycle;
×
60
    switch (this->transfer_direction()) {
×
61
        case DataTransferDirection::D2H:
×
62
            direction = " D2H";
×
63
            break;
×
64
        case DataTransferDirection::H2D:
×
65
            direction = " H2D";
×
66
            break;
×
67
        default:
×
68
            direction = " NONE";
×
69
            break;
×
70
    }
×
71
    switch (this->buffer_lifecycle()) {
×
72
        case BufferLifecycle::FREE:
×
73
            lifecycle = " FREE";
×
74
            break;
×
75
        case BufferLifecycle::ALLOC:
×
76
            lifecycle = " ALLOC";
×
77
            break;
×
78
        default:
×
79
            lifecycle = " NO_CHANGE";
×
80
            break;
×
81
    }
×
82
    std::string res = std::string(this->code_.value());
×
83
    if (dump_offload_node_ids) {
×
84
        res += " #" + std::to_string(element_id_);
×
85
    }
×
86
    res += direction + lifecycle;
×
87
    return res;
×
88
}
×
89

90
symbolic::Expression DataOffloadingNode::flop() const { return symbolic::zero(); }
×
91

92
bool DataOffloadingNode::is_compatible_with(const DataOffloadingNode& other) const {
24✔
93
    if (code() != other.code()) {
24✔
94
        return false;
×
95
    }
×
96
    if (!symbolic::null_safe_eq(size(), other.size())) {
24✔
97
        return false;
×
98
    }
×
99
    return true;
24✔
100
}
24✔
101

102
bool DataOffloadingNode::redundant_with(const DataOffloadingNode& other) const {
×
103
    if (!is_compatible_with(other)) {
×
104
        return false;
×
105
    }
×
106
    if ((static_cast<int8_t>(transfer_direction()) + static_cast<int8_t>(other.transfer_direction())) != 0) {
×
107
        return false; // not the inverse
×
108
    }
×
109
    if ((static_cast<int8_t>(buffer_lifecycle()) + static_cast<int8_t>(other.buffer_lifecycle())) != 0) {
×
110
        return false;
×
111
    }
×
112

113
    return true; // add more checks in sub-classes
×
114
}
×
115

116
bool DataOffloadingNode::equal_with(const DataOffloadingNode& other) const {
8✔
117
    if (!is_compatible_with(other)) {
8✔
118
        return false;
×
119
    }
×
120
    if (this->transfer_direction() != other.transfer_direction()) {
8✔
121
        return false;
×
122
    }
×
123
    if (this->buffer_lifecycle() != other.buffer_lifecycle()) {
8✔
124
        return false;
×
125
    }
×
126

127
    return true; // add more checks in sub-classes
8✔
128
}
8✔
129

130
bool DataOffloadingNode::is_d2h() const { return is_D2H(this->transfer_direction()); }
133✔
131

132
bool DataOffloadingNode::is_h2d() const { return is_H2D(this->transfer_direction()); }
110✔
133

134
bool DataOffloadingNode::has_transfer() const { return this->is_d2h() || this->is_h2d(); }
15✔
135

136
bool DataOffloadingNode::is_free() const { return is_FREE(this->buffer_lifecycle()); }
55✔
137

138
bool DataOffloadingNode::is_alloc() const { return is_ALLOC(this->buffer_lifecycle()); }
43✔
139

140
void DataOffloadingNode::remove_h2d() {
3✔
141
    if (this->is_h2d()) {
3✔
142
        if (!this->is_alloc()) {
3✔
143
            throw InvalidSDFGException("DataOffloadingNode: Tried removing h2d but node has no other purpose");
×
144
        }
×
145
        this->transfer_direction_ = DataTransferDirection::NONE;
3✔
146
        this->inputs_.erase(this->inputs_.begin()); // Standard nodes only have one, others need to override
3✔
147
    }
3✔
148
}
3✔
149

150
data_flow::PointerAccessType DataOffloadingNode::pointer_access_type(int input_idx) const {
3✔
151
    if (is_h2d() && input_idx == 0) {
3✔
152
        return data_flow::PointerReadOnly(size_, true);
3✔
153
    } else {
3✔
154
        return LibraryNode::pointer_access_type(input_idx);
×
155
    }
×
156
}
3✔
157

158
void DataOffloadingNode::remove_free() {
3✔
159
    if (this->is_free()) {
3✔
160
        if (!this->has_transfer()) {
3✔
161
            throw InvalidSDFGException("DataOffloadingNode: Tried removing free but no data transfer direction present"
×
162
            );
×
163
        }
×
164
        this->buffer_lifecycle_ = BufferLifecycle::NO_CHANGE;
3✔
165
    }
3✔
166
}
3✔
167

168
void DataOffloadingNode::remove_d2h() {
5✔
169
    if (this->is_d2h()) {
5✔
170
        if (!this->is_free()) {
5✔
171
            throw InvalidSDFGException("DataOffloadingNode: Tried removing d2h but node has no other purpose");
×
UNCOV
172
        }
×
173
        this->transfer_direction_ = DataTransferDirection::NONE;
5✔
174
    }
5✔
175
}
5✔
176

177
data_flow::EdgeRemoveOption DataOffloadingNode::
178
    can_remove_out_edge(const data_flow::DataFlowGraph& graph, const data_flow::Memlet* memlet) const {
1✔
179
    if (graph.out_edges_for_connector(*this, memlet->src_conn()).size() > 1) {
1✔
UNCOV
180
        return data_flow::EdgeRemoveOption::Trivially;
×
181
    } else if (transfer_direction_ != DataTransferDirection::NONE && outputs_.size() == 1 &&
1✔
182
               memlet->src_conn() == outputs_.at(0)) {
1✔
183
        // the node represents a transfer, whose output is dead.
184
        if (buffer_lifecycle_ != BufferLifecycle::NO_CHANGE) {
1✔
185
            // the node still has remaining purpose without the transfer
UNCOV
186
            return data_flow::EdgeRemoveOption::RequiresUpdate;
×
187
        } else {
1✔
188
            // the node in its entirety is dead if it the transfer is not needed
189
            return data_flow::EdgeRemoveOption::RemoveNodeAfter;
1✔
190
        }
1✔
191
    } else {
1✔
UNCOV
192
        return data_flow::EdgeRemoveOption::NotRemovable;
×
193
    }
×
194
}
1✔
195

UNCOV
196
bool DataOffloadingNode::update_edge_removed(const std::string& out_conn) {
×
UNCOV
197
    if (transfer_direction_ != DataTransferDirection::NONE && outputs_.size() == 1 && out_conn == outputs_.at(0)) {
×
UNCOV
198
        transfer_direction_ = DataTransferDirection::NONE;
×
UNCOV
199
        outputs_.erase(outputs_.begin());
×
UNCOV
200
        return true;
×
UNCOV
201
    } else {
×
UNCOV
202
        return false;
×
UNCOV
203
    }
×
UNCOV
204
}
×
205

206
} // namespace offloading
207
} // 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