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

daisytuner / sdfglib / 20440855126

22 Dec 2025 06:40PM UTC coverage: 39.033% (-0.001%) from 39.034%
20440855126

push

github

web-flow
Merge pull request #404 from daisytuner/loop-info

Adds loop info to analysis and instrumentation

13484 of 44849 branches covered (30.07%)

Branch coverage included in aggregate %.

59 of 110 new or added lines in 7 files covered. (53.64%)

11 existing lines in 6 files now uncovered.

11622 of 19471 relevant lines covered (59.69%)

83.87 hits per line

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

31.16
/src/codegen/dispatchers/map_dispatcher.cpp
1
#include "sdfg/codegen/dispatchers/map_dispatcher.h"
2

3
#include "sdfg/analysis/loop_analysis.h"
4
#include "sdfg/analysis/users.h"
5
#include "sdfg/codegen/dispatchers/node_dispatcher_registry.h"
6
#include "sdfg/codegen/dispatchers/sequence_dispatcher.h"
7
#include "sdfg/codegen/instrumentation/instrumentation_info.h"
8
#include "sdfg/structured_control_flow/map.h"
9

10
namespace sdfg {
11
namespace codegen {
12

13
SchedTypeMapDispatcher::SchedTypeMapDispatcher(
1✔
14
    LanguageExtension& language_extension,
15
    StructuredSDFG& sdfg,
16
    analysis::AnalysisManager& analysis_manager,
17
    structured_control_flow::Map& node,
18
    InstrumentationPlan& instrumentation_plan,
19
    ArgCapturePlan& arg_capture_plan
20
)
21
    : NodeDispatcher(language_extension, sdfg, analysis_manager, node, instrumentation_plan, arg_capture_plan),
1✔
22
      node_(node) {
1✔
23

24
      };
1✔
25

26
void SchedTypeMapDispatcher::
27
    dispatch(PrettyPrinter& main_stream, PrettyPrinter& globals_stream, CodeSnippetFactory& library_snippet_factory) {
1✔
28
    auto dispatcher = MapDispatcherRegistry::instance().get_map_dispatcher(node_.schedule_type().value());
1!
29
    if (dispatcher) {
1!
30
        auto dispatcher_ptr =
31
            dispatcher(language_extension_, sdfg_, analysis_manager_, node_, instrumentation_plan_, arg_capture_plan_);
1!
32
        dispatcher_ptr->dispatch(main_stream, globals_stream, library_snippet_factory);
1!
33
    } else {
1✔
34
        throw std::runtime_error("Unsupported map schedule type: " + std::string(node_.schedule_type().value()));
×
35
    }
36
};
1✔
37

38
SequentialMapDispatcher::SequentialMapDispatcher(
1✔
39
    LanguageExtension& language_extension,
40
    StructuredSDFG& sdfg,
41
    analysis::AnalysisManager& analysis_manager,
42
    structured_control_flow::Map& node,
43
    InstrumentationPlan& instrumentation_plan,
44
    ArgCapturePlan& arg_capture_plan
45
)
46
    : NodeDispatcher(language_extension, sdfg, analysis_manager, node, instrumentation_plan, arg_capture_plan),
1✔
47
      node_(node) {
1✔
48

49
      };
1✔
50

51
void SequentialMapDispatcher::dispatch_node(
1✔
52
    PrettyPrinter& main_stream, PrettyPrinter& globals_stream, CodeSnippetFactory& library_snippet_factory
53
) {
54
    main_stream << "// Map" << std::endl;
1✔
55
    main_stream << "for";
1✔
56
    main_stream << "(";
1✔
57
    main_stream << node_.indvar()->get_name();
1!
58
    main_stream << " = ";
1✔
59
    main_stream << language_extension_.expression(node_.init());
1!
60
    main_stream << ";";
1✔
61
    main_stream << language_extension_.expression(node_.condition());
1!
62
    main_stream << ";";
1✔
63
    main_stream << node_.indvar()->get_name();
1!
64
    main_stream << " = ";
1✔
65
    main_stream << language_extension_.expression(node_.update());
1!
66
    main_stream << ")" << std::endl;
1✔
67
    main_stream << "{" << std::endl;
1✔
68

69
    main_stream.setIndent(main_stream.indent() + 4);
1✔
70
    SequenceDispatcher
71
        dispatcher(language_extension_, sdfg_, analysis_manager_, node_.root(), instrumentation_plan_, arg_capture_plan_);
1✔
72
    dispatcher.dispatch(main_stream, globals_stream, library_snippet_factory);
1✔
73
    main_stream.setIndent(main_stream.indent() - 4);
1✔
74

75
    main_stream << "}" << std::endl;
1✔
76
};
1✔
77

78
CPUParallelMapDispatcher::CPUParallelMapDispatcher(
3✔
79
    LanguageExtension& language_extension,
80
    StructuredSDFG& sdfg,
81
    analysis::AnalysisManager& analysis_manager,
82
    structured_control_flow::Map& node,
83
    InstrumentationPlan& instrumentation_plan,
84
    ArgCapturePlan& arg_capture_plan
85
)
86
    : NodeDispatcher(language_extension, sdfg, analysis_manager, node, instrumentation_plan, arg_capture_plan),
3✔
87
      node_(node) {
3✔
88

89
      };
3✔
90

91
void CPUParallelMapDispatcher::dispatch_node(
3✔
92
    PrettyPrinter& main_stream, PrettyPrinter& globals_stream, CodeSnippetFactory& library_snippet_factory
93
) {
94
    // Mark written locals as private
95
    analysis::AnalysisManager analysis_manager(sdfg_);
3✔
96
    auto& users = analysis_manager.get<analysis::Users>();
3!
97
    analysis::UsersView users_view(users, node_.root());
3!
98

99
    std::vector<std::string> locals;
3✔
100
    for (auto& entry : users.locals(node_.root())) {
3!
101
        if (users_view.writes(entry).size() > 0 || users_view.moves(entry).size() > 0) {
×
102
            locals.push_back(entry);
×
103
        }
×
104
    }
105

106
    // Generate code
107
    main_stream << "// Map" << std::endl;
3!
108
    main_stream << "#pragma omp parallel for";
3!
109

110
    main_stream << " schedule(";
3!
111
    if (structured_control_flow::ScheduleType_CPU_Parallel::omp_schedule(node_.schedule_type()) ==
3!
112
        structured_control_flow::OpenMPSchedule::Static) {
113
        main_stream << "static)";
1!
114
    } else if (structured_control_flow::ScheduleType_CPU_Parallel::omp_schedule(node_.schedule_type()) ==
3!
115
               structured_control_flow::OpenMPSchedule::Dynamic) {
116
        main_stream << "dynamic)";
2!
117
    } else if (structured_control_flow::ScheduleType_CPU_Parallel::omp_schedule(node_.schedule_type()) ==
2!
118
               structured_control_flow::OpenMPSchedule::Guided) {
119
        main_stream << "guided)";
×
120
    } else {
×
121
        throw std::runtime_error("Unsupported OpenMP schedule type");
×
122
    }
123

124
    if (!structured_control_flow::ScheduleType_CPU_Parallel::num_threads(node_.schedule_type()).is_null()) {
3!
125
        main_stream << " num_threads(";
1!
126
        main_stream
2✔
127
            << language_extension_
2!
128
                   .expression(structured_control_flow::ScheduleType_CPU_Parallel::num_threads(node_.schedule_type()));
1!
129
        main_stream << ")";
1!
130
    }
1✔
131

132
    if (locals.size() > 0) {
3!
133
        main_stream << " private(" << helpers::join(locals, ", ") << ")";
×
134
    }
×
135
    main_stream << std::endl;
3!
136
    main_stream << "for";
3!
137
    main_stream << "(";
3!
138
    main_stream << node_.indvar()->get_name();
3!
139
    main_stream << " = ";
3!
140
    main_stream << language_extension_.expression(node_.init());
3!
141
    main_stream << ";";
3!
142
    main_stream << language_extension_.expression(node_.condition());
3!
143
    main_stream << ";";
3!
144
    main_stream << node_.indvar()->get_name();
3!
145
    main_stream << " = ";
3!
146
    main_stream << language_extension_.expression(node_.update());
3!
147
    main_stream << ")" << std::endl;
3!
148
    main_stream << "{" << std::endl;
3!
149

150
    for (auto& local : locals) {
3!
151
        auto& type = sdfg_.type(local);
×
152
        if (type.storage_type().allocation() == types::StorageType::AllocationType::Managed) {
×
153
            if (type.storage_type().is_cpu_stack()) {
×
154
                main_stream << local << " = ";
×
155
                main_stream << "alloca(" << language_extension_.expression(type.storage_type().allocation_size())
×
156
                            << ")";
×
157
                main_stream << ";" << std::endl;
×
158
            } else if (type.storage_type().is_cpu_heap()) {
×
159
                main_stream << local << " = ";
×
160
                main_stream << language_extension_.external_prefix() << "malloc("
×
161
                            << language_extension_.expression(type.storage_type().allocation_size()) << ")";
×
162
                main_stream << ";" << std::endl;
×
163
            }
×
164
        }
×
165
    }
166

167
    main_stream.setIndent(main_stream.indent() + 4);
3!
168
    SequenceDispatcher
169
        dispatcher(language_extension_, sdfg_, analysis_manager_, node_.root(), instrumentation_plan_, arg_capture_plan_);
3!
170
    dispatcher.dispatch(main_stream, globals_stream, library_snippet_factory);
3!
171
    main_stream.setIndent(main_stream.indent() - 4);
3!
172

173
    for (auto& local : locals) {
3!
174
        auto& type = sdfg_.type(local);
×
175
        if (type.storage_type().deallocation() == types::StorageType::AllocationType::Managed) {
×
176
            if (type.storage_type().is_cpu_heap()) {
×
177
                main_stream << language_extension_.external_prefix() << "free(" << local << ");" << std::endl;
×
178
            }
×
179
        }
×
180
    }
181

182
    main_stream << "}" << std::endl;
3!
183
};
3✔
184

185
InstrumentationInfo MapDispatcher::instrumentation_info() const {
×
186
    auto dispatcher = MapDispatcherRegistry::instance().get_map_dispatcher(node_.schedule_type().value());
×
187
    if (dispatcher) {
×
188
        auto dispatcher_ptr =
189
            dispatcher(language_extension_, sdfg_, analysis_manager_, node_, instrumentation_plan_, arg_capture_plan_);
×
190
        auto map_dispatcher_ptr = static_cast<MapDispatcher*>(dispatcher_ptr.get());
×
191
        return map_dispatcher_ptr->instrumentation_info();
×
192
    } else {
×
193
        throw std::runtime_error("Unsupported map schedule type: " + std::string(node_.schedule_type().value()));
×
194
    }
195
};
×
196

197
InstrumentationInfo SequentialMapDispatcher::instrumentation_info() const {
×
NEW
198
    long long loopnest_index = -1;
×
199

200
    // Check if this is an outermost loop
NEW
201
    auto& loop_tree_analysis = analysis_manager_.get<analysis::LoopAnalysis>();
×
202
    auto outermost_loops = loop_tree_analysis.outermost_loops();
×
203
    for (size_t i = 0; i < outermost_loops.size(); i++) {
×
204
        if (outermost_loops[i] == &node_) {
×
205
            loopnest_index = i;
×
206
            break;
×
207
        }
208
    }
×
209

210
    // Query LoopInfo
211
    analysis::LoopInfo loop_info;
NEW
212
    if (loopnest_index != -1) {
×
NEW
213
        loop_info = loop_tree_analysis.loop_info(&node_);
×
NEW
214
    }
×
215

216
    // Perform FlopAnalysis
217
    std::unordered_map<std::string, std::string> metrics;
×
218
    auto& flop_analysis = analysis_manager_.get<analysis::FlopAnalysis>();
×
219
    auto flop = flop_analysis.get_if_available_for_codegen(&node_);
×
220
    if (!flop.is_null()) {
×
221
        std::string flop_str = language_extension_.expression(flop);
×
222
        metrics.insert({"flop", flop_str});
×
223
    }
×
224

NEW
225
    return InstrumentationInfo(
×
NEW
226
        node_.element_id(), ElementType_Map, TargetType_SEQUENTIAL, loop_info, loopnest_index, metrics
×
227
    );
UNCOV
228
};
×
229

230
InstrumentationInfo CPUParallelMapDispatcher::instrumentation_info() const {
×
NEW
231
    long long loopnest_index = -1;
×
232

233
    // Check if this is an outermost loop
NEW
234
    auto& loop_tree_analysis = analysis_manager_.get<analysis::LoopAnalysis>();
×
235
    auto outermost_loops = loop_tree_analysis.outermost_loops();
×
236
    for (size_t i = 0; i < outermost_loops.size(); i++) {
×
237
        if (outermost_loops[i] == &node_) {
×
238
            loopnest_index = i;
×
239
            break;
×
240
        }
241
    }
×
242

243
    // Query LoopInfo
244
    analysis::LoopInfo loop_info;
NEW
245
    if (loopnest_index != -1) {
×
NEW
246
        loop_info = loop_tree_analysis.loop_info(&node_);
×
NEW
247
    }
×
248

249
    // Perform FlopAnalysis
250
    std::unordered_map<std::string, std::string> metrics;
×
251
    auto& flop_analysis = analysis_manager_.get<analysis::FlopAnalysis>();
×
252
    auto flop = flop_analysis.get_if_available_for_codegen(&node_);
×
253
    if (!flop.is_null()) {
×
254
        std::string flop_str = language_extension_.expression(flop);
×
255
        metrics.insert({"flop", flop_str});
×
256
    }
×
257

NEW
258
    return InstrumentationInfo(
×
NEW
259
        node_.element_id(), ElementType_Map, TargetType_CPU_PARALLEL, loop_info, loopnest_index, metrics
×
260
    );
UNCOV
261
};
×
262

263
} // namespace codegen
264
} // 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