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

daisytuner / docc / 21873449786

10 Feb 2026 04:31PM UTC coverage: 66.315% (-0.2%) from 66.496%
21873449786

Pull #513

github

web-flow
Merge 55ce04c5d into 5750a460e
Pull Request #513: adds tensor type

244 of 431 new or added lines in 18 files covered. (56.61%)

186 existing lines in 15 files now uncovered.

23488 of 35419 relevant lines covered (66.31%)

372.32 hits per line

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

71.43
/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/optimization_report/pass_report_consumer.h"
16
#include "sdfg/types/utils.h"
17
#include "symengine/symengine_rcp.h"
18

19
namespace sdfg {
20
namespace transformations {
21

22
OffloadTransform::OffloadTransform(structured_control_flow::Map& map, bool allow_dynamic_sizes)
23
    : map_(map), allow_dynamic_sizes_(allow_dynamic_sizes) {}
7✔
24

25
bool OffloadTransform::can_be_applied(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
7✔
26
    auto& sdfg = builder.subject();
7✔
27

28
    auto& arguments_analysis = analysis_manager.get<analysis::ArgumentsAnalysis>();
7✔
29

30
    if (!arguments_analysis.inferred_types(analysis_manager, this->map_)) {
7✔
31
        if (report_) report_->transform_impossible(this, "unranged args");
×
32
        DEBUG_PRINTLN("Cannot apply transform: argument types not inferred");
×
33
        return false;
×
34
    }
×
35
    auto& arguments = arguments_analysis.arguments(analysis_manager, this->map_);
7✔
36

37
    // Criterion: arg Data Types must be continuous
38
    for (auto& [argument, meta] : arguments) {
16✔
39
        auto base_type = analysis::TypeAnalysis(sdfg, &map_, analysis_manager).get_outer_type(argument);
16✔
40
        if (base_type == nullptr) {
16✔
41
            if (report_) report_->transform_impossible(this, "cannot infer type");
×
42
            DEBUG_PRINTLN("Cannot apply transform: argument type cannot be inferred");
×
43
            return false;
×
44
        }
×
45
        if (!types::is_contiguous_type(*base_type, sdfg)) {
16✔
46
            if (report_) report_->transform_impossible(this, "type is not contiguous");
×
47
            DEBUG_PRINTLN("Cannot apply transform: argument type is not contiguous");
×
48
            return false;
×
49
        }
×
50
        if (meta.is_scalar && meta.is_output) {
16✔
51
            if (report_) report_->transform_impossible(this, "scalar output");
×
52
            DEBUG_PRINTLN("Cannot apply transform: map writes to scalar argument");
×
53
            return false;
×
54
        }
×
55
    }
16✔
56

57
    // Criterion: Map must start at 0
58
    if (!symbolic::eq(this->map_.init(), symbolic::zero())) {
7✔
59
        if (report_) report_->transform_impossible(this, "non zero start");
×
60
        DEBUG_PRINTLN("Cannot apply transform: map does not start at zero");
×
61
        return false;
×
62
    }
×
63

64
    // Criterion: Map cannot write to scalar arguments
65
    for (auto& [argument, meta] : arguments) {
16✔
66
        if (meta.is_scalar && meta.is_output) {
16✔
67
            if (report_) report_->transform_impossible(this, "scalar output");
×
68
            DEBUG_PRINTLN("Cannot apply transform: map writes to scalar argument");
×
69
            return false;
×
70
        }
×
71
    }
16✔
72

73
    // Criterion: arg ranges must be known
74
    auto& mem_access_ranges = analysis_manager.get<analysis::MemAccessRanges>();
7✔
75

76
    if (!arguments_analysis.argument_size_known(analysis_manager, this->map_, allow_dynamic_sizes_)) {
7✔
77
        if (report_) report_->transform_impossible(this, "args not understood");
×
78
        DEBUG_PRINTLN("Cannot apply transform: argument sizes not known");
×
79
        return false;
×
80
    }
×
81

82
    if (report_) report_->transform_possible(this);
7✔
83
    return true;
7✔
84
}
7✔
85

86
void OffloadTransform::apply(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
7✔
87
    // Schedule
88
    builder.update_schedule_type(this->map_, transformed_schedule_type());
7✔
89

90
    auto& sdfg = builder.subject();
7✔
91

92
    // Identify arguments and locals
93
    auto& arguments_analysis = analysis_manager.get<analysis::ArgumentsAnalysis>();
7✔
94

95
    auto& arguments = arguments_analysis.arguments(analysis_manager, this->map_);
7✔
96
    auto& locals = arguments_analysis.locals(analysis_manager, this->map_);
7✔
97

98
    // Infer subsets for arguments
99
    auto& mem_access_ranges = analysis_manager.get<analysis::MemAccessRanges>();
7✔
100
    auto& argument_sizes = arguments_analysis.argument_sizes(analysis_manager, this->map_, allow_dynamic_sizes_);
7✔
101

102
    auto& scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
7✔
103
    auto parent_scope = static_cast<structured_control_flow::Sequence*>(scope_analysis.parent_scope(&this->map_));
7✔
104

105
    std::string container_prefix = copy_prefix() + std::to_string(parent_scope->element_id()) + "_";
7✔
106

107
    // Allocate arguments and locals
108
    allocate_locals_on_device_stack(builder, analysis_manager, locals);
7✔
109
    handle_device_setup_and_teardown(builder, arguments, argument_sizes, container_prefix);
7✔
110

111
    // Copy-in arguments to device memory & allocation
112
    for (auto& [argument, meta] : arguments) {
16✔
113
        if (!meta.is_ptr) {
16✔
114
            continue;
10✔
115
        }
10✔
116
        auto argument_device = container_prefix + argument;
6✔
117
        auto& new_block = builder.add_block_before(*parent_scope, this->map_, {}, this->map_.debug_info());
6✔
118
        auto& size = argument_sizes.at(argument);
6✔
119
        copy_to_device_with_allocation(builder, argument, argument_device, size, SymEngine::null, new_block);
6✔
120
    }
6✔
121

122
    update_map_containers(arguments, container_prefix);
7✔
123

124
    // Copy-out arguments to host memory & free
125
    for (auto& [argument, meta] : arguments) {
16✔
126
        if (!meta.is_ptr) {
16✔
127
            continue;
10✔
128
        }
10✔
129
        auto argument_device = container_prefix + argument;
6✔
130
        auto& new_block = builder.add_block_after(*parent_scope, this->map_, {}, this->map_.debug_info());
6✔
131
        auto& size = argument_sizes.at(argument);
6✔
132
        if (meta.is_output) {
6✔
133
            copy_from_device_with_free(builder, new_block, argument, argument_device, size, SymEngine::null);
6✔
134
        } else {
6✔
UNCOV
135
            deallocate_device_arg(builder, new_block, argument_device, size, SymEngine::null);
×
UNCOV
136
        }
×
137
    }
6✔
138

139
    if (report_) report_->transform_applied(this);
7✔
140
}
7✔
141

142
void OffloadTransform::handle_device_setup_and_teardown(
143
    builder::StructuredSDFGBuilder& builder,
144

145
    const std::map<std::string, analysis::RegionArgument>& arguments,
146
    const std::unordered_map<std::string, symbolic::Expression>& argument_sizes,
147
    std::string prefix
148
) {
7✔
149
    // Add managed buffers for pointer arguments
150
    for (auto& [argument, meta] : arguments) {
16✔
151
        if (!meta.is_ptr || builder.subject().exists(prefix + argument)) {
16✔
152
            continue;
12✔
153
        }
12✔
154
        auto argument_device = prefix + argument;
4✔
155

156
        auto arg_size = argument_sizes.at(argument);
4✔
157

158
        add_device_buffer(builder, argument, argument_device, arg_size);
4✔
159
    }
4✔
160
}
7✔
161

162
void OffloadTransform::
163
    update_map_containers(const std::map<std::string, analysis::RegionArgument>& arguments, std::string prefix) {
7✔
164
    for (auto& [argument, meta] : arguments) {
16✔
165
        if (meta.is_ptr) {
16✔
166
            auto argument_device = prefix + argument;
6✔
167
            this->map_.replace(symbolic::symbol(argument), symbolic::symbol(argument_device));
6✔
168
        }
6✔
169
    }
16✔
170
}
7✔
171

172
} // namespace transformations
173
} // 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