2 * Copyright 2012 Ecole Normale Superieure
3 * Copyright 2015-2016 Sven Verdoolaege
5 * Use of this software is governed by the MIT license
7 * Written by Sven Verdoolaege,
8 * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
11 #include <isl_schedule_constraints.h>
12 #include <isl/schedule.h>
15 #include <isl/union_set.h>
16 #include <isl/union_map.h>
18 /* The constraints that need to be satisfied by a schedule on "domain".
20 * "context" specifies extra constraints on the parameters.
22 * "validity" constraints map domain elements i to domain elements
23 * that should be scheduled after i. (Hard constraint)
24 * "proximity" constraints map domain elements i to domains elements
25 * that should be scheduled as early as possible after i (or before i).
28 * "condition" and "conditional_validity" constraints map possibly "tagged"
29 * domain elements i -> s to "tagged" domain elements j -> t.
30 * The elements of the "conditional_validity" constraints, but without the
31 * tags (i.e., the elements i -> j) are treated as validity constraints,
32 * except that during the construction of a tilable band,
33 * the elements of the "conditional_validity" constraints may be violated
34 * provided that all adjacent elements of the "condition" constraints
35 * are local within the band.
36 * A dependence is local within a band if domain and range are mapped
37 * to the same schedule point by the band.
39 struct isl_schedule_constraints
{
40 isl_union_set
*domain
;
43 isl_union_map
*constraint
[isl_edge_last
+ 1];
46 __isl_give isl_schedule_constraints
*isl_schedule_constraints_copy(
47 __isl_keep isl_schedule_constraints
*sc
)
50 isl_schedule_constraints
*sc_copy
;
53 ctx
= isl_union_set_get_ctx(sc
->domain
);
54 sc_copy
= isl_calloc_type(ctx
, struct isl_schedule_constraints
);
58 sc_copy
->domain
= isl_union_set_copy(sc
->domain
);
59 sc_copy
->context
= isl_set_copy(sc
->context
);
60 if (!sc_copy
->domain
|| !sc_copy
->context
)
61 return isl_schedule_constraints_free(sc_copy
);
63 for (i
= isl_edge_first
; i
<= isl_edge_last
; ++i
) {
64 sc_copy
->constraint
[i
] = isl_union_map_copy(sc
->constraint
[i
]);
65 if (!sc_copy
->constraint
[i
])
66 return isl_schedule_constraints_free(sc_copy
);
72 /* Construct an isl_schedule_constraints object for computing a schedule
73 * on "domain". The initial object does not impose any constraints.
75 __isl_give isl_schedule_constraints
*isl_schedule_constraints_on_domain(
76 __isl_take isl_union_set
*domain
)
80 isl_schedule_constraints
*sc
;
87 ctx
= isl_union_set_get_ctx(domain
);
88 sc
= isl_calloc_type(ctx
, struct isl_schedule_constraints
);
92 space
= isl_union_set_get_space(domain
);
94 sc
->context
= isl_set_universe(isl_space_copy(space
));
95 empty
= isl_union_map_empty(space
);
96 for (i
= isl_edge_first
; i
<= isl_edge_last
; ++i
) {
97 sc
->constraint
[i
] = isl_union_map_copy(empty
);
98 if (!sc
->constraint
[i
])
99 sc
->domain
= isl_union_set_free(sc
->domain
);
101 isl_union_map_free(empty
);
103 if (!sc
->domain
|| !sc
->context
)
104 return isl_schedule_constraints_free(sc
);
108 isl_union_set_free(domain
);
112 /* Replace the context of "sc" by "context".
114 __isl_give isl_schedule_constraints
*isl_schedule_constraints_set_context(
115 __isl_take isl_schedule_constraints
*sc
, __isl_take isl_set
*context
)
120 isl_set_free(sc
->context
);
121 sc
->context
= context
;
125 isl_schedule_constraints_free(sc
);
126 isl_set_free(context
);
130 /* Replace the validity constraints of "sc" by "validity".
132 __isl_give isl_schedule_constraints
*isl_schedule_constraints_set_validity(
133 __isl_take isl_schedule_constraints
*sc
,
134 __isl_take isl_union_map
*validity
)
136 if (!sc
|| !validity
)
139 isl_union_map_free(sc
->constraint
[isl_edge_validity
]);
140 sc
->constraint
[isl_edge_validity
] = validity
;
144 isl_schedule_constraints_free(sc
);
145 isl_union_map_free(validity
);
149 /* Replace the coincidence constraints of "sc" by "coincidence".
151 __isl_give isl_schedule_constraints
*isl_schedule_constraints_set_coincidence(
152 __isl_take isl_schedule_constraints
*sc
,
153 __isl_take isl_union_map
*coincidence
)
155 if (!sc
|| !coincidence
)
158 isl_union_map_free(sc
->constraint
[isl_edge_coincidence
]);
159 sc
->constraint
[isl_edge_coincidence
] = coincidence
;
163 isl_schedule_constraints_free(sc
);
164 isl_union_map_free(coincidence
);
168 /* Replace the proximity constraints of "sc" by "proximity".
170 __isl_give isl_schedule_constraints
*isl_schedule_constraints_set_proximity(
171 __isl_take isl_schedule_constraints
*sc
,
172 __isl_take isl_union_map
*proximity
)
174 if (!sc
|| !proximity
)
177 isl_union_map_free(sc
->constraint
[isl_edge_proximity
]);
178 sc
->constraint
[isl_edge_proximity
] = proximity
;
182 isl_schedule_constraints_free(sc
);
183 isl_union_map_free(proximity
);
187 /* Replace the conditional validity constraints of "sc" by "condition"
190 __isl_give isl_schedule_constraints
*
191 isl_schedule_constraints_set_conditional_validity(
192 __isl_take isl_schedule_constraints
*sc
,
193 __isl_take isl_union_map
*condition
,
194 __isl_take isl_union_map
*validity
)
196 if (!sc
|| !condition
|| !validity
)
199 isl_union_map_free(sc
->constraint
[isl_edge_condition
]);
200 sc
->constraint
[isl_edge_condition
] = condition
;
201 isl_union_map_free(sc
->constraint
[isl_edge_conditional_validity
]);
202 sc
->constraint
[isl_edge_conditional_validity
] = validity
;
206 isl_schedule_constraints_free(sc
);
207 isl_union_map_free(condition
);
208 isl_union_map_free(validity
);
212 __isl_null isl_schedule_constraints
*isl_schedule_constraints_free(
213 __isl_take isl_schedule_constraints
*sc
)
215 enum isl_edge_type i
;
220 isl_union_set_free(sc
->domain
);
221 isl_set_free(sc
->context
);
222 for (i
= isl_edge_first
; i
<= isl_edge_last
; ++i
)
223 isl_union_map_free(sc
->constraint
[i
]);
230 isl_ctx
*isl_schedule_constraints_get_ctx(
231 __isl_keep isl_schedule_constraints
*sc
)
233 return sc
? isl_union_set_get_ctx(sc
->domain
) : NULL
;
236 /* Return the domain of "sc".
238 __isl_give isl_union_set
*isl_schedule_constraints_get_domain(
239 __isl_keep isl_schedule_constraints
*sc
)
244 return isl_union_set_copy(sc
->domain
);
247 /* Return the context of "sc".
249 __isl_give isl_set
*isl_schedule_constraints_get_context(
250 __isl_keep isl_schedule_constraints
*sc
)
255 return isl_set_copy(sc
->context
);
258 /* Return the constraints of type "type" in "sc".
260 __isl_give isl_union_map
*isl_schedule_constraints_get(
261 __isl_keep isl_schedule_constraints
*sc
, enum isl_edge_type type
)
266 return isl_union_map_copy(sc
->constraint
[type
]);
269 /* Return the validity constraints of "sc".
271 __isl_give isl_union_map
*isl_schedule_constraints_get_validity(
272 __isl_keep isl_schedule_constraints
*sc
)
274 return isl_schedule_constraints_get(sc
, isl_edge_validity
);
277 /* Return the coincidence constraints of "sc".
279 __isl_give isl_union_map
*isl_schedule_constraints_get_coincidence(
280 __isl_keep isl_schedule_constraints
*sc
)
282 return isl_schedule_constraints_get(sc
, isl_edge_coincidence
);
285 /* Return the proximity constraints of "sc".
287 __isl_give isl_union_map
*isl_schedule_constraints_get_proximity(
288 __isl_keep isl_schedule_constraints
*sc
)
290 return isl_schedule_constraints_get(sc
, isl_edge_proximity
);
293 /* Return the conditional validity constraints of "sc".
295 __isl_give isl_union_map
*isl_schedule_constraints_get_conditional_validity(
296 __isl_keep isl_schedule_constraints
*sc
)
298 return isl_schedule_constraints_get(sc
, isl_edge_conditional_validity
);
301 /* Return the conditions for the conditional validity constraints of "sc".
303 __isl_give isl_union_map
*
304 isl_schedule_constraints_get_conditional_validity_condition(
305 __isl_keep isl_schedule_constraints
*sc
)
307 return isl_schedule_constraints_get(sc
, isl_edge_condition
);
310 /* Add "c" to the constraints of type "type" in "sc".
312 __isl_give isl_schedule_constraints
*isl_schedule_constraints_add(
313 __isl_take isl_schedule_constraints
*sc
, enum isl_edge_type type
,
314 __isl_take isl_union_map
*c
)
319 c
= isl_union_map_union(sc
->constraint
[type
], c
);
320 sc
->constraint
[type
] = c
;
322 return isl_schedule_constraints_free(sc
);
326 isl_schedule_constraints_free(sc
);
327 isl_union_map_free(c
);
331 /* Can a schedule constraint of type "type" be tagged?
333 static int may_be_tagged(enum isl_edge_type type
)
335 if (type
== isl_edge_condition
|| type
== isl_edge_conditional_validity
)
340 /* Apply "umap" to the domains of the wrapped relations
341 * inside the domain and range of "c".
343 * That is, for each map of the form
345 * [D -> S] -> [E -> T]
347 * in "c", apply "umap" to D and E.
349 * D is exposed by currying the relation to
351 * D -> [S -> [E -> T]]
353 * E is exposed by doing the same to the inverse of "c".
355 static __isl_give isl_union_map
*apply_factor_domain(
356 __isl_take isl_union_map
*c
, __isl_keep isl_union_map
*umap
)
358 c
= isl_union_map_curry(c
);
359 c
= isl_union_map_apply_domain(c
, isl_union_map_copy(umap
));
360 c
= isl_union_map_uncurry(c
);
362 c
= isl_union_map_reverse(c
);
363 c
= isl_union_map_curry(c
);
364 c
= isl_union_map_apply_domain(c
, isl_union_map_copy(umap
));
365 c
= isl_union_map_uncurry(c
);
366 c
= isl_union_map_reverse(c
);
371 /* Apply "umap" to domain and range of "c".
372 * If "tag" is set, then "c" may contain tags and then "umap"
373 * needs to be applied to the domains of the wrapped relations
374 * inside the domain and range of "c".
376 static __isl_give isl_union_map
*apply(__isl_take isl_union_map
*c
,
377 __isl_keep isl_union_map
*umap
, int tag
)
382 t
= isl_union_map_copy(c
);
383 c
= isl_union_map_apply_domain(c
, isl_union_map_copy(umap
));
384 c
= isl_union_map_apply_range(c
, isl_union_map_copy(umap
));
387 t
= apply_factor_domain(t
, umap
);
388 c
= isl_union_map_union(c
, t
);
392 /* Apply "umap" to the domain of the schedule constraints "sc".
394 * The two sides of the various schedule constraints are adjusted
397 __isl_give isl_schedule_constraints
*isl_schedule_constraints_apply(
398 __isl_take isl_schedule_constraints
*sc
,
399 __isl_take isl_union_map
*umap
)
401 enum isl_edge_type i
;
406 for (i
= isl_edge_first
; i
<= isl_edge_last
; ++i
) {
407 int tag
= may_be_tagged(i
);
409 sc
->constraint
[i
] = apply(sc
->constraint
[i
], umap
, tag
);
410 if (!sc
->constraint
[i
])
413 sc
->domain
= isl_union_set_apply(sc
->domain
, umap
);
415 return isl_schedule_constraints_free(sc
);
419 isl_schedule_constraints_free(sc
);
420 isl_union_map_free(umap
);
424 void isl_schedule_constraints_dump(__isl_keep isl_schedule_constraints
*sc
)
429 fprintf(stderr
, "domain: ");
430 isl_union_set_dump(sc
->domain
);
431 fprintf(stderr
, "context: ");
432 isl_set_dump(sc
->context
);
433 fprintf(stderr
, "validity: ");
434 isl_union_map_dump(sc
->constraint
[isl_edge_validity
]);
435 fprintf(stderr
, "proximity: ");
436 isl_union_map_dump(sc
->constraint
[isl_edge_proximity
]);
437 fprintf(stderr
, "coincidence: ");
438 isl_union_map_dump(sc
->constraint
[isl_edge_coincidence
]);
439 fprintf(stderr
, "condition: ");
440 isl_union_map_dump(sc
->constraint
[isl_edge_condition
]);
441 fprintf(stderr
, "conditional_validity: ");
442 isl_union_map_dump(sc
->constraint
[isl_edge_conditional_validity
]);
445 /* Align the parameters of the fields of "sc".
447 __isl_give isl_schedule_constraints
*
448 isl_schedule_constraints_align_params(__isl_take isl_schedule_constraints
*sc
)
451 enum isl_edge_type i
;
456 space
= isl_union_set_get_space(sc
->domain
);
457 space
= isl_space_align_params(space
, isl_set_get_space(sc
->context
));
458 for (i
= isl_edge_first
; i
<= isl_edge_last
; ++i
)
459 space
= isl_space_align_params(space
,
460 isl_union_map_get_space(sc
->constraint
[i
]));
462 for (i
= isl_edge_first
; i
<= isl_edge_last
; ++i
) {
463 sc
->constraint
[i
] = isl_union_map_align_params(
464 sc
->constraint
[i
], isl_space_copy(space
));
465 if (!sc
->constraint
[i
])
466 space
= isl_space_free(space
);
468 sc
->context
= isl_set_align_params(sc
->context
, isl_space_copy(space
));
469 sc
->domain
= isl_union_set_align_params(sc
->domain
, space
);
470 if (!sc
->context
|| !sc
->domain
)
471 return isl_schedule_constraints_free(sc
);
476 /* Add the number of basic maps in "map" to *n.
478 static isl_stat
add_n_basic_map(__isl_take isl_map
*map
, void *user
)
482 *n
+= isl_map_n_basic_map(map
);
488 /* Return the total number of isl_basic_maps in the constraints of "sc".
489 * Return -1 on error.
491 int isl_schedule_constraints_n_basic_map(
492 __isl_keep isl_schedule_constraints
*sc
)
494 enum isl_edge_type i
;
499 for (i
= isl_edge_first
; i
<= isl_edge_last
; ++i
)
500 if (isl_union_map_foreach_map(sc
->constraint
[i
],
501 &add_n_basic_map
, &n
) < 0)
507 /* Return the total number of isl_maps in the constraints of "sc".
509 int isl_schedule_constraints_n_map(__isl_keep isl_schedule_constraints
*sc
)
511 enum isl_edge_type i
;
514 for (i
= isl_edge_first
; i
<= isl_edge_last
; ++i
)
515 n
+= isl_union_map_n_map(sc
->constraint
[i
]);