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

daisytuner / docc / 24339912528

13 Apr 2026 11:02AM UTC coverage: 64.382% (-0.2%) from 64.608%
24339912528

push

github

web-flow
Data flow transfer elimination (#673)

* Fix: ScheduleType categorie was not preserved

* Towards Dataflow-based Transfer Elimination Analysis

 * generified / further split up BaseUserVisitor and its "Analyzers".
 + made existing code used in dead_data_elimination reusable and made them composable to use in a single pass
 + structured, forward dataflow analysis framework (WIP)
 + DataTransferEliminationAnalysis draft to find elimination candidates in execution order, respecting any barriers to elimination in between them

* New Dataflow-based DataTransferMinimizationPass works on resnet, does

 ! stop-gap: using user-analysis to decide whether to remove d2h all together. This is unsafe

* More options to aid in debugging offload transfer minimizations and other passes via DotViz by showing the element ids. Default disabled.

* Updated dev-ptr mapping when removing h2d nodes to match legacy transfer elimination changes

* Added missing header data_transfer_elimination_analysis.h

381 of 542 new or added lines in 12 files covered. (70.3%)

116 existing lines in 5 files now uncovered.

30456 of 47305 relevant lines covered (64.38%)

585.15 hits per line

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

44.79
/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(
83✔
32
          element_id, debug_info, vertex, parent, code, outputs, inputs, true, data_flow::ImplementationType_NONE
83✔
33
      ),
83✔
34
      transfer_direction_(transfer_direction), buffer_lifecycle_(buffer_lifecycle), size_(std::move(size)) {}
83✔
35

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

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

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

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

44
symbolic::SymbolSet DataOffloadingNode::symbols() const {
28✔
45
    if (this->size().is_null()) {
28✔
46
        return {};
×
47
    } else {
28✔
48
        return symbolic::atoms(this->size());
28✔
49
    }
28✔
50
}
28✔
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
    }
×
NEW
82
    std::string res = std::string(this->code_.value());
×
NEW
83
    if (dump_offload_node_ids) {
×
NEW
84
        res += " #" + std::to_string(element_id_);
×
NEW
85
    }
×
NEW
86
    res += direction + lifecycle;
×
NEW
87
    return res;
×
UNCOV
88
}
×
89

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

92
bool DataOffloadingNode::redundant_with(const DataOffloadingNode& other) const {
2✔
93
    if (code() != other.code()) {
2✔
94
        return false;
×
95
    }
×
96
    if ((static_cast<int8_t>(transfer_direction()) + static_cast<int8_t>(other.transfer_direction())) != 0) {
2✔
97
        return false; // not the inverse
×
98
    }
×
99
    if ((static_cast<int8_t>(buffer_lifecycle()) + static_cast<int8_t>(other.buffer_lifecycle())) != 0) {
2✔
100
        return false;
×
101
    }
×
102

103
    if (!symbolic::null_safe_eq(size(), other.size())) {
2✔
UNCOV
104
        return false;
×
UNCOV
105
    }
×
106

107
    return true; // add more checks in sub-classes
2✔
108
}
2✔
109

110
bool DataOffloadingNode::equal_with(const DataOffloadingNode& other) const {
8✔
111
    if (code() != other.code()) {
8✔
112
        return false;
×
113
    }
×
114
    if (this->transfer_direction() != other.transfer_direction()) {
8✔
115
        return false;
×
116
    }
×
117
    if (this->buffer_lifecycle() != other.buffer_lifecycle()) {
8✔
118
        return false;
×
119
    }
×
120

121
    if (!symbolic::null_safe_eq(size(), other.size())) {
8✔
122
        return false;
×
123
    }
×
124

125
    return true; // add more checks in sub-classes
8✔
126
}
8✔
127

128
bool DataOffloadingNode::is_d2h() const { return is_D2H(this->transfer_direction()); }
90✔
129

130
bool DataOffloadingNode::is_h2d() const { return is_H2D(this->transfer_direction()); }
77✔
131

132
bool DataOffloadingNode::has_transfer() const { return this->is_d2h() || this->is_h2d(); }
13✔
133

134
bool DataOffloadingNode::is_free() const { return is_FREE(this->buffer_lifecycle()); }
30✔
135

136
bool DataOffloadingNode::is_alloc() const { return is_ALLOC(this->buffer_lifecycle()); }
31✔
137

138
void DataOffloadingNode::remove_free() {
1✔
139
    if (this->is_free()) {
1✔
140
        if (!this->has_transfer()) {
1✔
141
            throw InvalidSDFGException("DataOffloadingNode: Tried removing free but no data transfer direction present"
×
142
            );
×
143
        }
×
144
        this->buffer_lifecycle_ = BufferLifecycle::NO_CHANGE;
1✔
145
    }
1✔
146
}
1✔
147

148
} // namespace offloading
149
} // 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