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
)
53 isl_schedule_band
*band
;
56 mupa
= isl_multi_union_pw_aff_floor(mupa
);
57 dim
= isl_multi_union_pw_aff_size(mupa
);
60 ctx
= isl_multi_union_pw_aff_get_ctx(mupa
);
61 band
= isl_schedule_band_alloc(ctx
);
66 band
->coincident
= isl_calloc_array(ctx
, int, band
->n
);
68 space
= isl_space_params_alloc(ctx
, 0);
69 band
->ast_build_options
= isl_union_set_empty(space
);
72 if ((band
->n
&& !band
->coincident
) || !band
->ast_build_options
)
73 return isl_schedule_band_free(band
);
77 isl_multi_union_pw_aff_free(mupa
);
81 /* Create a duplicate of the given isl_schedule_band.
83 __isl_give isl_schedule_band
*isl_schedule_band_dup(
84 __isl_keep isl_schedule_band
*band
)
88 isl_schedule_band
*dup
;
93 ctx
= isl_schedule_band_get_ctx(band
);
94 dup
= isl_schedule_band_alloc(ctx
);
99 dup
->coincident
= isl_alloc_array(ctx
, int, band
->n
);
100 if (band
->n
&& !dup
->coincident
)
101 return isl_schedule_band_free(dup
);
103 for (i
= 0; i
< band
->n
; ++i
)
104 dup
->coincident
[i
] = band
->coincident
[i
];
105 dup
->permutable
= band
->permutable
;
107 dup
->mupa
= isl_multi_union_pw_aff_copy(band
->mupa
);
108 dup
->ast_build_options
= isl_union_set_copy(band
->ast_build_options
);
109 if (!dup
->mupa
|| !dup
->ast_build_options
)
110 return isl_schedule_band_free(dup
);
112 if (band
->loop_type
) {
113 dup
->loop_type
= isl_alloc_array(ctx
,
114 enum isl_ast_loop_type
, band
->n
);
115 if (band
->n
&& !dup
->loop_type
)
116 return isl_schedule_band_free(dup
);
117 for (i
= 0; i
< band
->n
; ++i
)
118 dup
->loop_type
[i
] = band
->loop_type
[i
];
120 if (band
->isolate_loop_type
) {
121 dup
->isolate_loop_type
= isl_alloc_array(ctx
,
122 enum isl_ast_loop_type
, band
->n
);
123 if (band
->n
&& !dup
->isolate_loop_type
)
124 return isl_schedule_band_free(dup
);
125 for (i
= 0; i
< band
->n
; ++i
)
126 dup
->isolate_loop_type
[i
] = band
->isolate_loop_type
[i
];
132 /* Return an isl_schedule_band that is equal to "band" and that has only
133 * a single reference.
135 __isl_give isl_schedule_band
*isl_schedule_band_cow(
136 __isl_take isl_schedule_band
*band
)
144 return isl_schedule_band_dup(band
);
147 /* Return a new reference to "band".
149 __isl_give isl_schedule_band
*isl_schedule_band_copy(
150 __isl_keep isl_schedule_band
*band
)
159 /* Free a reference to "band" and return NULL.
161 __isl_null isl_schedule_band
*isl_schedule_band_free(
162 __isl_take isl_schedule_band
*band
)
170 isl_multi_union_pw_aff_free(band
->mupa
);
171 isl_union_set_free(band
->ast_build_options
);
172 free(band
->loop_type
);
173 free(band
->isolate_loop_type
);
174 free(band
->coincident
);
180 /* Are "band1" and "band2" obviously equal?
182 isl_bool
isl_schedule_band_plain_is_equal(__isl_keep isl_schedule_band
*band1
,
183 __isl_keep isl_schedule_band
*band2
)
188 if (!band1
|| !band2
)
189 return isl_bool_error
;
191 return isl_bool_true
;
193 if (band1
->n
!= band2
->n
)
194 return isl_bool_false
;
195 for (i
= 0; i
< band1
->n
; ++i
)
196 if (band1
->coincident
[i
] != band2
->coincident
[i
])
197 return isl_bool_false
;
198 if (band1
->permutable
!= band2
->permutable
)
199 return isl_bool_false
;
201 equal
= isl_multi_union_pw_aff_plain_is_equal(band1
->mupa
, band2
->mupa
);
202 if (equal
< 0 || !equal
)
205 if (!band1
->loop_type
!= !band2
->loop_type
)
206 return isl_bool_false
;
207 if (band1
->loop_type
)
208 for (i
= 0; i
< band1
->n
; ++i
)
209 if (band1
->loop_type
[i
] != band2
->loop_type
[i
])
210 return isl_bool_false
;
212 if (!band1
->isolate_loop_type
!= !band2
->isolate_loop_type
)
213 return isl_bool_false
;
214 if (band1
->isolate_loop_type
)
215 for (i
= 0; i
< band1
->n
; ++i
)
216 if (band1
->isolate_loop_type
[i
] !=
217 band2
->isolate_loop_type
[i
])
218 return isl_bool_false
;
220 return isl_union_set_is_equal(band1
->ast_build_options
,
221 band2
->ast_build_options
);
224 /* Return the number of scheduling dimensions in the band.
226 isl_size
isl_schedule_band_n_member(__isl_keep isl_schedule_band
*band
)
228 return band
? band
->n
: isl_size_error
;
231 /* Is the given scheduling dimension coincident within the band and
232 * with respect to the coincidence constraints?
234 isl_bool
isl_schedule_band_member_get_coincident(
235 __isl_keep isl_schedule_band
*band
, int pos
)
238 return isl_bool_error
;
240 if (pos
< 0 || pos
>= band
->n
)
241 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
242 "invalid member position", return isl_bool_error
);
244 return isl_bool_ok(band
->coincident
[pos
]);
247 /* Mark the given scheduling dimension as being coincident or not
248 * according to "coincident".
250 __isl_give isl_schedule_band
*isl_schedule_band_member_set_coincident(
251 __isl_take isl_schedule_band
*band
, int pos
, int coincident
)
255 if (isl_schedule_band_member_get_coincident(band
, pos
) == coincident
)
257 band
= isl_schedule_band_cow(band
);
261 if (pos
< 0 || pos
>= band
->n
)
262 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
263 "invalid member position",
264 return isl_schedule_band_free(band
));
266 band
->coincident
[pos
] = coincident
;
271 /* Is the schedule band mark permutable?
273 isl_bool
isl_schedule_band_get_permutable(__isl_keep isl_schedule_band
*band
)
276 return isl_bool_error
;
277 return isl_bool_ok(band
->permutable
);
280 /* Mark the schedule band permutable or not according to "permutable"?
282 __isl_give isl_schedule_band
*isl_schedule_band_set_permutable(
283 __isl_take isl_schedule_band
*band
, int permutable
)
287 if (band
->permutable
== permutable
)
289 band
= isl_schedule_band_cow(band
);
293 band
->permutable
= permutable
;
298 /* Is the band node "node" anchored? That is, does it reference
299 * the outer band nodes?
301 int isl_schedule_band_is_anchored(__isl_keep isl_schedule_band
*band
)
303 return band
? band
->anchored
: -1;
306 /* Return the schedule space of the band.
308 __isl_give isl_space
*isl_schedule_band_get_space(
309 __isl_keep isl_schedule_band
*band
)
313 return isl_multi_union_pw_aff_get_space(band
->mupa
);
316 /* Intersect the domain of the band schedule of "band" with "domain".
318 __isl_give isl_schedule_band
*isl_schedule_band_intersect_domain(
319 __isl_take isl_schedule_band
*band
, __isl_take isl_union_set
*domain
)
321 band
= isl_schedule_band_cow(band
);
322 if (!band
|| !domain
)
325 band
->mupa
= isl_multi_union_pw_aff_intersect_domain(band
->mupa
,
328 return isl_schedule_band_free(band
);
332 isl_schedule_band_free(band
);
333 isl_union_set_free(domain
);
337 /* Return the schedule of the band in isolation.
339 __isl_give isl_multi_union_pw_aff
*isl_schedule_band_get_partial_schedule(
340 __isl_keep isl_schedule_band
*band
)
342 return band
? isl_multi_union_pw_aff_copy(band
->mupa
) : NULL
;
345 /* Replace the schedule of "band" by "schedule".
347 __isl_give isl_schedule_band
*isl_schedule_band_set_partial_schedule(
348 __isl_take isl_schedule_band
*band
,
349 __isl_take isl_multi_union_pw_aff
*schedule
)
351 band
= isl_schedule_band_cow(band
);
352 if (!band
|| !schedule
)
355 isl_multi_union_pw_aff_free(band
->mupa
);
356 band
->mupa
= schedule
;
360 isl_schedule_band_free(band
);
361 isl_multi_union_pw_aff_free(schedule
);
365 /* Return the loop AST generation type for the band member of "band"
368 enum isl_ast_loop_type
isl_schedule_band_member_get_ast_loop_type(
369 __isl_keep isl_schedule_band
*band
, int pos
)
372 return isl_ast_loop_error
;
374 if (pos
< 0 || pos
>= band
->n
)
375 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
376 "invalid member position", return isl_ast_loop_error
);
378 if (!band
->loop_type
)
379 return isl_ast_loop_default
;
381 return band
->loop_type
[pos
];
384 /* Set the loop AST generation type for the band member of "band"
385 * at position "pos" to "type".
387 __isl_give isl_schedule_band
*isl_schedule_band_member_set_ast_loop_type(
388 __isl_take isl_schedule_band
*band
, int pos
,
389 enum isl_ast_loop_type type
)
393 if (isl_schedule_band_member_get_ast_loop_type(band
, pos
) == type
)
396 if (pos
< 0 || pos
>= band
->n
)
397 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
398 "invalid member position",
399 return isl_schedule_band_free(band
));
401 band
= isl_schedule_band_cow(band
);
403 return isl_schedule_band_free(band
);
405 if (!band
->loop_type
) {
408 ctx
= isl_schedule_band_get_ctx(band
);
409 band
->loop_type
= isl_calloc_array(ctx
,
410 enum isl_ast_loop_type
, band
->n
);
411 if (band
->n
&& !band
->loop_type
)
412 return isl_schedule_band_free(band
);
415 band
->loop_type
[pos
] = type
;
420 /* Return the loop AST generation type for the band member of "band"
421 * at position "pos" for the part that has been isolated by the isolate option.
423 enum isl_ast_loop_type
isl_schedule_band_member_get_isolate_ast_loop_type(
424 __isl_keep isl_schedule_band
*band
, int pos
)
427 return isl_ast_loop_error
;
429 if (pos
< 0 || pos
>= band
->n
)
430 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
431 "invalid member position", return isl_ast_loop_error
);
433 if (!band
->isolate_loop_type
)
434 return isl_ast_loop_default
;
436 return band
->isolate_loop_type
[pos
];
439 /* Set the loop AST generation type for the band member of "band"
440 * at position "pos" to "type" for the part that has been isolated
441 * by the isolate option.
443 __isl_give isl_schedule_band
*
444 isl_schedule_band_member_set_isolate_ast_loop_type(
445 __isl_take isl_schedule_band
*band
, int pos
,
446 enum isl_ast_loop_type type
)
450 if (isl_schedule_band_member_get_isolate_ast_loop_type(band
, pos
) ==
454 if (pos
< 0 || pos
>= band
->n
)
455 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
456 "invalid member position",
457 return isl_schedule_band_free(band
));
459 band
= isl_schedule_band_cow(band
);
461 return isl_schedule_band_free(band
);
463 if (!band
->isolate_loop_type
) {
466 ctx
= isl_schedule_band_get_ctx(band
);
467 band
->isolate_loop_type
= isl_calloc_array(ctx
,
468 enum isl_ast_loop_type
, band
->n
);
469 if (band
->n
&& !band
->isolate_loop_type
)
470 return isl_schedule_band_free(band
);
473 band
->isolate_loop_type
[pos
] = type
;
478 static const char *option_str
[] = {
479 [isl_ast_loop_atomic
] = "atomic",
480 [isl_ast_loop_unroll
] = "unroll",
481 [isl_ast_loop_separate
] = "separate"
484 /* Given a parameter space "space", extend it to a set space
490 * { [isolate[] -> type[x]] }
492 * depending on whether "isolate" is set.
493 * These can be used to encode loop AST generation options of the given type.
495 static __isl_give isl_space
*loop_type_space(__isl_take isl_space
*space
,
496 enum isl_ast_loop_type type
, int isolate
)
500 name
= option_str
[type
];
501 space
= isl_space_set_from_params(space
);
502 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
503 space
= isl_space_set_tuple_name(space
, isl_dim_set
, name
);
506 space
= isl_space_from_range(space
);
507 space
= isl_space_set_tuple_name(space
, isl_dim_in
, "isolate");
508 space
= isl_space_wrap(space
);
513 /* Add encodings of the "n" loop AST generation options "type" to "options".
514 * If "isolate" is set, then these options refer to the isolated part.
516 * In particular, for each sequence of consecutive identical types "t",
517 * different from the default, add an option
519 * { t[x] : first <= x <= last }
523 * { [isolate[] -> t[x]] : first <= x <= last }
525 static __isl_give isl_union_set
*add_loop_types(
526 __isl_take isl_union_set
*options
, int n
, enum isl_ast_loop_type
*type
,
536 for (i
= 0; i
< n
; ++i
) {
541 if (type
[i
] == isl_ast_loop_default
)
545 while (i
+ 1 < n
&& type
[i
+ 1] == type
[i
])
548 space
= isl_union_set_get_space(options
);
549 space
= loop_type_space(space
, type
[i
], isolate
);
550 option
= isl_set_universe(space
);
551 option
= isl_set_lower_bound_si(option
, isl_dim_set
, 0, first
);
552 option
= isl_set_upper_bound_si(option
, isl_dim_set
, 0, i
);
553 options
= isl_union_set_add_set(options
, option
);
559 /* Return the AST build options associated to "band".
561 __isl_give isl_union_set
*isl_schedule_band_get_ast_build_options(
562 __isl_keep isl_schedule_band
*band
)
564 isl_union_set
*options
;
569 options
= isl_union_set_copy(band
->ast_build_options
);
570 options
= add_loop_types(options
, band
->n
, band
->loop_type
, 0);
571 options
= add_loop_types(options
, band
->n
, band
->isolate_loop_type
, 1);
576 /* Internal data structure for not().
578 struct isl_not_data
{
579 isl_bool (*is
)(__isl_keep isl_set
*set
);
582 /* Does "set" not satisfy data->is()?
584 static isl_bool
not(__isl_keep isl_set
*set
, void *user
)
586 struct isl_not_data
*data
= user
;
588 return isl_bool_not(data
->is(set
));
591 /* Does "uset" contain any set that satisfies "is"?
592 * In other words, is it not the case that all of them do not satisfy "is"?
594 static isl_bool
has_any(__isl_keep isl_union_set
*uset
,
595 isl_bool (*is
)(__isl_keep isl_set
*set
))
597 struct isl_not_data data
= { is
};
599 return isl_bool_not(isl_union_set_every_set(uset
, ¬, &data
));
602 /* Does "set" live in a space of the form
604 * isolate[[...] -> [...]]
608 static isl_bool
is_isolate(__isl_keep isl_set
*set
)
610 if (isl_set_has_tuple_name(set
)) {
612 name
= isl_set_get_tuple_name(set
);
613 if (isl_set_is_wrapping(set
) && !strcmp(name
, "isolate"))
614 return isl_bool_true
;
617 return isl_bool_false
;
620 /* Does "options" include an option of the ofrm
622 * isolate[[...] -> [...]]
626 static isl_bool
has_isolate_option(__isl_keep isl_union_set
*options
)
628 return has_any(options
, &is_isolate
);
631 /* Does "set" encode a loop AST generation option?
633 static isl_bool
is_loop_type_option(__isl_keep isl_set
*set
)
637 dim
= isl_set_dim(set
, isl_dim_set
);
639 return isl_bool_error
;
640 if (dim
== 1 && isl_set_has_tuple_name(set
)) {
642 enum isl_ast_loop_type type
;
643 name
= isl_set_get_tuple_name(set
);
644 for (type
= isl_ast_loop_atomic
;
645 type
<= isl_ast_loop_separate
; ++type
) {
646 if (strcmp(name
, option_str
[type
]))
648 return isl_bool_true
;
652 return isl_bool_false
;
655 /* Does "set" encode a loop AST generation option for the isolated part?
656 * That is, is of the form
658 * { [isolate[] -> t[x]] }
660 * with t equal to "atomic", "unroll" or "separate"?
662 static isl_bool
is_isolate_loop_type_option(__isl_keep isl_set
*set
)
665 enum isl_ast_loop_type type
;
668 if (!isl_set_is_wrapping(set
))
669 return isl_bool_false
;
670 map
= isl_set_unwrap(isl_set_copy(set
));
671 if (!isl_map_has_tuple_name(map
, isl_dim_in
) ||
672 !isl_map_has_tuple_name(map
, isl_dim_out
)) {
674 return isl_bool_false
;
676 name
= isl_map_get_tuple_name(map
, isl_dim_in
);
677 if (!strcmp(name
, "isolate")) {
678 name
= isl_map_get_tuple_name(map
, isl_dim_out
);
679 for (type
= isl_ast_loop_atomic
;
680 type
<= isl_ast_loop_separate
; ++type
) {
681 if (strcmp(name
, option_str
[type
]))
684 return isl_bool_true
;
689 return isl_bool_false
;
692 /* Does "options" encode any loop AST generation options
693 * for the isolated part?
695 static isl_bool
has_isolate_loop_type_options(__isl_keep isl_union_set
*options
)
697 return has_any(options
, &is_isolate_loop_type_option
);
700 /* Does "options" encode any loop AST generation options?
702 static isl_bool
has_loop_type_options(__isl_keep isl_union_set
*options
)
704 return has_any(options
, &is_loop_type_option
);
707 /* Extract the loop AST generation type for the band member
708 * at position "pos" from "options".
709 * If "isolate" is set, then extract the loop types for the isolated part.
711 static enum isl_ast_loop_type
extract_loop_type(
712 __isl_keep isl_union_set
*options
, int pos
, int isolate
)
715 enum isl_ast_loop_type type
, res
= isl_ast_loop_default
;
717 ctx
= isl_union_set_get_ctx(options
);
718 for (type
= isl_ast_loop_atomic
;
719 type
<= isl_ast_loop_separate
; ++type
) {
724 space
= isl_union_set_get_space(options
);
725 space
= loop_type_space(space
, type
, isolate
);
726 option
= isl_union_set_extract_set(options
, space
);
727 option
= isl_set_fix_si(option
, isl_dim_set
, 0, pos
);
728 empty
= isl_set_is_empty(option
);
729 isl_set_free(option
);
732 return isl_ast_loop_error
;
735 if (res
!= isl_ast_loop_default
)
736 isl_die(ctx
, isl_error_invalid
,
737 "conflicting loop type options",
738 return isl_ast_loop_error
);
745 /* Extract the loop AST generation types for the members of "band"
746 * from "options" and store them in band->loop_type.
747 * Return -1 on error.
749 static int extract_loop_types(__isl_keep isl_schedule_band
*band
,
750 __isl_keep isl_union_set
*options
)
754 if (!band
->loop_type
) {
755 isl_ctx
*ctx
= isl_schedule_band_get_ctx(band
);
756 band
->loop_type
= isl_alloc_array(ctx
,
757 enum isl_ast_loop_type
, band
->n
);
758 if (band
->n
&& !band
->loop_type
)
761 for (i
= 0; i
< band
->n
; ++i
) {
762 band
->loop_type
[i
] = extract_loop_type(options
, i
, 0);
763 if (band
->loop_type
[i
] == isl_ast_loop_error
)
770 /* Extract the loop AST generation types for the members of "band"
771 * from "options" for the isolated part and
772 * store them in band->isolate_loop_type.
773 * Return -1 on error.
775 static int extract_isolate_loop_types(__isl_keep isl_schedule_band
*band
,
776 __isl_keep isl_union_set
*options
)
780 if (!band
->isolate_loop_type
) {
781 isl_ctx
*ctx
= isl_schedule_band_get_ctx(band
);
782 band
->isolate_loop_type
= isl_alloc_array(ctx
,
783 enum isl_ast_loop_type
, band
->n
);
784 if (band
->n
&& !band
->isolate_loop_type
)
787 for (i
= 0; i
< band
->n
; ++i
) {
788 band
->isolate_loop_type
[i
] = extract_loop_type(options
, i
, 1);
789 if (band
->isolate_loop_type
[i
] == isl_ast_loop_error
)
796 /* Construct universe sets of the spaces that encode loop AST generation
797 * types (for the isolated part if "isolate" is set). That is, construct
799 * { atomic[x]; separate[x]; unroll[x] }
803 * { [isolate[] -> atomic[x]]; [isolate[] -> separate[x]];
804 * [isolate[] -> unroll[x]] }
806 static __isl_give isl_union_set
*loop_types(__isl_take isl_space
*space
,
809 enum isl_ast_loop_type type
;
810 isl_union_set
*types
;
812 types
= isl_union_set_empty(space
);
813 for (type
= isl_ast_loop_atomic
;
814 type
<= isl_ast_loop_separate
; ++type
) {
817 space
= isl_union_set_get_space(types
);
818 space
= loop_type_space(space
, type
, isolate
);
819 set
= isl_set_universe(space
);
820 types
= isl_union_set_add_set(types
, set
);
826 /* Remove all elements from spaces that encode loop AST generation types
829 static __isl_give isl_union_set
*clear_loop_types(
830 __isl_take isl_union_set
*options
)
832 isl_union_set
*types
;
834 types
= loop_types(isl_union_set_get_space(options
), 0);
835 options
= isl_union_set_subtract(options
, types
);
840 /* Remove all elements from spaces that encode loop AST generation types
841 * for the isolated part from "options".
843 static __isl_give isl_union_set
*clear_isolate_loop_types(
844 __isl_take isl_union_set
*options
)
846 isl_union_set
*types
;
848 types
= loop_types(isl_union_set_get_space(options
), 1);
849 options
= isl_union_set_subtract(options
, types
);
854 /* Replace the AST build options associated to "band" by "options".
855 * If there are any loop AST generation type options, then they
856 * are extracted and stored in band->loop_type. Otherwise,
857 * band->loop_type is removed to indicate that the default applies
858 * to all members. Similarly for the loop AST generation type options
859 * for the isolated part, which are stored in band->isolate_loop_type.
860 * The remaining options are stored in band->ast_build_options.
862 * Set anchored if the options include an isolate option since the
863 * domain of the wrapped map references the outer band node schedules.
865 __isl_give isl_schedule_band
*isl_schedule_band_set_ast_build_options(
866 __isl_take isl_schedule_band
*band
, __isl_take isl_union_set
*options
)
868 isl_bool has_isolate
, has_loop_type
, has_isolate_loop_type
;
870 band
= isl_schedule_band_cow(band
);
871 if (!band
|| !options
)
873 has_isolate
= has_isolate_option(options
);
876 has_loop_type
= has_loop_type_options(options
);
877 if (has_loop_type
< 0)
879 has_isolate_loop_type
= has_isolate_loop_type_options(options
);
880 if (has_isolate_loop_type
< 0)
883 if (!has_loop_type
) {
884 free(band
->loop_type
);
885 band
->loop_type
= NULL
;
887 if (extract_loop_types(band
, options
) < 0)
889 options
= clear_loop_types(options
);
894 if (!has_isolate_loop_type
) {
895 free(band
->isolate_loop_type
);
896 band
->isolate_loop_type
= NULL
;
898 if (extract_isolate_loop_types(band
, options
) < 0)
900 options
= clear_isolate_loop_types(options
);
905 isl_union_set_free(band
->ast_build_options
);
906 band
->ast_build_options
= options
;
907 band
->anchored
= has_isolate
;
911 isl_schedule_band_free(band
);
912 isl_union_set_free(options
);
916 /* Return the "isolate" option associated to "band", assuming
917 * it at appears at schedule depth "depth".
919 * The isolate option is of the form
921 * isolate[[flattened outer bands] -> band]
923 __isl_give isl_set
*isl_schedule_band_get_ast_isolate_option(
924 __isl_keep isl_schedule_band
*band
, int depth
)
932 space
= isl_schedule_band_get_space(band
);
933 space
= isl_space_from_range(space
);
934 space
= isl_space_add_dims(space
, isl_dim_in
, depth
);
935 space
= isl_space_wrap(space
);
936 space
= isl_space_set_tuple_name(space
, isl_dim_set
, "isolate");
938 isolate
= isl_union_set_extract_set(band
->ast_build_options
, space
);
943 /* Replace the option "drop" in the AST build options by "add".
944 * That is, remove "drop" and add "add".
946 __isl_give isl_schedule_band
*isl_schedule_band_replace_ast_build_option(
947 __isl_take isl_schedule_band
*band
, __isl_take isl_set
*drop
,
948 __isl_take isl_set
*add
)
950 isl_union_set
*options
;
952 band
= isl_schedule_band_cow(band
);
956 options
= band
->ast_build_options
;
957 options
= isl_union_set_subtract(options
, isl_union_set_from_set(drop
));
958 options
= isl_union_set_union(options
, isl_union_set_from_set(add
));
959 band
->ast_build_options
= options
;
961 if (!band
->ast_build_options
)
962 return isl_schedule_band_free(band
);
966 isl_schedule_band_free(band
);
972 /* Multiply the partial schedule of "band" with the factors in "mv".
973 * Replace the result by its greatest integer part to ensure
974 * that the schedule is always integral.
976 __isl_give isl_schedule_band
*isl_schedule_band_scale(
977 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
979 band
= isl_schedule_band_cow(band
);
982 band
->mupa
= isl_multi_union_pw_aff_scale_multi_val(band
->mupa
, mv
);
983 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
985 return isl_schedule_band_free(band
);
988 isl_schedule_band_free(band
);
989 isl_multi_val_free(mv
);
993 /* Divide the partial schedule of "band" by the factors in "mv".
994 * Replace the result by its greatest integer part to ensure
995 * that the schedule is always integral.
997 __isl_give isl_schedule_band
*isl_schedule_band_scale_down(
998 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
1000 band
= isl_schedule_band_cow(band
);
1003 band
->mupa
= isl_multi_union_pw_aff_scale_down_multi_val(band
->mupa
,
1005 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
1007 return isl_schedule_band_free(band
);
1010 isl_schedule_band_free(band
);
1011 isl_multi_val_free(mv
);
1015 /* Reduce the partial schedule of "band" modulo the factors in "mv".
1017 __isl_give isl_schedule_band
*isl_schedule_band_mod(
1018 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
1020 band
= isl_schedule_band_cow(band
);
1023 band
->mupa
= isl_multi_union_pw_aff_mod_multi_val(band
->mupa
, mv
);
1025 return isl_schedule_band_free(band
);
1028 isl_schedule_band_free(band
);
1029 isl_multi_val_free(mv
);
1033 /* Shift the partial schedule of "band" by "shift" after checking
1034 * that the domain of the partial schedule would not be affected
1037 __isl_give isl_schedule_band
*isl_schedule_band_shift(
1038 __isl_take isl_schedule_band
*band
,
1039 __isl_take isl_multi_union_pw_aff
*shift
)
1041 isl_union_set
*dom1
, *dom2
;
1044 band
= isl_schedule_band_cow(band
);
1045 if (!band
|| !shift
)
1047 dom1
= isl_multi_union_pw_aff_domain(
1048 isl_multi_union_pw_aff_copy(band
->mupa
));
1049 dom2
= isl_multi_union_pw_aff_domain(
1050 isl_multi_union_pw_aff_copy(shift
));
1051 subset
= isl_union_set_is_subset(dom1
, dom2
);
1052 isl_union_set_free(dom1
);
1053 isl_union_set_free(dom2
);
1057 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
1058 "domain of shift needs to include domain of "
1059 "partial schedule", goto error
);
1060 band
->mupa
= isl_multi_union_pw_aff_add(band
->mupa
, shift
);
1062 return isl_schedule_band_free(band
);
1065 isl_schedule_band_free(band
);
1066 isl_multi_union_pw_aff_free(shift
);
1070 /* Given the schedule of a band, construct the corresponding
1071 * schedule for the tile loops based on the given tile sizes
1072 * and return the result.
1074 * If the scale tile loops options is set, then the tile loops
1075 * are scaled by the tile sizes.
1077 * That is replace each schedule dimension "i" by either
1078 * "floor(i/s)" or "s * floor(i/s)".
1080 static isl_multi_union_pw_aff
*isl_multi_union_pw_aff_tile(
1081 __isl_take isl_multi_union_pw_aff
*sched
,
1082 __isl_take isl_multi_val
*sizes
)
1090 ctx
= isl_multi_val_get_ctx(sizes
);
1091 scale
= isl_options_get_tile_scale_tile_loops(ctx
);
1093 n
= isl_multi_union_pw_aff_size(sched
);
1095 sched
= isl_multi_union_pw_aff_free(sched
);
1096 for (i
= 0; i
< n
; ++i
) {
1097 isl_union_pw_aff
*upa
;
1099 upa
= isl_multi_union_pw_aff_get_union_pw_aff(sched
, i
);
1100 v
= isl_multi_val_get_val(sizes
, i
);
1102 upa
= isl_union_pw_aff_scale_down_val(upa
, isl_val_copy(v
));
1103 upa
= isl_union_pw_aff_floor(upa
);
1105 upa
= isl_union_pw_aff_scale_val(upa
, isl_val_copy(v
));
1108 sched
= isl_multi_union_pw_aff_set_union_pw_aff(sched
, i
, upa
);
1111 isl_multi_val_free(sizes
);
1115 /* Replace "band" by a band corresponding to the tile loops of a tiling
1116 * with the given tile sizes.
1118 __isl_give isl_schedule_band
*isl_schedule_band_tile(
1119 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*sizes
)
1121 band
= isl_schedule_band_cow(band
);
1122 if (!band
|| !sizes
)
1124 band
->mupa
= isl_multi_union_pw_aff_tile(band
->mupa
, sizes
);
1126 return isl_schedule_band_free(band
);
1129 isl_schedule_band_free(band
);
1130 isl_multi_val_free(sizes
);
1134 /* Replace "band" by a band corresponding to the point loops of a tiling
1135 * with the given tile sizes.
1136 * "tile" is the corresponding tile loop band.
1138 * If the shift point loops option is set, then the point loops
1139 * are shifted to start at zero. That is, each schedule dimension "i"
1140 * is replaced by "i - s * floor(i/s)".
1141 * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
1144 * Otherwise, the band is left untouched.
1146 __isl_give isl_schedule_band
*isl_schedule_band_point(
1147 __isl_take isl_schedule_band
*band
, __isl_keep isl_schedule_band
*tile
,
1148 __isl_take isl_multi_val
*sizes
)
1151 isl_multi_union_pw_aff
*scaled
;
1153 if (!band
|| !sizes
)
1156 ctx
= isl_schedule_band_get_ctx(band
);
1157 if (!isl_options_get_tile_shift_point_loops(ctx
)) {
1158 isl_multi_val_free(sizes
);
1161 band
= isl_schedule_band_cow(band
);
1165 scaled
= isl_schedule_band_get_partial_schedule(tile
);
1166 if (!isl_options_get_tile_scale_tile_loops(ctx
))
1167 scaled
= isl_multi_union_pw_aff_scale_multi_val(scaled
, sizes
);
1169 isl_multi_val_free(sizes
);
1170 band
->mupa
= isl_multi_union_pw_aff_sub(band
->mupa
, scaled
);
1172 return isl_schedule_band_free(band
);
1175 isl_schedule_band_free(band
);
1176 isl_multi_val_free(sizes
);
1180 /* Drop the "n" dimensions starting at "pos" from "band".
1182 * We apply the transformation even if "n" is zero to ensure consistent
1183 * behavior with respect to changes in the schedule space.
1185 * The caller is responsible for updating the isolate option.
1187 __isl_give isl_schedule_band
*isl_schedule_band_drop(
1188 __isl_take isl_schedule_band
*band
, int pos
, int n
)
1192 if (pos
< 0 || n
< 0 || pos
+ n
> band
->n
)
1193 isl_die(isl_schedule_band_get_ctx(band
), isl_error_internal
,
1194 "range out of bounds",
1195 return isl_schedule_band_free(band
));
1197 band
= isl_schedule_band_cow(band
);
1201 band
->mupa
= isl_multi_union_pw_aff_drop_dims(band
->mupa
,
1202 isl_dim_set
, pos
, n
);
1204 return isl_schedule_band_free(band
);
1206 for (i
= pos
+ n
; i
< band
->n
; ++i
)
1207 band
->coincident
[i
- n
] = band
->coincident
[i
];
1208 if (band
->loop_type
)
1209 for (i
= pos
+ n
; i
< band
->n
; ++i
)
1210 band
->loop_type
[i
- n
] = band
->loop_type
[i
];
1211 if (band
->isolate_loop_type
)
1212 for (i
= pos
+ n
; i
< band
->n
; ++i
)
1213 band
->isolate_loop_type
[i
- n
] =
1214 band
->isolate_loop_type
[i
];
1221 /* Reset the user pointer on all identifiers of parameters and tuples
1224 __isl_give isl_schedule_band
*isl_schedule_band_reset_user(
1225 __isl_take isl_schedule_band
*band
)
1227 band
= isl_schedule_band_cow(band
);
1231 band
->mupa
= isl_multi_union_pw_aff_reset_user(band
->mupa
);
1232 band
->ast_build_options
=
1233 isl_union_set_reset_user(band
->ast_build_options
);
1234 if (!band
->mupa
|| !band
->ast_build_options
)
1235 return isl_schedule_band_free(band
);
1240 /* Align the parameters of "band" to those of "space".
1242 __isl_give isl_schedule_band
*isl_schedule_band_align_params(
1243 __isl_take isl_schedule_band
*band
, __isl_take isl_space
*space
)
1245 band
= isl_schedule_band_cow(band
);
1246 if (!band
|| !space
)
1249 band
->mupa
= isl_multi_union_pw_aff_align_params(band
->mupa
,
1250 isl_space_copy(space
));
1251 band
->ast_build_options
=
1252 isl_union_set_align_params(band
->ast_build_options
, space
);
1253 if (!band
->mupa
|| !band
->ast_build_options
)
1254 return isl_schedule_band_free(band
);
1258 isl_space_free(space
);
1259 isl_schedule_band_free(band
);
1263 /* Compute the pullback of "band" by the function represented by "upma".
1264 * In other words, plug in "upma" in the iteration domains of "band".
1266 __isl_give isl_schedule_band
*isl_schedule_band_pullback_union_pw_multi_aff(
1267 __isl_take isl_schedule_band
*band
,
1268 __isl_take isl_union_pw_multi_aff
*upma
)
1270 band
= isl_schedule_band_cow(band
);
1275 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(band
->mupa
,
1278 return isl_schedule_band_free(band
);
1282 isl_union_pw_multi_aff_free(upma
);
1283 isl_schedule_band_free(band
);
1287 /* Compute the gist of "band" with respect to "context".
1288 * In particular, compute the gist of the associated partial schedule.
1290 __isl_give isl_schedule_band
*isl_schedule_band_gist(
1291 __isl_take isl_schedule_band
*band
, __isl_take isl_union_set
*context
)
1293 if (!band
|| !context
)
1296 isl_union_set_free(context
);
1299 band
= isl_schedule_band_cow(band
);
1302 band
->mupa
= isl_multi_union_pw_aff_gist(band
->mupa
, context
);
1304 return isl_schedule_band_free(band
);
1307 isl_union_set_free(context
);
1308 isl_schedule_band_free(band
);