isl_schedule_node.c: collect_filter_prefix: allow caller to initialize filter
[isl.git] / isl_schedule_band.c
blob77808be4fa3d1aa4ce150b1744538749d4577d64
1 /*
2 * Copyright 2013-2014 Ecole Normale Superieure
3 * Copyright 2014 INRIA Rocquencourt
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
9 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
10 * B.P. 105 - 78153 Le Chesnay, France
13 #include <string.h>
14 #include <isl/map.h>
15 #include <isl/schedule_node.h>
16 #include <isl_schedule_band.h>
17 #include <isl_schedule_private.h>
19 isl_ctx *isl_schedule_band_get_ctx(__isl_keep isl_schedule_band *band)
21 return band ? isl_multi_union_pw_aff_get_ctx(band->mupa) : NULL;
24 /* Return a new uninitialized isl_schedule_band.
26 static __isl_give isl_schedule_band *isl_schedule_band_alloc(isl_ctx *ctx)
28 isl_schedule_band *band;
30 band = isl_calloc_type(ctx, isl_schedule_band);
31 if (!band)
32 return NULL;
34 band->ref = 1;
36 return band;
39 /* Return a new isl_schedule_band with partial schedule "mupa".
40 * First replace "mupa" by its greatest integer part to ensure
41 * that the schedule is always integral.
42 * The band is not marked permutable, the dimensions are not
43 * marked coincident and the AST build options are empty.
44 * Since there are no build options, the node is not anchored.
46 __isl_give isl_schedule_band *isl_schedule_band_from_multi_union_pw_aff(
47 __isl_take isl_multi_union_pw_aff *mupa)
49 isl_ctx *ctx;
50 isl_schedule_band *band;
51 isl_space *space;
53 mupa = isl_multi_union_pw_aff_floor(mupa);
54 if (!mupa)
55 return NULL;
56 ctx = isl_multi_union_pw_aff_get_ctx(mupa);
57 band = isl_schedule_band_alloc(ctx);
58 if (!band)
59 goto error;
61 band->n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
62 band->coincident = isl_calloc_array(ctx, int, band->n);
63 band->mupa = mupa;
64 space = isl_space_params_alloc(ctx, 0);
65 band->ast_build_options = isl_union_set_empty(space);
66 band->anchored = 0;
68 if ((band->n && !band->coincident) || !band->ast_build_options)
69 return isl_schedule_band_free(band);
71 return band;
72 error:
73 isl_multi_union_pw_aff_free(mupa);
74 return NULL;
77 /* Create a duplicate of the given isl_schedule_band.
79 __isl_give isl_schedule_band *isl_schedule_band_dup(
80 __isl_keep isl_schedule_band *band)
82 int i;
83 isl_ctx *ctx;
84 isl_schedule_band *dup;
86 if (!band)
87 return NULL;
89 ctx = isl_schedule_band_get_ctx(band);
90 dup = isl_schedule_band_alloc(ctx);
91 if (!dup)
92 return NULL;
94 dup->n = band->n;
95 dup->coincident = isl_alloc_array(ctx, int, band->n);
96 if (band->n && !dup->coincident)
97 return isl_schedule_band_free(dup);
99 for (i = 0; i < band->n; ++i)
100 dup->coincident[i] = band->coincident[i];
101 dup->permutable = band->permutable;
103 dup->mupa = isl_multi_union_pw_aff_copy(band->mupa);
104 dup->ast_build_options = isl_union_set_copy(band->ast_build_options);
105 if (!dup->mupa || !dup->ast_build_options)
106 return isl_schedule_band_free(dup);
108 if (band->loop_type) {
109 dup->loop_type = isl_alloc_array(ctx,
110 enum isl_ast_loop_type, band->n);
111 if (band->n && !dup->loop_type)
112 return isl_schedule_band_free(dup);
113 for (i = 0; i < band->n; ++i)
114 dup->loop_type[i] = band->loop_type[i];
116 if (band->isolate_loop_type) {
117 dup->isolate_loop_type = isl_alloc_array(ctx,
118 enum isl_ast_loop_type, band->n);
119 if (band->n && !dup->isolate_loop_type)
120 return isl_schedule_band_free(dup);
121 for (i = 0; i < band->n; ++i)
122 dup->isolate_loop_type[i] = band->isolate_loop_type[i];
125 return dup;
128 /* Return an isl_schedule_band that is equal to "band" and that has only
129 * a single reference.
131 __isl_give isl_schedule_band *isl_schedule_band_cow(
132 __isl_take isl_schedule_band *band)
134 if (!band)
135 return NULL;
137 if (band->ref == 1)
138 return band;
139 band->ref--;
140 return isl_schedule_band_dup(band);
143 /* Return a new reference to "band".
145 __isl_give isl_schedule_band *isl_schedule_band_copy(
146 __isl_keep isl_schedule_band *band)
148 if (!band)
149 return NULL;
151 band->ref++;
152 return band;
155 /* Free a reference to "band" and return NULL.
157 __isl_null isl_schedule_band *isl_schedule_band_free(
158 __isl_take isl_schedule_band *band)
160 if (!band)
161 return NULL;
163 if (--band->ref > 0)
164 return NULL;
166 isl_multi_union_pw_aff_free(band->mupa);
167 isl_union_set_free(band->ast_build_options);
168 free(band->loop_type);
169 free(band->isolate_loop_type);
170 free(band->coincident);
171 free(band);
173 return NULL;
176 /* Are "band1" and "band2" obviously equal?
178 int isl_schedule_band_plain_is_equal(__isl_keep isl_schedule_band *band1,
179 __isl_keep isl_schedule_band *band2)
181 int i;
182 int equal;
184 if (!band1 || !band2)
185 return -1;
186 if (band1 == band2)
187 return 1;
189 if (band1->n != band2->n)
190 return 0;
191 for (i = 0; i < band1->n; ++i)
192 if (band1->coincident[i] != band2->coincident[i])
193 return 0;
194 if (band1->permutable != band2->permutable)
195 return 0;
197 equal = isl_multi_union_pw_aff_plain_is_equal(band1->mupa, band2->mupa);
198 if (equal < 0 || !equal)
199 return equal;
201 if (!band1->loop_type != !band2->loop_type)
202 return 0;
203 if (band1->loop_type)
204 for (i = 0; i < band1->n; ++i)
205 if (band1->loop_type[i] != band2->loop_type[i])
206 return 0;
208 if (!band1->isolate_loop_type != !band2->isolate_loop_type)
209 return 0;
210 if (band1->isolate_loop_type)
211 for (i = 0; i < band1->n; ++i)
212 if (band1->isolate_loop_type[i] !=
213 band2->isolate_loop_type[i])
214 return 0;
216 return isl_union_set_is_equal(band1->ast_build_options,
217 band2->ast_build_options);
220 /* Return the number of scheduling dimensions in the band.
222 int isl_schedule_band_n_member(__isl_keep isl_schedule_band *band)
224 return band ? band->n : 0;
227 /* Is the given scheduling dimension coincident within the band and
228 * with respect to the coincidence constraints?
230 int isl_schedule_band_member_get_coincident(__isl_keep isl_schedule_band *band,
231 int pos)
233 if (!band)
234 return -1;
236 if (pos < 0 || pos >= band->n)
237 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
238 "invalid member position", return -1);
240 return band->coincident[pos];
243 /* Mark the given scheduling dimension as being coincident or not
244 * according to "coincident".
246 __isl_give isl_schedule_band *isl_schedule_band_member_set_coincident(
247 __isl_take isl_schedule_band *band, int pos, int coincident)
249 if (!band)
250 return NULL;
251 if (isl_schedule_band_member_get_coincident(band, pos) == coincident)
252 return band;
253 band = isl_schedule_band_cow(band);
254 if (!band)
255 return NULL;
257 if (pos < 0 || pos >= band->n)
258 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
259 "invalid member position",
260 isl_schedule_band_free(band));
262 band->coincident[pos] = coincident;
264 return band;
267 /* Is the schedule band mark permutable?
269 int isl_schedule_band_get_permutable(__isl_keep isl_schedule_band *band)
271 if (!band)
272 return -1;
273 return band->permutable;
276 /* Mark the schedule band permutable or not according to "permutable"?
278 __isl_give isl_schedule_band *isl_schedule_band_set_permutable(
279 __isl_take isl_schedule_band *band, int permutable)
281 if (!band)
282 return NULL;
283 if (band->permutable == permutable)
284 return band;
285 band = isl_schedule_band_cow(band);
286 if (!band)
287 return NULL;
289 band->permutable = permutable;
291 return band;
294 /* Is the band node "node" anchored? That is, does it reference
295 * the outer band nodes?
297 int isl_schedule_band_is_anchored(__isl_keep isl_schedule_band *band)
299 return band ? band->anchored : -1;
302 /* Return the schedule space of the band.
304 __isl_give isl_space *isl_schedule_band_get_space(
305 __isl_keep isl_schedule_band *band)
307 if (!band)
308 return NULL;
309 return isl_multi_union_pw_aff_get_space(band->mupa);
312 /* Return the schedule of the band in isolation.
314 __isl_give isl_multi_union_pw_aff *isl_schedule_band_get_partial_schedule(
315 __isl_keep isl_schedule_band *band)
317 return band ? isl_multi_union_pw_aff_copy(band->mupa) : NULL;
320 /* Return the loop AST generation type for the band member of "band"
321 * at position "pos".
323 enum isl_ast_loop_type isl_schedule_band_member_get_ast_loop_type(
324 __isl_keep isl_schedule_band *band, int pos)
326 if (!band)
327 return isl_ast_loop_error;
329 if (pos < 0 || pos >= band->n)
330 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
331 "invalid member position", return -1);
333 if (!band->loop_type)
334 return isl_ast_loop_default;
336 return band->loop_type[pos];
339 /* Set the loop AST generation type for the band member of "band"
340 * at position "pos" to "type".
342 __isl_give isl_schedule_band *isl_schedule_band_member_set_ast_loop_type(
343 __isl_take isl_schedule_band *band, int pos,
344 enum isl_ast_loop_type type)
346 if (!band)
347 return NULL;
348 if (isl_schedule_band_member_get_ast_loop_type(band, pos) == type)
349 return band;
351 if (pos < 0 || pos >= band->n)
352 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
353 "invalid member position",
354 isl_schedule_band_free(band));
356 band = isl_schedule_band_cow(band);
357 if (!band)
358 return isl_schedule_band_free(band);
360 if (!band->loop_type) {
361 isl_ctx *ctx;
363 ctx = isl_schedule_band_get_ctx(band);
364 band->loop_type = isl_calloc_array(ctx,
365 enum isl_ast_loop_type, band->n);
366 if (band->n && !band->loop_type)
367 return isl_schedule_band_free(band);
370 band->loop_type[pos] = type;
372 return band;
375 /* Return the loop AST generation type for the band member of "band"
376 * at position "pos" for the part that has been isolated by the isolate option.
378 enum isl_ast_loop_type isl_schedule_band_member_get_isolate_ast_loop_type(
379 __isl_keep isl_schedule_band *band, int pos)
381 if (!band)
382 return isl_ast_loop_error;
384 if (pos < 0 || pos >= band->n)
385 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
386 "invalid member position", return -1);
388 if (!band->isolate_loop_type)
389 return isl_ast_loop_default;
391 return band->isolate_loop_type[pos];
394 /* Set the loop AST generation type for the band member of "band"
395 * at position "pos" to "type" for the part that has been isolated
396 * by the isolate option.
398 __isl_give isl_schedule_band *
399 isl_schedule_band_member_set_isolate_ast_loop_type(
400 __isl_take isl_schedule_band *band, int pos,
401 enum isl_ast_loop_type type)
403 if (!band)
404 return NULL;
405 if (isl_schedule_band_member_get_isolate_ast_loop_type(band, pos) ==
406 type)
407 return band;
409 if (pos < 0 || pos >= band->n)
410 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
411 "invalid member position",
412 isl_schedule_band_free(band));
414 band = isl_schedule_band_cow(band);
415 if (!band)
416 return isl_schedule_band_free(band);
418 if (!band->isolate_loop_type) {
419 isl_ctx *ctx;
421 ctx = isl_schedule_band_get_ctx(band);
422 band->isolate_loop_type = isl_calloc_array(ctx,
423 enum isl_ast_loop_type, band->n);
424 if (band->n && !band->isolate_loop_type)
425 return isl_schedule_band_free(band);
428 band->isolate_loop_type[pos] = type;
430 return band;
433 static const char *option_str[] = {
434 [isl_ast_loop_atomic] = "atomic",
435 [isl_ast_loop_unroll] = "unroll",
436 [isl_ast_loop_separate] = "separate"
439 /* Given a parameter space "space", extend it to a set space
441 * { type[x] }
443 * or
445 * { [isolate[] -> type[x]] }
447 * depending on whether "isolate" is set.
448 * These can be used to encode loop AST generation options of the given type.
450 static __isl_give isl_space *loop_type_space(__isl_take isl_space *space,
451 enum isl_ast_loop_type type, int isolate)
453 const char *name;
455 name = option_str[type];
456 space = isl_space_set_from_params(space);
457 space = isl_space_add_dims(space, isl_dim_set, 1);
458 space = isl_space_set_tuple_name(space, isl_dim_set, name);
459 if (!isolate)
460 return space;
461 space = isl_space_from_range(space);
462 space = isl_space_set_tuple_name(space, isl_dim_in, "isolate");
463 space = isl_space_wrap(space);
465 return space;
468 /* Add encodings of the "n" loop AST generation options "type" to "options".
469 * If "isolate" is set, then these options refer to the isolated part.
471 * In particular, for each sequence of consecutive identical types "t",
472 * different from the default, add an option
474 * { t[x] : first <= x <= last }
476 * or
478 * { [isolate[] -> t[x]] : first <= x <= last }
480 static __isl_give isl_union_set *add_loop_types(
481 __isl_take isl_union_set *options, int n, enum isl_ast_loop_type *type,
482 int isolate)
484 int i;
485 isl_ctx *ctx;
487 if (!type)
488 return options;
489 if (!options)
490 return NULL;
492 ctx = isl_union_set_get_ctx(options);
493 for (i = 0; i < n; ++i) {
494 int first;
495 isl_space *space;
496 isl_set *option;
498 if (type[i] == isl_ast_loop_default)
499 continue;
501 first = i;
502 while (i + 1 < n && type[i + 1] == type[i])
503 ++i;
505 space = isl_union_set_get_space(options);
506 space = loop_type_space(space, type[i], isolate);
507 option = isl_set_universe(space);
508 option = isl_set_lower_bound_si(option, isl_dim_set, 0, first);
509 option = isl_set_upper_bound_si(option, isl_dim_set, 0, i);
510 options = isl_union_set_add_set(options, option);
513 return options;
516 /* Return the AST build options associated to "band".
518 __isl_give isl_union_set *isl_schedule_band_get_ast_build_options(
519 __isl_keep isl_schedule_band *band)
521 isl_union_set *options;
523 if (!band)
524 return NULL;
526 options = isl_union_set_copy(band->ast_build_options);
527 options = add_loop_types(options, band->n, band->loop_type, 0);
528 options = add_loop_types(options, band->n, band->isolate_loop_type, 1);
530 return options;
533 /* Does "uset" contain any set that satisfies "is"?
534 * "is" is assumed to set its integer argument to 1 if it is satisfied.
536 static int has_any(__isl_keep isl_union_set *uset,
537 int (*is)(__isl_take isl_set *set, void *user))
539 int found = 0;
541 if (isl_union_set_foreach_set(uset, is, &found) < 0 && !found)
542 return -1;
544 return found;
547 /* Does "set" live in a space of the form
549 * isolate[[...] -> [...]]
553 * If so, set *found and abort the search.
555 static int is_isolate(__isl_take isl_set *set, void *user)
557 int *found = user;
559 if (isl_set_has_tuple_name(set)) {
560 const char *name;
561 name = isl_set_get_tuple_name(set);
562 if (isl_set_is_wrapping(set) && !strcmp(name, "isolate"))
563 *found = 1;
565 isl_set_free(set);
567 return *found ? -1 : 0;
570 /* Does "options" include an option of the ofrm
572 * isolate[[...] -> [...]]
576 static int has_isolate_option(__isl_keep isl_union_set *options)
578 return has_any(options, &is_isolate);
581 /* Does "set" encode a loop AST generation option?
583 static int is_loop_type_option(__isl_take isl_set *set, void *user)
585 int *found = user;
587 if (isl_set_dim(set, isl_dim_set) == 1 &&
588 isl_set_has_tuple_name(set)) {
589 const char *name;
590 enum isl_ast_loop_type type;
591 name = isl_set_get_tuple_name(set);
592 for (type = isl_ast_loop_atomic;
593 type <= isl_ast_loop_separate; ++type) {
594 if (strcmp(name, option_str[type]))
595 continue;
596 *found = 1;
597 break;
600 isl_set_free(set);
602 return *found ? -1 : 0;
605 /* Does "set" encode a loop AST generation option for the isolated part?
606 * That is, is of the form
608 * { [isolate[] -> t[x]] }
610 * with t equal to "atomic", "unroll" or "separate"?
612 static int is_isolate_loop_type_option(__isl_take isl_set *set, void *user)
614 int *found = user;
615 const char *name;
616 enum isl_ast_loop_type type;
617 isl_map *map;
619 if (!isl_set_is_wrapping(set)) {
620 isl_set_free(set);
621 return 0;
623 map = isl_set_unwrap(set);
624 if (!isl_map_has_tuple_name(map, isl_dim_in) ||
625 !isl_map_has_tuple_name(map, isl_dim_out)) {
626 isl_map_free(map);
627 return 0;
629 name = isl_map_get_tuple_name(map, isl_dim_in);
630 if (!strcmp(name, "isolate")) {
631 name = isl_map_get_tuple_name(map, isl_dim_out);
632 for (type = isl_ast_loop_atomic;
633 type <= isl_ast_loop_separate; ++type) {
634 if (strcmp(name, option_str[type]))
635 continue;
636 *found = 1;
637 break;
640 isl_map_free(map);
642 return *found ? -1 : 0;
645 /* Does "options" encode any loop AST generation options
646 * for the isolated part?
648 static int has_isolate_loop_type_options(__isl_keep isl_union_set *options)
650 return has_any(options, &is_isolate_loop_type_option);
653 /* Does "options" encode any loop AST generation options?
655 static int has_loop_type_options(__isl_keep isl_union_set *options)
657 return has_any(options, &is_loop_type_option);
660 /* Extract the loop AST generation type for the band member
661 * at position "pos" from "options".
662 * If "isolate" is set, then extract the loop types for the isolated part.
664 static enum isl_ast_loop_type extract_loop_type(
665 __isl_keep isl_union_set *options, int pos, int isolate)
667 isl_ctx *ctx;
668 enum isl_ast_loop_type type, res = isl_ast_loop_default;
670 ctx = isl_union_set_get_ctx(options);
671 for (type = isl_ast_loop_atomic;
672 type <= isl_ast_loop_separate; ++type) {
673 isl_space *space;
674 isl_set *option;
675 int empty;
677 space = isl_union_set_get_space(options);
678 space = loop_type_space(space, type, isolate);
679 option = isl_union_set_extract_set(options, space);
680 option = isl_set_fix_si(option, isl_dim_set, 0, pos);
681 empty = isl_set_is_empty(option);
682 isl_set_free(option);
684 if (empty < 0)
685 return isl_ast_loop_error;
686 if (empty)
687 continue;
688 if (res != isl_ast_loop_default)
689 isl_die(ctx, isl_error_invalid,
690 "conflicting loop type options",
691 return isl_ast_loop_error);
692 res = type;
695 return res;
698 /* Extract the loop AST generation types for the members of "band"
699 * from "options" and store them in band->loop_type.
700 * Return -1 on error.
702 static int extract_loop_types(__isl_keep isl_schedule_band *band,
703 __isl_keep isl_union_set *options)
705 int i;
707 if (!band->loop_type) {
708 isl_ctx *ctx = isl_schedule_band_get_ctx(band);
709 band->loop_type = isl_alloc_array(ctx,
710 enum isl_ast_loop_type, band->n);
711 if (band->n && !band->loop_type)
712 return -1;
714 for (i = 0; i < band->n; ++i) {
715 band->loop_type[i] = extract_loop_type(options, i, 0);
716 if (band->loop_type[i] == isl_ast_loop_error)
717 return -1;
720 return 0;
723 /* Extract the loop AST generation types for the members of "band"
724 * from "options" for the isolated part and
725 * store them in band->isolate_loop_type.
726 * Return -1 on error.
728 static int extract_isolate_loop_types(__isl_keep isl_schedule_band *band,
729 __isl_keep isl_union_set *options)
731 int i;
733 if (!band->isolate_loop_type) {
734 isl_ctx *ctx = isl_schedule_band_get_ctx(band);
735 band->isolate_loop_type = isl_alloc_array(ctx,
736 enum isl_ast_loop_type, band->n);
737 if (band->n && !band->isolate_loop_type)
738 return -1;
740 for (i = 0; i < band->n; ++i) {
741 band->isolate_loop_type[i] = extract_loop_type(options, i, 1);
742 if (band->isolate_loop_type[i] == isl_ast_loop_error)
743 return -1;
746 return 0;
749 /* Construct universe sets of the spaces that encode loop AST generation
750 * types (for the isolated part if "isolate" is set). That is, construct
752 * { atomic[x]; separate[x]; unroll[x] }
754 * or
756 * { [isolate[] -> atomic[x]]; [isolate[] -> separate[x]];
757 * [isolate[] -> unroll[x]] }
759 static __isl_give isl_union_set *loop_types(__isl_take isl_space *space,
760 int isolate)
762 enum isl_ast_loop_type type;
763 isl_union_set *types;
765 types = isl_union_set_empty(space);
766 for (type = isl_ast_loop_atomic;
767 type <= isl_ast_loop_separate; ++type) {
768 isl_set *set;
770 space = isl_union_set_get_space(types);
771 space = loop_type_space(space, type, isolate);
772 set = isl_set_universe(space);
773 types = isl_union_set_add_set(types, set);
776 return types;
779 /* Remove all elements from spaces that encode loop AST generation types
780 * from "options".
782 static __isl_give isl_union_set *clear_loop_types(
783 __isl_take isl_union_set *options)
785 isl_union_set *types;
787 types = loop_types(isl_union_set_get_space(options), 0);
788 options = isl_union_set_subtract(options, types);
790 return options;
793 /* Remove all elements from spaces that encode loop AST generation types
794 * for the isolated part from "options".
796 static __isl_give isl_union_set *clear_isolate_loop_types(
797 __isl_take isl_union_set *options)
799 isl_union_set *types;
801 types = loop_types(isl_union_set_get_space(options), 1);
802 options = isl_union_set_subtract(options, types);
804 return options;
807 /* Replace the AST build options associated to "band" by "options".
808 * If there are any loop AST generation type options, then they
809 * are extracted and stored in band->loop_type. Otherwise,
810 * band->loop_type is removed to indicate that the default applies
811 * to all members. Similarly for the loop AST generation type options
812 * for the isolated part, which are stored in band->isolate_loop_type.
813 * The remaining options are stored in band->ast_build_options.
815 * Set anchored if the options include an isolate option since the
816 * domain of the wrapped map references the outer band node schedules.
818 __isl_give isl_schedule_band *isl_schedule_band_set_ast_build_options(
819 __isl_take isl_schedule_band *band, __isl_take isl_union_set *options)
821 int has_isolate, has_loop_type, has_isolate_loop_type;
823 band = isl_schedule_band_cow(band);
824 if (!band || !options)
825 goto error;
826 has_isolate = has_isolate_option(options);
827 if (has_isolate < 0)
828 goto error;
829 has_loop_type = has_loop_type_options(options);
830 if (has_loop_type < 0)
831 goto error;
832 has_isolate_loop_type = has_isolate_loop_type_options(options);
833 if (has_isolate_loop_type < 0)
834 goto error;
836 if (!has_loop_type) {
837 free(band->loop_type);
838 band->loop_type = NULL;
839 } else {
840 if (extract_loop_types(band, options) < 0)
841 goto error;
842 options = clear_loop_types(options);
843 if (!options)
844 goto error;
847 if (!has_isolate_loop_type) {
848 free(band->isolate_loop_type);
849 band->isolate_loop_type = NULL;
850 } else {
851 if (extract_isolate_loop_types(band, options) < 0)
852 goto error;
853 options = clear_isolate_loop_types(options);
854 if (!options)
855 goto error;
858 isl_union_set_free(band->ast_build_options);
859 band->ast_build_options = options;
860 band->anchored = has_isolate;
862 return band;
863 error:
864 isl_schedule_band_free(band);
865 isl_union_set_free(options);
866 return NULL;
869 /* Multiply the partial schedule of "band" with the factors in "mv".
870 * Replace the result by its greatest integer part to ensure
871 * that the schedule is always integral.
873 __isl_give isl_schedule_band *isl_schedule_band_scale(
874 __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
876 band = isl_schedule_band_cow(band);
877 if (!band || !mv)
878 goto error;
879 band->mupa = isl_multi_union_pw_aff_scale_multi_val(band->mupa, mv);
880 band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
881 if (!band->mupa)
882 return isl_schedule_band_free(band);
883 return band;
884 error:
885 isl_schedule_band_free(band);
886 isl_multi_val_free(mv);
887 return NULL;
890 /* Divide the partial schedule of "band" by the factors in "mv".
891 * Replace the result by its greatest integer part to ensure
892 * that the schedule is always integral.
894 __isl_give isl_schedule_band *isl_schedule_band_scale_down(
895 __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
897 band = isl_schedule_band_cow(band);
898 if (!band || !mv)
899 goto error;
900 band->mupa = isl_multi_union_pw_aff_scale_down_multi_val(band->mupa,
901 mv);
902 band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
903 if (!band->mupa)
904 return isl_schedule_band_free(band);
905 return band;
906 error:
907 isl_schedule_band_free(band);
908 isl_multi_val_free(mv);
909 return NULL;
912 /* Given the schedule of a band, construct the corresponding
913 * schedule for the tile loops based on the given tile sizes
914 * and return the result.
916 * If the scale tile loops options is set, then the tile loops
917 * are scaled by the tile sizes.
919 * That is replace each schedule dimension "i" by either
920 * "floor(i/s)" or "s * floor(i/s)".
922 static isl_multi_union_pw_aff *isl_multi_union_pw_aff_tile(
923 __isl_take isl_multi_union_pw_aff *sched,
924 __isl_take isl_multi_val *sizes)
926 isl_ctx *ctx;
927 int i, n;
928 isl_val *v;
929 int scale;
931 ctx = isl_multi_val_get_ctx(sizes);
932 scale = isl_options_get_tile_scale_tile_loops(ctx);
934 n = isl_multi_union_pw_aff_dim(sched, isl_dim_set);
935 for (i = 0; i < n; ++i) {
936 isl_union_pw_aff *upa;
938 upa = isl_multi_union_pw_aff_get_union_pw_aff(sched, i);
939 v = isl_multi_val_get_val(sizes, i);
941 upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(v));
942 upa = isl_union_pw_aff_floor(upa);
943 if (scale)
944 upa = isl_union_pw_aff_scale_val(upa, isl_val_copy(v));
945 isl_val_free(v);
947 sched = isl_multi_union_pw_aff_set_union_pw_aff(sched, i, upa);
950 isl_multi_val_free(sizes);
951 return sched;
954 /* Replace "band" by a band corresponding to the tile loops of a tiling
955 * with the given tile sizes.
957 __isl_give isl_schedule_band *isl_schedule_band_tile(
958 __isl_take isl_schedule_band *band, __isl_take isl_multi_val *sizes)
960 band = isl_schedule_band_cow(band);
961 if (!band || !sizes)
962 goto error;
963 band->mupa = isl_multi_union_pw_aff_tile(band->mupa, sizes);
964 if (!band->mupa)
965 return isl_schedule_band_free(band);
966 return band;
967 error:
968 isl_schedule_band_free(band);
969 isl_multi_val_free(sizes);
970 return NULL;
973 /* Replace "band" by a band corresponding to the point loops of a tiling
974 * with the given tile sizes.
975 * "tile" is the corresponding tile loop band.
977 * If the shift point loops option is set, then the point loops
978 * are shifted to start at zero. That is, each schedule dimension "i"
979 * is replaced by "i - s * floor(i/s)".
980 * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
981 * the tile band.
983 * Otherwise, the band is left untouched.
985 __isl_give isl_schedule_band *isl_schedule_band_point(
986 __isl_take isl_schedule_band *band, __isl_keep isl_schedule_band *tile,
987 __isl_take isl_multi_val *sizes)
989 isl_ctx *ctx;
990 isl_multi_union_pw_aff *scaled;
992 if (!band || !sizes)
993 goto error;
995 ctx = isl_schedule_band_get_ctx(band);
996 if (!isl_options_get_tile_shift_point_loops(ctx)) {
997 isl_multi_val_free(sizes);
998 return band;
1000 band = isl_schedule_band_cow(band);
1001 if (!band)
1002 goto error;
1004 scaled = isl_schedule_band_get_partial_schedule(tile);
1005 if (!isl_options_get_tile_scale_tile_loops(ctx))
1006 scaled = isl_multi_union_pw_aff_scale_multi_val(scaled, sizes);
1007 else
1008 isl_multi_val_free(sizes);
1009 band->mupa = isl_multi_union_pw_aff_sub(band->mupa, scaled);
1010 if (!band->mupa)
1011 return isl_schedule_band_free(band);
1012 return band;
1013 error:
1014 isl_schedule_band_free(band);
1015 isl_multi_val_free(sizes);
1016 return NULL;
1019 /* Drop the "n" dimensions starting at "pos" from "band".
1021 * We apply the transformation even if "n" is zero to ensure consistent
1022 * behavior with respect to changes in the schedule space.
1024 * The loop AST generation types for the isolated part become
1025 * meaningless after dropping dimensions, so we remove them.
1027 __isl_give isl_schedule_band *isl_schedule_band_drop(
1028 __isl_take isl_schedule_band *band, int pos, int n)
1030 int i;
1032 if (pos < 0 || n < 0 || pos + n > band->n)
1033 isl_die(isl_schedule_band_get_ctx(band), isl_error_internal,
1034 "range out of bounds",
1035 return isl_schedule_band_free(band));
1037 band = isl_schedule_band_cow(band);
1038 if (!band)
1039 return NULL;
1041 band->mupa = isl_multi_union_pw_aff_drop_dims(band->mupa,
1042 isl_dim_set, pos, n);
1043 if (!band->mupa)
1044 return isl_schedule_band_free(band);
1046 for (i = pos + n; i < band->n; ++i)
1047 band->coincident[i - n] = band->coincident[i];
1048 if (band->loop_type)
1049 for (i = pos + n; i < band->n; ++i)
1050 band->loop_type[i - n] = band->loop_type[i];
1051 free(band->isolate_loop_type);
1052 band->isolate_loop_type = NULL;
1054 band->n -= n;
1056 return band;
1059 /* Reset the user pointer on all identifiers of parameters and tuples
1060 * in "band".
1062 __isl_give isl_schedule_band *isl_schedule_band_reset_user(
1063 __isl_take isl_schedule_band *band)
1065 band = isl_schedule_band_cow(band);
1066 if (!band)
1067 return NULL;
1069 band->mupa = isl_multi_union_pw_aff_reset_user(band->mupa);
1070 band->ast_build_options =
1071 isl_union_set_reset_user(band->ast_build_options);
1072 if (!band->mupa || !band->ast_build_options)
1073 return isl_schedule_band_free(band);
1075 return band;
1078 /* Align the parameters of "band" to those of "space".
1080 __isl_give isl_schedule_band *isl_schedule_band_align_params(
1081 __isl_take isl_schedule_band *band, __isl_take isl_space *space)
1083 band = isl_schedule_band_cow(band);
1084 if (!band || !space)
1085 goto error;
1087 band->mupa = isl_multi_union_pw_aff_align_params(band->mupa,
1088 isl_space_copy(space));
1089 band->ast_build_options =
1090 isl_union_set_align_params(band->ast_build_options, space);
1091 if (!band->mupa || !band->ast_build_options)
1092 return isl_schedule_band_free(band);
1094 return band;
1095 error:
1096 isl_space_free(space);
1097 isl_schedule_band_free(band);
1098 return NULL;
1101 /* Compute the pullback of "band" by the function represented by "upma".
1102 * In other words, plug in "upma" in the iteration domains of "band".
1104 __isl_give isl_schedule_band *isl_schedule_band_pullback_union_pw_multi_aff(
1105 __isl_take isl_schedule_band *band,
1106 __isl_take isl_union_pw_multi_aff *upma)
1108 band = isl_schedule_band_cow(band);
1109 if (!band || !upma)
1110 goto error;
1112 band->mupa =
1113 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(band->mupa,
1114 upma);
1115 if (!band->mupa)
1116 return isl_schedule_band_free(band);
1118 return band;
1119 error:
1120 isl_union_pw_multi_aff_free(upma);
1121 isl_schedule_band_free(band);
1122 return NULL;
1125 /* Compute the gist of "band" with respect to "context".
1126 * In particular, compute the gist of the associated partial schedule.
1128 __isl_give isl_schedule_band *isl_schedule_band_gist(
1129 __isl_take isl_schedule_band *band, __isl_take isl_union_set *context)
1131 if (!band || !context)
1132 goto error;
1133 if (band->n == 0) {
1134 isl_union_set_free(context);
1135 return band;
1137 band = isl_schedule_band_cow(band);
1138 if (!band)
1139 goto error;
1140 band->mupa = isl_multi_union_pw_aff_gist(band->mupa, context);
1141 if (!band->mupa)
1142 return isl_schedule_band_free(band);
1143 return band;
1144 error:
1145 isl_union_set_free(context);
1146 isl_schedule_band_free(band);
1147 return NULL;