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

daisytuner / docc / 28106147644

24 Jun 2026 02:32PM UTC coverage: 61.922% (+0.1%) from 61.779%
28106147644

Pull #806

github

web-flow
Merge 2be414d54 into 57cc1db99
Pull Request #806: Map Collapse for Multiple targets in a neste sequence

165 of 185 new or added lines in 2 files covered. (89.19%)

419 existing lines in 30 files now uncovered.

37705 of 60891 relevant lines covered (61.92%)

1004.4 hits per line

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

72.86
/opt/src/transformations/offloading/gpu_condition_propagation.cpp
1
#include "sdfg/transformations/offloading/gpu_condition_propagation.h"
2
#include <vector>
3
#include "sdfg/analysis/users.h"
4
#include "sdfg/data_flow/library_nodes/barrier_local_node.h"
5
#include "sdfg/element.h"
6
#include "sdfg/structured_control_flow/control_flow_node.h"
7
#include "sdfg/structured_control_flow/map.h"
8
#include "sdfg/structured_sdfg.h"
9
#include "sdfg/targets/gpu/gpu_schedule_type.h"
10
#include "sdfg/visitor/structured_sdfg_visitor.h"
11

12
namespace sdfg {
13
namespace transformations {
14

15
GPUConditionPropagation::GPUConditionPropagation(structured_control_flow::Map& map_) : map_(map_) {};
6✔
16

17

18
bool GPUConditionPropagation::
19
    can_be_applied(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
4✔
20
    // Criterion: Must be a GPU map (CUDA or ROCm)
21
    if (!gpu::is_gpu_schedule(map_.schedule_type())) {
4✔
22
        return false;
×
23
    }
×
24

25
    // Criterion: Loop must contain thread barriers
26
    BarrierFinder barrier_finder(builder, analysis_manager);
4✔
27
    if (!barrier_finder.visit(&map_)) {
4✔
28
        return false;
×
29
    }
×
30

31
    return true;
4✔
32
}
4✔
33

34
void GPUConditionPropagation::apply(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
4✔
35
    //  1. iterate over all nodes in the map body
36
    //  2. for each node, check if it contains a barrier
37
    //  3. if, propagate the map condition to the barrier
38
    //  4. else mark the node as relevant for condition propagation
39

40
    auto new_sched_type = map_.schedule_type();
4✔
41
    new_sched_type.set_property("nested_sync", "true");
4✔
42
    builder.update_schedule_type(map_, new_sched_type);
4✔
43

44
    std::vector<structured_control_flow::ControlFlowNode*> nodes_to_visit;
4✔
45
    nodes_to_visit.push_back(&map_.root());
4✔
46
    BarrierFinder barrier_finder(builder, analysis_manager);
4✔
47

48
    auto& users = analysis_manager.get<analysis::Users>();
4✔
49

50
    while (!nodes_to_visit.empty()) {
52✔
51
        auto current_node = nodes_to_visit.back();
48✔
52
        nodes_to_visit.pop_back();
48✔
53
        auto parent_scope = current_node->get_parent();
48✔
54
        auto parent_sequence = dynamic_cast<structured_control_flow::Sequence*>(parent_scope);
48✔
55
        analysis::UsersView current_users(users, *current_node);
48✔
56
        auto uses = current_users.uses(map_.indvar()->get_name());
48✔
57
        if (uses.empty()) {
48✔
58
            // Node does not use the map indvar, skip
59
            continue;
20✔
60
        }
20✔
61

62
        if (auto block_node = dynamic_cast<structured_control_flow::Block*>(current_node)) {
28✔
63
            if (!barrier_finder.visit(block_node)) {
×
64
                auto& if_else = builder.add_if_else_before(*parent_sequence, *block_node, {}, DebugInfo());
×
65
                auto& branch = builder.add_case(if_else, map_.condition());
×
66
                builder.move_child(*parent_sequence, parent_sequence->index(*block_node), branch);
×
67
            }
×
68
        } else if (auto seq_node = dynamic_cast<structured_control_flow::Sequence*>(current_node)) {
28✔
69
            if (barrier_finder.visit(seq_node)) {
10✔
70
                for (int i = 0; i < seq_node->size(); i++) {
48✔
71
                    nodes_to_visit.push_back(&seq_node->at(i).first);
38✔
72
                }
38✔
73
            } else {
10✔
74
                auto& if_else = builder.add_if_else_before(*parent_sequence, seq_node->at(0).first, {}, DebugInfo());
×
75
                auto& branch = builder.add_case(if_else, map_.condition());
×
76
                for (int i = 0; i < seq_node->size(); i++) {
×
77
                    builder.move_child(*seq_node, seq_node->index(seq_node->at(0).first), branch);
×
78
                }
×
79
            }
×
80
        } else if (auto ifelse_node = dynamic_cast<structured_control_flow::IfElse*>(current_node)) {
18✔
81
            if (barrier_finder.visit(ifelse_node)) {
6✔
82
                for (size_t i = 0; i < ifelse_node->size(); i++) {
×
83
                    nodes_to_visit.push_back(&ifelse_node->at(i).first);
×
84
                }
×
85
            } else {
6✔
86
                auto& if_else = builder.add_if_else_before(*parent_sequence, *ifelse_node, {}, DebugInfo());
6✔
87
                auto& branch = builder.add_case(if_else, map_.condition());
6✔
88
                builder.move_child(*parent_sequence, parent_sequence->index(*ifelse_node), branch);
6✔
89
            }
6✔
90
        } else if (auto for_node = dynamic_cast<structured_control_flow::For*>(current_node)) {
12✔
91
            if (barrier_finder.visit(for_node)) {
6✔
92
                nodes_to_visit.push_back(&for_node->root());
4✔
93
            } else {
4✔
94
                auto& if_else = builder.add_if_else_before(*parent_sequence, *for_node, {}, DebugInfo());
2✔
95
                auto& branch = builder.add_case(if_else, map_.condition());
2✔
96
                builder.move_child(*parent_sequence, parent_sequence->index(*for_node), branch);
2✔
97
            }
2✔
98
        } else if (auto while_node = dynamic_cast<structured_control_flow::While*>(current_node)) {
6✔
99
            if (barrier_finder.visit(while_node)) {
×
100
                nodes_to_visit.push_back(&while_node->root());
×
101
            } else {
×
102
                auto& if_else = builder.add_if_else_before(*parent_sequence, *while_node, {}, DebugInfo());
×
103
                auto& branch = builder.add_case(if_else, map_.condition());
×
104
                builder.move_child(*parent_sequence, parent_sequence->index(*while_node), branch);
×
105
            }
×
106
        } else if (auto map_node = dynamic_cast<structured_control_flow::Map*>(current_node)) {
6✔
107
            if (barrier_finder.visit(map_node)) {
6✔
108
                nodes_to_visit.push_back(&map_node->root());
2✔
109
            } else {
4✔
110
                auto& if_else = builder.add_if_else_before(*parent_sequence, *map_node, {}, DebugInfo());
4✔
111
                auto& branch = builder.add_case(if_else, map_.condition());
4✔
112
                builder.move_child(*parent_sequence, parent_sequence->index(*map_node), branch);
4✔
113
            }
4✔
114
        }
6✔
115
    }
28✔
116
    analysis_manager.invalidate_all();
4✔
117
}
4✔
118

119
std::string GPUConditionPropagation::name() const { return "GPUConditionPropagation"; };
3✔
120

121
void GPUConditionPropagation::to_json(nlohmann::json& j) const {
1✔
122
    j["transformation_type"] = this->name();
1✔
123
    j["parameters"] = nlohmann::json::object();
1✔
124

125
    serializer::JSONSerializer ser_flat(false);
1✔
126
    j["subgraph"] = nlohmann::json::object();
1✔
127
    j["subgraph"]["0"] = nlohmann::json::object();
1✔
128
    ser_flat.serialize_node(j["subgraph"]["0"], map_);
1✔
129
}
1✔
130

131
GPUConditionPropagation GPUConditionPropagation::
132
    from_json(builder::StructuredSDFGBuilder& builder, const nlohmann::json& j) {
1✔
133
    size_t map_id;
1✔
134
    const auto& node_desc = j.at("subgraph").at("0");
1✔
135
    map_id = node_desc.at("element_id").get<size_t>();
1✔
136

137
    auto element = builder.find_element_by_id(map_id);
1✔
138
    if (!element) {
1✔
UNCOV
139
        throw InvalidTransformationDescriptionException("Element with ID " + std::to_string(map_id) + " not found.");
×
UNCOV
140
    }
×
141
    auto map = dynamic_cast<structured_control_flow::Map*>(element);
1✔
142

143
    return GPUConditionPropagation(*map);
1✔
144
}
1✔
145

146
BarrierFinder::BarrierFinder(builder::StructuredSDFGBuilder& builder, sdfg::analysis::AnalysisManager& analysis_manager)
147
    : visitor::StructuredSDFGVisitor(builder, analysis_manager) {}
8✔
148

149
bool BarrierFinder::accept(structured_control_flow::Block& node) {
38✔
150
    for (auto& library_node : node.dataflow().nodes()) {
82✔
151
        if (auto barrier_node = dynamic_cast<data_flow::BarrierLocalNode*>(&library_node)) {
82✔
152
            return true;
20✔
153
        }
20✔
154
    }
82✔
155
    return false;
18✔
156
}
38✔
157

158
bool BarrierFinder::visit(structured_control_flow::ControlFlowNode* node) {
32✔
159
    if (auto block_stmt = dynamic_cast<structured_control_flow::Block*>(node)) {
32✔
UNCOV
160
        return this->accept(*block_stmt);
×
161
    } else if (auto sequence_stmt = dynamic_cast<structured_control_flow::Sequence*>(node)) {
32✔
162
        return this->visit_internal(*sequence_stmt);
10✔
163
    } else if (auto if_else_stmt = dynamic_cast<structured_control_flow::IfElse*>(node)) {
22✔
164
        for (int i = 0; i < if_else_stmt->size(); i++) {
12✔
165
            if (this->visit_internal(if_else_stmt->at(i).first)) {
6✔
UNCOV
166
                return true;
×
UNCOV
167
            }
×
168
        }
6✔
169
    } else if (auto for_stmt = dynamic_cast<structured_control_flow::For*>(node)) {
16✔
170
        return this->visit_internal(for_stmt->root());
6✔
171
    } else if (auto map_stmt = dynamic_cast<structured_control_flow::Map*>(node)) {
10✔
172
        return this->visit_internal(map_stmt->root());
10✔
173
    } else if (auto while_stmt = dynamic_cast<structured_control_flow::While*>(node)) {
10✔
UNCOV
174
        return this->visit_internal(while_stmt->root());
×
UNCOV
175
    } else if (auto continue_stmt = dynamic_cast<structured_control_flow::Continue*>(node)) {
×
UNCOV
176
        return this->accept(*continue_stmt);
×
177
    } else if (auto break_stmt = dynamic_cast<structured_control_flow::Break*>(node)) {
×
178
        return this->accept(*break_stmt);
×
179
    } else if (auto return_stmt = dynamic_cast<structured_control_flow::Return*>(node)) {
×
180
        return this->accept(*return_stmt);
×
181
    }
×
182

183
    return false;
6✔
184
}
32✔
185

186
} // namespace transformations
187
} // 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