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

daisytuner / docc / 23979317520

04 Apr 2026 12:54PM UTC coverage: 64.736% (+0.006%) from 64.73%
23979317520

push

github

web-flow
Merge pull request #644 from daisytuner/loop-normal-form-api

adapts new loop analysis api

39 of 44 new or added lines in 16 files covered. (88.64%)

4 existing lines in 3 files now uncovered.

29098 of 44949 relevant lines covered (64.74%)

532.85 hits per line

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

0.0
/opt/src/transformations/offloading/rocm_parallelize_nested_map.cpp
1
#include "sdfg/transformations/offloading/rocm_parallelize_nested_map.h"
2

3
#include <sdfg/analysis/loop_analysis.h>
4
#include "sdfg/exceptions.h"
5
#include "sdfg/symbolic/symbolic.h"
6
#include "sdfg/targets/rocm/rocm.h"
7

8
namespace sdfg {
9
namespace transformations {
10

11
ROCMParallelizeNestedMap::ROCMParallelizeNestedMap(structured_control_flow::Map& loop, size_t block_size)
12
    : loop_(loop), block_size_(block_size) {}
×
13

14
std::string ROCMParallelizeNestedMap::name() const { return "ROCMParallelizeNestedMap"; }
×
15

16
bool ROCMParallelizeNestedMap::
17
    can_be_applied(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
×
18
    auto& loop_analysis = analysis_manager.get<analysis::LoopAnalysis>();
×
19

20
    // Condition: Check if map is not yet parallelized with ROCM
21
    if (loop_.schedule_type().value() != ScheduleType_Sequential::value()) {
×
22
        return false;
×
23
    }
×
24

25
    // Condition: Check if parent loop exists
26
    auto parent = loop_analysis.parent_loop(&loop_);
×
27
    if (parent == nullptr) {
×
28
        return false;
×
29
    }
×
30

31
    // Condition: Check if parent loop is a ROCM map, and not Z dimension (final dimension)
32
    if (auto map = dynamic_cast<structured_control_flow::Map*>(parent)) {
×
33
        if (map->schedule_type().value() != rocm::ScheduleType_ROCM::value()) {
×
34
            return false;
×
35
        }
×
36
        if (rocm::ScheduleType_ROCM::dimension(map->schedule_type()) == rocm::ROCMDimension::Z) {
×
37
            return false;
×
38
        }
×
39
        auto parent_indvar = map->indvar();
×
40
        auto ancestor = parent;
×
41
        while (ancestor) {
×
42
            if (auto map_ancestor = dynamic_cast<structured_control_flow::Map*>(ancestor)) {
×
43
                parent_indvar = map_ancestor->indvar();
×
44
                for (auto& arg : symbolic::atoms(loop_.condition())) {
×
45
                    if (symbolic::eq(arg, parent_indvar)) {
×
46
                        return false;
×
47
                    }
×
48
                }
×
49
            }
×
50
            ancestor = loop_analysis.parent_loop(ancestor);
×
51
        }
×
52
    } else {
×
53
        return false;
×
54
    }
×
55

56
    // Condition: Check if current loop starts from 0
57
    if (!symbolic::eq(loop_.init(), symbolic::zero())) {
×
58
        return false;
×
59
    }
×
60

61
    // Condition: Loop has a stride of 1
NEW
62
    auto stride = loop_.stride();
×
63
    if (!symbolic::eq(stride, symbolic::one())) {
×
64
        return false;
×
65
    }
×
66

67
    return true;
×
68
}
×
69

70
void ROCMParallelizeNestedMap::apply(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
×
71
    auto& loop_analysis = analysis_manager.get<analysis::LoopAnalysis>();
×
72
    auto parent = loop_analysis.parent_loop(&loop_);
×
73

74
    auto parent_dim =
×
75
        rocm::ScheduleType_ROCM::dimension(static_cast<structured_control_flow::Map*>(parent)->schedule_type());
×
76

77
    rocm::ROCMDimension child_dim;
×
78
    if (parent_dim == rocm::ROCMDimension::X) {
×
79
        child_dim = rocm::ROCMDimension::Y;
×
80
    } else if (parent_dim == rocm::ROCMDimension::Y) {
×
81
        child_dim = rocm::ROCMDimension::Z;
×
82
    } else {
×
83
        throw InvalidSDFGException("Parent loop is Z dimension, cannot parallelize nested map.");
×
84
    }
×
85

86
    auto new_schedule = rocm::ScheduleType_ROCM::create();
×
87
    rocm::ScheduleType_ROCM::dimension(new_schedule, child_dim);
×
88
    rocm::ScheduleType_ROCM::block_size(new_schedule, symbolic::integer(block_size_));
×
89

90
    builder.update_schedule_type(loop_, new_schedule);
×
91
}
×
92

93
void ROCMParallelizeNestedMap::to_json(nlohmann::json& j) const {
×
94
    if (dynamic_cast<structured_control_flow::For*>(&loop_)) {
×
95
        throw std::runtime_error("ROCMParallelizeNestedMap transformation does not support for-loops.");
×
96
    }
×
97
    j["transformation_type"] = this->name();
×
98

99
    // Describe the subgraph in a form compatible with EmbeddingRecorder/EmbeddingReplayer.
100
    // Keep the existing "loop" and "block_size" fields for backward compatibility.
101
    j["subgraph"] = {{"0", {{"element_id", loop_.element_id()}, {"type", "map"}}}};
×
102

103
    j["parameters"] = {{"block_size", block_size_}};
×
104

105
    j["loop"] = loop_.element_id();
×
106
    j["block_size"] = block_size_;
×
107
}
×
108

109
ROCMParallelizeNestedMap ROCMParallelizeNestedMap::
110
    from_json(builder::StructuredSDFGBuilder& builder, const nlohmann::json& j) {
×
111
    // Prefer the embedding-compatible representation (subgraph/parameters),
112
    // but fall back to legacy fields (loop/block_size) if needed.
113
    size_t loop_id;
×
114
    if (j.contains("subgraph")) {
×
115
        const auto& subgraph = j.at("subgraph");
×
116
        const auto& node_desc = subgraph.at("0");
×
117
        loop_id = node_desc.at("element_id").get<size_t>();
×
118
    } else {
×
119
        loop_id = j.at("loop").get<size_t>();
×
120
    }
×
121

122
    size_t block_size;
×
123
    if (j.contains("parameters") && j.at("parameters").contains("block_size")) {
×
124
        block_size = j.at("parameters").at("block_size").get<size_t>();
×
125
    } else {
×
126
        block_size = j.at("block_size").get<size_t>();
×
127
    }
×
128
    auto element = builder.find_element_by_id(loop_id);
×
129
    if (!element) {
×
130
        throw InvalidTransformationDescriptionException("Element with ID " + std::to_string(loop_id) + " not found.");
×
131
    }
×
132
    auto loop = dynamic_cast<structured_control_flow::Map*>(element);
×
133
    if (!loop) {
×
134
        throw InvalidTransformationDescriptionException("Element with ID " + std::to_string(loop_id) + " is not a loop.");
×
135
    }
×
136
    return ROCMParallelizeNestedMap(*loop, block_size);
×
137
}
×
138

139
} // namespace transformations
140
} // 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