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

daisytuner / docc / 23207680822

17 Mar 2026 05:30PM UTC coverage: 63.838% (-0.1%) from 63.973%
23207680822

Pull #583

github

web-flow
Merge d81aa24e4 into 3868c059f
Pull Request #583: [MLIR] Setup a Model Zoo to test different End-to-End networks

12 of 96 new or added lines in 4 files covered. (12.5%)

161 existing lines in 2 files now uncovered.

26079 of 40852 relevant lines covered (63.84%)

401.75 hits per line

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

68.6
/opt/src/transformations/offloading/offload_transform.cpp
1
#include "sdfg/transformations/offloading/offload_transform.h"
2

3
#include <map>
4
#include <string>
5

6
#include "sdfg/analysis/mem_access_range_analysis.h"
7
#include "sdfg/analysis/scope_analysis.h"
8
#include "sdfg/analysis/type_analysis.h"
9
#include "sdfg/data_flow/access_node.h"
10
#include "sdfg/structured_control_flow/block.h"
11
#include "sdfg/structured_control_flow/if_else.h"
12
#include "sdfg/structured_control_flow/map.h"
13
#include "sdfg/symbolic/symbolic.h"
14

15
#include "sdfg/data_flow/library_node.h"
16
#include "sdfg/optimization_report/pass_report_consumer.h"
17
#include "sdfg/types/utils.h"
18
#include "sdfg/visitor/immutable_structured_sdfg_visitor.h"
19
#include "symengine/symengine_rcp.h"
20

