1 | /* |
2 | * Copyright 2012 Ecole Normale Superieure |
3 | * Copyright 2015-2016 Sven Verdoolaege |
4 | * |
5 | * Use of this software is governed by the MIT license |
6 | * |
7 | * Written by Sven Verdoolaege, |
8 | * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France |
9 | */ |
10 | |
11 | #include <isl_schedule_constraints.h> |
12 | #include <isl/schedule.h> |
13 | #include <isl/space.h> |
14 | #include <isl/set.h> |
15 | #include <isl/map.h> |
16 | #include <isl/union_set.h> |
17 | #include <isl/union_map.h> |
18 | #include <isl/stream.h> |
19 | |
20 | /* The constraints that need to be satisfied by a schedule on "domain". |
21 | * |
22 | * "context" specifies extra constraints on the parameters. |
23 | * |
24 | * "validity" constraints map domain elements i to domain elements |
25 | * that should be scheduled after i. (Hard constraint) |
26 | * "proximity" constraints map domain elements i to domains elements |
27 | * that should be scheduled as early as possible after i (or before i). |
28 | * (Soft constraint) |
29 | * |
30 | * "condition" and "conditional_validity" constraints map possibly "tagged" |
31 | * domain elements i -> s to "tagged" domain elements j -> t. |
32 | * The elements of the "conditional_validity" constraints, but without the |
33 | * tags (i.e., the elements i -> j) are treated as validity constraints, |
34 | * except that during the construction of a tilable band, |
35 | * the elements of the "conditional_validity" constraints may be violated |
36 | * provided that all adjacent elements of the "condition" constraints |
37 | * are local within the band. |
38 | * A dependence is local within a band if domain and range are mapped |
39 | * to the same schedule point by the band. |
40 | */ |
41 | struct isl_schedule_constraints { |
42 | isl_union_set *domain; |
43 | isl_set *context; |
44 | |
45 | isl_union_map *constraint[isl_edge_last + 1]; |
46 | }; |
47 | |
48 | __isl_give isl_schedule_constraints *isl_schedule_constraints_copy( |
49 | __isl_keep isl_schedule_constraints *sc) |
50 | { |
51 | isl_ctx *ctx; |
52 | isl_schedule_constraints *sc_copy; |
53 | enum isl_edge_type i; |
54 | |
55 | ctx = isl_union_set_get_ctx(uset: sc->domain); |
56 | sc_copy = isl_calloc_type(ctx, struct isl_schedule_constraints); |
57 | if (!sc_copy) |
58 | return NULL; |
59 | |
60 | sc_copy->domain = isl_union_set_copy(uset: sc->domain); |
61 | sc_copy->context = isl_set_copy(set: sc->context); |
62 | if (!sc_copy->domain || !sc_copy->context) |
63 | return isl_schedule_constraints_free(sc: sc_copy); |
64 | |
65 | for (i = isl_edge_first; i <= isl_edge_last; ++i) { |
66 | sc_copy->constraint[i] = isl_union_map_copy(umap: sc->constraint[i]); |
67 | if (!sc_copy->constraint[i]) |
68 | return isl_schedule_constraints_free(sc: sc_copy); |
69 | } |
70 | |
71 | return sc_copy; |
72 | } |
73 | |
74 | /* Construct an empty (invalid) isl_schedule_constraints object. |
75 | * The caller is responsible for setting the domain and initializing |
76 | * all the other fields, e.g., by calling isl_schedule_constraints_init. |
77 | */ |
78 | static __isl_give isl_schedule_constraints *isl_schedule_constraints_alloc( |
79 | isl_ctx *ctx) |
80 | { |
81 | return isl_calloc_type(ctx, struct isl_schedule_constraints); |
82 | } |
83 | |
84 | /* Initialize all the fields of "sc", except domain, which is assumed |
85 | * to have been set by the caller. |
86 | */ |
87 | static __isl_give isl_schedule_constraints *isl_schedule_constraints_init( |
88 | __isl_take isl_schedule_constraints *sc) |
89 | { |
90 | isl_space *space; |
91 | isl_union_map *empty; |
92 | enum isl_edge_type i; |
93 | |
94 | if (!sc) |
95 | return NULL; |
96 | if (!sc->domain) |
97 | return isl_schedule_constraints_free(sc); |
98 | space = isl_union_set_get_space(uset: sc->domain); |
99 | if (!sc->context) |
100 | sc->context = isl_set_universe(space: isl_space_copy(space)); |
101 | empty = isl_union_map_empty(space); |
102 | for (i = isl_edge_first; i <= isl_edge_last; ++i) { |
103 | if (sc->constraint[i]) |
104 | continue; |
105 | sc->constraint[i] = isl_union_map_copy(umap: empty); |
106 | if (!sc->constraint[i]) |
107 | sc->domain = isl_union_set_free(uset: sc->domain); |
108 | } |
109 | isl_union_map_free(umap: empty); |
110 | |
111 | if (!sc->domain || !sc->context) |
112 | return isl_schedule_constraints_free(sc); |
113 | |
114 | return sc; |
115 | } |
116 | |
117 | /* Construct an isl_schedule_constraints object for computing a schedule |
118 | * on "domain". The initial object does not impose any constraints. |
119 | */ |
120 | __isl_give isl_schedule_constraints *isl_schedule_constraints_on_domain( |
121 | __isl_take isl_union_set *domain) |
122 | { |
123 | isl_ctx *ctx; |
124 | isl_schedule_constraints *sc; |
125 | |
126 | if (!domain) |
127 | return NULL; |
128 | |
129 | ctx = isl_union_set_get_ctx(uset: domain); |
130 | sc = isl_schedule_constraints_alloc(ctx); |
131 | if (!sc) |
132 | goto error; |
133 | |
134 | sc->domain = domain; |
135 | return isl_schedule_constraints_init(sc); |
136 | error: |
137 | isl_union_set_free(uset: domain); |
138 | return NULL; |
139 | } |
140 | |
141 | /* Replace the domain of "sc" by "domain". |
142 | */ |
143 | static __isl_give isl_schedule_constraints *isl_schedule_constraints_set_domain( |
144 | __isl_take isl_schedule_constraints *sc, |
145 | __isl_take isl_union_set *domain) |
146 | { |
147 | if (!sc || !domain) |
148 | goto error; |
149 | |
150 | isl_union_set_free(uset: sc->domain); |
151 | sc->domain = domain; |
152 | |
153 | return sc; |
154 | error: |
155 | isl_schedule_constraints_free(sc); |
156 | isl_union_set_free(uset: domain); |
157 | return NULL; |
158 | } |
159 | |
160 | /* Replace the context of "sc" by "context". |
161 | */ |
162 | __isl_give isl_schedule_constraints *isl_schedule_constraints_set_context( |
163 | __isl_take isl_schedule_constraints *sc, __isl_take isl_set *context) |
164 | { |
165 | if (!sc || !context) |
166 | goto error; |
167 | |
168 | isl_set_free(set: sc->context); |
169 | sc->context = context; |
170 | |
171 | return sc; |
172 | error: |
173 | isl_schedule_constraints_free(sc); |
174 | isl_set_free(set: context); |
175 | return NULL; |
176 | } |
177 | |
178 | /* Replace the constraints of type "type" in "sc" by "c". |
179 | * |
180 | * First detect any equality constraints that may be implicit in "c" |
181 | * in order to try and improve the accuracy of the input (and therefore |
182 | * also the output) of the isl_set_coefficients calls |
183 | * that are eventually performed on (some of) these constraints. |
184 | */ |
185 | static __isl_give isl_schedule_constraints *isl_schedule_constraints_set( |
186 | __isl_take isl_schedule_constraints *sc, enum isl_edge_type type, |
187 | __isl_take isl_union_map *c) |
188 | { |
189 | c = isl_union_map_detect_equalities(umap: c); |
190 | if (!sc || !c) |
191 | goto error; |
192 | |
193 | isl_union_map_free(umap: sc->constraint[type]); |
194 | sc->constraint[type] = c; |
195 | |
196 | return sc; |
197 | error: |
198 | isl_schedule_constraints_free(sc); |
199 | isl_union_map_free(umap: c); |
200 | return NULL; |
201 | } |
202 | |
203 | /* Replace the validity constraints of "sc" by "validity". |
204 | */ |
205 | __isl_give isl_schedule_constraints *isl_schedule_constraints_set_validity( |
206 | __isl_take isl_schedule_constraints *sc, |
207 | __isl_take isl_union_map *validity) |
208 | { |
209 | return isl_schedule_constraints_set(sc, type: isl_edge_validity, c: validity); |
210 | } |
211 | |
212 | /* Replace the coincidence constraints of "sc" by "coincidence". |
213 | */ |
214 | __isl_give isl_schedule_constraints *isl_schedule_constraints_set_coincidence( |
215 | __isl_take isl_schedule_constraints *sc, |
216 | __isl_take isl_union_map *coincidence) |
217 | { |
218 | return isl_schedule_constraints_set(sc, type: isl_edge_coincidence, |
219 | c: coincidence); |
220 | } |
221 | |
222 | /* Replace the proximity constraints of "sc" by "proximity". |
223 | */ |
224 | __isl_give isl_schedule_constraints *isl_schedule_constraints_set_proximity( |
225 | __isl_take isl_schedule_constraints *sc, |
226 | __isl_take isl_union_map *proximity) |
227 | { |
228 | return isl_schedule_constraints_set(sc, type: isl_edge_proximity, c: proximity); |
229 | } |
230 | |
231 | /* Replace the conditional validity constraints of "sc" by "condition" |
232 | * and "validity". |
233 | */ |
234 | __isl_give isl_schedule_constraints * |
235 | isl_schedule_constraints_set_conditional_validity( |
236 | __isl_take isl_schedule_constraints *sc, |
237 | __isl_take isl_union_map *condition, |
238 | __isl_take isl_union_map *validity) |
239 | { |
240 | sc = isl_schedule_constraints_set(sc, type: isl_edge_condition, c: condition); |
241 | sc = isl_schedule_constraints_set(sc, type: isl_edge_conditional_validity, |
242 | c: validity); |
243 | return sc; |
244 | } |
245 | |
246 | __isl_null isl_schedule_constraints *isl_schedule_constraints_free( |
247 | __isl_take isl_schedule_constraints *sc) |
248 | { |
249 | enum isl_edge_type i; |
250 | |
251 | if (!sc) |
252 | return NULL; |
253 | |
254 | isl_union_set_free(uset: sc->domain); |
255 | isl_set_free(set: sc->context); |
256 | for (i = isl_edge_first; i <= isl_edge_last; ++i) |
257 | isl_union_map_free(umap: sc->constraint[i]); |
258 | |
259 | free(ptr: sc); |
260 | |
261 | return NULL; |
262 | } |
263 | |
264 | isl_ctx *isl_schedule_constraints_get_ctx( |
265 | __isl_keep isl_schedule_constraints *sc) |
266 | { |
267 | return sc ? isl_union_set_get_ctx(uset: sc->domain) : NULL; |
268 | } |
269 | |
270 | /* Return the domain of "sc". |
271 | */ |
272 | __isl_give isl_union_set *isl_schedule_constraints_get_domain( |
273 | __isl_keep isl_schedule_constraints *sc) |
274 | { |
275 | if (!sc) |
276 | return NULL; |
277 | |
278 | return isl_union_set_copy(uset: sc->domain); |
279 | } |
280 | |
281 | /* Return the context of "sc". |
282 | */ |
283 | __isl_give isl_set *isl_schedule_constraints_get_context( |
284 | __isl_keep isl_schedule_constraints *sc) |
285 | { |
286 | if (!sc) |
287 | return NULL; |
288 | |
289 | return isl_set_copy(set: sc->context); |
290 | } |
291 | |
292 | /* Return the constraints of type "type" in "sc". |
293 | */ |
294 | __isl_give isl_union_map *isl_schedule_constraints_get( |
295 | __isl_keep isl_schedule_constraints *sc, enum isl_edge_type type) |
296 | { |
297 | if (!sc) |
298 | return NULL; |
299 | |
300 | return isl_union_map_copy(umap: sc->constraint[type]); |
301 | } |
302 | |
303 | /* Return the validity constraints of "sc". |
304 | */ |
305 | __isl_give isl_union_map *isl_schedule_constraints_get_validity( |
306 | __isl_keep isl_schedule_constraints *sc) |
307 | { |
308 | return isl_schedule_constraints_get(sc, type: isl_edge_validity); |
309 | } |
310 | |
311 | /* Return the coincidence constraints of "sc". |
312 | */ |
313 | __isl_give isl_union_map *isl_schedule_constraints_get_coincidence( |
314 | __isl_keep isl_schedule_constraints *sc) |
315 | { |
316 | return isl_schedule_constraints_get(sc, type: isl_edge_coincidence); |
317 | } |
318 | |
319 | /* Return the proximity constraints of "sc". |
320 | */ |
321 | __isl_give isl_union_map *isl_schedule_constraints_get_proximity( |
322 | __isl_keep isl_schedule_constraints *sc) |
323 | { |
324 | return isl_schedule_constraints_get(sc, type: isl_edge_proximity); |
325 | } |
326 | |
327 | /* Return the conditional validity constraints of "sc". |
328 | */ |
329 | __isl_give isl_union_map *isl_schedule_constraints_get_conditional_validity( |
330 | __isl_keep isl_schedule_constraints *sc) |
331 | { |
332 | return isl_schedule_constraints_get(sc, type: isl_edge_conditional_validity); |
333 | } |
334 | |
335 | /* Return the conditions for the conditional validity constraints of "sc". |
336 | */ |
337 | __isl_give isl_union_map * |
338 | isl_schedule_constraints_get_conditional_validity_condition( |
339 | __isl_keep isl_schedule_constraints *sc) |
340 | { |
341 | return isl_schedule_constraints_get(sc, type: isl_edge_condition); |
342 | } |
343 | |
344 | /* Add "c" to the constraints of type "type" in "sc". |
345 | */ |
346 | __isl_give isl_schedule_constraints *isl_schedule_constraints_add( |
347 | __isl_take isl_schedule_constraints *sc, enum isl_edge_type type, |
348 | __isl_take isl_union_map *c) |
349 | { |
350 | if (!sc || !c) |
351 | goto error; |
352 | |
353 | c = isl_union_map_union(umap1: sc->constraint[type], umap2: c); |
354 | sc->constraint[type] = c; |
355 | if (!c) |
356 | return isl_schedule_constraints_free(sc); |
357 | |
358 | return sc; |
359 | error: |
360 | isl_schedule_constraints_free(sc); |
361 | isl_union_map_free(umap: c); |
362 | return NULL; |
363 | } |
364 | |
365 | /* Can a schedule constraint of type "type" be tagged? |
366 | */ |
367 | static int may_be_tagged(enum isl_edge_type type) |
368 | { |
369 | if (type == isl_edge_condition || type == isl_edge_conditional_validity) |
370 | return 1; |
371 | return 0; |
372 | } |
373 | |
374 | /* Apply "umap" to the domains of the wrapped relations |
375 | * inside the domain and range of "c". |
376 | * |
377 | * That is, for each map of the form |
378 | * |
379 | * [D -> S] -> [E -> T] |
380 | * |
381 | * in "c", apply "umap" to D and E. |
382 | * |
383 | * D is exposed by currying the relation to |
384 | * |
385 | * D -> [S -> [E -> T]] |
386 | * |
387 | * E is exposed by doing the same to the inverse of "c". |
388 | */ |
389 | static __isl_give isl_union_map *apply_factor_domain( |
390 | __isl_take isl_union_map *c, __isl_keep isl_union_map *umap) |
391 | { |
392 | c = isl_union_map_curry(umap: c); |
393 | c = isl_union_map_apply_domain(umap1: c, umap2: isl_union_map_copy(umap)); |
394 | c = isl_union_map_uncurry(umap: c); |
395 | |
396 | c = isl_union_map_reverse(umap: c); |
397 | c = isl_union_map_curry(umap: c); |
398 | c = isl_union_map_apply_domain(umap1: c, umap2: isl_union_map_copy(umap)); |
399 | c = isl_union_map_uncurry(umap: c); |
400 | c = isl_union_map_reverse(umap: c); |
401 | |
402 | return c; |
403 | } |
404 | |
405 | /* Apply "umap" to domain and range of "c". |
406 | * If "tag" is set, then "c" may contain tags and then "umap" |
407 | * needs to be applied to the domains of the wrapped relations |
408 | * inside the domain and range of "c". |
409 | */ |
410 | static __isl_give isl_union_map *apply(__isl_take isl_union_map *c, |
411 | __isl_keep isl_union_map *umap, int tag) |
412 | { |
413 | isl_union_map *t; |
414 | |
415 | if (tag) |
416 | t = isl_union_map_copy(umap: c); |
417 | c = isl_union_map_apply_domain(umap1: c, umap2: isl_union_map_copy(umap)); |
418 | c = isl_union_map_apply_range(umap1: c, umap2: isl_union_map_copy(umap)); |
419 | if (!tag) |
420 | return c; |
421 | t = apply_factor_domain(c: t, umap); |
422 | c = isl_union_map_union(umap1: c, umap2: t); |
423 | return c; |
424 | } |
425 | |
426 | /* Apply "umap" to the domain of the schedule constraints "sc". |
427 | * |
428 | * The two sides of the various schedule constraints are adjusted |
429 | * accordingly. |
430 | */ |
431 | __isl_give isl_schedule_constraints *isl_schedule_constraints_apply( |
432 | __isl_take isl_schedule_constraints *sc, |
433 | __isl_take isl_union_map *umap) |
434 | { |
435 | enum isl_edge_type i; |
436 | |
437 | if (!sc || !umap) |
438 | goto error; |
439 | |
440 | for (i = isl_edge_first; i <= isl_edge_last; ++i) { |
441 | int tag = may_be_tagged(type: i); |
442 | |
443 | sc->constraint[i] = apply(c: sc->constraint[i], umap, tag); |
444 | if (!sc->constraint[i]) |
445 | goto error; |
446 | } |
447 | sc->domain = isl_union_set_apply(uset: sc->domain, umap); |
448 | if (!sc->domain) |
449 | return isl_schedule_constraints_free(sc); |
450 | |
451 | return sc; |
452 | error: |
453 | isl_schedule_constraints_free(sc); |
454 | isl_union_map_free(umap); |
455 | return NULL; |
456 | } |
457 | |
458 | /* An enumeration of the various keys that may appear in a YAML mapping |
459 | * of an isl_schedule_constraints object. |
460 | * The keys for the edge types are assumed to have the same values |
461 | * as the edge types in isl_edge_type. |
462 | */ |
463 | enum isl_sc_key { |
464 | isl_sc_key_error = -1, |
465 | isl_sc_key_validity = isl_edge_validity, |
466 | isl_sc_key_coincidence = isl_edge_coincidence, |
467 | isl_sc_key_condition = isl_edge_condition, |
468 | isl_sc_key_conditional_validity = isl_edge_conditional_validity, |
469 | isl_sc_key_proximity = isl_edge_proximity, |
470 | isl_sc_key_domain, |
471 | isl_sc_key_context, |
472 | isl_sc_key_end |
473 | }; |
474 | |
475 | /* Textual representations of the YAML keys for an isl_schedule_constraints |
476 | * object. |
477 | */ |
478 | static char *key_str[] = { |
479 | [isl_sc_key_validity] = "validity" , |
480 | [isl_sc_key_coincidence] = "coincidence" , |
481 | [isl_sc_key_condition] = "condition" , |
482 | [isl_sc_key_conditional_validity] = "conditional_validity" , |
483 | [isl_sc_key_proximity] = "proximity" , |
484 | [isl_sc_key_domain] = "domain" , |
485 | [isl_sc_key_context] = "context" , |
486 | }; |
487 | |
488 | #undef BASE |
489 | #define BASE set |
490 | #include "print_yaml_field_templ.c" |
491 | |
492 | #undef BASE |
493 | #define BASE union_set |
494 | #include "print_yaml_field_templ.c" |
495 | |
496 | #undef BASE |
497 | #define BASE union_map |
498 | #include "print_yaml_field_templ.c" |
499 | |
500 | /* Print a key, value pair for the edge of type "type" in "sc" to "p". |
501 | * |
502 | * If the edge relation is empty, then it is not printed since |
503 | * an empty relation is the default value. |
504 | */ |
505 | static __isl_give isl_printer *print_constraint(__isl_take isl_printer *p, |
506 | __isl_keep isl_schedule_constraints *sc, enum isl_edge_type type) |
507 | { |
508 | isl_bool empty; |
509 | |
510 | empty = isl_union_map_plain_is_empty(umap: sc->constraint[type]); |
511 | if (empty < 0) |
512 | return isl_printer_free(printer: p); |
513 | if (empty) |
514 | return p; |
515 | |
516 | p = print_yaml_field_union_map(p, name: key_str[type], val: sc->constraint[type]); |
517 | |
518 | return p; |
519 | } |
520 | |
521 | /* Print "sc" to "p" |
522 | * |
523 | * In particular, print the isl_schedule_constraints object as a YAML document. |
524 | * Fields with values that are (obviously) equal to their default values |
525 | * are not printed. |
526 | */ |
527 | __isl_give isl_printer *isl_printer_print_schedule_constraints( |
528 | __isl_take isl_printer *p, __isl_keep isl_schedule_constraints *sc) |
529 | { |
530 | isl_bool universe; |
531 | |
532 | if (!sc) |
533 | return isl_printer_free(printer: p); |
534 | |
535 | p = isl_printer_yaml_start_mapping(p); |
536 | p = print_yaml_field_union_set(p, name: key_str[isl_sc_key_domain], |
537 | val: sc->domain); |
538 | universe = isl_set_plain_is_universe(set: sc->context); |
539 | if (universe < 0) |
540 | return isl_printer_free(printer: p); |
541 | if (!universe) |
542 | p = print_yaml_field_set(p, name: key_str[isl_sc_key_context], |
543 | val: sc->context); |
544 | p = print_constraint(p, sc, type: isl_edge_validity); |
545 | p = print_constraint(p, sc, type: isl_edge_proximity); |
546 | p = print_constraint(p, sc, type: isl_edge_coincidence); |
547 | p = print_constraint(p, sc, type: isl_edge_condition); |
548 | p = print_constraint(p, sc, type: isl_edge_conditional_validity); |
549 | p = isl_printer_yaml_end_mapping(p); |
550 | |
551 | return p; |
552 | } |
553 | |
554 | #undef BASE |
555 | #define BASE schedule_constraints |
556 | #include <print_templ_yaml.c> |
557 | |
558 | #undef KEY |
559 | #define KEY enum isl_sc_key |
560 | #undef KEY_ERROR |
561 | #define KEY_ERROR isl_sc_key_error |
562 | #undef KEY_END |
563 | #define KEY_END isl_sc_key_end |
564 | #undef KEY_STR |
565 | #define KEY_STR key_str |
566 | #undef KEY_EXTRACT |
567 | #define extract_key |
568 | #undef KEY_GET |
569 | #define KEY_GET get_key |
570 | #include "extract_key.c" |
571 | |
572 | #undef BASE |
573 | #define BASE set |
574 | #include "read_in_string_templ.c" |
575 | |
576 | #undef BASE |
577 | #define BASE union_set |
578 | #include "read_in_string_templ.c" |
579 | |
580 | #undef BASE |
581 | #define BASE union_map |
582 | #include "read_in_string_templ.c" |
583 | |
584 | /* Read an isl_schedule_constraints object from "s". |
585 | * |
586 | * Start off with an empty (invalid) isl_schedule_constraints object and |
587 | * then fill up the fields based on the input. |
588 | * The input needs to contain at least a description of the domain. |
589 | * The other fields are set to defaults by isl_schedule_constraints_init |
590 | * if they are not specified in the input. |
591 | */ |
592 | __isl_give isl_schedule_constraints *isl_stream_read_schedule_constraints( |
593 | isl_stream *s) |
594 | { |
595 | isl_ctx *ctx; |
596 | isl_schedule_constraints *sc; |
597 | isl_bool more; |
598 | int domain_set = 0; |
599 | |
600 | if (isl_stream_yaml_read_start_mapping(s) < 0) |
601 | return NULL; |
602 | |
603 | ctx = isl_stream_get_ctx(s); |
604 | sc = isl_schedule_constraints_alloc(ctx); |
605 | while ((more = isl_stream_yaml_next(s)) == isl_bool_true) { |
606 | enum isl_sc_key key; |
607 | enum isl_edge_type type; |
608 | isl_set *context; |
609 | isl_union_set *domain; |
610 | isl_union_map *constraints; |
611 | |
612 | key = get_key(s); |
613 | if (isl_stream_yaml_next(s) < 0) |
614 | return isl_schedule_constraints_free(sc); |
615 | switch (key) { |
616 | case isl_sc_key_end: |
617 | case isl_sc_key_error: |
618 | return isl_schedule_constraints_free(sc); |
619 | case isl_sc_key_domain: |
620 | domain_set = 1; |
621 | domain = read_union_set(s); |
622 | sc = isl_schedule_constraints_set_domain(sc, domain); |
623 | if (!sc) |
624 | return NULL; |
625 | break; |
626 | case isl_sc_key_context: |
627 | context = read_set(s); |
628 | sc = isl_schedule_constraints_set_context(sc, context); |
629 | if (!sc) |
630 | return NULL; |
631 | break; |
632 | case isl_sc_key_validity: |
633 | case isl_sc_key_coincidence: |
634 | case isl_sc_key_condition: |
635 | case isl_sc_key_conditional_validity: |
636 | case isl_sc_key_proximity: |
637 | type = (enum isl_edge_type) key; |
638 | constraints = read_union_map(s); |
639 | sc = isl_schedule_constraints_set(sc, type, |
640 | c: constraints); |
641 | if (!sc) |
642 | return NULL; |
643 | break; |
644 | } |
645 | } |
646 | if (more < 0) |
647 | return isl_schedule_constraints_free(sc); |
648 | |
649 | if (isl_stream_yaml_read_end_mapping(s) < 0) |
650 | return isl_schedule_constraints_free(sc); |
651 | |
652 | if (!domain_set) { |
653 | isl_stream_error(s, NULL, msg: "no domain specified" ); |
654 | return isl_schedule_constraints_free(sc); |
655 | } |
656 | |
657 | return isl_schedule_constraints_init(sc); |
658 | } |
659 | |
660 | /* Read an isl_schedule_constraints object from the file "input". |
661 | */ |
662 | __isl_give isl_schedule_constraints *isl_schedule_constraints_read_from_file( |
663 | isl_ctx *ctx, FILE *input) |
664 | { |
665 | struct isl_stream *s; |
666 | isl_schedule_constraints *sc; |
667 | |
668 | s = isl_stream_new_file(ctx, file: input); |
669 | if (!s) |
670 | return NULL; |
671 | sc = isl_stream_read_schedule_constraints(s); |
672 | isl_stream_free(s); |
673 | |
674 | return sc; |
675 | } |
676 | |
677 | #undef TYPE_BASE |
678 | #define TYPE_BASE schedule_constraints |
679 | #include "isl_read_from_str_templ.c" |
680 | |
681 | /* Align the parameters of the fields of "sc". |
682 | */ |
683 | __isl_give isl_schedule_constraints * |
684 | isl_schedule_constraints_align_params(__isl_take isl_schedule_constraints *sc) |
685 | { |
686 | isl_space *space; |
687 | enum isl_edge_type i; |
688 | |
689 | if (!sc) |
690 | return NULL; |
691 | |
692 | space = isl_union_set_get_space(uset: sc->domain); |
693 | space = isl_space_align_params(space1: space, space2: isl_set_get_space(set: sc->context)); |
694 | for (i = isl_edge_first; i <= isl_edge_last; ++i) |
695 | space = isl_space_align_params(space1: space, |
696 | space2: isl_union_map_get_space(umap: sc->constraint[i])); |
697 | |
698 | for (i = isl_edge_first; i <= isl_edge_last; ++i) { |
699 | sc->constraint[i] = isl_union_map_align_params( |
700 | umap: sc->constraint[i], model: isl_space_copy(space)); |
701 | if (!sc->constraint[i]) |
702 | space = isl_space_free(space); |
703 | } |
704 | sc->context = isl_set_align_params(set: sc->context, model: isl_space_copy(space)); |
705 | sc->domain = isl_union_set_align_params(uset: sc->domain, model: space); |
706 | if (!sc->context || !sc->domain) |
707 | return isl_schedule_constraints_free(sc); |
708 | |
709 | return sc; |
710 | } |
711 | |
712 | /* Add the number of basic maps in "map" to *n. |
713 | */ |
714 | static isl_stat add_n_basic_map(__isl_take isl_map *map, void *user) |
715 | { |
716 | int *n = user; |
717 | isl_size n_basic_map; |
718 | |
719 | n_basic_map = isl_map_n_basic_map(map); |
720 | *n += n_basic_map; |
721 | isl_map_free(map); |
722 | |
723 | return n_basic_map < 0 ? isl_stat_error : isl_stat_ok; |
724 | } |
725 | |
726 | /* Return the total number of isl_basic_maps in the constraints of "sc". |
727 | * Return -1 on error. |
728 | */ |
729 | int isl_schedule_constraints_n_basic_map( |
730 | __isl_keep isl_schedule_constraints *sc) |
731 | { |
732 | enum isl_edge_type i; |
733 | int n = 0; |
734 | |
735 | if (!sc) |
736 | return -1; |
737 | for (i = isl_edge_first; i <= isl_edge_last; ++i) |
738 | if (isl_union_map_foreach_map(umap: sc->constraint[i], |
739 | fn: &add_n_basic_map, user: &n) < 0) |
740 | return -1; |
741 | |
742 | return n; |
743 | } |
744 | |
745 | /* Return the total number of isl_maps in the constraints of "sc". |
746 | */ |
747 | isl_size isl_schedule_constraints_n_map(__isl_keep isl_schedule_constraints *sc) |
748 | { |
749 | enum isl_edge_type i; |
750 | int n = 0; |
751 | |
752 | for (i = isl_edge_first; i <= isl_edge_last; ++i) { |
753 | isl_size n_i; |
754 | |
755 | n_i = isl_union_map_n_map(umap: sc->constraint[i]); |
756 | if (n_i < 0) |
757 | return isl_size_error; |
758 | n += n_i; |
759 | } |
760 | |
761 | return n; |
762 | } |
763 | |