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

daisytuner / docc / 25459771247

06 May 2026 08:37PM UTC coverage: 65.659% (+0.4%) from 65.223%
25459771247

push

github

web-flow
Merge pull request #704 from daisytuner/lcd-analysis

Refactors LoopCarriedDependencyAnalysis into standalone analysis

731 of 828 new or added lines in 13 files covered. (88.29%)

42 existing lines in 5 files now uncovered.

32175 of 49003 relevant lines covered (65.66%)

12934.86 hits per line

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

78.57
/sdfg/src/symbolic/utils.cpp
1
#include "sdfg/symbolic/utils.h"
2

3
#include <isl/ctx.h>
4
#include <isl/set.h>
5
#include <isl/space.h>
6

7
#include "sdfg/builder/sdfg_builder.h"
8
#include "sdfg/codegen/language_extensions/c_language_extension.h"
9
#include "sdfg/symbolic/assumptions.h"
10
#include "sdfg/symbolic/extreme_values.h"
11
#include "sdfg/symbolic/polynomials.h"
12
#include "sdfg/symbolic/symbolic.h"
13

14
namespace sdfg {
15
namespace symbolic {
16

17
// ISL-compatible printer that converts idiv to floord
18
class ISLSymbolicPrinter : public SymEngine::BaseVisitor<ISLSymbolicPrinter, SymEngine::CodePrinter> {
19
public:
20
    using SymEngine::CodePrinter::apply;
21
    using SymEngine::CodePrinter::bvisit;
22
    using SymEngine::CodePrinter::str_;
23

24
    void bvisit(const SymEngine::FunctionSymbol& x) {
232✔
25
        if (x.get_name() == "idiv") {
232✔
26
            // ISL uses floord(a, b) for floor division
27
            str_ = "floord(" + apply(x.get_args()[0]) + ", " + apply(x.get_args()[1]) + ")";
232✔
28
        } else if (x.get_name() == "iabs") {
232✔
29
            // ISL doesn't support abs directly, but we can express it
30
            str_ = apply(x.get_args()[0]); // Simplify: assume non-negative for ISL constraints
×
31
        } else {
×
32
            // Unknown function - print as-is and let ISL reject it during parsing
33
            std::ostringstream ss;
×
34
            ss << x.get_name() << "(";
×
35
            auto args = x.get_args();
×
36
            for (size_t i = 0; i < args.size(); i++) {
×
37
                ss << apply(args[i]);
×
38
                if (i < args.size() - 1) {
×
39
                    ss << ", ";
×
40
                }
×
41
            }
×
42
            ss << ")";
×
43
            str_ = ss.str();
×
44
        }
×
45
    }
232✔
46

47
    void _print_pow(
48
        std::ostringstream& o,
49
        const SymEngine::RCP<const SymEngine::Basic>& a,
50
        const SymEngine::RCP<const SymEngine::Basic>& b
51
    ) {
×
52
        // ISL doesn't support power - expand to multiplication for positive integer exponents
53
        if (SymEngine::is_a<SymEngine::Integer>(*b)) {
×
54
            auto exp_int = SymEngine::rcp_static_cast<const SymEngine::Integer>(b);
×
55
            try {
×
56
                long long val = exp_int->as_int();
×
57
                if (val >= 0 && val <= 10) { // Reasonable limit for expansion
×
58
                    std::string base_str = apply(a);
×
59
                    if (val == 0) {
×
60
                        o << "1";
×
61
                        return;
×
62
                    }
×
63
                    // For simple symbols/integers, don't add extra parentheses
64
                    bool needs_parens = !SymEngine::is_a<SymEngine::Symbol>(*a) &&
×
65
                                        !SymEngine::is_a<SymEngine::Integer>(*a);
×
66
                    for (long long i = 0; i < val; ++i) {
×
67
                        if (i > 0) {
×
68
                            o << "*";
×
69
                        }
×
70
                        if (needs_parens) {
×
71
                            o << "(" << base_str << ")";
×
72
                        } else {
×
73
                            o << base_str;
×
74
                        }
×
75
                    }
×
76
                    return;
×
77
                }
×
78
            } catch (const SymEngine::SymEngineException&) {
×
79
                // Fall through to default
80
            }
×
81
        }
×
82
        // Fall back to default printing (will likely fail in ISL)
83
        o << "(" << apply(a) << ")**(" << apply(b) << ")";
×
84
    }
×
85
};
86

87
static ISLSymbolicPrinter isl_printer;
88

89
std::string expression_to_map_str(const MultiExpression& expr, const Assumptions& assums) {
1,033✔
90
    // Get all symbols
91
    symbolic::SymbolSet syms;
1,033✔
92
    for (auto& expr : expr) {
1,549✔
93
        auto syms_expr = symbolic::atoms(expr);
1,549✔
94
        syms.insert(syms_expr.begin(), syms_expr.end());
1,549✔
95
    }
1,549✔
96

97
    // Distinguish between dimensions and parameters
98
    std::vector<std::string> dimensions;
1,033✔
99
    SymbolSet dimensions_syms;
1,033✔
100
    std::vector<std::string> parameters;
1,033✔
101
    SymbolSet parameters_syms;
1,033✔
102
    for (auto& sym : syms) {
1,479✔
103
        auto it = assums.find(sym);
1,479✔
104
        if (it != assums.end() && it->second.constant() && it->second.map().is_null()) {
1,479✔
105
            if (parameters_syms.find(sym) != parameters_syms.end()) {
4✔
106
                continue;
×
107
            }
×
108
            parameters.push_back(sym->get_name());
4✔
109
            parameters_syms.insert(sym);
4✔
110
        } else {
1,475✔
111
            if (dimensions_syms.find(sym) != dimensions_syms.end()) {
1,475✔
112
                continue;
×
113
            }
×
114
            dimensions.push_back(sym->get_name());
1,475✔
115
            dimensions_syms.insert(sym);
1,475✔
116
        }
1,475✔
117
    }
1,479✔
118

119
    // Generate constraints
120
    SymbolSet seen;
1,033✔
121
    auto constraints_syms = generate_constraints(syms, assums, seen);
1,033✔
122

123
    // Extend parameters with additional symbols from constraints
124
    for (auto& con : constraints_syms) {
8,188✔
125
        auto con_syms = symbolic::atoms(con);
8,188✔
126
        for (auto& con_sym : con_syms) {
10,135✔
127
            if (dimensions_syms.find(con_sym) == dimensions_syms.end()) {
10,135✔
128
                if (parameters_syms.find(con_sym) != parameters_syms.end()) {
4,927✔
129
                    continue;
3,816✔
130
                }
3,816✔
131
                parameters.push_back(con_sym->get_name());
1,111✔
132
                parameters_syms.insert(con_sym);
1,111✔
133
            }
1,111✔
134
        }
10,135✔
135
    }
8,188✔
136

137
    // Define map
138
    std::stringstream map_ss;
1,033✔
139
    if (!parameters.empty()) {
1,033✔
140
        std::sort(parameters.begin(), parameters.end());
913✔
141
        map_ss << "[";
913✔
142
        map_ss << helpers::join(parameters, ", ");
913✔
143
        map_ss << "] -> ";
913✔
144
    }
913✔
145
    map_ss << "{ [" + helpers::join(dimensions, ", ") + "] -> [";
1,033✔
146
    for (size_t i = 0; i < expr.size(); i++) {
2,582✔
147
        auto dim = expr[i];
1,549✔
148
        map_ss << isl_printer.apply(dim);
1,549✔
149
        if (i < expr.size() - 1) {
1,549✔
150
            map_ss << ", ";
516✔
151
        }
516✔
152
    }
1,549✔
153
    map_ss << "] ";
1,033✔
154

155
    std::vector<std::string> constraints;
1,033✔
156
    for (auto& con : constraints_syms) {
8,188✔
157
        auto con_str = constraint_to_isl_str(con);
8,188✔
158
        if (!con_str.empty()) {
8,188✔
159
            constraints.push_back(con_str);
5,746✔
160
        }
5,746✔
161
    }
8,188✔
162
    for (auto& dim : dimensions) {
1,475✔
163
        auto sym = symbolic::symbol(dim);
1,475✔
164
        auto map_func = assums.at(sym).map();
1,475✔
165
        if (map_func == SymEngine::null) {
1,475✔
166
            continue;
54✔
167
        }
54✔
168
        if (!SymEngine::is_a<SymEngine::Add>(*map_func)) {
1,421✔
169
            continue;
×
170
        }
×
171
        auto args = SymEngine::rcp_static_cast<const SymEngine::Add>(map_func)->get_args();
1,421✔
172
        if (args.size() != 2) {
1,421✔
173
            continue;
×
174
        }
×
175
        auto arg0 = args[0];
1,421✔
176
        auto arg1 = args[1];
1,421✔
177
        if (!symbolic::eq(arg0, symbolic::symbol(dim))) {
1,421✔
178
            arg0 = args[1];
1,421✔
179
            arg1 = args[0];
1,421✔
180
        }
1,421✔
181
        if (!symbolic::eq(arg0, symbolic::symbol(dim))) {
1,421✔
182
            continue;
×
183
        }
×
184
        if (!SymEngine::is_a<SymEngine::Integer>(*arg1)) {
1,421✔
185
            continue;
×
186
        }
×
187
        if (symbolic::eq(arg1, symbolic::one())) {
1,421✔
188
            continue;
1,403✔
189
        }
1,403✔
190
        auto lb = assums.at(sym).tight_lower_bound();
18✔
191
        if (lb == SymEngine::null) {
18✔
NEW
192
            continue;
×
NEW
193
        }
×
194
        if (!SymEngine::is_a<SymEngine::Integer>(*lb)) {
18✔
195
            continue;
6✔
196
        }
6✔
197

198
        std::string iter = "__daisy_iterator_" + dim;
12✔
199
        std::string con = "exists " + iter + " : " + dim + " = " + isl_printer.apply(lb) + " + " + iter + " * " +
12✔
200
                          isl_printer.apply(arg1);
12✔
201
        constraints.push_back(con);
12✔
202
    }
12✔
203
    if (!constraints.empty()) {
1,033✔
204
        map_ss << " : ";
943✔
205
        map_ss << helpers::join(constraints, " and ");
943✔
206
    }
943✔
207

208
    map_ss << " }";
1,033✔
209

210
    std::string map = map_ss.str();
1,033✔
211
    return map;
1,033✔
212
}
1,033✔
213

214
std::tuple<std::string, std::string, std::string> expressions_to_intersection_map_str(
215
    const MultiExpression& expr1,
216
    const MultiExpression& expr2,
217
    const Symbol indvar,
218
    const Assumptions& assums1,
219
    const Assumptions& assums2
220
) {
2,560✔
221
    // Get all symbols
222
    symbolic::SymbolSet syms;
2,560✔
223
    for (auto& expr : expr1) {
3,144✔
224
        auto syms_expr = symbolic::atoms(expr);
3,144✔
225
        syms.insert(syms_expr.begin(), syms_expr.end());
3,144✔
226
    }
3,144✔
227
    for (auto& expr : expr2) {
3,144✔
228
        auto syms_expr = symbolic::atoms(expr);
3,144✔
229
        syms.insert(syms_expr.begin(), syms_expr.end());
3,144✔
230
    }
3,144✔
231

232
    // Distinguish between dimensions and parameters
233
    std::vector<std::string> dimensions;
2,560✔
234
    SymbolSet dimensions_syms;
2,560✔
235
    std::vector<std::string> parameters;
2,560✔
236
    SymbolSet parameters_syms;
2,560✔
237
    for (auto& sym : syms) {
4,380✔
238
        if (sym->get_name() != indvar->get_name() && assums1.at(sym).constant() && assums2.at(sym).constant()) {
4,380✔
239
            if (parameters_syms.find(sym) != parameters_syms.end()) {
882✔
240
                continue;
×
241
            }
×
242
            parameters.push_back(sym->get_name());
882✔
243
            parameters_syms.insert(sym);
882✔
244
        } else {
3,498✔
245
            if (dimensions_syms.find(sym) != dimensions_syms.end()) {
3,498✔
246
                continue;
×
247
            }
×
248
            dimensions.push_back(sym->get_name());
3,498✔
249
            dimensions_syms.insert(sym);
3,498✔
250
        }
3,498✔
251
    }
4,380✔
252

253
    // Generate constraints
254
    SymbolSet seen;
2,560✔
255
    auto constraints_syms_1 = generate_constraints(syms, assums1, seen);
2,560✔
256
    seen.clear();
2,560✔
257
    auto constraints_syms_2 = generate_constraints(syms, assums2, seen);
2,560✔
258

259
    // Extend parameters with additional symbols from constraints
260
    for (auto& con : constraints_syms_1) {
27,873✔
261
        auto con_syms = symbolic::atoms(con);
27,873✔
262
        for (auto& con_sym : con_syms) {
36,084✔
263
            if (dimensions_syms.find(con_sym) == dimensions_syms.end()) {
36,084✔
264
                if (parameters_syms.find(con_sym) != parameters_syms.end()) {
21,495✔
265
                    continue;
17,412✔
266
                }
17,412✔
267
                // Check if this symbol is the indvar - if so, it should be a dimension, not a parameter
268
                if (con_sym->get_name() == indvar->get_name()) {
4,083✔
269
                    dimensions.push_back(con_sym->get_name());
400✔
270
                    dimensions_syms.insert(con_sym);
400✔
271
                } else {
3,683✔
272
                    parameters.push_back(con_sym->get_name());
3,683✔
273
                    parameters_syms.insert(con_sym);
3,683✔
274
                }
3,683✔
275
            }
4,083✔
276
        }
36,084✔
277
    }
27,873✔
278
    for (auto& con : constraints_syms_2) {
28,406✔
279
        auto con_syms = symbolic::atoms(con);
28,406✔
280
        for (auto& con_sym : con_syms) {
36,990✔
281
            if (dimensions_syms.find(con_sym) == dimensions_syms.end()) {
36,990✔
282
                if (parameters_syms.find(con_sym) != parameters_syms.end()) {
21,506✔
283
                    continue;
21,429✔
284
                }
21,429✔
285
                // Check if this symbol is the indvar - if so, it should be a dimension, not a parameter
286
                if (con_sym->get_name() == indvar->get_name()) {
77✔
287
                    dimensions.push_back(con_sym->get_name());
×
288
                    dimensions_syms.insert(con_sym);
×
289
                } else {
77✔
290
                    parameters.push_back(con_sym->get_name());
77✔
291
                    parameters_syms.insert(con_sym);
77✔
292
                }
77✔
293
            }
77✔
294
        }
36,990✔
295
    }
28,406✔
296

297
    // Define two maps
298
    std::stringstream map_1_ss;
2,560✔
299
    std::stringstream map_2_ss;
2,560✔
300
    if (!parameters.empty()) {
2,560✔
301
        map_1_ss << "[";
2,425✔
302
        map_1_ss << helpers::join(parameters, ", ");
2,425✔
303
        map_1_ss << "] -> ";
2,425✔
304
        map_2_ss << "[";
2,425✔
305
        map_2_ss << helpers::join(parameters, ", ");
2,425✔
306
        map_2_ss << "] -> ";
2,425✔
307
    }
2,425✔
308
    map_1_ss << "{ [";
2,560✔
309
    map_2_ss << "{ [";
2,560✔
310
    for (size_t i = 0; i < dimensions.size(); i++) {
6,458✔
311
        map_1_ss << dimensions[i] + "_1";
3,898✔
312
        map_2_ss << dimensions[i] + "_2";
3,898✔
313
        if (i < dimensions.size() - 1) {
3,898✔
314
            map_1_ss << ", ";
1,930✔
315
            map_2_ss << ", ";
1,930✔
316
        }
1,930✔
317
    }
3,898✔
318
    map_1_ss << "] -> [";
2,560✔
319
    map_2_ss << "] -> [";
2,560✔
320
    for (size_t i = 0; i < expr1.size(); i++) {
5,704✔
321
        auto dim = expr1[i];
3,144✔
322
        for (auto& iter : dimensions) {
5,247✔
323
            dim = symbolic::subs(dim, symbolic::symbol(iter), symbolic::symbol(iter + "_1"));
5,247✔
324
        }
5,247✔
325
        map_1_ss << isl_printer.apply(dim);
3,144✔
326
        if (i < expr1.size() - 1) {
3,144✔
327
            map_1_ss << ", ";
584✔
328
        }
584✔
329
    }
3,144✔
330
    for (size_t i = 0; i < expr2.size(); i++) {
5,704✔
331
        auto dim = expr2[i];
3,144✔
332
        for (auto& iter : dimensions) {
5,247✔
333
            dim = symbolic::subs(dim, symbolic::symbol(iter), symbolic::symbol(iter + "_2"));
5,247✔
334
        }
5,247✔
335
        map_2_ss << isl_printer.apply(dim);
3,144✔
336
        if (i < expr2.size() - 1) {
3,144✔
337
            map_2_ss << ", ";
584✔
338
        }
584✔
339
    }
3,144✔
340
    map_1_ss << "] ";
2,560✔
341
    map_2_ss << "] ";
2,560✔
342

343
    std::vector<std::string> constraints_1;
2,560✔
344
    // Add bounds
345
    for (auto& con : constraints_syms_1) {
27,873✔
346
        auto con_1 = con;
27,873✔
347
        for (auto& iter : dimensions) {
54,320✔
348
            con_1 = symbolic::subs(con_1, symbolic::symbol(iter), symbolic::symbol(iter + "_1"));
54,320✔
349
        }
54,320✔
350
        auto con_str_1 = constraint_to_isl_str(con_1);
27,873✔
351
        if (con_str_1.empty()) {
27,873✔
352
            continue;
8,321✔
353
        }
8,321✔
354
        constraints_1.push_back(con_str_1);
19,552✔
355
    }
19,552✔
356
    for (auto& dim : dimensions) {
3,898✔
357
        auto sym = symbolic::symbol(dim);
3,898✔
358
        auto map_func = assums1.at(sym).map();
3,898✔
359
        if (map_func == SymEngine::null) {
3,898✔
360
            continue;
777✔
361
        }
777✔
362
        if (!SymEngine::is_a<SymEngine::Add>(*map_func)) {
3,121✔
363
            continue;
×
364
        }
×
365
        auto args = SymEngine::rcp_static_cast<const SymEngine::Add>(map_func)->get_args();
3,121✔
366
        if (args.size() != 2) {
3,121✔
367
            continue;
×
368
        }
×
369
        auto arg0 = args[0];
3,121✔
370
        auto arg1 = args[1];
3,121✔
371
        if (!symbolic::eq(arg0, symbolic::symbol(dim))) {
3,121✔
372
            arg0 = args[1];
3,121✔
373
            arg1 = args[0];
3,121✔
374
        }
3,121✔
375
        if (!symbolic::eq(arg0, symbolic::symbol(dim))) {
3,121✔
376
            continue;
×
377
        }
×
378
        if (!SymEngine::is_a<SymEngine::Integer>(*arg1)) {
3,121✔
379
            continue;
×
380
        }
×
381
        if (symbolic::eq(arg1, symbolic::one())) {
3,121✔
382
            continue;
2,727✔
383
        }
2,727✔
384
        auto lb = assums1.at(sym).tight_lower_bound();
394✔
385
        if (!SymEngine::is_a<SymEngine::Integer>(*lb)) {
394✔
386
            continue;
102✔
387
        }
102✔
388

389
        std::string dim1 = dim + "_1";
292✔
390
        std::string iter = "__daisy_iterator_" + dim1;
292✔
391
        std::string con = "exists " + iter + " : " + dim1 + " = " + isl_printer.apply(lb) + " + " + iter + " * " +
292✔
392
                          isl_printer.apply(arg1);
292✔
393
        constraints_1.push_back(con);
292✔
394
    }
292✔
395
    if (!constraints_1.empty()) {
2,560✔
396
        map_1_ss << " : ";
2,520✔
397
        map_1_ss << helpers::join(constraints_1, " and ");
2,520✔
398
    }
2,520✔
399
    map_1_ss << " }";
2,560✔
400

401
    std::vector<std::string> constraints_2;
2,560✔
402
    for (auto& con : constraints_syms_2) {
28,406✔
403
        auto con_2 = con;
28,406✔
404
        for (auto& iter : dimensions) {
56,497✔
405
            con_2 = symbolic::subs(con_2, symbolic::symbol(iter), symbolic::symbol(iter + "_2"));
56,497✔
406
        }
56,497✔
407
        auto con_str_2 = constraint_to_isl_str(con_2);
28,406✔
408
        if (con_str_2.empty()) {
28,406✔
409
            continue;
8,365✔
410
        }
8,365✔
411
        constraints_2.push_back(con_str_2);
20,041✔
412
    }
20,041✔
413
    for (auto& dim : dimensions) {
3,898✔
414
        auto sym = symbolic::symbol(dim);
3,898✔
415
        auto map_func = assums2.at(sym).map();
3,898✔
416
        if (map_func.is_null()) {
3,898✔
417
            continue;
675✔
418
        }
675✔
419
        if (!SymEngine::is_a<SymEngine::Add>(*map_func)) {
3,223✔
420
            continue;
×
421
        }
×
422
        auto args = SymEngine::rcp_static_cast<const SymEngine::Add>(map_func)->get_args();
3,223✔
423
        if (args.size() != 2) {
3,223✔
424
            continue;
×
425
        }
×
426
        auto arg0 = args[0];
3,223✔
427
        auto arg1 = args[1];
3,223✔
428
        if (!symbolic::eq(arg0, symbolic::symbol(dim))) {
3,223✔
429
            arg0 = args[1];
3,223✔
430
            arg1 = args[0];
3,223✔
431
        }
3,223✔
432
        if (!symbolic::eq(arg0, symbolic::symbol(dim))) {
3,223✔
433
            continue;
×
434
        }
×
435
        if (!SymEngine::is_a<SymEngine::Integer>(*arg1)) {
3,223✔
436
            continue;
×
437
        }
×
438
        if (symbolic::eq(arg1, symbolic::one())) {
3,223✔
439
            continue;
2,829✔
440
        }
2,829✔
441
        auto lb = assums2.at(sym).tight_lower_bound();
394✔
442
        if (!SymEngine::is_a<SymEngine::Integer>(*lb)) {
394✔
443
            continue;
102✔
444
        }
102✔
445

446
        std::string dim2 = dim + "_2";
292✔
447
        std::string iter = "__daisy_iterator_" + dim2;
292✔
448
        std::string con = "exists " + iter + " : " + dim2 + " = " + isl_printer.apply(lb) + " + " + iter + " * " +
292✔
449
                          isl_printer.apply(arg1);
292✔
450
        constraints_2.push_back(con);
292✔
451
    }
292✔
452
    if (!constraints_2.empty()) {
2,560✔
453
        map_2_ss << " : ";
2,520✔
454
        map_2_ss << helpers::join(constraints_2, " and ");
2,520✔
455
    }
2,520✔
456
    map_2_ss << " }";
2,560✔
457

458
    std::stringstream map_3_ss;
2,560✔
459
    map_3_ss << "{ [";
2,560✔
460
    for (size_t i = 0; i < dimensions.size(); i++) {
6,458✔
461
        map_3_ss << dimensions[i] + "_2";
3,898✔
462
        if (i < dimensions.size() - 1) {
3,898✔
463
            map_3_ss << ", ";
1,930✔
464
        }
1,930✔
465
    }
3,898✔
466
    map_3_ss << "] -> [";
2,560✔
467
    for (size_t i = 0; i < dimensions.size(); i++) {
6,458✔
468
        map_3_ss << dimensions[i] + "_1";
3,898✔
469
        if (i < dimensions.size() - 1) {
3,898✔
470
            map_3_ss << ", ";
1,930✔
471
        }
1,930✔
472
    }
3,898✔
473
    map_3_ss << "]";
2,560✔
474
    std::vector<std::string> monotonicity_constraints;
2,560✔
475
    if (dimensions_syms.find(indvar) != dimensions_syms.end()) {
2,560✔
476
        // For loop-carried dependencies, we only care about the forward direction
477
        // (iteration_1 < iteration_2 in execution order).
478
        // This ensures we detect real dependencies, not symmetric pairs.
479
        monotonicity_constraints.push_back(indvar->get_name() + "_1 < " + indvar->get_name() + "_2");
1,023✔
480
    }
1,023✔
481
    if (!monotonicity_constraints.empty()) {
2,560✔
482
        map_3_ss << " : ";
1,023✔
483
        map_3_ss << helpers::join(monotonicity_constraints, " and ");
1,023✔
484
    }
1,023✔
485
    map_3_ss << " }";
2,560✔
486

487
    std::string map_1 = map_1_ss.str();
2,560✔
488
    std::string map_2 = map_2_ss.str();
2,560✔
489
    std::string map_3 = map_3_ss.str();
2,560✔
490

491
    return {map_1, map_2, map_3};
2,560✔
492
}
2,560✔
493

494
ExpressionSet generate_constraints(SymbolSet& syms, const Assumptions& assums, SymbolSet& seen) {
70,626✔
495
    ExpressionSet constraints;
70,626✔
496
    for (auto& sym : syms) {
93,456✔
497
        if (assums.find(sym) == assums.end()) {
93,456✔
498
            continue;
8✔
499
        }
8✔
500
        if (seen.find(sym) != seen.end()) {
93,448✔
501
            continue;
73,893✔
502
        }
73,893✔
503
        seen.insert(sym);
19,555✔
504

505
        for (auto& ub : assums.at(sym).upper_bounds()) {
33,272✔
506
            auto con = symbolic::Le(sym, ub);
33,272✔
507
            auto con_syms = symbolic::atoms(con);
33,272✔
508
            constraints.insert(con);
33,272✔
509

510
            auto con_cons = generate_constraints(con_syms, assums, seen);
33,272✔
511
            constraints.insert(con_cons.begin(), con_cons.end());
33,272✔
512
        }
33,272✔
513
        for (auto& lb : assums.at(sym).lower_bounds()) {
31,201✔
514
            auto con = symbolic::Ge(sym, lb);
31,201✔
515
            auto con_syms = symbolic::atoms(con);
31,201✔
516
            constraints.insert(con);
31,201✔
517

518
            auto con_cons = generate_constraints(con_syms, assums, seen);
31,201✔
519
            constraints.insert(con_cons.begin(), con_cons.end());
31,201✔
520
        }
31,201✔
521
    }
19,555✔
522
    return constraints;
70,626✔
523
}
70,626✔
524

525
std::string constraint_to_isl_str(const Expression con) {
64,467✔
526
    if (SymEngine::is_a<SymEngine::StrictLessThan>(*con)) {
64,467✔
527
        auto le = SymEngine::rcp_static_cast<const SymEngine::StrictLessThan>(con);
×
528
        auto lhs = le->get_arg1();
×
529
        auto rhs = le->get_arg2();
×
530
        if (SymEngine::is_a<SymEngine::Infty>(*lhs) || SymEngine::is_a<SymEngine::Infty>(*rhs)) {
×
531
            return "";
×
532
        }
×
533
        auto res = isl_printer.apply(con);
×
534
        return res;
×
535
    } else if (SymEngine::is_a<SymEngine::LessThan>(*con)) {
64,467✔
536
        auto le = SymEngine::rcp_static_cast<const SymEngine::LessThan>(con);
64,465✔
537
        auto lhs = le->get_arg1();
64,465✔
538
        auto rhs = le->get_arg2();
64,465✔
539
        if (SymEngine::is_a<SymEngine::Infty>(*lhs) || SymEngine::is_a<SymEngine::Infty>(*rhs)) {
64,465✔
540
            return "";
19,126✔
541
        }
19,126✔
542
        auto res = isl_printer.apply(con);
45,339✔
543
        return res;
45,339✔
544
    } else if (SymEngine::is_a<SymEngine::Equality>(*con)) {
64,465✔
545
        auto eq = SymEngine::rcp_static_cast<const SymEngine::Equality>(con);
×
546
        auto lhs = eq->get_arg1();
×
547
        auto rhs = eq->get_arg2();
×
548
        if (SymEngine::is_a<SymEngine::Infty>(*lhs) || SymEngine::is_a<SymEngine::Infty>(*rhs)) {
×
549
            return "";
×
550
        }
×
551
        auto res = isl_printer.apply(con);
×
552
        return res;
×
553
    } else if (SymEngine::is_a<SymEngine::Unequality>(*con)) {
2✔
554
        auto ne = SymEngine::rcp_static_cast<const SymEngine::Unequality>(con);
×
555
        auto lhs = ne->get_arg1();
×
556
        auto rhs = ne->get_arg2();
×
557
        if (SymEngine::is_a<SymEngine::Infty>(*lhs) || SymEngine::is_a<SymEngine::Infty>(*rhs)) {
×
558
            return "";
×
559
        }
×
560
        auto res = isl_printer.apply(con);
×
561
        return res;
×
562
    }
×
563

564
    return "";
2✔
565
}
64,467✔
566

567
void canonicalize_map_dims(isl_map* map, const std::string& in_prefix, const std::string& out_prefix) {
916✔
568
    int n_in = isl_map_dim(map, isl_dim_in);
916✔
569
    int n_out = isl_map_dim(map, isl_dim_out);
916✔
570

571
    for (int i = 0; i < n_in; ++i) {
2,217✔
572
        std::string name = in_prefix + std::to_string(i);
1,301✔
573
        map = isl_map_set_dim_name(map, isl_dim_in, i, name.c_str());
1,301✔
574
    }
1,301✔
575

576
    for (int i = 0; i < n_out; ++i) {
2,307✔
577
        std::string name = out_prefix + std::to_string(i);
1,391✔
578
        map = isl_map_set_dim_name(map, isl_dim_out, i, name.c_str());
1,391✔
579
    }
1,391✔
580
}
916✔
581

582
} // namespace symbolic
583
} // 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