21
namespace sdfg {
22
namespace transformations {
23

24
class SideEffectFinder : public visitor::ImmutableStructuredSDFGVisitor {
25
private:
26
    structured_control_flow::Map& map_;
27

28
public:
29
    SideEffectFinder(StructuredSDFG& sdfg, analysis::AnalysisManager& analysis_manager, structured_control_flow::Map& map)
30
        : visitor::ImmutableStructuredSDFGVisitor(sdfg, analysis_manager), map_(map) {}
5✔
31

32
    bool visit() override { return visit_internal(map_.root()); }
5✔
33

34
    bool accept(structured_control_flow::Block& node) override {
4✔
35
        for (const auto& lib_node : node.dataflow().library_nodes()) {
4✔
NEW
36
            if (lib_node->side_effect()) {
×
NEW
37
                return true;
×
NEW
38
            }
×
NEW
39
        }
×
40
        return false;
4✔
41
    }
4✔
42
};
43

44
OffloadTransform::OffloadTransform(structured_control_flow::Map& map, bool allow_dynamic_sizes)
45
    : map_(map), allow_dynamic_sizes_(allow_dynamic_sizes) {}
5✔
46

47

48
bool OffloadTransform::can_be_applied(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
5✔
49
    auto& sdfg = builder.subject();
5✔
50

51
    auto& arguments_analysis = analysis_manager.get<analysis::ArgumentsAnalysis>();
5✔
52

53
    if (!arguments_analysis.inferred_types(analysis_manager, this->map_)) {
5✔
54
        if (report_) report_->transform_impossible(this, "unranged args");
×
55
        DEBUG_PRINTLN("Cannot apply transform: argument types not inferred");
×
56
        return false;
×
57
    }
×
58
    auto& arguments = arguments_analysis.arguments(analysis_manager, this->map_);
5✔
59

60
    // Criterion: arg Data Types must be continuous
61
    for (auto& [argument, meta] : arguments) {
10✔
62
        auto base_type = analysis::TypeAnalysis(sdfg, &map_, analysis_manager).get_outer_type(argument);
10✔
63
        if (base_type == nullptr) {
10✔
64
            if (report_) report_->transform_impossible(this, "cannot infer type");
×
65
            DEBUG_PRINTLN("Cannot apply transform: argument type cannot be inferred");
×
66
            return false;
×
67
        }
×
68
        if (!types::is_contiguous_type(*base_type, sdfg)) {
10✔
69
            if (report_) report_->transform_impossible(this, "type is not contiguous");
×
70
            DEBUG_PRINTLN("Cannot apply transform: argument type is not contiguous");
×
71
            return false;
×
72
        }
×
73
        if (meta.is_scalar && meta.is_output) {
10✔
74
            if (report_) report_->transform_impossible(this, "scalar output");
×
75
            DEBUG_PRINTLN("Cannot apply transform: map writes to scalar argument");
×
76
            return false;
×
77
        }
×
78
    }
10✔
79

80
    // Criterion: Map must start at 0
81
    if (!symbolic::eq(this->map_.init(), symbolic::zero())) {
5✔
82
        if (report_) report_->transform_impossible(this, "non zero start");
×
83
        DEBUG_PRINTLN("Cannot apply transform: map does not start at zero");
×
84
        return false;
×
85
    }
×
86

87
    // Criterion: Map cannot write to scalar arguments
88
    for (auto& [argument, meta] : arguments) {
10✔
89
        if (meta.is_scalar && meta.is_output) {
10✔
90
            if (report_) report_->transform_impossible(this, "scalar output");
×
91
            DEBUG_PRINTLN("Cannot apply transform: map writes to scalar argument");
×
92
            return false;
×
93
        }
×
94
    }
10✔
95

96
    // Criterion: arg ranges must be known
97
    auto& mem_access_ranges = analysis_manager.get<analysis::MemAccessRanges>();
5✔
98

99
    if (!arguments_analysis.argument_size_known(analysis_manager, this->map_, allow_dynamic_sizes_)) {
5✔
100
        if (report_) report_->transform_impossible(this, "args not understood");
×
101
        DEBUG_PRINTLN("Cannot apply transform: argument sizes not known");
×
102
        return false;
×
103
    }
×
104

105
    // Criterion: Map cannot contain function calls with side effects (e.g. library nodes that write to memory)
106
    SideEffectFinder side_effect_finder(sdfg, analysis_manager, this->map_);
5✔
107
    if (side_effect_finder.visit()) {
5✔
NEW
108
        if (report_) report_->transform_impossible(this, "side effects");
×
NEW
109
        DEBUG_PRINTLN("Cannot apply transform: map contains library nodes with side effects");
×
NEW
110
        return false;
×
NEW
111
    }
×
112

113
    if (report_) report_->transform_possible(this);
5✔
114
    return true;
5✔
115
}
5✔
116

117
void OffloadTransform::apply(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
5✔
118
    // Schedule
119
    builder.update_schedule_type(this->map_, transformed_schedule_type());
5✔
120

121
    auto& sdfg = builder.subject();
5✔
122

123
    // Identify arguments and locals
124
    auto& arguments_analysis = analysis_manager.get<analysis::ArgumentsAnalysis>();
5✔
125

126
    auto& arguments = arguments_analysis.arguments(analysis_manager, this->map_);
5✔
127
    auto& locals = arguments_analysis.locals(analysis_manager, this->map_);
5✔
128

129
    // Infer subsets for arguments
130
    auto& mem_access_ranges = analysis_manager.get<analysis::MemAccessRanges>();
5✔
131
    auto& argument_sizes = arguments_analysis.argument_sizes(analysis_manager, this->map_, allow_dynamic_sizes_);
5✔
132

133
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
5✔
134
    auto parent_scope = static_cast<structured_control_flow::Sequence*>(scope_analysis.parent_scope(&this->map_));
5✔
135

136
    std::string container_prefix = copy_prefix() + std::to_string(parent_scope->element_id()) + "_";
5✔
137

138
    // Allocate arguments and locals
139
    allocate_locals_on_device_stack(builder, analysis_manager, locals);
5✔
140
    handle_device_setup_and_teardown(builder, arguments, argument_sizes, container_prefix);
5✔
141

142
    // Copy-in arguments to device memory & allocation
143
    for (auto& [argument, meta] : arguments) {
10✔
144
        if (!meta.is_ptr) {
10✔
145
            continue;
6✔
146
        }
6✔
147
        auto argument_device = container_prefix + argument;
4✔
148
        auto& new_block = builder.add_block_before(*parent_scope, this->map_, {}, this->map_.debug_info());
4✔
149
        auto& size = argument_sizes.at(argument);
4✔
150
        copy_to_device_with_allocation(builder, argument, argument_device, size, SymEngine::null, new_block);
4✔
151
    }
4✔
152

153
    update_map_containers(arguments, container_prefix);
5✔
154

155
    // Copy-out arguments to host memory & free
156
    for (auto& [argument, meta] : arguments) {
10✔
157
        if (!meta.is_ptr) {
10✔
158
            continue;
6✔
159
        }
6✔
160
        auto argument_device = container_prefix + argument;
4✔
161
        auto& new_block = builder.add_block_after(*parent_scope, this->map_, {}, this->map_.debug_info());
4✔
162
        auto& size = argument_sizes.at(argument);
4✔
163
        if (meta.is_output) {
4✔
164
            copy_from_device_with_free(builder, new_block, argument, argument_device, size, SymEngine::null);
4✔
165
        } else {
4✔
166
            deallocate_device_arg(builder, new_block, argument_device, size, SymEngine::null);
×
167
        }
×
168
    }
4✔
169

170
    if (report_) report_->transform_applied(this);
5✔
171
}
5✔
172

173
void OffloadTransform::handle_device_setup_and_teardown(
174
    builder::StructuredSDFGBuilder& builder,
175

176
    const std::map<std::string, analysis::RegionArgument>& arguments,
177
    const std::unordered_map<std::string, symbolic::Expression>& argument_sizes,
178
    std::string prefix
179
) {
5✔
180
    // Add managed buffers for pointer arguments
181
    for (auto& [argument, meta] : arguments) {
10✔
182
        if (!meta.is_ptr || builder.subject().exists(prefix + argument)) {
10✔
183
            continue;
7✔
184
        }
7✔
185
        auto argument_device = prefix + argument;
3✔
186

187
        auto arg_size = argument_sizes.at(argument);
3✔
188

189
        add_device_buffer(builder, argument, argument_device, arg_size);
3✔
190
    }
3✔
191
}
5✔
192

193
void OffloadTransform::
194
    update_map_containers(const std::map<std::string, analysis::RegionArgument>& arguments, std::string prefix) {
5✔
195
    for (auto& [argument, meta] : arguments) {
10✔
196
        if (meta.is_ptr) {
10✔
197
            auto argument_device = prefix + argument;
4✔
198
            this->map_.replace(symbolic::symbol(argument), symbolic::symbol(argument_device));
4✔
199
        }
4✔
200
    }
10✔
201
}
5✔
202

203
} // namespace transformations
204
} // 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