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

daisytuner / sdfglib / 17948757733

23 Sep 2025 02:05PM UTC coverage: 61.239% (+0.07%) from 61.165%
17948757733

push

github

web-flow
Merge pull request #239 from daisytuner/loop-normalization-rotation

extends loop normalization to rotate loops

75 of 97 new or added lines in 2 files covered. (77.32%)

19 existing lines in 3 files now uncovered.

9557 of 15606 relevant lines covered (61.24%)

108.78 hits per line

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

59.63
/src/codegen/code_generator.cpp
1
#include "sdfg/codegen/code_generator.h"
2
#include <symengine/constants.h>
3
#include <symengine/dict.h>
4
#include <symengine/number.h>
5
#include "sdfg/analysis/analysis.h"
6
#include "sdfg/analysis/mem_access_range_analysis.h"
7
#include "sdfg/analysis/type_analysis.h"
8
#include "sdfg/codegen/instrumentation/capture_var_plan.h"
9
#include "sdfg/symbolic/symbolic.h"
10
#include "sdfg/types/structure.h"
11

12
namespace sdfg {
13
namespace codegen {
14

15
std::tuple<int, types::PrimitiveType> CodeGenerator::analyze_type_rec(
5✔
16
    symbolic::Expression* dims,
17
    int max_dim,
18
    int dim_idx,
19
    const types::IType& type,
20
    int arg_idx,
21
    const analysis::MemAccessRange* range,
22
    analysis::AnalysisManager& analysis_manager,
23
    const StructuredSDFG& sdfg,
24
    std::string var_name
25
) {
26
    if (dim_idx > max_dim) {
5✔
27
        std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << ": data nesting deeper than " << max_dim
×
28
                  << ", ignoring" << std::endl;
×
29
        return std::make_tuple(-1, types::Void);
×
30
    }
31

32
    if (auto* scalarType = dynamic_cast<const types::Scalar*>(&type)) {
5✔
33
        return std::make_tuple(dim_idx, scalarType->primitive_type());
3✔
34
    } else if (auto structureType = dynamic_cast<const sdfg::types::Structure*>(&type)) {
2✔
35
        return std::make_tuple(dim_idx, types::Void);
×
36
    } else if (auto* arrayType = dynamic_cast<const types::Array*>(&type)) {
2✔
37
        dims[dim_idx] = arrayType->num_elements();
1✔
38
        auto& inner = arrayType->element_type();
1✔
39

40
        return analyze_type_rec(dims, max_dim, dim_idx + 1, inner, arg_idx, range, analysis_manager, sdfg, var_name);
1✔
41
    } else if (auto* ptrType = dynamic_cast<const types::Pointer*>(&type)) {
1✔
42
        if (range && !range->is_undefined()) {
1✔
43
            const auto& dim = range->dims()[dim_idx];
1✔
44

45
            if (symbolic::eq(symbolic::zero(), dim.first)) {
1✔
46
                dims[dim_idx] = symbolic::add(dim.second, symbolic::one());
1✔
47
                const types::IType* inner = nullptr;
1✔
48
                if (ptrType->has_pointee_type()) {
1✔
49
                    inner = &(ptrType->pointee_type());
1✔
50
                } else {
1✔
51
                    if (dim_idx > 0) {
×
52
                        std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
53
                                  << ": missing pointee type for dim > 0, cannot capture!" << std::endl;
×
54
                        return std::make_tuple(-2, types::Void);
×
55
                    } else {
56
                        auto& type_analysis = analysis_manager.get<analysis::TypeAnalysis>();
×
57
                        auto outer = type_analysis.get_outer_type(var_name);
×
58
                        if (outer != nullptr) {
×
59
                            if (auto* ptrType_new = dynamic_cast<const types::Pointer*>(outer)) {
×
60
                                if (ptrType_new->has_pointee_type()) {
×
61
                                    inner = &(ptrType_new->pointee_type());
×
62
                                } else {
×
63
                                    std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
64
                                              << ": missing pointee type, cannot capture!" << std::endl;
×
65
                                    return std::make_tuple(-2, types::Void);
×
66
                                }
67
                            }
×
68
                        } else {
×
69
                            std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
70
                                      << ": could not infer type from container, cannot capture!" << std::endl;
×
71
                            return std::make_tuple(-2, types::Void);
×
72
                        }
73
                    }
74
                    if (inner == nullptr) {
×
75
                        std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
76
                                  << ": could not infer type from container, cannot capture!" << std::endl;
×
77
                        return std::make_tuple(-2, types::Void);
×
78
                    }
79
                }
80

81
                return analyze_type_rec(
1✔
82
                    dims, max_dim, dim_idx + 1, *inner, arg_idx, range, analysis_manager, sdfg, var_name
1✔
83
                );
84
            } else {
85
                std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx << ": has upper bound "
×
UNCOV
86
                          << dim.second->__str__() << ", but does not start at 0, cannot capture" << std::endl;
×
UNCOV
87
                return std::make_tuple(-2, types::Void);
×
88
            }
89
        } else {
90
            std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << " dim" << dim_idx
×
UNCOV
91
                      << ": missing range, cannot capture!" << std::endl;
×
UNCOV
92
            return std::make_tuple(-2, types::Void);
×
93
        }
94
    } else {
95
        std::cerr << "In '" << sdfg_.name() << "', arg" << arg_idx << ": unsupported type " << type.print()
×
UNCOV
96
                  << ", cannot capture!" << std::endl;
×
UNCOV
97
        return std::make_tuple(-1, types::Void);
×
98
    }
99
}
5✔
100

101
bool CodeGenerator::add_capture_plan(
3✔
102
    const std::string& var_name,
103
    int arg_idx,
104
    bool is_external,
105
    std::vector<CaptureVarPlan>& plan,
106
    const analysis::MemAccessRanges& ranges
107
) {
108
    const types::IType* type = nullptr;
3✔
109
    if (is_external) {
3✔
110
        auto& pointer_type = dynamic_cast<const types::Pointer&>(sdfg_.type(var_name));
1✔
111
        assert(pointer_type.has_pointee_type() && "Externals must have a pointee type");
2✔
112
        type = &pointer_type.pointee_type();
1✔
113
    } else {
1✔
114
        type = &sdfg_.type(var_name);
2✔
115
    }
116

117
    const auto* range = ranges.get(var_name);
3✔
118

119
    analysis::AnalysisManager analysis_manager(sdfg_);
3✔
120

121
    symbolic::Expression dims[3];
9✔
122

123
    int dim_count = 0;
3✔
124
    types::PrimitiveType inner_type;
125

126
    std::tie(dim_count, inner_type) =
3✔
127
        analyze_type_rec(dims, 3, 0, *type, arg_idx, range, analysis_manager, sdfg_, var_name);
3✔
128

129
    bool is_read = range ? range->saw_read() : true;
3✔
130
    bool is_written = range ? range->saw_write() : true;
3✔
131

132
    if (dim_count == 0) {
3✔
133
        plan.emplace_back(
4✔
134
            is_read || is_written, is_written && is_external, CaptureVarType::CapRaw, arg_idx, is_external, inner_type
2✔
135
        );
136
    } else if (dim_count == 1) {
3✔
UNCOV
137
        plan.emplace_back(is_read, is_written, CaptureVarType::Cap1D, arg_idx, is_external, inner_type, dims[0]);
×
138
    } else if (dim_count == 2) {
1✔
139
        plan.emplace_back(is_read, is_written, CaptureVarType::Cap2D, arg_idx, is_external, inner_type, dims[0], dims[1]);
1✔
140
    } else if (dim_count == 3) {
1✔
UNCOV
141
        plan.emplace_back(
×
UNCOV
142
            is_read, is_written, CaptureVarType::Cap3D, arg_idx, is_external, inner_type, dims[0], dims[1], dims[2]
×
143
        );
UNCOV
144
    } else {
×
UNCOV
145
        return false;
×
146
    }
147

148
    return true;
3✔
149
}
3✔
150

151
std::unique_ptr<std::vector<CaptureVarPlan>> CodeGenerator::create_capture_plans() {
1✔
152
    auto name = sdfg_.name();
1✔
153

154
    analysis::AnalysisManager analysis_manager(sdfg_);
1✔
155
    const auto& args = sdfg_.arguments();
1✔
156
    auto& exts = sdfg_.externals();
1✔
157
    const auto& ranges = analysis_manager.get<analysis::MemAccessRanges>();
1✔
158

159
    auto plan = std::make_unique<std::vector<CaptureVarPlan>>();
1✔
160

161
    bool working = true;
1✔
162

163
    int arg_idx = -1;
1✔
164
    for (auto& arg_name : args) {
3✔
165
        ++arg_idx;
2✔
166

167
        working &= add_capture_plan(arg_name, arg_idx, false, *plan.get(), ranges);
2✔
168
    }
169

170
    for (auto& arg_name : exts) {
2✔
171
        if (sdfg_.type(arg_name).type_id() == types::TypeID::Function) {
1✔
UNCOV
172
            continue;
×
173
        }
174
        ++arg_idx;
1✔
175

176
        working &= add_capture_plan(arg_name, arg_idx, true, *plan.get(), ranges);
1✔
177
    }
178

179
    if (!working) {
1✔
UNCOV
180
        std::cerr << "In '" << name << "': could not create capture plan, returning empty plan" << std::endl;
×
UNCOV
181
        return std::make_unique<std::vector<CaptureVarPlan>>();
×
182
    }
183

184
    return plan;
1✔
185
}
1✔
186

187
} // namespace codegen
188
} // 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