/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_schedule_constraints.c
Line | Count | Source (jump to first uncovered line) |
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 | 160 | { |
51 | 160 | isl_ctx *ctx; |
52 | 160 | isl_schedule_constraints *sc_copy; |
53 | 160 | enum isl_edge_type i; |
54 | 160 | |
55 | 160 | ctx = isl_union_set_get_ctx(sc->domain); |
56 | 160 | sc_copy = isl_calloc_type(ctx, struct isl_schedule_constraints); |
57 | 160 | if (!sc_copy) |
58 | 0 | return NULL; |
59 | 160 | |
60 | 160 | sc_copy->domain = isl_union_set_copy(sc->domain); |
61 | 160 | sc_copy->context = isl_set_copy(sc->context); |
62 | 160 | if (!sc_copy->domain || !sc_copy->context) |
63 | 0 | return isl_schedule_constraints_free(sc_copy); |
64 | 160 | |
65 | 960 | for (i = isl_edge_first; 160 i <= isl_edge_last; ++i800 ) { |
66 | 800 | sc_copy->constraint[i] = isl_union_map_copy(sc->constraint[i]); |
67 | 800 | if (!sc_copy->constraint[i]) |
68 | 0 | return isl_schedule_constraints_free(sc_copy); |
69 | 800 | } |
70 | 160 | |
71 | 160 | return sc_copy; |
72 | 160 | } |
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 | 153 | { |
81 | 153 | return isl_calloc_type(ctx, struct isl_schedule_constraints); |
82 | 153 | } |
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 | 153 | { |
90 | 153 | isl_space *space; |
91 | 153 | isl_union_map *empty; |
92 | 153 | enum isl_edge_type i; |
93 | 153 | |
94 | 153 | if (!sc) |
95 | 0 | return NULL; |
96 | 153 | if (!sc->domain) |
97 | 0 | return isl_schedule_constraints_free(sc); |
98 | 153 | space = isl_union_set_get_space(sc->domain); |
99 | 153 | if (!sc->context) |
100 | 153 | sc->context = isl_set_universe(isl_space_copy(space)); |
101 | 153 | empty = isl_union_map_empty(space); |
102 | 918 | for (i = isl_edge_first; i <= isl_edge_last; ++i765 ) { |
103 | 765 | if (sc->constraint[i]) |
104 | 0 | continue; |
105 | 765 | sc->constraint[i] = isl_union_map_copy(empty); |
106 | 765 | if (!sc->constraint[i]) |
107 | 0 | sc->domain = isl_union_set_free(sc->domain); |
108 | 765 | } |
109 | 153 | isl_union_map_free(empty); |
110 | 153 | |
111 | 153 | if (!sc->domain || !sc->context) |
112 | 0 | return isl_schedule_constraints_free(sc); |
113 | 153 | |
114 | 153 | return sc; |
115 | 153 | } |
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 | 153 | { |
123 | 153 | isl_ctx *ctx; |
124 | 153 | isl_schedule_constraints *sc; |
125 | 153 | |
126 | 153 | if (!domain) |
127 | 0 | return NULL; |
128 | 153 | |
129 | 153 | ctx = isl_union_set_get_ctx(domain); |
130 | 153 | sc = isl_schedule_constraints_alloc(ctx); |
131 | 153 | if (!sc) |
132 | 0 | goto error; |
133 | 153 | |
134 | 153 | sc->domain = domain; |
135 | 153 | return isl_schedule_constraints_init(sc); |
136 | 0 | error: |
137 | 0 | isl_union_set_free(domain); |
138 | 0 | return NULL; |
139 | 153 | } |
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 | 0 | { |
147 | 0 | if (!sc || !domain) |
148 | 0 | goto error; |
149 | 0 | |
150 | 0 | isl_union_set_free(sc->domain); |
151 | 0 | sc->domain = domain; |
152 | 0 |
|
153 | 0 | return sc; |
154 | 0 | error: |
155 | 0 | isl_schedule_constraints_free(sc); |
156 | 0 | isl_union_set_free(domain); |
157 | 0 | return NULL; |
158 | 0 | } |
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 | 22 | { |
165 | 22 | if (!sc || !context) |
166 | 0 | goto error; |
167 | 22 | |
168 | 22 | isl_set_free(sc->context); |
169 | 22 | sc->context = context; |
170 | 22 | |
171 | 22 | return sc; |
172 | 0 | error: |
173 | 0 | isl_schedule_constraints_free(sc); |
174 | 0 | isl_set_free(context); |
175 | 0 | return NULL; |
176 | 22 | } |
177 | | |
178 | | /* Replace the constraints of type "type" in "sc" by "c". |
179 | | */ |
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 | 334 | { |
184 | 334 | if (!sc || !c) |
185 | 0 | goto error; |
186 | 334 | |
187 | 334 | isl_union_map_free(sc->constraint[type]); |
188 | 334 | sc->constraint[type] = c; |
189 | 334 | |
190 | 334 | return sc; |
191 | 0 | error: |
192 | 0 | isl_schedule_constraints_free(sc); |
193 | 0 | isl_union_map_free(c); |
194 | 0 | return NULL; |
195 | 334 | } |
196 | | |
197 | | /* Replace the validity constraints of "sc" by "validity". |
198 | | */ |
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 | 116 | { |
203 | 116 | return isl_schedule_constraints_set(sc, isl_edge_validity, validity); |
204 | 116 | } |
205 | | |
206 | | /* Replace the coincidence constraints of "sc" by "coincidence". |
207 | | */ |
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 | 80 | { |
212 | 80 | return isl_schedule_constraints_set(sc, isl_edge_coincidence, |
213 | 80 | coincidence); |
214 | 80 | } |
215 | | |
216 | | /* Replace the proximity constraints of "sc" by "proximity". |
217 | | */ |
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 | 114 | { |
222 | 114 | return isl_schedule_constraints_set(sc, isl_edge_proximity, proximity); |
223 | 114 | } |
224 | | |
225 | | /* Replace the conditional validity constraints of "sc" by "condition" |
226 | | * and "validity". |
227 | | */ |
228 | | __isl_give isl_schedule_constraints * |
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 | 12 | { |
234 | 12 | sc = isl_schedule_constraints_set(sc, isl_edge_condition, condition); |
235 | 12 | sc = isl_schedule_constraints_set(sc, isl_edge_conditional_validity, |
236 | 12 | validity); |
237 | 12 | return sc; |
238 | 12 | } |
239 | | |
240 | | __isl_null isl_schedule_constraints *isl_schedule_constraints_free( |
241 | | __isl_take isl_schedule_constraints *sc) |
242 | 313 | { |
243 | 313 | enum isl_edge_type i; |
244 | 313 | |
245 | 313 | if (!sc) |
246 | 0 | return NULL; |
247 | 313 | |
248 | 313 | isl_union_set_free(sc->domain); |
249 | 313 | isl_set_free(sc->context); |
250 | 1.87k | for (i = isl_edge_first; i <= isl_edge_last; ++i1.56k ) |
251 | 1.56k | isl_union_map_free(sc->constraint[i]); |
252 | 313 | |
253 | 313 | free(sc); |
254 | 313 | |
255 | 313 | return NULL; |
256 | 313 | } |
257 | | |
258 | | isl_ctx *isl_schedule_constraints_get_ctx( |
259 | | __isl_keep isl_schedule_constraints *sc) |
260 | 271 | { |
261 | 271 | return sc ? isl_union_set_get_ctx(sc->domain) : NULL; |
262 | 271 | } |
263 | | |
264 | | /* Return the domain of "sc". |
265 | | */ |
266 | | __isl_give isl_union_set *isl_schedule_constraints_get_domain( |
267 | | __isl_keep isl_schedule_constraints *sc) |
268 | 577 | { |
269 | 577 | if (!sc) |
270 | 0 | return NULL; |
271 | 577 | |
272 | 577 | return isl_union_set_copy(sc->domain); |
273 | 577 | } |
274 | | |
275 | | /* Return the context of "sc". |
276 | | */ |
277 | | __isl_give isl_set *isl_schedule_constraints_get_context( |
278 | | __isl_keep isl_schedule_constraints *sc) |
279 | 153 | { |
280 | 153 | if (!sc) |
281 | 0 | return NULL; |
282 | 153 | |
283 | 153 | return isl_set_copy(sc->context); |
284 | 153 | } |
285 | | |
286 | | /* Return the constraints of type "type" in "sc". |
287 | | */ |
288 | | __isl_give isl_union_map *isl_schedule_constraints_get( |
289 | | __isl_keep isl_schedule_constraints *sc, enum isl_edge_type type) |
290 | 1.53k | { |
291 | 1.53k | if (!sc) |
292 | 0 | return NULL; |
293 | 1.53k | |
294 | 1.53k | return isl_union_map_copy(sc->constraint[type]); |
295 | 1.53k | } |
296 | | |
297 | | /* Return the validity constraints of "sc". |
298 | | */ |
299 | | __isl_give isl_union_map *isl_schedule_constraints_get_validity( |
300 | | __isl_keep isl_schedule_constraints *sc) |
301 | 0 | { |
302 | 0 | return isl_schedule_constraints_get(sc, isl_edge_validity); |
303 | 0 | } |
304 | | |
305 | | /* Return the coincidence constraints of "sc". |
306 | | */ |
307 | | __isl_give isl_union_map *isl_schedule_constraints_get_coincidence( |
308 | | __isl_keep isl_schedule_constraints *sc) |
309 | 0 | { |
310 | 0 | return isl_schedule_constraints_get(sc, isl_edge_coincidence); |
311 | 0 | } |
312 | | |
313 | | /* Return the proximity constraints of "sc". |
314 | | */ |
315 | | __isl_give isl_union_map *isl_schedule_constraints_get_proximity( |
316 | | __isl_keep isl_schedule_constraints *sc) |
317 | 0 | { |
318 | 0 | return isl_schedule_constraints_get(sc, isl_edge_proximity); |
319 | 0 | } |
320 | | |
321 | | /* Return the conditional validity constraints of "sc". |
322 | | */ |
323 | | __isl_give isl_union_map *isl_schedule_constraints_get_conditional_validity( |
324 | | __isl_keep isl_schedule_constraints *sc) |
325 | 0 | { |
326 | 0 | return isl_schedule_constraints_get(sc, isl_edge_conditional_validity); |
327 | 0 | } |
328 | | |
329 | | /* Return the conditions for the conditional validity constraints of "sc". |
330 | | */ |
331 | | __isl_give isl_union_map * |
332 | | isl_schedule_constraints_get_conditional_validity_condition( |
333 | | __isl_keep isl_schedule_constraints *sc) |
334 | 0 | { |
335 | 0 | return isl_schedule_constraints_get(sc, isl_edge_condition); |
336 | 0 | } |
337 | | |
338 | | /* Add "c" to the constraints of type "type" in "sc". |
339 | | */ |
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 | 209 | { |
344 | 209 | if (!sc || !c) |
345 | 0 | goto error; |
346 | 209 | |
347 | 209 | c = isl_union_map_union(sc->constraint[type], c); |
348 | 209 | sc->constraint[type] = c; |
349 | 209 | if (!c) |
350 | 0 | return isl_schedule_constraints_free(sc); |
351 | 209 | |
352 | 209 | return sc; |
353 | 0 | error: |
354 | 0 | isl_schedule_constraints_free(sc); |
355 | 0 | isl_union_map_free(c); |
356 | 0 | return NULL; |
357 | 209 | } |
358 | | |
359 | | /* Can a schedule constraint of type "type" be tagged? |
360 | | */ |
361 | | static int may_be_tagged(enum isl_edge_type type) |
362 | 0 | { |
363 | 0 | if (type == isl_edge_condition || type == isl_edge_conditional_validity) |
364 | 0 | return 1; |
365 | 0 | return 0; |
366 | 0 | } |
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 | | static __isl_give isl_union_map *apply_factor_domain( |
384 | | __isl_take isl_union_map *c, __isl_keep isl_union_map *umap) |
385 | 0 | { |
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 | 0 |
|
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 | 0 |
|
396 | 0 | return c; |
397 | 0 | } |
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 | | static __isl_give isl_union_map *apply(__isl_take isl_union_map *c, |
405 | | __isl_keep isl_union_map *umap, int tag) |
406 | 0 | { |
407 | 0 | isl_union_map *t; |
408 | 0 |
|
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 | 0 | } |
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 | | __isl_give isl_schedule_constraints *isl_schedule_constraints_apply( |
426 | | __isl_take isl_schedule_constraints *sc, |
427 | | __isl_take isl_union_map *umap) |
428 | 0 | { |
429 | 0 | enum isl_edge_type i; |
430 | 0 |
|
431 | 0 | if (!sc || !umap) |
432 | 0 | goto error; |
433 | 0 | |
434 | 0 | for (i = isl_edge_first; i <= isl_edge_last; ++i) { |
435 | 0 | int tag = may_be_tagged(i); |
436 | 0 |
|
437 | 0 | sc->constraint[i] = apply(sc->constraint[i], umap, tag); |
438 | 0 | if (!sc->constraint[i]) |
439 | 0 | goto error; |
440 | 0 | } |
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 | 0 | |
445 | 0 | return sc; |
446 | 0 | error: |
447 | 0 | isl_schedule_constraints_free(sc); |
448 | 0 | isl_union_map_free(umap); |
449 | 0 | return NULL; |
450 | 0 | } |
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 | | 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 | 0 | { |
490 | 0 | isl_bool empty; |
491 | 0 |
|
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 | 0 | |
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 | 0 |
|
503 | 0 | return p; |
504 | 0 | } |
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 | | __isl_give isl_printer *isl_printer_print_schedule_constraints( |
513 | | __isl_take isl_printer *p, __isl_keep isl_schedule_constraints *sc) |
514 | 0 | { |
515 | 0 | isl_bool universe; |
516 | 0 |
|
517 | 0 | if (!sc) |
518 | 0 | return isl_printer_free(p); |
519 | 0 | |
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 | 0 | } |
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 | 0 |
|
541 | 0 | return p; |
542 | 0 | } |
543 | | |
544 | | #undef BASE |
545 | | #define BASE schedule_constraints |
546 | | #include <print_templ_yaml.c> |
547 | | |
548 | | #undef KEY |
549 | 0 | #define KEY enum isl_sc_key |
550 | | #undef KEY_ERROR |
551 | 0 | #define KEY_ERROR isl_sc_key_error |
552 | | #undef KEY_END |
553 | 0 | #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 | | __isl_give isl_schedule_constraints *isl_stream_read_schedule_constraints( |
577 | | isl_stream *s) |
578 | 0 | { |
579 | 0 | isl_ctx *ctx; |
580 | 0 | isl_schedule_constraints *sc; |
581 | 0 | int more; |
582 | 0 | int domain_set = 0; |
583 | 0 |
|
584 | 0 | if (isl_stream_yaml_read_start_mapping(s)) |
585 | 0 | return NULL; |
586 | 0 | |
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 | 0 | enum isl_sc_key key; |
591 | 0 | isl_set *context; |
592 | 0 | isl_union_set *domain; |
593 | 0 | isl_union_map *constraints; |
594 | 0 |
|
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 | 0 | case isl_sc_key_end: |
600 | 0 | case isl_sc_key_error: |
601 | 0 | return isl_schedule_constraints_free(sc); |
602 | 0 | 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 | 0 | 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 | 0 | case isl_sc_key_validity: |
616 | 0 | case isl_sc_key_coincidence: |
617 | 0 | case isl_sc_key_condition: |
618 | 0 | case isl_sc_key_conditional_validity: |
619 | 0 | 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 | 0 | } |
626 | 0 | } |
627 | 0 | if (more < 0) |
628 | 0 | return isl_schedule_constraints_free(sc); |
629 | 0 | |
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 | 0 | } |
634 | 0 | |
635 | 0 | if (!domain_set) { |
636 | 0 | isl_stream_error(s, NULL, "no domain specified"); |
637 | 0 | return isl_schedule_constraints_free(sc); |
638 | 0 | } |
639 | 0 | |
640 | 0 | return isl_schedule_constraints_init(sc); |
641 | 0 | } |
642 | | |
643 | | /* Read an isl_schedule_constraints object from the file "input". |
644 | | */ |
645 | | __isl_give isl_schedule_constraints *isl_schedule_constraints_read_from_file( |
646 | | isl_ctx *ctx, FILE *input) |
647 | 0 | { |
648 | 0 | struct isl_stream *s; |
649 | 0 | isl_schedule_constraints *sc; |
650 | 0 |
|
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 | 0 |
|
657 | 0 | return sc; |
658 | 0 | } |
659 | | |
660 | | /* Read an isl_schedule_constraints object from the string "str". |
661 | | */ |
662 | | __isl_give isl_schedule_constraints *isl_schedule_constraints_read_from_str( |
663 | | isl_ctx *ctx, const char *str) |
664 | 0 | { |
665 | 0 | struct isl_stream *s; |
666 | 0 | isl_schedule_constraints *sc; |
667 | 0 |
|
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 | 0 |
|
674 | 0 | return sc; |
675 | 0 | } |
676 | | |
677 | | /* Align the parameters of the fields of "sc". |
678 | | */ |
679 | | __isl_give isl_schedule_constraints * |
680 | | isl_schedule_constraints_align_params(__isl_take isl_schedule_constraints *sc) |
681 | 118 | { |
682 | 118 | isl_space *space; |
683 | 118 | enum isl_edge_type i; |
684 | 118 | |
685 | 118 | if (!sc) |
686 | 0 | return NULL; |
687 | 118 | |
688 | 118 | space = isl_union_set_get_space(sc->domain); |
689 | 118 | space = isl_space_align_params(space, isl_set_get_space(sc->context)); |
690 | 708 | for (i = isl_edge_first; i <= isl_edge_last; ++i590 ) |
691 | 590 | space = isl_space_align_params(space, |
692 | 590 | isl_union_map_get_space(sc->constraint[i])); |
693 | 118 | |
694 | 708 | for (i = isl_edge_first; i <= isl_edge_last; ++i590 ) { |
695 | 590 | sc->constraint[i] = isl_union_map_align_params( |
696 | 590 | sc->constraint[i], isl_space_copy(space)); |
697 | 590 | if (!sc->constraint[i]) |
698 | 0 | space = isl_space_free(space); |
699 | 590 | } |
700 | 118 | sc->context = isl_set_align_params(sc->context, isl_space_copy(space)); |
701 | 118 | sc->domain = isl_union_set_align_params(sc->domain, space); |
702 | 118 | if (!sc->context || !sc->domain) |
703 | 0 | return isl_schedule_constraints_free(sc); |
704 | 118 | |
705 | 118 | return sc; |
706 | 118 | } |
707 | | |
708 | | /* Add the number of basic maps in "map" to *n. |
709 | | */ |
710 | | static isl_stat add_n_basic_map(__isl_take isl_map *map, void *user) |
711 | 684 | { |
712 | 684 | int *n = user; |
713 | 684 | |
714 | 684 | *n += isl_map_n_basic_map(map); |
715 | 684 | isl_map_free(map); |
716 | 684 | |
717 | 684 | return isl_stat_ok; |
718 | 684 | } |
719 | | |
720 | | /* Return the total number of isl_basic_maps in the constraints of "sc". |
721 | | * Return -1 on error. |
722 | | */ |
723 | | int isl_schedule_constraints_n_basic_map( |
724 | | __isl_keep isl_schedule_constraints *sc) |
725 | 153 | { |
726 | 153 | enum isl_edge_type i; |
727 | 153 | int n = 0; |
728 | 153 | |
729 | 153 | if (!sc) |
730 | 0 | return -1; |
731 | 918 | for (i = isl_edge_first; 153 i <= isl_edge_last; ++i765 ) |
732 | 765 | if (isl_union_map_foreach_map(sc->constraint[i], |
733 | 765 | &add_n_basic_map, &n) < 0) |
734 | 0 | return -1; |
735 | 153 | |
736 | 153 | return n; |
737 | 153 | } |
738 | | |
739 | | /* Return the total number of isl_maps in the constraints of "sc". |
740 | | */ |
741 | | int isl_schedule_constraints_n_map(__isl_keep isl_schedule_constraints *sc) |
742 | 153 | { |
743 | 153 | enum isl_edge_type i; |
744 | 153 | int n = 0; |
745 | 153 | |
746 | 918 | for (i = isl_edge_first; i <= isl_edge_last; ++i765 ) |
747 | 765 | n += isl_union_map_n_map(sc->constraint[i]); |
748 | 153 | |
749 | 153 | return n; |
750 | 153 | } |