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/space.h>
17 #include <isl/schedule_node.h>
18 #include <isl_schedule_band.h>
19 #include <isl_schedule_private.h>
21 isl_ctx
*isl_schedule_band_get_ctx(__isl_keep isl_schedule_band
*band
)
23 return band
? isl_multi_union_pw_aff_get_ctx(band
->mupa
) : NULL
;
26 /* Return a new uninitialized isl_schedule_band.
28 static __isl_give isl_schedule_band
*isl_schedule_band_alloc(isl_ctx
*ctx
)
30 isl_schedule_band
*band
;
32 band
= isl_calloc_type(ctx
, isl_schedule_band
);
41 /* Return a new isl_schedule_band with partial schedule "mupa".
42 * First replace "mupa" by its greatest integer part to ensure
43 * that the schedule is always integral.
44 * The band is not marked permutable, the dimensions are not
45 * marked coincident and the AST build options are empty.
46 * Since there are no build options, the node is not anchored.
48 __isl_give isl_schedule_band
*isl_schedule_band_from_multi_union_pw_aff(
49 __isl_take isl_multi_union_pw_aff
*mupa
)
52 isl_schedule_band
*band
;
55 mupa
= isl_multi_union_pw_aff_floor(mupa
);
58 ctx
= isl_multi_union_pw_aff_get_ctx(mupa
);
59 band
= isl_schedule_band_alloc(ctx
);
63 band
->n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
64 band
->coincident
= isl_calloc_array(ctx
, int, band
->n
);
66 space
= isl_space_params_alloc(ctx
, 0);
67 band
->ast_build_options
= isl_union_set_empty(space
);
70 if ((band
->n
&& !band
->coincident
) || !band
->ast_build_options
)
71 return isl_schedule_band_free(band
);
75 isl_multi_union_pw_aff_free(mupa
);
79 /* Create a duplicate of the given isl_schedule_band.
81 __isl_give isl_schedule_band
*isl_schedule_band_dup(
82 __isl_keep isl_schedule_band
*band
)
86 isl_schedule_band
*dup
;
91 ctx
= isl_schedule_band_get_ctx(band
);
92 dup
= isl_schedule_band_alloc(ctx
);
97 dup
->coincident
= isl_alloc_array(ctx
, int, band
->n
);
98 if (band
->n
&& !dup
->coincident
)
99 return isl_schedule_band_free(dup
);
101 for (i
= 0; i
< band
->n
; ++i
)
102 dup
->coincident
[i
] = band
->coincident
[i
];
103 dup
->permutable
= band
->permutable
;
105 dup
->mupa
= isl_multi_union_pw_aff_copy(band
->mupa
);
106 dup
->ast_build_options
= isl_union_set_copy(band
->ast_build_options
);
107 if (!dup
->mupa
|| !dup
->ast_build_options
)
108 return isl_schedule_band_free(dup
);
110 if (band
->loop_type
) {
111 dup
->loop_type
= isl_alloc_array(ctx
,
112 enum isl_ast_loop_type
, band
->n
);
113 if (band
->n
&& !dup
->loop_type
)
114 return isl_schedule_band_free(dup
);
115 for (i
= 0; i
< band
->n
; ++i
)
116 dup
->loop_type
[i
] = band
->loop_type
[i
];
118 if (band
->isolate_loop_type
) {
119 dup
->isolate_loop_type
= isl_alloc_array(ctx
,
120 enum isl_ast_loop_type
, band
->n
);
121 if (band
->n
&& !dup
->isolate_loop_type
)
122 return isl_schedule_band_free(dup
);
123 for (i
= 0; i
< band
->n
; ++i
)
124 dup
->isolate_loop_type
[i
] = band
->isolate_loop_type
[i
];
130 /* Return an isl_schedule_band that is equal to "band" and that has only
131 * a single reference.
133 __isl_give isl_schedule_band
*isl_schedule_band_cow(
134 __isl_take isl_schedule_band
*band
)
142 return isl_schedule_band_dup(band
);
145 /* Return a new reference to "band".
147 __isl_give isl_schedule_band
*isl_schedule_band_copy(
148 __isl_keep isl_schedule_band
*band
)
157 /* Free a reference to "band" and return NULL.
159 __isl_null isl_schedule_band
*isl_schedule_band_free(
160 __isl_take isl_schedule_band
*band
)
168 isl_multi_union_pw_aff_free(band
->mupa
);
169 isl_union_set_free(band
->ast_build_options
);
170 free(band
->loop_type
);
171 free(band
->isolate_loop_type
);
172 free(band
->coincident
);
178 /* Are "band1" and "band2" obviously equal?
180 isl_bool
isl_schedule_band_plain_is_equal(__isl_keep isl_schedule_band
*band1
,
181 __isl_keep isl_schedule_band
*band2
)
186 if (!band1
|| !band2
)
187 return isl_bool_error
;
189 return isl_bool_true
;
191 if (band1
->n
!= band2
->n
)
192 return isl_bool_false
;
193 for (i
= 0; i
< band1
->n
; ++i
)
194 if (band1
->coincident
[i
] != band2
->coincident
[i
])
195 return isl_bool_false
;
196 if (band1
->permutable
!= band2
->permutable
)
197 return isl_bool_false
;
199 equal
= isl_multi_union_pw_aff_plain_is_equal(band1
->mupa
, band2
->mupa
);
200 if (equal
< 0 || !equal
)
203 if (!band1
->loop_type
!= !band2
->loop_type
)
204 return isl_bool_false
;
205 if (band1
->loop_type
)
206 for (i
= 0; i
< band1
->n
; ++i
)
207 if (band1
->loop_type
[i
] != band2
->loop_type
[i
])
208 return isl_bool_false
;
210 if (!band1
->isolate_loop_type
!= !band2
->isolate_loop_type
)
211 return isl_bool_false
;
212 if (band1
->isolate_loop_type
)
213 for (i
= 0; i
< band1
->n
; ++i
)
214 if (band1
->isolate_loop_type
[i
] !=
215 band2
->isolate_loop_type
[i
])
216 return isl_bool_false
;
218 return isl_union_set_is_equal(band1
->ast_build_options
,
219 band2
->ast_build_options
);
222 /* Return the number of scheduling dimensions in the band.
224 int isl_schedule_band_n_member(__isl_keep isl_schedule_band
*band
)
226 return band
? band
->n
: 0;
229 /* Is the given scheduling dimension coincident within the band and
230 * with respect to the coincidence constraints?
232 isl_bool
isl_schedule_band_member_get_coincident(
233 __isl_keep isl_schedule_band
*band
, int pos
)
236 return isl_bool_error
;
238 if (pos
< 0 || pos
>= band
->n
)
239 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
240 "invalid member position", return isl_bool_error
);
242 return band
->coincident
[pos
];
245 /* Mark the given scheduling dimension as being coincident or not
246 * according to "coincident".
248 __isl_give isl_schedule_band
*isl_schedule_band_member_set_coincident(
249 __isl_take isl_schedule_band
*band
, int pos
, int coincident
)
253 if (isl_schedule_band_member_get_coincident(band
, pos
) == coincident
)
255 band
= isl_schedule_band_cow(band
);
259 if (pos
< 0 || pos
>= band
->n
)
260 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
261 "invalid member position",
262 return isl_schedule_band_free(band
));
264 band
->coincident
[pos
] = coincident
;
269 /* Is the schedule band mark permutable?
271 isl_bool
isl_schedule_band_get_permutable(__isl_keep isl_schedule_band
*band
)
274 return isl_bool_error
;
275 return band
->permutable
;
278 /* Mark the schedule band permutable or not according to "permutable"?
280 __isl_give isl_schedule_band
*isl_schedule_band_set_permutable(
281 __isl_take isl_schedule_band
*band
, int permutable
)
285 if (band
->permutable
== permutable
)
287 band
= isl_schedule_band_cow(band
);
291 band
->permutable
= permutable
;
296 /* Is the band node "node" anchored? That is, does it reference
297 * the outer band nodes?
299 int isl_schedule_band_is_anchored(__isl_keep isl_schedule_band
*band
)
301 return band
? band
->anchored
: -1;
304 /* Return the schedule space of the band.
306 __isl_give isl_space
*isl_schedule_band_get_space(
307 __isl_keep isl_schedule_band
*band
)
311 return isl_multi_union_pw_aff_get_space(band
->mupa
);
314 /* Intersect the domain of the band schedule of "band" with "domain".
316 __isl_give isl_schedule_band
*isl_schedule_band_intersect_domain(
317 __isl_take isl_schedule_band
*band
, __isl_take isl_union_set
*domain
)
319 band
= isl_schedule_band_cow(band
);
320 if (!band
|| !domain
)
323 band
->mupa
= isl_multi_union_pw_aff_intersect_domain(band
->mupa
,
326 return isl_schedule_band_free(band
);
330 isl_schedule_band_free(band
);
331 isl_union_set_free(domain
);
335 /* Return the schedule of the band in isolation.
337 __isl_give isl_multi_union_pw_aff
*isl_schedule_band_get_partial_schedule(
338 __isl_keep isl_schedule_band
*band
)
340 return band
? isl_multi_union_pw_aff_copy(band
->mupa
) : NULL
;
343 /* Replace the schedule of "band" by "schedule".
345 __isl_give isl_schedule_band
*isl_schedule_band_set_partial_schedule(
346 __isl_take isl_schedule_band
*band
,
347 __isl_take isl_multi_union_pw_aff
*schedule
)
349 band
= isl_schedule_band_cow(band
);
350 if (!band
|| !schedule
)
353 isl_multi_union_pw_aff_free(band
->mupa
);
354 band
->mupa
= schedule
;
358 isl_schedule_band_free(band
);
359 isl_multi_union_pw_aff_free(schedule
);
363 /* Return the loop AST generation type for the band member of "band"
366 enum isl_ast_loop_type
isl_schedule_band_member_get_ast_loop_type(
367 __isl_keep isl_schedule_band
*band
, int pos
)
370 return isl_ast_loop_error
;
372 if (pos
< 0 || pos
>= band
->n
)
373 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
374 "invalid member position", return isl_ast_loop_error
);
376 if (!band
->loop_type
)
377 return isl_ast_loop_default
;
379 return band
->loop_type
[pos
];
382 /* Set the loop AST generation type for the band member of "band"
383 * at position "pos" to "type".
385 __isl_give isl_schedule_band
*isl_schedule_band_member_set_ast_loop_type(
386 __isl_take isl_schedule_band
*band
, int pos
,
387 enum isl_ast_loop_type type
)
391 if (isl_schedule_band_member_get_ast_loop_type(band
, pos
) == type
)
394 if (pos
< 0 || pos
>= band
->n
)
395 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
396 "invalid member position",
397 return isl_schedule_band_free(band
));
399 band
= isl_schedule_band_cow(band
);
401 return isl_schedule_band_free(band
);
403 if (!band
->loop_type
) {
406 ctx
= isl_schedule_band_get_ctx(band
);
407 band
->loop_type
= isl_calloc_array(ctx
,
408 enum isl_ast_loop_type
, band
->n
);
409 if (band
->n
&& !band
->loop_type
)
410 return isl_schedule_band_free(band
);
413 band
->loop_type
[pos
] = type
;
418 /* Return the loop AST generation type for the band member of "band"
419 * at position "pos" for the part that has been isolated by the isolate option.
421 enum isl_ast_loop_type
isl_schedule_band_member_get_isolate_ast_loop_type(
422 __isl_keep isl_schedule_band
*band
, int pos
)
425 return isl_ast_loop_error
;
427 if (pos
< 0 || pos
>= band
->n
)
428 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
429 "invalid member position", return isl_ast_loop_error
);
431 if (!band
->isolate_loop_type
)
432 return isl_ast_loop_default
;
434 return band
->isolate_loop_type
[pos
];
437 /* Set the loop AST generation type for the band member of "band"
438 * at position "pos" to "type" for the part that has been isolated
439 * by the isolate option.
441 __isl_give isl_schedule_band
*
442 isl_schedule_band_member_set_isolate_ast_loop_type(
443 __isl_take isl_schedule_band
*band
, int pos
,
444 enum isl_ast_loop_type type
)
448 if (isl_schedule_band_member_get_isolate_ast_loop_type(band
, pos
) ==
452 if (pos
< 0 || pos
>= band
->n
)
453 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
454 "invalid member position",
455 return isl_schedule_band_free(band
));
457 band
= isl_schedule_band_cow(band
);
459 return isl_schedule_band_free(band
);
461 if (!band
->isolate_loop_type
) {
464 ctx
= isl_schedule_band_get_ctx(band
);
465 band
->isolate_loop_type
= isl_calloc_array(ctx
,
466 enum isl_ast_loop_type
, band
->n
);
467 if (band
->n
&& !band
->isolate_loop_type
)
468 return isl_schedule_band_free(band
);
471 band
->isolate_loop_type
[pos
] = type
;
476 static const char *option_str
[] = {
477 [isl_ast_loop_atomic
] = "atomic",
478 [isl_ast_loop_unroll
] = "unroll",
479 [isl_ast_loop_separate
] = "separate"
482 /* Given a parameter space "space", extend it to a set space
488 * { [isolate[] -> type[x]] }
490 * depending on whether "isolate" is set.
491 * These can be used to encode loop AST generation options of the given type.
493 static __isl_give isl_space
*loop_type_space(__isl_take isl_space
*space
,
494 enum isl_ast_loop_type type
, int isolate
)
498 name
= option_str
[type
];
499 space
= isl_space_set_from_params(space
);
500 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
501 space
= isl_space_set_tuple_name(space
, isl_dim_set
, name
);
504 space
= isl_space_from_range(space
);
505 space
= isl_space_set_tuple_name(space
, isl_dim_in
, "isolate");
506 space
= isl_space_wrap(space
);
511 /* Add encodings of the "n" loop AST generation options "type" to "options".
512 * If "isolate" is set, then these options refer to the isolated part.
514 * In particular, for each sequence of consecutive identical types "t",
515 * different from the default, add an option
517 * { t[x] : first <= x <= last }
521 * { [isolate[] -> t[x]] : first <= x <= last }
523 static __isl_give isl_union_set
*add_loop_types(
524 __isl_take isl_union_set
*options
, int n
, enum isl_ast_loop_type
*type
,
534 for (i
= 0; i
< n
; ++i
) {
539 if (type
[i
] == isl_ast_loop_default
)
543 while (i
+ 1 < n
&& type
[i
+ 1] == type
[i
])
546 space
= isl_union_set_get_space(options
);
547 space
= loop_type_space(space
, type
[i
], isolate
);
548 option
= isl_set_universe(space
);
549 option
= isl_set_lower_bound_si(option
, isl_dim_set
, 0, first
);
550 option
= isl_set_upper_bound_si(option
, isl_dim_set
, 0, i
);
551 options
= isl_union_set_add_set(options
, option
);
557 /* Return the AST build options associated to "band".
559 __isl_give isl_union_set
*isl_schedule_band_get_ast_build_options(
560 __isl_keep isl_schedule_band
*band
)
562 isl_union_set
*options
;
567 options
= isl_union_set_copy(band
->ast_build_options
);
568 options
= add_loop_types(options
, band
->n
, band
->loop_type
, 0);
569 options
= add_loop_types(options
, band
->n
, band
->isolate_loop_type
, 1);
574 /* Does "uset" contain any set that satisfies "is"?
575 * "is" is assumed to set its integer argument to 1 if it is satisfied.
577 static int has_any(__isl_keep isl_union_set
*uset
,
578 isl_stat (*is
)(__isl_take isl_set
*set
, void *user
))
582 if (isl_union_set_foreach_set(uset
, is
, &found
) < 0 && !found
)
588 /* Does "set" live in a space of the form
590 * isolate[[...] -> [...]]
594 * If so, set *found and abort the search.
596 static isl_stat
is_isolate(__isl_take isl_set
*set
, void *user
)
600 if (isl_set_has_tuple_name(set
)) {
602 name
= isl_set_get_tuple_name(set
);
603 if (isl_set_is_wrapping(set
) && !strcmp(name
, "isolate"))
608 return *found
? isl_stat_error
: isl_stat_ok
;
611 /* Does "options" include an option of the ofrm
613 * isolate[[...] -> [...]]
617 static int has_isolate_option(__isl_keep isl_union_set
*options
)
619 return has_any(options
, &is_isolate
);
622 /* Does "set" encode a loop AST generation option?
624 static isl_stat
is_loop_type_option(__isl_take isl_set
*set
, void *user
)
628 if (isl_set_dim(set
, isl_dim_set
) == 1 &&
629 isl_set_has_tuple_name(set
)) {
631 enum isl_ast_loop_type type
;
632 name
= isl_set_get_tuple_name(set
);
633 for (type
= isl_ast_loop_atomic
;
634 type
<= isl_ast_loop_separate
; ++type
) {
635 if (strcmp(name
, option_str
[type
]))
643 return *found
? isl_stat_error
: isl_stat_ok
;
646 /* Does "set" encode a loop AST generation option for the isolated part?
647 * That is, is of the form
649 * { [isolate[] -> t[x]] }
651 * with t equal to "atomic", "unroll" or "separate"?
653 static isl_stat
is_isolate_loop_type_option(__isl_take isl_set
*set
, void *user
)
657 enum isl_ast_loop_type type
;
660 if (!isl_set_is_wrapping(set
)) {
664 map
= isl_set_unwrap(set
);
665 if (!isl_map_has_tuple_name(map
, isl_dim_in
) ||
666 !isl_map_has_tuple_name(map
, isl_dim_out
)) {
670 name
= isl_map_get_tuple_name(map
, isl_dim_in
);
671 if (!strcmp(name
, "isolate")) {
672 name
= isl_map_get_tuple_name(map
, isl_dim_out
);
673 for (type
= isl_ast_loop_atomic
;
674 type
<= isl_ast_loop_separate
; ++type
) {
675 if (strcmp(name
, option_str
[type
]))
683 return *found
? isl_stat_error
: isl_stat_ok
;
686 /* Does "options" encode any loop AST generation options
687 * for the isolated part?
689 static int has_isolate_loop_type_options(__isl_keep isl_union_set
*options
)
691 return has_any(options
, &is_isolate_loop_type_option
);
694 /* Does "options" encode any loop AST generation options?
696 static int has_loop_type_options(__isl_keep isl_union_set
*options
)
698 return has_any(options
, &is_loop_type_option
);
701 /* Extract the loop AST generation type for the band member
702 * at position "pos" from "options".
703 * If "isolate" is set, then extract the loop types for the isolated part.
705 static enum isl_ast_loop_type
extract_loop_type(
706 __isl_keep isl_union_set
*options
, int pos
, int isolate
)
709 enum isl_ast_loop_type type
, res
= isl_ast_loop_default
;
711 ctx
= isl_union_set_get_ctx(options
);
712 for (type
= isl_ast_loop_atomic
;
713 type
<= isl_ast_loop_separate
; ++type
) {
718 space
= isl_union_set_get_space(options
);
719 space
= loop_type_space(space
, type
, isolate
);
720 option
= isl_union_set_extract_set(options
, space
);
721 option
= isl_set_fix_si(option
, isl_dim_set
, 0, pos
);
722 empty
= isl_set_is_empty(option
);
723 isl_set_free(option
);
726 return isl_ast_loop_error
;
729 if (res
!= isl_ast_loop_default
)
730 isl_die(ctx
, isl_error_invalid
,
731 "conflicting loop type options",
732 return isl_ast_loop_error
);
739 /* Extract the loop AST generation types for the members of "band"
740 * from "options" and store them in band->loop_type.
741 * Return -1 on error.
743 static int extract_loop_types(__isl_keep isl_schedule_band
*band
,
744 __isl_keep isl_union_set
*options
)
748 if (!band
->loop_type
) {
749 isl_ctx
*ctx
= isl_schedule_band_get_ctx(band
);
750 band
->loop_type
= isl_alloc_array(ctx
,
751 enum isl_ast_loop_type
, band
->n
);
752 if (band
->n
&& !band
->loop_type
)
755 for (i
= 0; i
< band
->n
; ++i
) {
756 band
->loop_type
[i
] = extract_loop_type(options
, i
, 0);
757 if (band
->loop_type
[i
] == isl_ast_loop_error
)
764 /* Extract the loop AST generation types for the members of "band"
765 * from "options" for the isolated part and
766 * store them in band->isolate_loop_type.
767 * Return -1 on error.
769 static int extract_isolate_loop_types(__isl_keep isl_schedule_band
*band
,
770 __isl_keep isl_union_set
*options
)
774 if (!band
->isolate_loop_type
) {
775 isl_ctx
*ctx
= isl_schedule_band_get_ctx(band
);
776 band
->isolate_loop_type
= isl_alloc_array(ctx
,
777 enum isl_ast_loop_type
, band
->n
);
778 if (band
->n
&& !band
->isolate_loop_type
)
781 for (i
= 0; i
< band
->n
; ++i
) {
782 band
->isolate_loop_type
[i
] = extract_loop_type(options
, i
, 1);
783 if (band
->isolate_loop_type
[i
] == isl_ast_loop_error
)
790 /* Construct universe sets of the spaces that encode loop AST generation
791 * types (for the isolated part if "isolate" is set). That is, construct
793 * { atomic[x]; separate[x]; unroll[x] }
797 * { [isolate[] -> atomic[x]]; [isolate[] -> separate[x]];
798 * [isolate[] -> unroll[x]] }
800 static __isl_give isl_union_set
*loop_types(__isl_take isl_space
*space
,
803 enum isl_ast_loop_type type
;
804 isl_union_set
*types
;
806 types
= isl_union_set_empty(space
);
807 for (type
= isl_ast_loop_atomic
;
808 type
<= isl_ast_loop_separate
; ++type
) {
811 space
= isl_union_set_get_space(types
);
812 space
= loop_type_space(space
, type
, isolate
);
813 set
= isl_set_universe(space
);
814 types
= isl_union_set_add_set(types
, set
);
820 /* Remove all elements from spaces that encode loop AST generation types
823 static __isl_give isl_union_set
*clear_loop_types(
824 __isl_take isl_union_set
*options
)
826 isl_union_set
*types
;
828 types
= loop_types(isl_union_set_get_space(options
), 0);
829 options
= isl_union_set_subtract(options
, types
);
834 /* Remove all elements from spaces that encode loop AST generation types
835 * for the isolated part from "options".
837 static __isl_give isl_union_set
*clear_isolate_loop_types(
838 __isl_take isl_union_set
*options
)
840 isl_union_set
*types
;
842 types
= loop_types(isl_union_set_get_space(options
), 1);
843 options
= isl_union_set_subtract(options
, types
);
848 /* Replace the AST build options associated to "band" by "options".
849 * If there are any loop AST generation type options, then they
850 * are extracted and stored in band->loop_type. Otherwise,
851 * band->loop_type is removed to indicate that the default applies
852 * to all members. Similarly for the loop AST generation type options
853 * for the isolated part, which are stored in band->isolate_loop_type.
854 * The remaining options are stored in band->ast_build_options.
856 * Set anchored if the options include an isolate option since the
857 * domain of the wrapped map references the outer band node schedules.
859 __isl_give isl_schedule_band
*isl_schedule_band_set_ast_build_options(
860 __isl_take isl_schedule_band
*band
, __isl_take isl_union_set
*options
)
862 int has_isolate
, has_loop_type
, has_isolate_loop_type
;
864 band
= isl_schedule_band_cow(band
);
865 if (!band
|| !options
)
867 has_isolate
= has_isolate_option(options
);
870 has_loop_type
= has_loop_type_options(options
);
871 if (has_loop_type
< 0)
873 has_isolate_loop_type
= has_isolate_loop_type_options(options
);
874 if (has_isolate_loop_type
< 0)
877 if (!has_loop_type
) {
878 free(band
->loop_type
);
879 band
->loop_type
= NULL
;
881 if (extract_loop_types(band
, options
) < 0)
883 options
= clear_loop_types(options
);
888 if (!has_isolate_loop_type
) {
889 free(band
->isolate_loop_type
);
890 band
->isolate_loop_type
= NULL
;
892 if (extract_isolate_loop_types(band
, options
) < 0)
894 options
= clear_isolate_loop_types(options
);
899 isl_union_set_free(band
->ast_build_options
);
900 band
->ast_build_options
= options
;
901 band
->anchored
= has_isolate
;
905 isl_schedule_band_free(band
);
906 isl_union_set_free(options
);
910 /* Return the "isolate" option associated to "band", assuming
911 * it at appears at schedule depth "depth".
913 * The isolate option is of the form
915 * isolate[[flattened outer bands] -> band]
917 __isl_give isl_set
*isl_schedule_band_get_ast_isolate_option(
918 __isl_keep isl_schedule_band
*band
, int depth
)
926 space
= isl_schedule_band_get_space(band
);
927 space
= isl_space_from_range(space
);
928 space
= isl_space_add_dims(space
, isl_dim_in
, depth
);
929 space
= isl_space_wrap(space
);
930 space
= isl_space_set_tuple_name(space
, isl_dim_set
, "isolate");
932 isolate
= isl_union_set_extract_set(band
->ast_build_options
, space
);
937 /* Replace the option "drop" in the AST build options by "add".
938 * That is, remove "drop" and add "add".
940 __isl_give isl_schedule_band
*isl_schedule_band_replace_ast_build_option(
941 __isl_take isl_schedule_band
*band
, __isl_take isl_set
*drop
,
942 __isl_take isl_set
*add
)
944 isl_union_set
*options
;
946 band
= isl_schedule_band_cow(band
);
950 options
= band
->ast_build_options
;
951 options
= isl_union_set_subtract(options
, isl_union_set_from_set(drop
));
952 options
= isl_union_set_union(options
, isl_union_set_from_set(add
));
953 band
->ast_build_options
= options
;
955 if (!band
->ast_build_options
)
956 return isl_schedule_band_free(band
);
960 isl_schedule_band_free(band
);
966 /* Multiply the partial schedule of "band" with the factors in "mv".
967 * Replace the result by its greatest integer part to ensure
968 * that the schedule is always integral.
970 __isl_give isl_schedule_band
*isl_schedule_band_scale(
971 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
973 band
= isl_schedule_band_cow(band
);
976 band
->mupa
= isl_multi_union_pw_aff_scale_multi_val(band
->mupa
, mv
);
977 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
979 return isl_schedule_band_free(band
);
982 isl_schedule_band_free(band
);
983 isl_multi_val_free(mv
);
987 /* Divide the partial schedule of "band" by the factors in "mv".
988 * Replace the result by its greatest integer part to ensure
989 * that the schedule is always integral.
991 __isl_give isl_schedule_band
*isl_schedule_band_scale_down(
992 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
994 band
= isl_schedule_band_cow(band
);
997 band
->mupa
= isl_multi_union_pw_aff_scale_down_multi_val(band
->mupa
,
999 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
1001 return isl_schedule_band_free(band
);
1004 isl_schedule_band_free(band
);
1005 isl_multi_val_free(mv
);
1009 /* Reduce the partial schedule of "band" modulo the factors in "mv".
1011 __isl_give isl_schedule_band
*isl_schedule_band_mod(
1012 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
1014 band
= isl_schedule_band_cow(band
);
1017 band
->mupa
= isl_multi_union_pw_aff_mod_multi_val(band
->mupa
, mv
);
1019 return isl_schedule_band_free(band
);
1022 isl_schedule_band_free(band
);
1023 isl_multi_val_free(mv
);
1027 /* Shift the partial schedule of "band" by "shift" after checking
1028 * that the domain of the partial schedule would not be affected
1031 __isl_give isl_schedule_band
*isl_schedule_band_shift(
1032 __isl_take isl_schedule_band
*band
,
1033 __isl_take isl_multi_union_pw_aff
*shift
)
1035 isl_union_set
*dom1
, *dom2
;
1038 band
= isl_schedule_band_cow(band
);
1039 if (!band
|| !shift
)
1041 dom1
= isl_multi_union_pw_aff_domain(
1042 isl_multi_union_pw_aff_copy(band
->mupa
));
1043 dom2
= isl_multi_union_pw_aff_domain(
1044 isl_multi_union_pw_aff_copy(shift
));
1045 subset
= isl_union_set_is_subset(dom1
, dom2
);
1046 isl_union_set_free(dom1
);
1047 isl_union_set_free(dom2
);
1051 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
1052 "domain of shift needs to include domain of "
1053 "partial schedule", goto error
);
1054 band
->mupa
= isl_multi_union_pw_aff_add(band
->mupa
, shift
);
1056 return isl_schedule_band_free(band
);
1059 isl_schedule_band_free(band
);
1060 isl_multi_union_pw_aff_free(shift
);
1064 /* Given the schedule of a band, construct the corresponding
1065 * schedule for the tile loops based on the given tile sizes
1066 * and return the result.
1068 * If the scale tile loops options is set, then the tile loops
1069 * are scaled by the tile sizes.
1071 * That is replace each schedule dimension "i" by either
1072 * "floor(i/s)" or "s * floor(i/s)".
1074 static isl_multi_union_pw_aff
*isl_multi_union_pw_aff_tile(
1075 __isl_take isl_multi_union_pw_aff
*sched
,
1076 __isl_take isl_multi_val
*sizes
)
1083 ctx
= isl_multi_val_get_ctx(sizes
);
1084 scale
= isl_options_get_tile_scale_tile_loops(ctx
);
1086 n
= isl_multi_union_pw_aff_dim(sched
, isl_dim_set
);
1087 for (i
= 0; i
< n
; ++i
) {
1088 isl_union_pw_aff
*upa
;
1090 upa
= isl_multi_union_pw_aff_get_union_pw_aff(sched
, i
);
1091 v
= isl_multi_val_get_val(sizes
, i
);
1093 upa
= isl_union_pw_aff_scale_down_val(upa
, isl_val_copy(v
));
1094 upa
= isl_union_pw_aff_floor(upa
);
1096 upa
= isl_union_pw_aff_scale_val(upa
, isl_val_copy(v
));
1099 sched
= isl_multi_union_pw_aff_set_union_pw_aff(sched
, i
, upa
);
1102 isl_multi_val_free(sizes
);
1106 /* Replace "band" by a band corresponding to the tile loops of a tiling
1107 * with the given tile sizes.
1109 __isl_give isl_schedule_band
*isl_schedule_band_tile(
1110 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*sizes
)
1112 band
= isl_schedule_band_cow(band
);
1113 if (!band
|| !sizes
)
1115 band
->mupa
= isl_multi_union_pw_aff_tile(band
->mupa
, sizes
);
1117 return isl_schedule_band_free(band
);
1120 isl_schedule_band_free(band
);
1121 isl_multi_val_free(sizes
);
1125 /* Replace "band" by a band corresponding to the point loops of a tiling
1126 * with the given tile sizes.
1127 * "tile" is the corresponding tile loop band.
1129 * If the shift point loops option is set, then the point loops
1130 * are shifted to start at zero. That is, each schedule dimension "i"
1131 * is replaced by "i - s * floor(i/s)".
1132 * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
1135 * Otherwise, the band is left untouched.
1137 __isl_give isl_schedule_band
*isl_schedule_band_point(
1138 __isl_take isl_schedule_band
*band
, __isl_keep isl_schedule_band
*tile
,
1139 __isl_take isl_multi_val
*sizes
)
1142 isl_multi_union_pw_aff
*scaled
;
1144 if (!band
|| !sizes
)
1147 ctx
= isl_schedule_band_get_ctx(band
);
1148 if (!isl_options_get_tile_shift_point_loops(ctx
)) {
1149 isl_multi_val_free(sizes
);
1152 band
= isl_schedule_band_cow(band
);
1156 scaled
= isl_schedule_band_get_partial_schedule(tile
);
1157 if (!isl_options_get_tile_scale_tile_loops(ctx
))
1158 scaled
= isl_multi_union_pw_aff_scale_multi_val(scaled
, sizes
);
1160 isl_multi_val_free(sizes
);
1161 band
->mupa
= isl_multi_union_pw_aff_sub(band
->mupa
, scaled
);
1163 return isl_schedule_band_free(band
);
1166 isl_schedule_band_free(band
);
1167 isl_multi_val_free(sizes
);
1171 /* Drop the "n" dimensions starting at "pos" from "band".
1173 * We apply the transformation even if "n" is zero to ensure consistent
1174 * behavior with respect to changes in the schedule space.
1176 * The caller is responsible for updating the isolate option.
1178 __isl_give isl_schedule_band
*isl_schedule_band_drop(
1179 __isl_take isl_schedule_band
*band
, int pos
, int n
)
1183 if (pos
< 0 || n
< 0 || pos
+ n
> band
->n
)
1184 isl_die(isl_schedule_band_get_ctx(band
), isl_error_internal
,
1185 "range out of bounds",
1186 return isl_schedule_band_free(band
));
1188 band
= isl_schedule_band_cow(band
);
1192 band
->mupa
= isl_multi_union_pw_aff_drop_dims(band
->mupa
,
1193 isl_dim_set
, pos
, n
);
1195 return isl_schedule_band_free(band
);
1197 for (i
= pos
+ n
; i
< band
->n
; ++i
)
1198 band
->coincident
[i
- n
] = band
->coincident
[i
];
1199 if (band
->loop_type
)
1200 for (i
= pos
+ n
; i
< band
->n
; ++i
)
1201 band
->loop_type
[i
- n
] = band
->loop_type
[i
];
1202 if (band
->isolate_loop_type
)
1203 for (i
= pos
+ n
; i
< band
->n
; ++i
)
1204 band
->isolate_loop_type
[i
- n
] =
1205 band
->isolate_loop_type
[i
];
1212 /* Reset the user pointer on all identifiers of parameters and tuples
1215 __isl_give isl_schedule_band
*isl_schedule_band_reset_user(
1216 __isl_take isl_schedule_band
*band
)
1218 band
= isl_schedule_band_cow(band
);
1222 band
->mupa
= isl_multi_union_pw_aff_reset_user(band
->mupa
);
1223 band
->ast_build_options
=
1224 isl_union_set_reset_user(band
->ast_build_options
);
1225 if (!band
->mupa
|| !band
->ast_build_options
)
1226 return isl_schedule_band_free(band
);
1231 /* Align the parameters of "band" to those of "space".
1233 __isl_give isl_schedule_band
*isl_schedule_band_align_params(
1234 __isl_take isl_schedule_band
*band
, __isl_take isl_space
*space
)
1236 band
= isl_schedule_band_cow(band
);
1237 if (!band
|| !space
)
1240 band
->mupa
= isl_multi_union_pw_aff_align_params(band
->mupa
,
1241 isl_space_copy(space
));
1242 band
->ast_build_options
=
1243 isl_union_set_align_params(band
->ast_build_options
, space
);
1244 if (!band
->mupa
|| !band
->ast_build_options
)
1245 return isl_schedule_band_free(band
);
1249 isl_space_free(space
);
1250 isl_schedule_band_free(band
);
1254 /* Compute the pullback of "band" by the function represented by "upma".
1255 * In other words, plug in "upma" in the iteration domains of "band".
1257 __isl_give isl_schedule_band
*isl_schedule_band_pullback_union_pw_multi_aff(
1258 __isl_take isl_schedule_band
*band
,
1259 __isl_take isl_union_pw_multi_aff
*upma
)
1261 band
= isl_schedule_band_cow(band
);
1266 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(band
->mupa
,
1269 return isl_schedule_band_free(band
);
1273 isl_union_pw_multi_aff_free(upma
);
1274 isl_schedule_band_free(band
);
1278 /* Compute the gist of "band" with respect to "context".
1279 * In particular, compute the gist of the associated partial schedule.
1281 __isl_give isl_schedule_band
*isl_schedule_band_gist(
1282 __isl_take isl_schedule_band
*band
, __isl_take isl_union_set
*context
)
1284 if (!band
|| !context
)
1287 isl_union_set_free(context
);
1290 band
= isl_schedule_band_cow(band
);
1293 band
->mupa
= isl_multi_union_pw_aff_gist(band
->mupa
, context
);
1295 return isl_schedule_band_free(band
);
1298 isl_union_set_free(context
);
1299 isl_schedule_band_free(band
);