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