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 
isl_schedule_constraints_copy(__isl_keep isl_schedule_constraints * sc)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(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(sc->domain);
61 	sc_copy->context = isl_set_copy(sc->context);
62 	if (!sc_copy->domain || !sc_copy->context)
63 		return isl_schedule_constraints_free(sc_copy);
64 
65 	for (i = isl_edge_first; i <= isl_edge_last; ++i) {
66 		sc_copy->constraint[i] = isl_union_map_copy(sc->constraint[i]);
67 		if (!sc_copy->constraint[i])
68 			return isl_schedule_constraints_free(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  */
isl_schedule_constraints_alloc(isl_ctx * ctx)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  */
isl_schedule_constraints_init(__isl_take isl_schedule_constraints * sc)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(sc->domain);
99 	if (!sc->context)
100 		sc->context = isl_set_universe(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(empty);
106 		if (!sc->constraint[i])
107 			sc->domain = isl_union_set_free(sc->domain);
108 	}
109 	isl_union_map_free(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  */
isl_schedule_constraints_on_domain(__isl_take isl_union_set * domain)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(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(domain);
138 	return NULL;
139 }
140 
141 /* Replace the domain of "sc" by "domain".
142  */
isl_schedule_constraints_set_domain(__isl_take isl_schedule_constraints * sc,__isl_take isl_union_set * domain)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(sc->domain);
151 	sc->domain = domain;
152 
153 	return sc;
154 error:
155 	isl_schedule_constraints_free(sc);
156 	isl_union_set_free(domain);
157 	return NULL;
158 }
159 
160 /* Replace the context of "sc" by "context".
161  */
isl_schedule_constraints_set_context(__isl_take isl_schedule_constraints * sc,__isl_take isl_set * context)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(sc->context);
169 	sc->context = context;
170 
171 	return sc;
172 error:
173 	isl_schedule_constraints_free(sc);
174 	isl_set_free(context);
175 	return NULL;
176 }
177 
178 /* Replace the constraints of type "type" in "sc" by "c".
179  */
isl_schedule_constraints_set(__isl_take isl_schedule_constraints * sc,enum isl_edge_type type,__isl_take isl_union_map * c)180 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 	if (!sc || !c)
185 		goto error;
186 
187 	isl_union_map_free(sc->constraint[type]);
188 	sc->constraint[type] = c;
189 
190 	return sc;
191 error:
192 	isl_schedule_constraints_free(sc);
193 	isl_union_map_free(c);
194 	return NULL;
195 }
196 
197 /* Replace the validity constraints of "sc" by "validity".
198  */
isl_schedule_constraints_set_validity(__isl_take isl_schedule_constraints * sc,__isl_take isl_union_map * validity)199 __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 	return isl_schedule_constraints_set(sc, isl_edge_validity, validity);
204 }
205 
206 /* Replace the coincidence constraints of "sc" by "coincidence".
207  */
isl_schedule_constraints_set_coincidence(__isl_take isl_schedule_constraints * sc,__isl_take isl_union_map * coincidence)208 __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 	return isl_schedule_constraints_set(sc, isl_edge_coincidence,
213 						coincidence);
214 }
215 
216 /* Replace the proximity constraints of "sc" by "proximity".
217  */
isl_schedule_constraints_set_proximity(__isl_take isl_schedule_constraints * sc,__isl_take isl_union_map * proximity)218 __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 	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 *
isl_schedule_constraints_set_conditional_validity(__isl_take isl_schedule_constraints * sc,__isl_take isl_union_map * condition,__isl_take isl_union_map * validity)229 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 	sc = isl_schedule_constraints_set(sc, isl_edge_condition, condition);
235 	sc = isl_schedule_constraints_set(sc, isl_edge_conditional_validity,
236 						validity);
237 	return sc;
238 }
239 
isl_schedule_constraints_free(__isl_take isl_schedule_constraints * sc)240 __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 	if (!sc)
246 		return NULL;
247 
248 	isl_union_set_free(sc->domain);
249 	isl_set_free(sc->context);
250 	for (i = isl_edge_first; i <= isl_edge_last; ++i)
251 		isl_union_map_free(sc->constraint[i]);
252 
253 	free(sc);
254 
255 	return NULL;
256 }
257 
isl_schedule_constraints_get_ctx(__isl_keep isl_schedule_constraints * sc)258 isl_ctx *isl_schedule_constraints_get_ctx(
259 	__isl_keep isl_schedule_constraints *sc)
260 {
261 	return sc ? isl_union_set_get_ctx(sc->domain) : NULL;
262 }
263 
264 /* Return the domain of "sc".
265  */
isl_schedule_constraints_get_domain(__isl_keep isl_schedule_constraints * sc)266 __isl_give isl_union_set *isl_schedule_constraints_get_domain(
267 	__isl_keep isl_schedule_constraints *sc)
268 {
269 	if (!sc)
270 		return NULL;
271 
272 	return isl_union_set_copy(sc->domain);
273 }
274 
275 /* Return the context of "sc".
276  */
isl_schedule_constraints_get_context(__isl_keep isl_schedule_constraints * sc)277 __isl_give isl_set *isl_schedule_constraints_get_context(
278 	__isl_keep isl_schedule_constraints *sc)
279 {
280 	if (!sc)
281 		return NULL;
282 
283 	return isl_set_copy(sc->context);
284 }
285 
286 /* Return the constraints of type "type" in "sc".
287  */
isl_schedule_constraints_get(__isl_keep isl_schedule_constraints * sc,enum isl_edge_type type)288 __isl_give isl_union_map *isl_schedule_constraints_get(
289 	__isl_keep isl_schedule_constraints *sc, enum isl_edge_type type)
290 {
291 	if (!sc)
292 		return NULL;
293 
294 	return isl_union_map_copy(sc->constraint[type]);
295 }
296 
297 /* Return the validity constraints of "sc".
298  */
isl_schedule_constraints_get_validity(__isl_keep isl_schedule_constraints * sc)299 __isl_give isl_union_map *isl_schedule_constraints_get_validity(
300 	__isl_keep isl_schedule_constraints *sc)
301 {
302 	return isl_schedule_constraints_get(sc, isl_edge_validity);
303 }
304 
305 /* Return the coincidence constraints of "sc".
306  */
isl_schedule_constraints_get_coincidence(__isl_keep isl_schedule_constraints * sc)307 __isl_give isl_union_map *isl_schedule_constraints_get_coincidence(
308 	__isl_keep isl_schedule_constraints *sc)
309 {
310 	return isl_schedule_constraints_get(sc, isl_edge_coincidence);
311 }
312 
313 /* Return the proximity constraints of "sc".
314  */
isl_schedule_constraints_get_proximity(__isl_keep isl_schedule_constraints * sc)315 __isl_give isl_union_map *isl_schedule_constraints_get_proximity(
316 	__isl_keep isl_schedule_constraints *sc)
317 {
318 	return isl_schedule_constraints_get(sc, isl_edge_proximity);
319 }
320 
321 /* Return the conditional validity constraints of "sc".
322  */
isl_schedule_constraints_get_conditional_validity(__isl_keep isl_schedule_constraints * sc)323 __isl_give isl_union_map *isl_schedule_constraints_get_conditional_validity(
324 	__isl_keep isl_schedule_constraints *sc)
325 {
326 	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 *
isl_schedule_constraints_get_conditional_validity_condition(__isl_keep isl_schedule_constraints * sc)332 isl_schedule_constraints_get_conditional_validity_condition(
333 	__isl_keep isl_schedule_constraints *sc)
334 {
335 	return isl_schedule_constraints_get(sc, isl_edge_condition);
336 }
337 
338 /* Add "c" to the constraints of type "type" in "sc".
339  */
isl_schedule_constraints_add(__isl_take isl_schedule_constraints * sc,enum isl_edge_type type,__isl_take isl_union_map * c)340 __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 	if (!sc || !c)
345 		goto error;
346 
347 	c = isl_union_map_union(sc->constraint[type], c);
348 	sc->constraint[type] = c;
349 	if (!c)
350 		return isl_schedule_constraints_free(sc);
351 
352 	return sc;
353 error:
354 	isl_schedule_constraints_free(sc);
355 	isl_union_map_free(c);
356 	return NULL;
357 }
358 
359 /* Can a schedule constraint of type "type" be tagged?
360  */
may_be_tagged(enum isl_edge_type type)361 static int may_be_tagged(enum isl_edge_type type)
362 {
363 	if (type == isl_edge_condition || type == isl_edge_conditional_validity)
364 		return 1;
365 	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  */
apply_factor_domain(__isl_take isl_union_map * c,__isl_keep isl_union_map * umap)383 static __isl_give isl_union_map *apply_factor_domain(
384 	__isl_take isl_union_map *c, __isl_keep isl_union_map *umap)
385 {
386 	c = isl_union_map_curry(c);
387 	c = isl_union_map_apply_domain(c, isl_union_map_copy(umap));
388 	c = isl_union_map_uncurry(c);
389 
390 	c = isl_union_map_reverse(c);
391 	c = isl_union_map_curry(c);
392 	c = isl_union_map_apply_domain(c, isl_union_map_copy(umap));
393 	c = isl_union_map_uncurry(c);
394 	c = isl_union_map_reverse(c);
395 
396 	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  */
apply(__isl_take isl_union_map * c,__isl_keep isl_union_map * umap,int tag)404 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 	if (tag)
410 		t = isl_union_map_copy(c);
411 	c = isl_union_map_apply_domain(c, isl_union_map_copy(umap));
412 	c = isl_union_map_apply_range(c, isl_union_map_copy(umap));
413 	if (!tag)
414 		return c;
415 	t = apply_factor_domain(t, umap);
416 	c = isl_union_map_union(c, t);
417 	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  */
isl_schedule_constraints_apply(__isl_take isl_schedule_constraints * sc,__isl_take isl_union_map * umap)425 __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 	if (!sc || !umap)
432 		goto error;
433 
434 	for (i = isl_edge_first; i <= isl_edge_last; ++i) {
435 		int tag = may_be_tagged(i);
436 
437 		sc->constraint[i] = apply(sc->constraint[i], umap, tag);
438 		if (!sc->constraint[i])
439 			goto error;
440 	}
441 	sc->domain = isl_union_set_apply(sc->domain, umap);
442 	if (!sc->domain)
443 		return isl_schedule_constraints_free(sc);
444 
445 	return sc;
446 error:
447 	isl_schedule_constraints_free(sc);
448 	isl_union_map_free(umap);
449 	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 #undef BASE
483 #define BASE set
484 #include "print_yaml_field_templ.c"
485 
486 #undef BASE
487 #define BASE union_set
488 #include "print_yaml_field_templ.c"
489 
490 #undef BASE
491 #define BASE union_map
492 #include "print_yaml_field_templ.c"
493 
494 /* Print a key, value pair for the edge of type "type" in "sc" to "p".
495  *
496  * If the edge relation is empty, then it is not printed since
497  * an empty relation is the default value.
498  */
print_constraint(__isl_take isl_printer * p,__isl_keep isl_schedule_constraints * sc,enum isl_edge_type type)499 static __isl_give isl_printer *print_constraint(__isl_take isl_printer *p,
500 	__isl_keep isl_schedule_constraints *sc, enum isl_edge_type type)
501 {
502 	isl_bool empty;
503 
504 	empty = isl_union_map_plain_is_empty(sc->constraint[type]);
505 	if (empty < 0)
506 		return isl_printer_free(p);
507 	if (empty)
508 		return p;
509 
510 	p = print_yaml_field_union_map(p, key_str[type], sc->constraint[type]);
511 
512 	return p;
513 }
514 
515 /* Print "sc" to "p"
516  *
517  * In particular, print the isl_schedule_constraints object as a YAML document.
518  * Fields with values that are (obviously) equal to their default values
519  * are not printed.
520  */
isl_printer_print_schedule_constraints(__isl_take isl_printer * p,__isl_keep isl_schedule_constraints * sc)521 __isl_give isl_printer *isl_printer_print_schedule_constraints(
522 	__isl_take isl_printer *p, __isl_keep isl_schedule_constraints *sc)
523 {
524 	isl_bool universe;
525 
526 	if (!sc)
527 		return isl_printer_free(p);
528 
529 	p = isl_printer_yaml_start_mapping(p);
530 	p = print_yaml_field_union_set(p, key_str[isl_sc_key_domain],
531 					sc->domain);
532 	universe = isl_set_plain_is_universe(sc->context);
533 	if (universe < 0)
534 		return isl_printer_free(p);
535 	if (!universe)
536 		p = print_yaml_field_set(p, key_str[isl_sc_key_context],
537 						sc->context);
538 	p = print_constraint(p, sc, isl_edge_validity);
539 	p = print_constraint(p, sc, isl_edge_proximity);
540 	p = print_constraint(p, sc, isl_edge_coincidence);
541 	p = print_constraint(p, sc, isl_edge_condition);
542 	p = print_constraint(p, sc, isl_edge_conditional_validity);
543 	p = isl_printer_yaml_end_mapping(p);
544 
545 	return p;
546 }
547 
548 #undef BASE
549 #define BASE schedule_constraints
550 #include <print_templ_yaml.c>
551 
552 #undef KEY
553 #define KEY enum isl_sc_key
554 #undef KEY_ERROR
555 #define KEY_ERROR isl_sc_key_error
556 #undef KEY_END
557 #define KEY_END isl_sc_key_end
558 #include "extract_key.c"
559 
560 #undef BASE
561 #define BASE set
562 #include "read_in_string_templ.c"
563 
564 #undef BASE
565 #define BASE union_set
566 #include "read_in_string_templ.c"
567 
568 #undef BASE
569 #define BASE union_map
570 #include "read_in_string_templ.c"
571 
572 /* Read an isl_schedule_constraints object from "s".
573  *
574  * Start off with an empty (invalid) isl_schedule_constraints object and
575  * then fill up the fields based on the input.
576  * The input needs to contain at least a description of the domain.
577  * The other fields are set to defaults by isl_schedule_constraints_init
578  * if they are not specified in the input.
579  */
isl_stream_read_schedule_constraints(isl_stream * s)580 __isl_give isl_schedule_constraints *isl_stream_read_schedule_constraints(
581 	isl_stream *s)
582 {
583 	isl_ctx *ctx;
584 	isl_schedule_constraints *sc;
585 	int more;
586 	int domain_set = 0;
587 
588 	if (isl_stream_yaml_read_start_mapping(s))
589 		return NULL;
590 
591 	ctx = isl_stream_get_ctx(s);
592 	sc = isl_schedule_constraints_alloc(ctx);
593 	while ((more = isl_stream_yaml_next(s)) > 0) {
594 		enum isl_sc_key key;
595 		isl_set *context;
596 		isl_union_set *domain;
597 		isl_union_map *constraints;
598 
599 		key = get_key(s);
600 		if (isl_stream_yaml_next(s) < 0)
601 			return isl_schedule_constraints_free(sc);
602 		switch (key) {
603 		case isl_sc_key_end:
604 		case isl_sc_key_error:
605 			return isl_schedule_constraints_free(sc);
606 		case isl_sc_key_domain:
607 			domain_set = 1;
608 			domain = read_union_set(s);
609 			sc = isl_schedule_constraints_set_domain(sc, domain);
610 			if (!sc)
611 				return NULL;
612 			break;
613 		case isl_sc_key_context:
614 			context = read_set(s);
615 			sc = isl_schedule_constraints_set_context(sc, context);
616 			if (!sc)
617 				return NULL;
618 			break;
619 		case isl_sc_key_validity:
620 		case isl_sc_key_coincidence:
621 		case isl_sc_key_condition:
622 		case isl_sc_key_conditional_validity:
623 		case isl_sc_key_proximity:
624 			constraints = read_union_map(s);
625 			sc = isl_schedule_constraints_set(sc, key, constraints);
626 			if (!sc)
627 				return NULL;
628 			break;
629 		}
630 	}
631 	if (more < 0)
632 		return isl_schedule_constraints_free(sc);
633 
634 	if (isl_stream_yaml_read_end_mapping(s) < 0) {
635 		isl_stream_error(s, NULL, "unexpected extra elements");
636 		return isl_schedule_constraints_free(sc);
637 	}
638 
639 	if (!domain_set) {
640 		isl_stream_error(s, NULL, "no domain specified");
641 		return isl_schedule_constraints_free(sc);
642 	}
643 
644 	return isl_schedule_constraints_init(sc);
645 }
646 
647 /* Read an isl_schedule_constraints object from the file "input".
648  */
isl_schedule_constraints_read_from_file(isl_ctx * ctx,FILE * input)649 __isl_give isl_schedule_constraints *isl_schedule_constraints_read_from_file(
650 	isl_ctx *ctx, FILE *input)
651 {
652 	struct isl_stream *s;
653 	isl_schedule_constraints *sc;
654 
655 	s = isl_stream_new_file(ctx, input);
656 	if (!s)
657 		return NULL;
658 	sc = isl_stream_read_schedule_constraints(s);
659 	isl_stream_free(s);
660 
661 	return sc;
662 }
663 
664 /* Read an isl_schedule_constraints object from the string "str".
665  */
isl_schedule_constraints_read_from_str(isl_ctx * ctx,const char * str)666 __isl_give isl_schedule_constraints *isl_schedule_constraints_read_from_str(
667 	isl_ctx *ctx, const char *str)
668 {
669 	struct isl_stream *s;
670 	isl_schedule_constraints *sc;
671 
672 	s = isl_stream_new_str(ctx, str);
673 	if (!s)
674 		return NULL;
675 	sc = isl_stream_read_schedule_constraints(s);
676 	isl_stream_free(s);
677 
678 	return sc;
679 }
680 
681 /* Align the parameters of the fields of "sc".
682  */
683 __isl_give isl_schedule_constraints *
isl_schedule_constraints_align_params(__isl_take isl_schedule_constraints * sc)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(sc->domain);
693 	space = isl_space_align_params(space, isl_set_get_space(sc->context));
694 	for (i = isl_edge_first; i <= isl_edge_last; ++i)
695 		space = isl_space_align_params(space,
696 				    isl_union_map_get_space(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 				    sc->constraint[i], isl_space_copy(space));
701 		if (!sc->constraint[i])
702 			space = isl_space_free(space);
703 	}
704 	sc->context = isl_set_align_params(sc->context, isl_space_copy(space));
705 	sc->domain = isl_union_set_align_params(sc->domain, 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  */
add_n_basic_map(__isl_take isl_map * map,void * user)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  */
isl_schedule_constraints_n_basic_map(__isl_keep isl_schedule_constraints * sc)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(sc->constraint[i],
739 						&add_n_basic_map, &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  */
isl_schedule_constraints_n_map(__isl_keep isl_schedule_constraints * sc)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(sc->constraint[i]);
756 		if (n_i < 0)
757 			return isl_size_error;
758 		n += n_i;
759 	}
760 
761 	return n;
762 }
763