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
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
);
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
)
50 isl_schedule_band
*band
;
53 mupa
= isl_multi_union_pw_aff_floor(mupa
);
56 ctx
= isl_multi_union_pw_aff_get_ctx(mupa
);
57 band
= isl_schedule_band_alloc(ctx
);
61 band
->n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
62 band
->coincident
= isl_calloc_array(ctx
, int, band
->n
);
64 space
= isl_space_params_alloc(ctx
, 0);
65 band
->ast_build_options
= isl_union_set_empty(space
);
68 if ((band
->n
&& !band
->coincident
) || !band
->ast_build_options
)
69 return isl_schedule_band_free(band
);
73 isl_multi_union_pw_aff_free(mupa
);
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
)
84 isl_schedule_band
*dup
;
89 ctx
= isl_schedule_band_get_ctx(band
);
90 dup
= isl_schedule_band_alloc(ctx
);
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
];
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
)
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
)
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
)
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
);
176 /* Are "band1" and "band2" obviously equal?
178 isl_bool
isl_schedule_band_plain_is_equal(__isl_keep isl_schedule_band
*band1
,
179 __isl_keep isl_schedule_band
*band2
)
184 if (!band1
|| !band2
)
185 return isl_bool_error
;
187 return isl_bool_true
;
189 if (band1
->n
!= band2
->n
)
190 return isl_bool_false
;
191 for (i
= 0; i
< band1
->n
; ++i
)
192 if (band1
->coincident
[i
] != band2
->coincident
[i
])
193 return isl_bool_false
;
194 if (band1
->permutable
!= band2
->permutable
)
195 return isl_bool_false
;
197 equal
= isl_multi_union_pw_aff_plain_is_equal(band1
->mupa
, band2
->mupa
);
198 if (equal
< 0 || !equal
)
201 if (!band1
->loop_type
!= !band2
->loop_type
)
202 return isl_bool_false
;
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 isl_bool_false
;
208 if (!band1
->isolate_loop_type
!= !band2
->isolate_loop_type
)
209 return isl_bool_false
;
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 isl_bool_false
;
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 isl_bool
isl_schedule_band_member_get_coincident(
231 __isl_keep isl_schedule_band
*band
, int pos
)
234 return isl_bool_error
;
236 if (pos
< 0 || pos
>= band
->n
)
237 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
238 "invalid member position", return isl_bool_error
);
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
)
251 if (isl_schedule_band_member_get_coincident(band
, pos
) == coincident
)
253 band
= isl_schedule_band_cow(band
);
257 if (pos
< 0 || pos
>= band
->n
)
258 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
259 "invalid member position",
260 return isl_schedule_band_free(band
));
262 band
->coincident
[pos
] = coincident
;
267 /* Is the schedule band mark permutable?
269 isl_bool
isl_schedule_band_get_permutable(__isl_keep isl_schedule_band
*band
)
272 return isl_bool_error
;
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
)
283 if (band
->permutable
== permutable
)
285 band
= isl_schedule_band_cow(band
);
289 band
->permutable
= permutable
;
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
)
309 return isl_multi_union_pw_aff_get_space(band
->mupa
);
312 /* Intersect the domain of the band schedule of "band" with "domain".
314 __isl_give isl_schedule_band
*isl_schedule_band_intersect_domain(
315 __isl_take isl_schedule_band
*band
, __isl_take isl_union_set
*domain
)
317 band
= isl_schedule_band_cow(band
);
318 if (!band
|| !domain
)
321 band
->mupa
= isl_multi_union_pw_aff_intersect_domain(band
->mupa
,
324 return isl_schedule_band_free(band
);
328 isl_schedule_band_free(band
);
329 isl_union_set_free(domain
);
333 /* Return the schedule of the band in isolation.
335 __isl_give isl_multi_union_pw_aff
*isl_schedule_band_get_partial_schedule(
336 __isl_keep isl_schedule_band
*band
)
338 return band
? isl_multi_union_pw_aff_copy(band
->mupa
) : NULL
;
341 /* Replace the schedule of "band" by "schedule".
343 __isl_give isl_schedule_band
*isl_schedule_band_set_partial_schedule(
344 __isl_take isl_schedule_band
*band
,
345 __isl_take isl_multi_union_pw_aff
*schedule
)
347 band
= isl_schedule_band_cow(band
);
348 if (!band
|| !schedule
)
351 isl_multi_union_pw_aff_free(band
->mupa
);
352 band
->mupa
= schedule
;
356 isl_schedule_band_free(band
);
357 isl_multi_union_pw_aff_free(schedule
);
361 /* Return the loop AST generation type for the band member of "band"
364 enum isl_ast_loop_type
isl_schedule_band_member_get_ast_loop_type(
365 __isl_keep isl_schedule_band
*band
, int pos
)
368 return isl_ast_loop_error
;
370 if (pos
< 0 || pos
>= band
->n
)
371 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
372 "invalid member position", return -1);
374 if (!band
->loop_type
)
375 return isl_ast_loop_default
;
377 return band
->loop_type
[pos
];
380 /* Set the loop AST generation type for the band member of "band"
381 * at position "pos" to "type".
383 __isl_give isl_schedule_band
*isl_schedule_band_member_set_ast_loop_type(
384 __isl_take isl_schedule_band
*band
, int pos
,
385 enum isl_ast_loop_type type
)
389 if (isl_schedule_band_member_get_ast_loop_type(band
, pos
) == type
)
392 if (pos
< 0 || pos
>= band
->n
)
393 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
394 "invalid member position",
395 return isl_schedule_band_free(band
));
397 band
= isl_schedule_band_cow(band
);
399 return isl_schedule_band_free(band
);
401 if (!band
->loop_type
) {
404 ctx
= isl_schedule_band_get_ctx(band
);
405 band
->loop_type
= isl_calloc_array(ctx
,
406 enum isl_ast_loop_type
, band
->n
);
407 if (band
->n
&& !band
->loop_type
)
408 return isl_schedule_band_free(band
);
411 band
->loop_type
[pos
] = type
;
416 /* Return the loop AST generation type for the band member of "band"
417 * at position "pos" for the part that has been isolated by the isolate option.
419 enum isl_ast_loop_type
isl_schedule_band_member_get_isolate_ast_loop_type(
420 __isl_keep isl_schedule_band
*band
, int pos
)
423 return isl_ast_loop_error
;
425 if (pos
< 0 || pos
>= band
->n
)
426 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
427 "invalid member position", return -1);
429 if (!band
->isolate_loop_type
)
430 return isl_ast_loop_default
;
432 return band
->isolate_loop_type
[pos
];
435 /* Set the loop AST generation type for the band member of "band"
436 * at position "pos" to "type" for the part that has been isolated
437 * by the isolate option.
439 __isl_give isl_schedule_band
*
440 isl_schedule_band_member_set_isolate_ast_loop_type(
441 __isl_take isl_schedule_band
*band
, int pos
,
442 enum isl_ast_loop_type type
)
446 if (isl_schedule_band_member_get_isolate_ast_loop_type(band
, pos
) ==
450 if (pos
< 0 || pos
>= band
->n
)
451 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
452 "invalid member position",
453 return isl_schedule_band_free(band
));
455 band
= isl_schedule_band_cow(band
);
457 return isl_schedule_band_free(band
);
459 if (!band
->isolate_loop_type
) {
462 ctx
= isl_schedule_band_get_ctx(band
);
463 band
->isolate_loop_type
= isl_calloc_array(ctx
,
464 enum isl_ast_loop_type
, band
->n
);
465 if (band
->n
&& !band
->isolate_loop_type
)
466 return isl_schedule_band_free(band
);
469 band
->isolate_loop_type
[pos
] = type
;
474 static const char *option_str
[] = {
475 [isl_ast_loop_atomic
] = "atomic",
476 [isl_ast_loop_unroll
] = "unroll",
477 [isl_ast_loop_separate
] = "separate"
480 /* Given a parameter space "space", extend it to a set space
486 * { [isolate[] -> type[x]] }
488 * depending on whether "isolate" is set.
489 * These can be used to encode loop AST generation options of the given type.
491 static __isl_give isl_space
*loop_type_space(__isl_take isl_space
*space
,
492 enum isl_ast_loop_type type
, int isolate
)
496 name
= option_str
[type
];
497 space
= isl_space_set_from_params(space
);
498 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
499 space
= isl_space_set_tuple_name(space
, isl_dim_set
, name
);
502 space
= isl_space_from_range(space
);
503 space
= isl_space_set_tuple_name(space
, isl_dim_in
, "isolate");
504 space
= isl_space_wrap(space
);
509 /* Add encodings of the "n" loop AST generation options "type" to "options".
510 * If "isolate" is set, then these options refer to the isolated part.
512 * In particular, for each sequence of consecutive identical types "t",
513 * different from the default, add an option
515 * { t[x] : first <= x <= last }
519 * { [isolate[] -> t[x]] : first <= x <= last }
521 static __isl_give isl_union_set
*add_loop_types(
522 __isl_take isl_union_set
*options
, int n
, enum isl_ast_loop_type
*type
,
532 for (i
= 0; i
< n
; ++i
) {
537 if (type
[i
] == isl_ast_loop_default
)
541 while (i
+ 1 < n
&& type
[i
+ 1] == type
[i
])
544 space
= isl_union_set_get_space(options
);
545 space
= loop_type_space(space
, type
[i
], isolate
);
546 option
= isl_set_universe(space
);
547 option
= isl_set_lower_bound_si(option
, isl_dim_set
, 0, first
);
548 option
= isl_set_upper_bound_si(option
, isl_dim_set
, 0, i
);
549 options
= isl_union_set_add_set(options
, option
);
555 /* Return the AST build options associated to "band".
557 __isl_give isl_union_set
*isl_schedule_band_get_ast_build_options(
558 __isl_keep isl_schedule_band
*band
)
560 isl_union_set
*options
;
565 options
= isl_union_set_copy(band
->ast_build_options
);
566 options
= add_loop_types(options
, band
->n
, band
->loop_type
, 0);
567 options
= add_loop_types(options
, band
->n
, band
->isolate_loop_type
, 1);
572 /* Does "uset" contain any set that satisfies "is"?
573 * "is" is assumed to set its integer argument to 1 if it is satisfied.
575 static int has_any(__isl_keep isl_union_set
*uset
,
576 isl_stat (*is
)(__isl_take isl_set
*set
, void *user
))
580 if (isl_union_set_foreach_set(uset
, is
, &found
) < 0 && !found
)
586 /* Does "set" live in a space of the form
588 * isolate[[...] -> [...]]
592 * If so, set *found and abort the search.
594 static isl_stat
is_isolate(__isl_take isl_set
*set
, void *user
)
598 if (isl_set_has_tuple_name(set
)) {
600 name
= isl_set_get_tuple_name(set
);
601 if (isl_set_is_wrapping(set
) && !strcmp(name
, "isolate"))
606 return *found
? isl_stat_error
: isl_stat_ok
;
609 /* Does "options" include an option of the ofrm
611 * isolate[[...] -> [...]]
615 static int has_isolate_option(__isl_keep isl_union_set
*options
)
617 return has_any(options
, &is_isolate
);
620 /* Does "set" encode a loop AST generation option?
622 static isl_stat
is_loop_type_option(__isl_take isl_set
*set
, void *user
)
626 if (isl_set_dim(set
, isl_dim_set
) == 1 &&
627 isl_set_has_tuple_name(set
)) {
629 enum isl_ast_loop_type type
;
630 name
= isl_set_get_tuple_name(set
);
631 for (type
= isl_ast_loop_atomic
;
632 type
<= isl_ast_loop_separate
; ++type
) {
633 if (strcmp(name
, option_str
[type
]))
641 return *found
? isl_stat_error
: isl_stat_ok
;
644 /* Does "set" encode a loop AST generation option for the isolated part?
645 * That is, is of the form
647 * { [isolate[] -> t[x]] }
649 * with t equal to "atomic", "unroll" or "separate"?
651 static isl_stat
is_isolate_loop_type_option(__isl_take isl_set
*set
, void *user
)
655 enum isl_ast_loop_type type
;
658 if (!isl_set_is_wrapping(set
)) {
662 map
= isl_set_unwrap(set
);
663 if (!isl_map_has_tuple_name(map
, isl_dim_in
) ||
664 !isl_map_has_tuple_name(map
, isl_dim_out
)) {
668 name
= isl_map_get_tuple_name(map
, isl_dim_in
);
669 if (!strcmp(name
, "isolate")) {
670 name
= isl_map_get_tuple_name(map
, isl_dim_out
);
671 for (type
= isl_ast_loop_atomic
;
672 type
<= isl_ast_loop_separate
; ++type
) {
673 if (strcmp(name
, option_str
[type
]))
681 return *found
? isl_stat_error
: isl_stat_ok
;
684 /* Does "options" encode any loop AST generation options
685 * for the isolated part?
687 static int has_isolate_loop_type_options(__isl_keep isl_union_set
*options
)
689 return has_any(options
, &is_isolate_loop_type_option
);
692 /* Does "options" encode any loop AST generation options?
694 static int has_loop_type_options(__isl_keep isl_union_set
*options
)
696 return has_any(options
, &is_loop_type_option
);
699 /* Extract the loop AST generation type for the band member
700 * at position "pos" from "options".
701 * If "isolate" is set, then extract the loop types for the isolated part.
703 static enum isl_ast_loop_type
extract_loop_type(
704 __isl_keep isl_union_set
*options
, int pos
, int isolate
)
707 enum isl_ast_loop_type type
, res
= isl_ast_loop_default
;
709 ctx
= isl_union_set_get_ctx(options
);
710 for (type
= isl_ast_loop_atomic
;
711 type
<= isl_ast_loop_separate
; ++type
) {
716 space
= isl_union_set_get_space(options
);
717 space
= loop_type_space(space
, type
, isolate
);
718 option
= isl_union_set_extract_set(options
, space
);
719 option
= isl_set_fix_si(option
, isl_dim_set
, 0, pos
);
720 empty
= isl_set_is_empty(option
);
721 isl_set_free(option
);
724 return isl_ast_loop_error
;
727 if (res
!= isl_ast_loop_default
)
728 isl_die(ctx
, isl_error_invalid
,
729 "conflicting loop type options",
730 return isl_ast_loop_error
);
737 /* Extract the loop AST generation types for the members of "band"
738 * from "options" and store them in band->loop_type.
739 * Return -1 on error.
741 static int extract_loop_types(__isl_keep isl_schedule_band
*band
,
742 __isl_keep isl_union_set
*options
)
746 if (!band
->loop_type
) {
747 isl_ctx
*ctx
= isl_schedule_band_get_ctx(band
);
748 band
->loop_type
= isl_alloc_array(ctx
,
749 enum isl_ast_loop_type
, band
->n
);
750 if (band
->n
&& !band
->loop_type
)
753 for (i
= 0; i
< band
->n
; ++i
) {
754 band
->loop_type
[i
] = extract_loop_type(options
, i
, 0);
755 if (band
->loop_type
[i
] == isl_ast_loop_error
)
762 /* Extract the loop AST generation types for the members of "band"
763 * from "options" for the isolated part and
764 * store them in band->isolate_loop_type.
765 * Return -1 on error.
767 static int extract_isolate_loop_types(__isl_keep isl_schedule_band
*band
,
768 __isl_keep isl_union_set
*options
)
772 if (!band
->isolate_loop_type
) {
773 isl_ctx
*ctx
= isl_schedule_band_get_ctx(band
);
774 band
->isolate_loop_type
= isl_alloc_array(ctx
,
775 enum isl_ast_loop_type
, band
->n
);
776 if (band
->n
&& !band
->isolate_loop_type
)
779 for (i
= 0; i
< band
->n
; ++i
) {
780 band
->isolate_loop_type
[i
] = extract_loop_type(options
, i
, 1);
781 if (band
->isolate_loop_type
[i
] == isl_ast_loop_error
)
788 /* Construct universe sets of the spaces that encode loop AST generation
789 * types (for the isolated part if "isolate" is set). That is, construct
791 * { atomic[x]; separate[x]; unroll[x] }
795 * { [isolate[] -> atomic[x]]; [isolate[] -> separate[x]];
796 * [isolate[] -> unroll[x]] }
798 static __isl_give isl_union_set
*loop_types(__isl_take isl_space
*space
,
801 enum isl_ast_loop_type type
;
802 isl_union_set
*types
;
804 types
= isl_union_set_empty(space
);
805 for (type
= isl_ast_loop_atomic
;
806 type
<= isl_ast_loop_separate
; ++type
) {
809 space
= isl_union_set_get_space(types
);
810 space
= loop_type_space(space
, type
, isolate
);
811 set
= isl_set_universe(space
);
812 types
= isl_union_set_add_set(types
, set
);
818 /* Remove all elements from spaces that encode loop AST generation types
821 static __isl_give isl_union_set
*clear_loop_types(
822 __isl_take isl_union_set
*options
)
824 isl_union_set
*types
;
826 types
= loop_types(isl_union_set_get_space(options
), 0);
827 options
= isl_union_set_subtract(options
, types
);
832 /* Remove all elements from spaces that encode loop AST generation types
833 * for the isolated part from "options".
835 static __isl_give isl_union_set
*clear_isolate_loop_types(
836 __isl_take isl_union_set
*options
)
838 isl_union_set
*types
;
840 types
= loop_types(isl_union_set_get_space(options
), 1);
841 options
= isl_union_set_subtract(options
, types
);
846 /* Replace the AST build options associated to "band" by "options".
847 * If there are any loop AST generation type options, then they
848 * are extracted and stored in band->loop_type. Otherwise,
849 * band->loop_type is removed to indicate that the default applies
850 * to all members. Similarly for the loop AST generation type options
851 * for the isolated part, which are stored in band->isolate_loop_type.
852 * The remaining options are stored in band->ast_build_options.
854 * Set anchored if the options include an isolate option since the
855 * domain of the wrapped map references the outer band node schedules.
857 __isl_give isl_schedule_band
*isl_schedule_band_set_ast_build_options(
858 __isl_take isl_schedule_band
*band
, __isl_take isl_union_set
*options
)
860 int has_isolate
, has_loop_type
, has_isolate_loop_type
;
862 band
= isl_schedule_band_cow(band
);
863 if (!band
|| !options
)
865 has_isolate
= has_isolate_option(options
);
868 has_loop_type
= has_loop_type_options(options
);
869 if (has_loop_type
< 0)
871 has_isolate_loop_type
= has_isolate_loop_type_options(options
);
872 if (has_isolate_loop_type
< 0)
875 if (!has_loop_type
) {
876 free(band
->loop_type
);
877 band
->loop_type
= NULL
;
879 if (extract_loop_types(band
, options
) < 0)
881 options
= clear_loop_types(options
);
886 if (!has_isolate_loop_type
) {
887 free(band
->isolate_loop_type
);
888 band
->isolate_loop_type
= NULL
;
890 if (extract_isolate_loop_types(band
, options
) < 0)
892 options
= clear_isolate_loop_types(options
);
897 isl_union_set_free(band
->ast_build_options
);
898 band
->ast_build_options
= options
;
899 band
->anchored
= has_isolate
;
903 isl_schedule_band_free(band
);
904 isl_union_set_free(options
);
908 /* Return the "isolate" option associated to "band", assuming
909 * it at appears at schedule depth "depth".
911 * The isolate option is of the form
913 * isolate[[flattened outer bands] -> band]
915 __isl_give isl_set
*isl_schedule_band_get_ast_isolate_option(
916 __isl_keep isl_schedule_band
*band
, int depth
)
924 space
= isl_schedule_band_get_space(band
);
925 space
= isl_space_from_range(space
);
926 space
= isl_space_add_dims(space
, isl_dim_in
, depth
);
927 space
= isl_space_wrap(space
);
928 space
= isl_space_set_tuple_name(space
, isl_dim_set
, "isolate");
930 isolate
= isl_union_set_extract_set(band
->ast_build_options
, space
);
935 /* Replace the option "drop" in the AST build options by "add".
936 * That is, remove "drop" and add "add".
938 __isl_give isl_schedule_band
*isl_schedule_band_replace_ast_build_option(
939 __isl_take isl_schedule_band
*band
, __isl_take isl_set
*drop
,
940 __isl_take isl_set
*add
)
942 isl_union_set
*options
;
944 band
= isl_schedule_band_cow(band
);
948 options
= band
->ast_build_options
;
949 options
= isl_union_set_subtract(options
, isl_union_set_from_set(drop
));
950 options
= isl_union_set_union(options
, isl_union_set_from_set(add
));
951 band
->ast_build_options
= options
;
953 if (!band
->ast_build_options
)
954 return isl_schedule_band_free(band
);
958 isl_schedule_band_free(band
);
964 /* Multiply the partial schedule of "band" with the factors in "mv".
965 * Replace the result by its greatest integer part to ensure
966 * that the schedule is always integral.
968 __isl_give isl_schedule_band
*isl_schedule_band_scale(
969 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
971 band
= isl_schedule_band_cow(band
);
974 band
->mupa
= isl_multi_union_pw_aff_scale_multi_val(band
->mupa
, mv
);
975 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
977 return isl_schedule_band_free(band
);
980 isl_schedule_band_free(band
);
981 isl_multi_val_free(mv
);
985 /* Divide the partial schedule of "band" by the factors in "mv".
986 * Replace the result by its greatest integer part to ensure
987 * that the schedule is always integral.
989 __isl_give isl_schedule_band
*isl_schedule_band_scale_down(
990 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
992 band
= isl_schedule_band_cow(band
);
995 band
->mupa
= isl_multi_union_pw_aff_scale_down_multi_val(band
->mupa
,
997 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
999 return isl_schedule_band_free(band
);
1002 isl_schedule_band_free(band
);
1003 isl_multi_val_free(mv
);
1007 /* Reduce the partial schedule of "band" modulo the factors in "mv".
1009 __isl_give isl_schedule_band
*isl_schedule_band_mod(
1010 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
1012 band
= isl_schedule_band_cow(band
);
1015 band
->mupa
= isl_multi_union_pw_aff_mod_multi_val(band
->mupa
, mv
);
1017 return isl_schedule_band_free(band
);
1020 isl_schedule_band_free(band
);
1021 isl_multi_val_free(mv
);
1025 /* Shift the partial schedule of "band" by "shift" after checking
1026 * that the domain of the partial schedule would not be affected
1029 __isl_give isl_schedule_band
*isl_schedule_band_shift(
1030 __isl_take isl_schedule_band
*band
,
1031 __isl_take isl_multi_union_pw_aff
*shift
)
1033 isl_union_set
*dom1
, *dom2
;
1036 band
= isl_schedule_band_cow(band
);
1037 if (!band
|| !shift
)
1039 dom1
= isl_multi_union_pw_aff_domain(
1040 isl_multi_union_pw_aff_copy(band
->mupa
));
1041 dom2
= isl_multi_union_pw_aff_domain(
1042 isl_multi_union_pw_aff_copy(shift
));
1043 subset
= isl_union_set_is_subset(dom1
, dom2
);
1044 isl_union_set_free(dom1
);
1045 isl_union_set_free(dom2
);
1049 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
1050 "domain of shift needs to include domain of "
1051 "partial schedule", goto error
);
1052 band
->mupa
= isl_multi_union_pw_aff_add(band
->mupa
, shift
);
1054 return isl_schedule_band_free(band
);
1057 isl_schedule_band_free(band
);
1058 isl_multi_union_pw_aff_free(shift
);
1062 /* Given the schedule of a band, construct the corresponding
1063 * schedule for the tile loops based on the given tile sizes
1064 * and return the result.
1066 * If the scale tile loops options is set, then the tile loops
1067 * are scaled by the tile sizes.
1069 * That is replace each schedule dimension "i" by either
1070 * "floor(i/s)" or "s * floor(i/s)".
1072 static isl_multi_union_pw_aff
*isl_multi_union_pw_aff_tile(
1073 __isl_take isl_multi_union_pw_aff
*sched
,
1074 __isl_take isl_multi_val
*sizes
)
1081 ctx
= isl_multi_val_get_ctx(sizes
);
1082 scale
= isl_options_get_tile_scale_tile_loops(ctx
);
1084 n
= isl_multi_union_pw_aff_dim(sched
, isl_dim_set
);
1085 for (i
= 0; i
< n
; ++i
) {
1086 isl_union_pw_aff
*upa
;
1088 upa
= isl_multi_union_pw_aff_get_union_pw_aff(sched
, i
);
1089 v
= isl_multi_val_get_val(sizes
, i
);
1091 upa
= isl_union_pw_aff_scale_down_val(upa
, isl_val_copy(v
));
1092 upa
= isl_union_pw_aff_floor(upa
);
1094 upa
= isl_union_pw_aff_scale_val(upa
, isl_val_copy(v
));
1097 sched
= isl_multi_union_pw_aff_set_union_pw_aff(sched
, i
, upa
);
1100 isl_multi_val_free(sizes
);
1104 /* Replace "band" by a band corresponding to the tile loops of a tiling
1105 * with the given tile sizes.
1107 __isl_give isl_schedule_band
*isl_schedule_band_tile(
1108 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*sizes
)
1110 band
= isl_schedule_band_cow(band
);
1111 if (!band
|| !sizes
)
1113 band
->mupa
= isl_multi_union_pw_aff_tile(band
->mupa
, sizes
);
1115 return isl_schedule_band_free(band
);
1118 isl_schedule_band_free(band
);
1119 isl_multi_val_free(sizes
);
1123 /* Replace "band" by a band corresponding to the point loops of a tiling
1124 * with the given tile sizes.
1125 * "tile" is the corresponding tile loop band.
1127 * If the shift point loops option is set, then the point loops
1128 * are shifted to start at zero. That is, each schedule dimension "i"
1129 * is replaced by "i - s * floor(i/s)".
1130 * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
1133 * Otherwise, the band is left untouched.
1135 __isl_give isl_schedule_band
*isl_schedule_band_point(
1136 __isl_take isl_schedule_band
*band
, __isl_keep isl_schedule_band
*tile
,
1137 __isl_take isl_multi_val
*sizes
)
1140 isl_multi_union_pw_aff
*scaled
;
1142 if (!band
|| !sizes
)
1145 ctx
= isl_schedule_band_get_ctx(band
);
1146 if (!isl_options_get_tile_shift_point_loops(ctx
)) {
1147 isl_multi_val_free(sizes
);
1150 band
= isl_schedule_band_cow(band
);
1154 scaled
= isl_schedule_band_get_partial_schedule(tile
);
1155 if (!isl_options_get_tile_scale_tile_loops(ctx
))
1156 scaled
= isl_multi_union_pw_aff_scale_multi_val(scaled
, sizes
);
1158 isl_multi_val_free(sizes
);
1159 band
->mupa
= isl_multi_union_pw_aff_sub(band
->mupa
, scaled
);
1161 return isl_schedule_band_free(band
);
1164 isl_schedule_band_free(band
);
1165 isl_multi_val_free(sizes
);
1169 /* Drop the "n" dimensions starting at "pos" from "band".
1171 * We apply the transformation even if "n" is zero to ensure consistent
1172 * behavior with respect to changes in the schedule space.
1174 * The caller is responsible for updating the isolate option.
1176 __isl_give isl_schedule_band
*isl_schedule_band_drop(
1177 __isl_take isl_schedule_band
*band
, int pos
, int n
)
1181 if (pos
< 0 || n
< 0 || pos
+ n
> band
->n
)
1182 isl_die(isl_schedule_band_get_ctx(band
), isl_error_internal
,
1183 "range out of bounds",
1184 return isl_schedule_band_free(band
));
1186 band
= isl_schedule_band_cow(band
);
1190 band
->mupa
= isl_multi_union_pw_aff_drop_dims(band
->mupa
,
1191 isl_dim_set
, pos
, n
);
1193 return isl_schedule_band_free(band
);
1195 for (i
= pos
+ n
; i
< band
->n
; ++i
)
1196 band
->coincident
[i
- n
] = band
->coincident
[i
];
1197 if (band
->loop_type
)
1198 for (i
= pos
+ n
; i
< band
->n
; ++i
)
1199 band
->loop_type
[i
- n
] = band
->loop_type
[i
];
1200 if (band
->isolate_loop_type
)
1201 for (i
= pos
+ n
; i
< band
->n
; ++i
)
1202 band
->isolate_loop_type
[i
- n
] =
1203 band
->isolate_loop_type
[i
];
1210 /* Reset the user pointer on all identifiers of parameters and tuples
1213 __isl_give isl_schedule_band
*isl_schedule_band_reset_user(
1214 __isl_take isl_schedule_band
*band
)
1216 band
= isl_schedule_band_cow(band
);
1220 band
->mupa
= isl_multi_union_pw_aff_reset_user(band
->mupa
);
1221 band
->ast_build_options
=
1222 isl_union_set_reset_user(band
->ast_build_options
);
1223 if (!band
->mupa
|| !band
->ast_build_options
)
1224 return isl_schedule_band_free(band
);
1229 /* Align the parameters of "band" to those of "space".
1231 __isl_give isl_schedule_band
*isl_schedule_band_align_params(
1232 __isl_take isl_schedule_band
*band
, __isl_take isl_space
*space
)
1234 band
= isl_schedule_band_cow(band
);
1235 if (!band
|| !space
)
1238 band
->mupa
= isl_multi_union_pw_aff_align_params(band
->mupa
,
1239 isl_space_copy(space
));
1240 band
->ast_build_options
=
1241 isl_union_set_align_params(band
->ast_build_options
, space
);
1242 if (!band
->mupa
|| !band
->ast_build_options
)
1243 return isl_schedule_band_free(band
);
1247 isl_space_free(space
);
1248 isl_schedule_band_free(band
);
1252 /* Compute the pullback of "band" by the function represented by "upma".
1253 * In other words, plug in "upma" in the iteration domains of "band".
1255 __isl_give isl_schedule_band
*isl_schedule_band_pullback_union_pw_multi_aff(
1256 __isl_take isl_schedule_band
*band
,
1257 __isl_take isl_union_pw_multi_aff
*upma
)
1259 band
= isl_schedule_band_cow(band
);
1264 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(band
->mupa
,
1267 return isl_schedule_band_free(band
);
1271 isl_union_pw_multi_aff_free(upma
);
1272 isl_schedule_band_free(band
);
1276 /* Compute the gist of "band" with respect to "context".
1277 * In particular, compute the gist of the associated partial schedule.
1279 __isl_give isl_schedule_band
*isl_schedule_band_gist(
1280 __isl_take isl_schedule_band
*band
, __isl_take isl_union_set
*context
)
1282 if (!band
|| !context
)
1285 isl_union_set_free(context
);
1288 band
= isl_schedule_band_cow(band
);
1291 band
->mupa
= isl_multi_union_pw_aff_gist(band
->mupa
, context
);
1293 return isl_schedule_band_free(band
);
1296 isl_union_set_free(context
);
1297 isl_schedule_band_free(band
);