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
14 #include <isl_schedule_band.h>
15 #include <isl_schedule_private.h>
18 #define EL isl_schedule_tree
20 #include <isl_list_templ.h>
23 #define BASE schedule_tree
25 #include <isl_list_templ.c>
27 /* Is "tree" the leaf of a schedule tree?
29 int isl_schedule_tree_is_leaf(__isl_keep isl_schedule_tree
*tree
)
31 return isl_schedule_tree_get_type(tree
) == isl_schedule_node_leaf
;
34 /* Create a new schedule tree of type "type".
35 * The caller is responsible for filling in the type specific fields and
38 * By default, the single node tree does not have any anchored nodes.
39 * The caller is responsible for updating the anchored field if needed.
41 static __isl_give isl_schedule_tree
*isl_schedule_tree_alloc(isl_ctx
*ctx
,
42 enum isl_schedule_node_type type
)
44 isl_schedule_tree
*tree
;
46 if (type
== isl_schedule_node_error
)
49 tree
= isl_calloc_type(ctx
, isl_schedule_tree
);
62 /* Return a fresh copy of "tree".
64 __isl_take isl_schedule_tree
*isl_schedule_tree_dup(
65 __isl_keep isl_schedule_tree
*tree
)
68 isl_schedule_tree
*dup
;
73 ctx
= isl_schedule_tree_get_ctx(tree
);
74 dup
= isl_schedule_tree_alloc(ctx
, tree
->type
);
79 case isl_schedule_node_error
:
80 isl_die(ctx
, isl_error_internal
,
81 "allocation should have failed",
82 isl_schedule_tree_free(dup
));
83 case isl_schedule_node_band
:
84 dup
->band
= isl_schedule_band_copy(tree
->band
);
86 return isl_schedule_tree_free(dup
);
88 case isl_schedule_node_context
:
89 dup
->context
= isl_set_copy(tree
->context
);
91 return isl_schedule_tree_free(dup
);
93 case isl_schedule_node_domain
:
94 dup
->domain
= isl_union_set_copy(tree
->domain
);
96 return isl_schedule_tree_free(dup
);
98 case isl_schedule_node_expansion
:
100 isl_union_pw_multi_aff_copy(tree
->contraction
);
101 dup
->expansion
= isl_union_map_copy(tree
->expansion
);
102 if (!dup
->contraction
|| !dup
->expansion
)
103 return isl_schedule_tree_free(dup
);
105 case isl_schedule_node_extension
:
106 dup
->extension
= isl_union_map_copy(tree
->extension
);
108 return isl_schedule_tree_free(dup
);
110 case isl_schedule_node_filter
:
111 dup
->filter
= isl_union_set_copy(tree
->filter
);
113 return isl_schedule_tree_free(dup
);
115 case isl_schedule_node_guard
:
116 dup
->guard
= isl_set_copy(tree
->guard
);
118 return isl_schedule_tree_free(dup
);
120 case isl_schedule_node_mark
:
121 dup
->mark
= isl_id_copy(tree
->mark
);
123 return isl_schedule_tree_free(dup
);
125 case isl_schedule_node_leaf
:
126 case isl_schedule_node_sequence
:
127 case isl_schedule_node_set
:
131 if (tree
->children
) {
132 dup
->children
= isl_schedule_tree_list_copy(tree
->children
);
134 return isl_schedule_tree_free(dup
);
136 dup
->anchored
= tree
->anchored
;
141 /* Return an isl_schedule_tree that is equal to "tree" and that has only
142 * a single reference.
144 * This function is called before a tree is modified.
145 * A static tree (with negative reference count) should never be modified,
146 * so it is not allowed to call this function on a static tree.
148 __isl_give isl_schedule_tree
*isl_schedule_tree_cow(
149 __isl_take isl_schedule_tree
*tree
)
155 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
156 "static trees cannot be modified",
157 return isl_schedule_tree_free(tree
));
162 return isl_schedule_tree_dup(tree
);
165 /* Return a new reference to "tree".
167 * A static tree (with negative reference count) does not keep track
168 * of the number of references and should not be modified.
170 __isl_give isl_schedule_tree
*isl_schedule_tree_copy(
171 __isl_keep isl_schedule_tree
*tree
)
183 /* Free "tree" and return NULL.
185 __isl_null isl_schedule_tree
*isl_schedule_tree_free(
186 __isl_take isl_schedule_tree
*tree
)
195 switch (tree
->type
) {
196 case isl_schedule_node_band
:
197 isl_schedule_band_free(tree
->band
);
199 case isl_schedule_node_context
:
200 isl_set_free(tree
->context
);
202 case isl_schedule_node_domain
:
203 isl_union_set_free(tree
->domain
);
205 case isl_schedule_node_expansion
:
206 isl_union_pw_multi_aff_free(tree
->contraction
);
207 isl_union_map_free(tree
->expansion
);
209 case isl_schedule_node_extension
:
210 isl_union_map_free(tree
->extension
);
212 case isl_schedule_node_filter
:
213 isl_union_set_free(tree
->filter
);
215 case isl_schedule_node_guard
:
216 isl_set_free(tree
->guard
);
218 case isl_schedule_node_mark
:
219 isl_id_free(tree
->mark
);
221 case isl_schedule_node_sequence
:
222 case isl_schedule_node_set
:
223 case isl_schedule_node_error
:
224 case isl_schedule_node_leaf
:
227 isl_schedule_tree_list_free(tree
->children
);
228 isl_ctx_deref(tree
->ctx
);
234 /* Create and return a new leaf schedule tree.
236 __isl_give isl_schedule_tree
*isl_schedule_tree_leaf(isl_ctx
*ctx
)
238 return isl_schedule_tree_alloc(ctx
, isl_schedule_node_leaf
);
241 /* Create a new band schedule tree referring to "band"
244 __isl_give isl_schedule_tree
*isl_schedule_tree_from_band(
245 __isl_take isl_schedule_band
*band
)
248 isl_schedule_tree
*tree
;
253 ctx
= isl_schedule_band_get_ctx(band
);
254 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_band
);
259 tree
->anchored
= isl_schedule_band_is_anchored(band
);
263 isl_schedule_band_free(band
);
267 /* Create a new context schedule tree with the given context and no children.
268 * Since the context references the outer schedule dimension,
269 * the tree is anchored.
271 __isl_give isl_schedule_tree
*isl_schedule_tree_from_context(
272 __isl_take isl_set
*context
)
275 isl_schedule_tree
*tree
;
280 ctx
= isl_set_get_ctx(context
);
281 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_context
);
285 tree
->context
= context
;
290 isl_set_free(context
);
294 /* Create a new domain schedule tree with the given domain and no children.
296 __isl_give isl_schedule_tree
*isl_schedule_tree_from_domain(
297 __isl_take isl_union_set
*domain
)
300 isl_schedule_tree
*tree
;
305 ctx
= isl_union_set_get_ctx(domain
);
306 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_domain
);
310 tree
->domain
= domain
;
314 isl_union_set_free(domain
);
318 /* Create a new expansion schedule tree with the given contraction and
319 * expansion and no children.
321 __isl_give isl_schedule_tree
*isl_schedule_tree_from_expansion(
322 __isl_take isl_union_pw_multi_aff
*contraction
,
323 __isl_take isl_union_map
*expansion
)
326 isl_schedule_tree
*tree
;
328 if (!contraction
|| !expansion
)
331 ctx
= isl_union_map_get_ctx(expansion
);
332 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_expansion
);
336 tree
->contraction
= contraction
;
337 tree
->expansion
= expansion
;
341 isl_union_pw_multi_aff_free(contraction
);
342 isl_union_map_free(expansion
);
346 /* Create a new extension schedule tree with the given extension and
348 * Since the domain of the extension refers to the outer schedule dimension,
349 * the tree is anchored.
351 __isl_give isl_schedule_tree
*isl_schedule_tree_from_extension(
352 __isl_take isl_union_map
*extension
)
355 isl_schedule_tree
*tree
;
360 ctx
= isl_union_map_get_ctx(extension
);
361 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_extension
);
365 tree
->extension
= extension
;
370 isl_union_map_free(extension
);
374 /* Create a new filter schedule tree with the given filter and no children.
376 __isl_give isl_schedule_tree
*isl_schedule_tree_from_filter(
377 __isl_take isl_union_set
*filter
)
380 isl_schedule_tree
*tree
;
385 ctx
= isl_union_set_get_ctx(filter
);
386 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_filter
);
390 tree
->filter
= filter
;
394 isl_union_set_free(filter
);
398 /* Create a new guard schedule tree with the given guard and no children.
399 * Since the guard references the outer schedule dimension,
400 * the tree is anchored.
402 __isl_give isl_schedule_tree
*isl_schedule_tree_from_guard(
403 __isl_take isl_set
*guard
)
406 isl_schedule_tree
*tree
;
411 ctx
= isl_set_get_ctx(guard
);
412 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_guard
);
425 /* Create a new mark schedule tree with the given mark identifier and
428 __isl_give isl_schedule_tree
*isl_schedule_tree_from_mark(
429 __isl_take isl_id
*mark
)
432 isl_schedule_tree
*tree
;
437 ctx
= isl_id_get_ctx(mark
);
438 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_mark
);
450 /* Does "tree" have any node that depends on its position
451 * in the complete schedule tree?
453 isl_bool
isl_schedule_tree_is_subtree_anchored(
454 __isl_keep isl_schedule_tree
*tree
)
456 return tree
? tree
->anchored
: isl_bool_error
;
459 /* Does the root node of "tree" depend on its position in the complete
461 * Band nodes may be anchored depending on the associated AST build options.
462 * Context, extension and guard nodes are always anchored.
464 int isl_schedule_tree_is_anchored(__isl_keep isl_schedule_tree
*tree
)
469 switch (isl_schedule_tree_get_type(tree
)) {
470 case isl_schedule_node_error
:
472 case isl_schedule_node_band
:
473 return isl_schedule_band_is_anchored(tree
->band
);
474 case isl_schedule_node_context
:
475 case isl_schedule_node_extension
:
476 case isl_schedule_node_guard
:
478 case isl_schedule_node_domain
:
479 case isl_schedule_node_expansion
:
480 case isl_schedule_node_filter
:
481 case isl_schedule_node_leaf
:
482 case isl_schedule_node_mark
:
483 case isl_schedule_node_sequence
:
484 case isl_schedule_node_set
:
488 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
489 "unhandled case", return -1);
492 /* Update the anchored field of "tree" based on whether the root node
493 * itself in anchored and the anchored fields of the children.
495 * This function should be called whenever the children of a tree node
496 * are changed or the anchoredness of the tree root itself changes.
498 __isl_give isl_schedule_tree
*isl_schedule_tree_update_anchored(
499 __isl_take isl_schedule_tree
*tree
)
507 anchored
= isl_schedule_tree_is_anchored(tree
);
509 return isl_schedule_tree_free(tree
);
511 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
512 for (i
= 0; !anchored
&& i
< n
; ++i
) {
513 isl_schedule_tree
*child
;
515 child
= isl_schedule_tree_get_child(tree
, i
);
517 return isl_schedule_tree_free(tree
);
518 anchored
= child
->anchored
;
519 isl_schedule_tree_free(child
);
522 if (anchored
== tree
->anchored
)
524 tree
= isl_schedule_tree_cow(tree
);
527 tree
->anchored
= anchored
;
531 /* Create a new tree of the given type (isl_schedule_node_sequence or
532 * isl_schedule_node_set) with the given children.
534 __isl_give isl_schedule_tree
*isl_schedule_tree_from_children(
535 enum isl_schedule_node_type type
,
536 __isl_take isl_schedule_tree_list
*list
)
539 isl_schedule_tree
*tree
;
544 ctx
= isl_schedule_tree_list_get_ctx(list
);
545 tree
= isl_schedule_tree_alloc(ctx
, type
);
549 tree
->children
= list
;
550 tree
= isl_schedule_tree_update_anchored(tree
);
554 isl_schedule_tree_list_free(list
);
558 /* Construct a tree with a root node of type "type" and as children
559 * "tree1" and "tree2".
560 * If the root of one (or both) of the input trees is itself of type "type",
561 * then the tree is replaced by its children.
563 __isl_give isl_schedule_tree
*isl_schedule_tree_from_pair(
564 enum isl_schedule_node_type type
, __isl_take isl_schedule_tree
*tree1
,
565 __isl_take isl_schedule_tree
*tree2
)
568 isl_schedule_tree_list
*list
;
570 if (!tree1
|| !tree2
)
573 ctx
= isl_schedule_tree_get_ctx(tree1
);
574 if (isl_schedule_tree_get_type(tree1
) == type
) {
575 list
= isl_schedule_tree_list_copy(tree1
->children
);
576 isl_schedule_tree_free(tree1
);
578 list
= isl_schedule_tree_list_alloc(ctx
, 2);
579 list
= isl_schedule_tree_list_add(list
, tree1
);
581 if (isl_schedule_tree_get_type(tree2
) == type
) {
582 isl_schedule_tree_list
*children
;
584 children
= isl_schedule_tree_list_copy(tree2
->children
);
585 list
= isl_schedule_tree_list_concat(list
, children
);
586 isl_schedule_tree_free(tree2
);
588 list
= isl_schedule_tree_list_add(list
, tree2
);
591 return isl_schedule_tree_from_children(type
, list
);
593 isl_schedule_tree_free(tree1
);
594 isl_schedule_tree_free(tree2
);
598 /* Construct a tree with a sequence root node and as children
599 * "tree1" and "tree2".
600 * If the root of one (or both) of the input trees is itself a sequence,
601 * then the tree is replaced by its children.
603 __isl_give isl_schedule_tree
*isl_schedule_tree_sequence_pair(
604 __isl_take isl_schedule_tree
*tree1
,
605 __isl_take isl_schedule_tree
*tree2
)
607 return isl_schedule_tree_from_pair(isl_schedule_node_sequence
,
611 /* Return the isl_ctx to which "tree" belongs.
613 isl_ctx
*isl_schedule_tree_get_ctx(__isl_keep isl_schedule_tree
*tree
)
615 return tree
? tree
->ctx
: NULL
;
618 /* Return the type of the root of the tree or isl_schedule_node_error
621 enum isl_schedule_node_type
isl_schedule_tree_get_type(
622 __isl_keep isl_schedule_tree
*tree
)
624 return tree
? tree
->type
: isl_schedule_node_error
;
627 /* Are "tree1" and "tree2" obviously equal to each other?
629 isl_bool
isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree
*tree1
,
630 __isl_keep isl_schedule_tree
*tree2
)
635 if (!tree1
|| !tree2
)
636 return isl_bool_error
;
638 return isl_bool_true
;
639 if (tree1
->type
!= tree2
->type
)
640 return isl_bool_false
;
642 switch (tree1
->type
) {
643 case isl_schedule_node_band
:
644 equal
= isl_schedule_band_plain_is_equal(tree1
->band
,
647 case isl_schedule_node_context
:
648 equal
= isl_set_is_equal(tree1
->context
, tree2
->context
);
650 case isl_schedule_node_domain
:
651 equal
= isl_union_set_is_equal(tree1
->domain
, tree2
->domain
);
653 case isl_schedule_node_expansion
:
654 equal
= isl_union_map_is_equal(tree1
->expansion
,
656 if (equal
>= 0 && equal
)
657 equal
= isl_union_pw_multi_aff_plain_is_equal(
658 tree1
->contraction
, tree2
->contraction
);
660 case isl_schedule_node_extension
:
661 equal
= isl_union_map_is_equal(tree1
->extension
,
664 case isl_schedule_node_filter
:
665 equal
= isl_union_set_is_equal(tree1
->filter
, tree2
->filter
);
667 case isl_schedule_node_guard
:
668 equal
= isl_set_is_equal(tree1
->guard
, tree2
->guard
);
670 case isl_schedule_node_mark
:
671 equal
= tree1
->mark
== tree2
->mark
;
673 case isl_schedule_node_leaf
:
674 case isl_schedule_node_sequence
:
675 case isl_schedule_node_set
:
676 equal
= isl_bool_true
;
678 case isl_schedule_node_error
:
679 equal
= isl_bool_error
;
683 if (equal
< 0 || !equal
)
686 n
= isl_schedule_tree_n_children(tree1
);
687 if (n
!= isl_schedule_tree_n_children(tree2
))
688 return isl_bool_false
;
689 for (i
= 0; i
< n
; ++i
) {
690 isl_schedule_tree
*child1
, *child2
;
692 child1
= isl_schedule_tree_get_child(tree1
, i
);
693 child2
= isl_schedule_tree_get_child(tree2
, i
);
694 equal
= isl_schedule_tree_plain_is_equal(child1
, child2
);
695 isl_schedule_tree_free(child1
);
696 isl_schedule_tree_free(child2
);
698 if (equal
< 0 || !equal
)
702 return isl_bool_true
;
705 /* Does "tree" have any children, other than an implicit leaf.
707 int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree
*tree
)
712 return tree
->children
!= NULL
;
715 /* Return the number of children of "tree", excluding implicit leaves.
717 int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree
*tree
)
722 return isl_schedule_tree_list_n_schedule_tree(tree
->children
);
725 /* Return a copy of the (explicit) child at position "pos" of "tree".
727 __isl_give isl_schedule_tree
*isl_schedule_tree_get_child(
728 __isl_keep isl_schedule_tree
*tree
, int pos
)
733 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
734 "schedule tree has no explicit children", return NULL
);
735 return isl_schedule_tree_list_get_schedule_tree(tree
->children
, pos
);
738 /* Return a copy of the (explicit) child at position "pos" of "tree" and
741 __isl_give isl_schedule_tree
*isl_schedule_tree_child(
742 __isl_take isl_schedule_tree
*tree
, int pos
)
744 isl_schedule_tree
*child
;
746 child
= isl_schedule_tree_get_child(tree
, pos
);
747 isl_schedule_tree_free(tree
);
751 /* Remove all (explicit) children from "tree".
753 __isl_give isl_schedule_tree
*isl_schedule_tree_reset_children(
754 __isl_take isl_schedule_tree
*tree
)
756 tree
= isl_schedule_tree_cow(tree
);
759 tree
->children
= isl_schedule_tree_list_free(tree
->children
);
763 /* Remove the child at position "pos" from the children of "tree".
764 * If there was only one child to begin with, then remove all children.
766 __isl_give isl_schedule_tree
*isl_schedule_tree_drop_child(
767 __isl_take isl_schedule_tree
*tree
, int pos
)
771 tree
= isl_schedule_tree_cow(tree
);
775 if (!isl_schedule_tree_has_children(tree
))
776 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
777 "tree does not have any explicit children",
778 return isl_schedule_tree_free(tree
));
779 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
780 if (pos
< 0 || pos
>= n
)
781 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
782 "position out of bounds",
783 return isl_schedule_tree_free(tree
));
785 return isl_schedule_tree_reset_children(tree
);
787 tree
->children
= isl_schedule_tree_list_drop(tree
->children
, pos
, 1);
789 return isl_schedule_tree_free(tree
);
794 /* Replace the child at position "pos" of "tree" by "child".
796 * If the new child is a leaf, then it is not explicitly
797 * recorded in the list of children. Instead, the list of children
798 * (which is assumed to have only one element) is removed.
799 * Note that the children of set and sequence nodes are always
800 * filters, so they cannot be replaced by empty trees.
802 __isl_give isl_schedule_tree
*isl_schedule_tree_replace_child(
803 __isl_take isl_schedule_tree
*tree
, int pos
,
804 __isl_take isl_schedule_tree
*child
)
806 tree
= isl_schedule_tree_cow(tree
);
810 if (isl_schedule_tree_is_leaf(child
)) {
811 isl_schedule_tree_free(child
);
812 if (!tree
->children
&& pos
== 0)
814 if (isl_schedule_tree_n_children(tree
) != 1)
815 isl_die(isl_schedule_tree_get_ctx(tree
),
817 "can only replace single child by leaf",
819 return isl_schedule_tree_reset_children(tree
);
822 if (!tree
->children
&& pos
== 0)
824 isl_schedule_tree_list_from_schedule_tree(child
);
826 tree
->children
= isl_schedule_tree_list_set_schedule_tree(
827 tree
->children
, pos
, child
);
830 return isl_schedule_tree_free(tree
);
831 tree
= isl_schedule_tree_update_anchored(tree
);
835 isl_schedule_tree_free(tree
);
836 isl_schedule_tree_free(child
);
840 /* Replace the (explicit) children of "tree" by "children"?
842 __isl_give isl_schedule_tree
*isl_schedule_tree_set_children(
843 __isl_take isl_schedule_tree
*tree
,
844 __isl_take isl_schedule_tree_list
*children
)
846 tree
= isl_schedule_tree_cow(tree
);
847 if (!tree
|| !children
)
849 isl_schedule_tree_list_free(tree
->children
);
850 tree
->children
= children
;
853 isl_schedule_tree_free(tree
);
854 isl_schedule_tree_list_free(children
);
858 /* Create a new band schedule tree referring to "band"
859 * with "tree" as single child.
861 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_band(
862 __isl_take isl_schedule_tree
*tree
, __isl_take isl_schedule_band
*band
)
864 isl_schedule_tree
*res
;
866 res
= isl_schedule_tree_from_band(band
);
867 return isl_schedule_tree_replace_child(res
, 0, tree
);
870 /* Create a new context schedule tree with the given context and
871 * with "tree" as single child.
873 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_context(
874 __isl_take isl_schedule_tree
*tree
, __isl_take isl_set
*context
)
876 isl_schedule_tree
*res
;
878 res
= isl_schedule_tree_from_context(context
);
879 return isl_schedule_tree_replace_child(res
, 0, tree
);
882 /* Create a new domain schedule tree with the given domain and
883 * with "tree" as single child.
885 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_domain(
886 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
888 isl_schedule_tree
*res
;
890 res
= isl_schedule_tree_from_domain(domain
);
891 return isl_schedule_tree_replace_child(res
, 0, tree
);
894 /* Create a new expansion schedule tree with the given contraction and
895 * expansion and with "tree" as single child.
897 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_expansion(
898 __isl_take isl_schedule_tree
*tree
,
899 __isl_take isl_union_pw_multi_aff
*contraction
,
900 __isl_take isl_union_map
*expansion
)
902 isl_schedule_tree
*res
;
904 res
= isl_schedule_tree_from_expansion(contraction
, expansion
);
905 return isl_schedule_tree_replace_child(res
, 0, tree
);
908 /* Create a new extension schedule tree with the given extension and
909 * with "tree" as single child.
911 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_extension(
912 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_map
*extension
)
914 isl_schedule_tree
*res
;
916 res
= isl_schedule_tree_from_extension(extension
);
917 return isl_schedule_tree_replace_child(res
, 0, tree
);
920 /* Create a new filter schedule tree with the given filter and single child.
922 * If the root of "tree" is itself a filter node, then the two
923 * filter nodes are merged into one node.
925 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_filter(
926 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
928 isl_schedule_tree
*res
;
930 if (isl_schedule_tree_get_type(tree
) == isl_schedule_node_filter
) {
931 isl_union_set
*tree_filter
;
933 tree_filter
= isl_schedule_tree_filter_get_filter(tree
);
934 tree_filter
= isl_union_set_intersect(tree_filter
, filter
);
935 tree
= isl_schedule_tree_filter_set_filter(tree
, tree_filter
);
939 res
= isl_schedule_tree_from_filter(filter
);
940 return isl_schedule_tree_replace_child(res
, 0, tree
);
943 /* Insert a filter node with filter set "filter"
944 * in each of the children of "tree".
946 __isl_give isl_schedule_tree
*isl_schedule_tree_children_insert_filter(
947 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
951 if (!tree
|| !filter
)
954 n
= isl_schedule_tree_n_children(tree
);
955 for (i
= 0; i
< n
; ++i
) {
956 isl_schedule_tree
*child
;
958 child
= isl_schedule_tree_get_child(tree
, i
);
959 child
= isl_schedule_tree_insert_filter(child
,
960 isl_union_set_copy(filter
));
961 tree
= isl_schedule_tree_replace_child(tree
, i
, child
);
964 isl_union_set_free(filter
);
967 isl_union_set_free(filter
);
968 isl_schedule_tree_free(tree
);
972 /* Create a new guard schedule tree with the given guard and
973 * with "tree" as single child.
975 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_guard(
976 __isl_take isl_schedule_tree
*tree
, __isl_take isl_set
*guard
)
978 isl_schedule_tree
*res
;
980 res
= isl_schedule_tree_from_guard(guard
);
981 return isl_schedule_tree_replace_child(res
, 0, tree
);
984 /* Create a new mark schedule tree with the given mark identifier and
987 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_mark(
988 __isl_take isl_schedule_tree
*tree
, __isl_take isl_id
*mark
)
990 isl_schedule_tree
*res
;
992 res
= isl_schedule_tree_from_mark(mark
);
993 return isl_schedule_tree_replace_child(res
, 0, tree
);
996 /* Return the number of members in the band tree root.
998 unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree
*tree
)
1003 if (tree
->type
!= isl_schedule_node_band
)
1004 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1005 "not a band node", return 0);
1007 return isl_schedule_band_n_member(tree
->band
);
1010 /* Is the band member at position "pos" of the band tree root
1011 * marked coincident?
1013 isl_bool
isl_schedule_tree_band_member_get_coincident(
1014 __isl_keep isl_schedule_tree
*tree
, int pos
)
1017 return isl_bool_error
;
1019 if (tree
->type
!= isl_schedule_node_band
)
1020 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1021 "not a band node", return isl_bool_error
);
1023 return isl_schedule_band_member_get_coincident(tree
->band
, pos
);
1026 /* Mark the given band member as being coincident or not
1027 * according to "coincident".
1029 __isl_give isl_schedule_tree
*isl_schedule_tree_band_member_set_coincident(
1030 __isl_take isl_schedule_tree
*tree
, int pos
, int coincident
)
1034 if (tree
->type
!= isl_schedule_node_band
)
1035 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1036 "not a band node", return isl_schedule_tree_free(tree
));
1037 if (isl_schedule_tree_band_member_get_coincident(tree
, pos
) ==
1040 tree
= isl_schedule_tree_cow(tree
);
1044 tree
->band
= isl_schedule_band_member_set_coincident(tree
->band
, pos
,
1047 return isl_schedule_tree_free(tree
);
1051 /* Is the band tree root marked permutable?
1053 isl_bool
isl_schedule_tree_band_get_permutable(
1054 __isl_keep isl_schedule_tree
*tree
)
1057 return isl_bool_error
;
1059 if (tree
->type
!= isl_schedule_node_band
)
1060 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1061 "not a band node", return isl_bool_error
);
1063 return isl_schedule_band_get_permutable(tree
->band
);
1066 /* Mark the band tree root permutable or not according to "permutable"?
1068 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_permutable(
1069 __isl_take isl_schedule_tree
*tree
, int permutable
)
1073 if (tree
->type
!= isl_schedule_node_band
)
1074 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1075 "not a band node", return isl_schedule_tree_free(tree
));
1076 if (isl_schedule_tree_band_get_permutable(tree
) == permutable
)
1078 tree
= isl_schedule_tree_cow(tree
);
1082 tree
->band
= isl_schedule_band_set_permutable(tree
->band
, permutable
);
1084 return isl_schedule_tree_free(tree
);
1088 /* Return the schedule space of the band tree root.
1090 __isl_give isl_space
*isl_schedule_tree_band_get_space(
1091 __isl_keep isl_schedule_tree
*tree
)
1096 if (tree
->type
!= isl_schedule_node_band
)
1097 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1098 "not a band node", return NULL
);
1100 return isl_schedule_band_get_space(tree
->band
);
1103 /* Intersect the domain of the band schedule of the band tree root
1106 __isl_give isl_schedule_tree
*isl_schedule_tree_band_intersect_domain(
1107 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
1109 if (!tree
|| !domain
)
1112 if (tree
->type
!= isl_schedule_node_band
)
1113 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1114 "not a band node", goto error
);
1116 tree
->band
= isl_schedule_band_intersect_domain(tree
->band
, domain
);
1118 return isl_schedule_tree_free(tree
);
1122 isl_schedule_tree_free(tree
);
1123 isl_union_set_free(domain
);
1127 /* Return the schedule of the band tree root in isolation.
1129 __isl_give isl_multi_union_pw_aff
*isl_schedule_tree_band_get_partial_schedule(
1130 __isl_keep isl_schedule_tree
*tree
)
1135 if (tree
->type
!= isl_schedule_node_band
)
1136 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1137 "not a band node", return NULL
);
1139 return isl_schedule_band_get_partial_schedule(tree
->band
);
1142 /* Replace the schedule of the band tree root by "schedule".
1144 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_partial_schedule(
1145 __isl_take isl_schedule_tree
*tree
,
1146 __isl_take isl_multi_union_pw_aff
*schedule
)
1148 tree
= isl_schedule_tree_cow(tree
);
1149 if (!tree
|| !schedule
)
1152 if (tree
->type
!= isl_schedule_node_band
)
1153 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1154 "not a band node", return NULL
);
1155 tree
->band
= isl_schedule_band_set_partial_schedule(tree
->band
,
1160 isl_schedule_tree_free(tree
);
1161 isl_multi_union_pw_aff_free(schedule
);
1165 /* Return the loop AST generation type for the band member
1166 * of the band tree root at position "pos".
1168 enum isl_ast_loop_type
isl_schedule_tree_band_member_get_ast_loop_type(
1169 __isl_keep isl_schedule_tree
*tree
, int pos
)
1172 return isl_ast_loop_error
;
1174 if (tree
->type
!= isl_schedule_node_band
)
1175 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1176 "not a band node", return isl_ast_loop_error
);
1178 return isl_schedule_band_member_get_ast_loop_type(tree
->band
, pos
);
1181 /* Set the loop AST generation type for the band member of the band tree root
1182 * at position "pos" to "type".
1184 __isl_give isl_schedule_tree
*isl_schedule_tree_band_member_set_ast_loop_type(
1185 __isl_take isl_schedule_tree
*tree
, int pos
,
1186 enum isl_ast_loop_type type
)
1188 tree
= isl_schedule_tree_cow(tree
);
1192 if (tree
->type
!= isl_schedule_node_band
)
1193 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1194 "not a band node", return isl_schedule_tree_free(tree
));
1196 tree
->band
= isl_schedule_band_member_set_ast_loop_type(tree
->band
,
1199 return isl_schedule_tree_free(tree
);
1204 /* Return the loop AST generation type for the band member
1205 * of the band tree root at position "pos" for the isolated part.
1207 enum isl_ast_loop_type
isl_schedule_tree_band_member_get_isolate_ast_loop_type(
1208 __isl_keep isl_schedule_tree
*tree
, int pos
)
1211 return isl_ast_loop_error
;
1213 if (tree
->type
!= isl_schedule_node_band
)
1214 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1215 "not a band node", return isl_ast_loop_error
);
1217 return isl_schedule_band_member_get_isolate_ast_loop_type(tree
->band
,
1221 /* Set the loop AST generation type for the band member of the band tree root
1222 * at position "pos" for the isolated part to "type".
1224 __isl_give isl_schedule_tree
*
1225 isl_schedule_tree_band_member_set_isolate_ast_loop_type(
1226 __isl_take isl_schedule_tree
*tree
, int pos
,
1227 enum isl_ast_loop_type type
)
1229 tree
= isl_schedule_tree_cow(tree
);
1233 if (tree
->type
!= isl_schedule_node_band
)
1234 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1235 "not a band node", return isl_schedule_tree_free(tree
));
1237 tree
->band
= isl_schedule_band_member_set_isolate_ast_loop_type(
1238 tree
->band
, pos
, type
);
1240 return isl_schedule_tree_free(tree
);
1245 /* Return the AST build options associated to the band tree root.
1247 __isl_give isl_union_set
*isl_schedule_tree_band_get_ast_build_options(
1248 __isl_keep isl_schedule_tree
*tree
)
1253 if (tree
->type
!= isl_schedule_node_band
)
1254 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1255 "not a band node", return NULL
);
1257 return isl_schedule_band_get_ast_build_options(tree
->band
);
1260 /* Replace the AST build options associated to band tree root by "options".
1261 * Updated the anchored field if the anchoredness of the root node itself
1264 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_ast_build_options(
1265 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*options
)
1269 tree
= isl_schedule_tree_cow(tree
);
1270 if (!tree
|| !options
)
1273 if (tree
->type
!= isl_schedule_node_band
)
1274 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1275 "not a band node", goto error
);
1277 was_anchored
= isl_schedule_tree_is_anchored(tree
);
1278 tree
->band
= isl_schedule_band_set_ast_build_options(tree
->band
,
1281 return isl_schedule_tree_free(tree
);
1282 if (isl_schedule_tree_is_anchored(tree
) != was_anchored
)
1283 tree
= isl_schedule_tree_update_anchored(tree
);
1287 isl_schedule_tree_free(tree
);
1288 isl_union_set_free(options
);
1292 /* Return the context of the context tree root.
1294 __isl_give isl_set
*isl_schedule_tree_context_get_context(
1295 __isl_keep isl_schedule_tree
*tree
)
1300 if (tree
->type
!= isl_schedule_node_context
)
1301 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1302 "not a context node", return NULL
);
1304 return isl_set_copy(tree
->context
);
1307 /* Return the domain of the domain tree root.
1309 __isl_give isl_union_set
*isl_schedule_tree_domain_get_domain(
1310 __isl_keep isl_schedule_tree
*tree
)
1315 if (tree
->type
!= isl_schedule_node_domain
)
1316 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1317 "not a domain node", return NULL
);
1319 return isl_union_set_copy(tree
->domain
);
1322 /* Replace the domain of domain tree root "tree" by "domain".
1324 __isl_give isl_schedule_tree
*isl_schedule_tree_domain_set_domain(
1325 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
1327 tree
= isl_schedule_tree_cow(tree
);
1328 if (!tree
|| !domain
)
1331 if (tree
->type
!= isl_schedule_node_domain
)
1332 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1333 "not a domain node", goto error
);
1335 isl_union_set_free(tree
->domain
);
1336 tree
->domain
= domain
;
1340 isl_schedule_tree_free(tree
);
1341 isl_union_set_free(domain
);
1345 /* Return the contraction of the expansion tree root.
1347 __isl_give isl_union_pw_multi_aff
*isl_schedule_tree_expansion_get_contraction(
1348 __isl_keep isl_schedule_tree
*tree
)
1353 if (tree
->type
!= isl_schedule_node_expansion
)
1354 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1355 "not an expansion node", return NULL
);
1357 return isl_union_pw_multi_aff_copy(tree
->contraction
);
1360 /* Return the expansion of the expansion tree root.
1362 __isl_give isl_union_map
*isl_schedule_tree_expansion_get_expansion(
1363 __isl_keep isl_schedule_tree
*tree
)
1368 if (tree
->type
!= isl_schedule_node_expansion
)
1369 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1370 "not an expansion node", return NULL
);
1372 return isl_union_map_copy(tree
->expansion
);
1375 /* Replace the contraction and the expansion of the expansion tree root "tree"
1376 * by "contraction" and "expansion".
1378 __isl_give isl_schedule_tree
*
1379 isl_schedule_tree_expansion_set_contraction_and_expansion(
1380 __isl_take isl_schedule_tree
*tree
,
1381 __isl_take isl_union_pw_multi_aff
*contraction
,
1382 __isl_take isl_union_map
*expansion
)
1384 tree
= isl_schedule_tree_cow(tree
);
1385 if (!tree
|| !contraction
|| !expansion
)
1388 if (tree
->type
!= isl_schedule_node_expansion
)
1389 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1390 "not an expansion node", return NULL
);
1392 isl_union_pw_multi_aff_free(tree
->contraction
);
1393 tree
->contraction
= contraction
;
1394 isl_union_map_free(tree
->expansion
);
1395 tree
->expansion
= expansion
;
1399 isl_schedule_tree_free(tree
);
1400 isl_union_pw_multi_aff_free(contraction
);
1401 isl_union_map_free(expansion
);
1405 /* Return the extension of the extension tree root.
1407 __isl_give isl_union_map
*isl_schedule_tree_extension_get_extension(
1408 __isl_take isl_schedule_tree
*tree
)
1413 if (tree
->type
!= isl_schedule_node_extension
)
1414 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1415 "not an extension node", return NULL
);
1417 return isl_union_map_copy(tree
->extension
);
1420 /* Replace the extension of extension tree root "tree" by "extension".
1422 __isl_give isl_schedule_tree
*isl_schedule_tree_extension_set_extension(
1423 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_map
*extension
)
1425 tree
= isl_schedule_tree_cow(tree
);
1426 if (!tree
|| !extension
)
1429 if (tree
->type
!= isl_schedule_node_extension
)
1430 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1431 "not an extension node", return NULL
);
1432 isl_union_map_free(tree
->extension
);
1433 tree
->extension
= extension
;
1437 isl_schedule_tree_free(tree
);
1438 isl_union_map_free(extension
);
1442 /* Return the filter of the filter tree root.
1444 __isl_give isl_union_set
*isl_schedule_tree_filter_get_filter(
1445 __isl_keep isl_schedule_tree
*tree
)
1450 if (tree
->type
!= isl_schedule_node_filter
)
1451 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1452 "not a filter node", return NULL
);
1454 return isl_union_set_copy(tree
->filter
);
1457 /* Replace the filter of the filter tree root by "filter".
1459 __isl_give isl_schedule_tree
*isl_schedule_tree_filter_set_filter(
1460 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
1462 tree
= isl_schedule_tree_cow(tree
);
1463 if (!tree
|| !filter
)
1466 if (tree
->type
!= isl_schedule_node_filter
)
1467 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1468 "not a filter node", return NULL
);
1470 isl_union_set_free(tree
->filter
);
1471 tree
->filter
= filter
;
1475 isl_schedule_tree_free(tree
);
1476 isl_union_set_free(filter
);
1480 /* Return the guard of the guard tree root.
1482 __isl_give isl_set
*isl_schedule_tree_guard_get_guard(
1483 __isl_take isl_schedule_tree
*tree
)
1488 if (tree
->type
!= isl_schedule_node_guard
)
1489 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1490 "not a guard node", return NULL
);
1492 return isl_set_copy(tree
->guard
);
1495 /* Return the mark identifier of the mark tree root "tree".
1497 __isl_give isl_id
*isl_schedule_tree_mark_get_id(
1498 __isl_keep isl_schedule_tree
*tree
)
1503 if (tree
->type
!= isl_schedule_node_mark
)
1504 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1505 "not a mark node", return NULL
);
1507 return isl_id_copy(tree
->mark
);
1510 /* Set dim to the range dimension of "map" and abort the search.
1512 static isl_stat
set_range_dim(__isl_take isl_map
*map
, void *user
)
1516 *dim
= isl_map_dim(map
, isl_dim_out
);
1519 return isl_stat_error
;
1522 /* Return the dimension of the range of "umap".
1523 * "umap" is assumed not to be empty and
1524 * all maps inside "umap" are assumed to have the same range.
1526 * We extract the range dimension from the first map in "umap".
1528 static int range_dim(__isl_keep isl_union_map
*umap
)
1534 if (isl_union_map_n_map(umap
) == 0)
1535 isl_die(isl_union_map_get_ctx(umap
), isl_error_internal
,
1536 "unexpected empty input", return -1);
1538 isl_union_map_foreach_map(umap
, &set_range_dim
, &dim
);
1543 /* Append an "extra" number of zeros to the range of "umap" and
1544 * return the result.
1546 static __isl_give isl_union_map
*append_range(__isl_take isl_union_map
*umap
,
1552 isl_union_pw_multi_aff
*suffix
;
1553 isl_union_map
*universe
;
1554 isl_union_map
*suffix_umap
;
1556 universe
= isl_union_map_universe(isl_union_map_copy(umap
));
1557 dom
= isl_union_map_domain(universe
);
1558 space
= isl_union_set_get_space(dom
);
1559 space
= isl_space_set_from_params(space
);
1560 space
= isl_space_add_dims(space
, isl_dim_set
, extra
);
1561 mv
= isl_multi_val_zero(space
);
1563 suffix
= isl_union_pw_multi_aff_multi_val_on_domain(dom
, mv
);
1564 suffix_umap
= isl_union_map_from_union_pw_multi_aff(suffix
);
1565 umap
= isl_union_map_flat_range_product(umap
, suffix_umap
);
1570 /* Should we skip the root of "tree" while looking for the first
1571 * descendant with schedule information?
1572 * That is, is it impossible to derive any information about
1573 * the iteration domain from this node?
1575 * We do not want to skip leaf or error nodes because there is
1576 * no point in looking any deeper from these nodes.
1577 * We can only extract partial iteration domain information
1578 * from an extension node, but extension nodes are not supported
1579 * by the caller and it will error out on them.
1581 static int domain_less(__isl_keep isl_schedule_tree
*tree
)
1583 enum isl_schedule_node_type type
;
1585 type
= isl_schedule_tree_get_type(tree
);
1587 case isl_schedule_node_band
:
1588 return isl_schedule_tree_band_n_member(tree
) == 0;
1589 case isl_schedule_node_context
:
1590 case isl_schedule_node_guard
:
1591 case isl_schedule_node_mark
:
1593 case isl_schedule_node_leaf
:
1594 case isl_schedule_node_error
:
1595 case isl_schedule_node_domain
:
1596 case isl_schedule_node_expansion
:
1597 case isl_schedule_node_extension
:
1598 case isl_schedule_node_filter
:
1599 case isl_schedule_node_set
:
1600 case isl_schedule_node_sequence
:
1604 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1605 "unhandled case", return 0);
1608 /* Move down to the first descendant of "tree" that contains any schedule
1609 * information or return "leaf" if there is no such descendant.
1611 __isl_give isl_schedule_tree
*isl_schedule_tree_first_schedule_descendant(
1612 __isl_take isl_schedule_tree
*tree
, __isl_keep isl_schedule_tree
*leaf
)
1614 while (domain_less(tree
)) {
1615 if (!isl_schedule_tree_has_children(tree
)) {
1616 isl_schedule_tree_free(tree
);
1617 return isl_schedule_tree_copy(leaf
);
1619 tree
= isl_schedule_tree_child(tree
, 0);
1625 static __isl_give isl_union_map
*subtree_schedule_extend(
1626 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
);
1628 /* Extend the schedule map "outer" with the subtree schedule
1629 * of the (single) child of "tree", if any.
1631 * If "tree" does not have any descendants (apart from those that
1632 * do not carry any schedule information), then we simply return "outer".
1633 * Otherwise, we extend the schedule map "outer" with the subtree schedule
1634 * of the single child.
1636 static __isl_give isl_union_map
*subtree_schedule_extend_child(
1637 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1639 isl_schedule_tree
*child
;
1643 return isl_union_map_free(outer
);
1644 if (!isl_schedule_tree_has_children(tree
))
1646 child
= isl_schedule_tree_get_child(tree
, 0);
1648 return isl_union_map_free(outer
);
1649 res
= subtree_schedule_extend(child
, outer
);
1650 isl_schedule_tree_free(child
);
1654 /* Extract the parameter space from one of the children of "tree",
1655 * which are assumed to be filters.
1657 static __isl_give isl_space
*extract_space_from_filter_child(
1658 __isl_keep isl_schedule_tree
*tree
)
1662 isl_schedule_tree
*child
;
1664 child
= isl_schedule_tree_list_get_schedule_tree(tree
->children
, 0);
1665 dom
= isl_schedule_tree_filter_get_filter(child
);
1666 space
= isl_union_set_get_space(dom
);
1667 isl_union_set_free(dom
);
1668 isl_schedule_tree_free(child
);
1673 /* Extend the schedule map "outer" with the subtree schedule
1674 * of a set or sequence node.
1676 * The schedule for the set or sequence node itself is composed of
1677 * pieces of the form
1685 * The first form is used if there is only a single child or
1686 * if the current node is a set node and the schedule_separate_components
1687 * option is not set.
1689 * Each of the pieces above is extended with the subtree schedule of
1690 * the child of the corresponding filter, if any, padded with zeros
1691 * to ensure that all pieces have the same range dimension.
1693 static __isl_give isl_union_map
*subtree_schedule_extend_from_children(
1694 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1703 isl_union_map
*umap
;
1708 ctx
= isl_schedule_tree_get_ctx(tree
);
1709 if (!tree
->children
)
1710 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1711 "missing children", return NULL
);
1712 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
1714 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1715 "missing children", return NULL
);
1717 separate
= n
> 1 && (tree
->type
== isl_schedule_node_sequence
||
1718 isl_options_get_schedule_separate_components(ctx
));
1720 space
= extract_space_from_filter_child(tree
);
1722 umap
= isl_union_map_empty(isl_space_copy(space
));
1723 space
= isl_space_set_from_params(space
);
1725 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
1726 v
= isl_val_zero(ctx
);
1728 mv
= isl_multi_val_zero(space
);
1730 dim
= isl_multi_val_dim(mv
, isl_dim_set
);
1731 for (i
= 0; i
< n
; ++i
) {
1732 isl_union_pw_multi_aff
*upma
;
1733 isl_union_map
*umap_i
;
1735 isl_schedule_tree
*child
;
1739 child
= isl_schedule_tree_list_get_schedule_tree(
1741 dom
= isl_schedule_tree_filter_get_filter(child
);
1744 mv
= isl_multi_val_set_val(mv
, 0, isl_val_copy(v
));
1745 v
= isl_val_add_ui(v
, 1);
1747 upma
= isl_union_pw_multi_aff_multi_val_on_domain(dom
,
1748 isl_multi_val_copy(mv
));
1749 umap_i
= isl_union_map_from_union_pw_multi_aff(upma
);
1750 umap_i
= isl_union_map_flat_range_product(
1751 isl_union_map_copy(outer
), umap_i
);
1752 umap_i
= subtree_schedule_extend_child(child
, umap_i
);
1753 isl_schedule_tree_free(child
);
1755 empty
= isl_union_map_is_empty(umap_i
);
1757 umap_i
= isl_union_map_free(umap_i
);
1759 isl_union_map_free(umap_i
);
1763 dim_i
= range_dim(umap_i
);
1765 umap
= isl_union_map_free(umap
);
1766 } else if (dim
< dim_i
) {
1767 umap
= append_range(umap
, dim_i
- dim
);
1769 } else if (dim_i
< dim
) {
1770 umap_i
= append_range(umap_i
, dim
- dim_i
);
1772 umap
= isl_union_map_union(umap
, umap_i
);
1776 isl_multi_val_free(mv
);
1777 isl_union_map_free(outer
);
1782 /* Extend the schedule map "outer" with the subtree schedule of "tree".
1784 * If the root of the tree is a set or a sequence, then we extend
1785 * the schedule map in subtree_schedule_extend_from_children.
1786 * Otherwise, we extend the schedule map with the partial schedule
1787 * corresponding to the root of the tree and then continue with
1788 * the single child of this root.
1789 * In the special case of an expansion, the schedule map is "extended"
1790 * by applying the expansion to the domain of the schedule map.
1792 static __isl_give isl_union_map
*subtree_schedule_extend(
1793 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1795 isl_multi_union_pw_aff
*mupa
;
1796 isl_union_map
*umap
;
1797 isl_union_set
*domain
;
1802 switch (tree
->type
) {
1803 case isl_schedule_node_error
:
1804 return isl_union_map_free(outer
);
1805 case isl_schedule_node_extension
:
1806 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1807 "cannot construct subtree schedule of tree "
1808 "with extension nodes",
1809 return isl_union_map_free(outer
));
1810 case isl_schedule_node_context
:
1811 case isl_schedule_node_guard
:
1812 case isl_schedule_node_mark
:
1813 return subtree_schedule_extend_child(tree
, outer
);
1814 case isl_schedule_node_band
:
1815 if (isl_schedule_tree_band_n_member(tree
) == 0)
1816 return subtree_schedule_extend_child(tree
, outer
);
1817 mupa
= isl_schedule_band_get_partial_schedule(tree
->band
);
1818 umap
= isl_union_map_from_multi_union_pw_aff(mupa
);
1819 outer
= isl_union_map_flat_range_product(outer
, umap
);
1820 umap
= subtree_schedule_extend_child(tree
, outer
);
1822 case isl_schedule_node_domain
:
1823 domain
= isl_schedule_tree_domain_get_domain(tree
);
1824 umap
= isl_union_map_from_domain(domain
);
1825 outer
= isl_union_map_flat_range_product(outer
, umap
);
1826 umap
= subtree_schedule_extend_child(tree
, outer
);
1828 case isl_schedule_node_expansion
:
1829 umap
= isl_schedule_tree_expansion_get_expansion(tree
);
1830 outer
= isl_union_map_apply_domain(outer
, umap
);
1831 umap
= subtree_schedule_extend_child(tree
, outer
);
1833 case isl_schedule_node_filter
:
1834 domain
= isl_schedule_tree_filter_get_filter(tree
);
1835 umap
= isl_union_map_from_domain(domain
);
1836 outer
= isl_union_map_flat_range_product(outer
, umap
);
1837 umap
= subtree_schedule_extend_child(tree
, outer
);
1839 case isl_schedule_node_leaf
:
1840 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1841 "leaf node should be handled by caller", return NULL
);
1842 case isl_schedule_node_set
:
1843 case isl_schedule_node_sequence
:
1844 umap
= subtree_schedule_extend_from_children(tree
, outer
);
1851 static __isl_give isl_union_set
*initial_domain(
1852 __isl_keep isl_schedule_tree
*tree
);
1854 /* Extract a universe domain from the children of the tree root "tree",
1855 * which is a set or sequence, meaning that its children are filters.
1856 * In particular, return the union of the universes of the filters.
1858 static __isl_give isl_union_set
*initial_domain_from_children(
1859 __isl_keep isl_schedule_tree
*tree
)
1863 isl_union_set
*domain
;
1865 if (!tree
->children
)
1866 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1867 "missing children", return NULL
);
1868 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
1870 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1871 "missing children", return NULL
);
1873 space
= extract_space_from_filter_child(tree
);
1874 domain
= isl_union_set_empty(space
);
1876 for (i
= 0; i
< n
; ++i
) {
1877 isl_schedule_tree
*child
;
1878 isl_union_set
*domain_i
;
1880 child
= isl_schedule_tree_get_child(tree
, i
);
1881 domain_i
= initial_domain(child
);
1882 domain
= isl_union_set_union(domain
, domain_i
);
1883 isl_schedule_tree_free(child
);
1889 /* Extract a universe domain from the tree root "tree".
1890 * The caller is responsible for making sure that this node
1891 * would not be skipped by isl_schedule_tree_first_schedule_descendant
1892 * and that it is not a leaf node.
1894 static __isl_give isl_union_set
*initial_domain(
1895 __isl_keep isl_schedule_tree
*tree
)
1897 isl_multi_union_pw_aff
*mupa
;
1898 isl_union_set
*domain
;
1904 switch (tree
->type
) {
1905 case isl_schedule_node_error
:
1907 case isl_schedule_node_context
:
1908 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1909 "context node should be handled by caller",
1911 case isl_schedule_node_guard
:
1912 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1913 "guard node should be handled by caller",
1915 case isl_schedule_node_mark
:
1916 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1917 "mark node should be handled by caller",
1919 case isl_schedule_node_extension
:
1920 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1921 "cannot construct subtree schedule of tree "
1922 "with extension nodes", return NULL
);
1923 case isl_schedule_node_band
:
1924 if (isl_schedule_tree_band_n_member(tree
) == 0)
1925 isl_die(isl_schedule_tree_get_ctx(tree
),
1927 "0D band should be handled by caller",
1929 mupa
= isl_schedule_band_get_partial_schedule(tree
->band
);
1930 domain
= isl_multi_union_pw_aff_domain(mupa
);
1931 domain
= isl_union_set_universe(domain
);
1933 case isl_schedule_node_domain
:
1934 domain
= isl_schedule_tree_domain_get_domain(tree
);
1935 domain
= isl_union_set_universe(domain
);
1937 case isl_schedule_node_expansion
:
1938 exp
= isl_schedule_tree_expansion_get_expansion(tree
);
1939 exp
= isl_union_map_universe(exp
);
1940 domain
= isl_union_map_domain(exp
);
1942 case isl_schedule_node_filter
:
1943 domain
= isl_schedule_tree_filter_get_filter(tree
);
1944 domain
= isl_union_set_universe(domain
);
1946 case isl_schedule_node_leaf
:
1947 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1948 "leaf node should be handled by caller", return NULL
);
1949 case isl_schedule_node_set
:
1950 case isl_schedule_node_sequence
:
1951 domain
= initial_domain_from_children(tree
);
1958 /* Return the subtree schedule of a node that contains some schedule
1959 * information, i.e., a node that would not be skipped by
1960 * isl_schedule_tree_first_schedule_descendant and that is not a leaf.
1962 * If the tree contains any expansions, then the returned subtree
1963 * schedule is formulated in terms of the expanded domains.
1964 * The tree is not allowed to contain any extension nodes.
1966 * We start with an initial zero-dimensional subtree schedule based
1967 * on the domain information in the root node and then extend it
1968 * based on the schedule information in the root node and its descendants.
1970 __isl_give isl_union_map
*isl_schedule_tree_get_subtree_schedule_union_map(
1971 __isl_keep isl_schedule_tree
*tree
)
1973 isl_union_set
*domain
;
1974 isl_union_map
*umap
;
1976 domain
= initial_domain(tree
);
1977 umap
= isl_union_map_from_domain(domain
);
1978 return subtree_schedule_extend(tree
, umap
);
1981 /* Multiply the partial schedule of the band root node of "tree"
1982 * with the factors in "mv".
1984 __isl_give isl_schedule_tree
*isl_schedule_tree_band_scale(
1985 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
1989 if (tree
->type
!= isl_schedule_node_band
)
1990 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1991 "not a band node", goto error
);
1993 tree
= isl_schedule_tree_cow(tree
);
1997 tree
->band
= isl_schedule_band_scale(tree
->band
, mv
);
1999 return isl_schedule_tree_free(tree
);
2003 isl_schedule_tree_free(tree
);
2004 isl_multi_val_free(mv
);
2008 /* Divide the partial schedule of the band root node of "tree"
2009 * by the factors in "mv".
2011 __isl_give isl_schedule_tree
*isl_schedule_tree_band_scale_down(
2012 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
2016 if (tree
->type
!= isl_schedule_node_band
)
2017 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2018 "not a band node", goto error
);
2020 tree
= isl_schedule_tree_cow(tree
);
2024 tree
->band
= isl_schedule_band_scale_down(tree
->band
, mv
);
2026 return isl_schedule_tree_free(tree
);
2030 isl_schedule_tree_free(tree
);
2031 isl_multi_val_free(mv
);
2035 /* Reduce the partial schedule of the band root node of "tree"
2036 * modulo the factors in "mv".
2038 __isl_give isl_schedule_tree
*isl_schedule_tree_band_mod(
2039 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
2043 if (tree
->type
!= isl_schedule_node_band
)
2044 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2045 "not a band node", goto error
);
2047 tree
= isl_schedule_tree_cow(tree
);
2051 tree
->band
= isl_schedule_band_mod(tree
->band
, mv
);
2053 return isl_schedule_tree_free(tree
);
2057 isl_schedule_tree_free(tree
);
2058 isl_multi_val_free(mv
);
2062 /* Shift the partial schedule of the band root node of "tree" by "shift".
2064 __isl_give isl_schedule_tree
*isl_schedule_tree_band_shift(
2065 __isl_take isl_schedule_tree
*tree
,
2066 __isl_take isl_multi_union_pw_aff
*shift
)
2068 if (!tree
|| !shift
)
2070 if (tree
->type
!= isl_schedule_node_band
)
2071 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2072 "not a band node", goto error
);
2074 tree
= isl_schedule_tree_cow(tree
);
2078 tree
->band
= isl_schedule_band_shift(tree
->band
, shift
);
2080 return isl_schedule_tree_free(tree
);
2084 isl_schedule_tree_free(tree
);
2085 isl_multi_union_pw_aff_free(shift
);
2089 /* Given two trees with sequence roots, replace the child at position
2090 * "pos" of "tree" with the children of "child".
2092 __isl_give isl_schedule_tree
*isl_schedule_tree_sequence_splice(
2093 __isl_take isl_schedule_tree
*tree
, int pos
,
2094 __isl_take isl_schedule_tree
*child
)
2097 isl_schedule_tree_list
*list1
, *list2
;
2099 tree
= isl_schedule_tree_cow(tree
);
2100 if (!tree
|| !child
)
2102 if (isl_schedule_tree_get_type(tree
) != isl_schedule_node_sequence
)
2103 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2104 "not a sequence node", goto error
);
2105 n
= isl_schedule_tree_n_children(tree
);
2106 if (pos
< 0 || pos
>= n
)
2107 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2108 "position out of bounds", goto error
);
2109 if (isl_schedule_tree_get_type(child
) != isl_schedule_node_sequence
)
2110 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2111 "not a sequence node", goto error
);
2113 list1
= isl_schedule_tree_list_copy(tree
->children
);
2114 list1
= isl_schedule_tree_list_drop(list1
, pos
, n
- pos
);
2115 list2
= isl_schedule_tree_list_copy(tree
->children
);
2116 list2
= isl_schedule_tree_list_drop(list2
, 0, pos
+ 1);
2117 list1
= isl_schedule_tree_list_concat(list1
,
2118 isl_schedule_tree_list_copy(child
->children
));
2119 list1
= isl_schedule_tree_list_concat(list1
, list2
);
2121 isl_schedule_tree_free(tree
);
2122 isl_schedule_tree_free(child
);
2123 return isl_schedule_tree_from_children(isl_schedule_node_sequence
,
2126 isl_schedule_tree_free(tree
);
2127 isl_schedule_tree_free(child
);
2131 /* Tile the band root node of "tree" with tile sizes "sizes".
2133 * We duplicate the band node, change the schedule of one of them
2134 * to the tile schedule and the other to the point schedule and then
2135 * attach the point band as a child to the tile band.
2137 __isl_give isl_schedule_tree
*isl_schedule_tree_band_tile(
2138 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*sizes
)
2140 isl_schedule_tree
*child
= NULL
;
2142 if (!tree
|| !sizes
)
2144 if (tree
->type
!= isl_schedule_node_band
)
2145 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2146 "not a band node", goto error
);
2148 child
= isl_schedule_tree_copy(tree
);
2149 tree
= isl_schedule_tree_cow(tree
);
2150 child
= isl_schedule_tree_cow(child
);
2151 if (!tree
|| !child
)
2154 tree
->band
= isl_schedule_band_tile(tree
->band
,
2155 isl_multi_val_copy(sizes
));
2158 child
->band
= isl_schedule_band_point(child
->band
, tree
->band
, sizes
);
2160 child
= isl_schedule_tree_free(child
);
2162 tree
= isl_schedule_tree_replace_child(tree
, 0, child
);
2166 isl_schedule_tree_free(child
);
2167 isl_schedule_tree_free(tree
);
2168 isl_multi_val_free(sizes
);
2172 /* Split the band root node of "tree" into two nested band nodes,
2173 * one with the first "pos" dimensions and
2174 * one with the remaining dimensions.
2176 __isl_give isl_schedule_tree
*isl_schedule_tree_band_split(
2177 __isl_take isl_schedule_tree
*tree
, int pos
)
2180 isl_schedule_tree
*child
;
2184 if (tree
->type
!= isl_schedule_node_band
)
2185 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2186 "not a band node", return isl_schedule_tree_free(tree
));
2188 n
= isl_schedule_tree_band_n_member(tree
);
2189 if (pos
< 0 || pos
> n
)
2190 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2191 "position out of bounds",
2192 return isl_schedule_tree_free(tree
));
2194 child
= isl_schedule_tree_copy(tree
);
2195 tree
= isl_schedule_tree_cow(tree
);
2196 child
= isl_schedule_tree_cow(child
);
2197 if (!tree
|| !child
)
2200 child
->band
= isl_schedule_band_drop(child
->band
, 0, pos
);
2201 tree
->band
= isl_schedule_band_drop(tree
->band
, pos
, n
- pos
);
2202 if (!child
->band
|| !tree
->band
)
2205 tree
= isl_schedule_tree_replace_child(tree
, 0, child
);
2209 isl_schedule_tree_free(child
);
2210 isl_schedule_tree_free(tree
);
2214 /* Attach "tree2" at each of the leaves of "tree1".
2216 * If "tree1" does not have any explicit children, then make "tree2"
2217 * its single child. Otherwise, attach "tree2" to the leaves of
2218 * each of the children of "tree1".
2220 __isl_give isl_schedule_tree
*isl_schedule_tree_append_to_leaves(
2221 __isl_take isl_schedule_tree
*tree1
,
2222 __isl_take isl_schedule_tree
*tree2
)
2226 if (!tree1
|| !tree2
)
2228 n
= isl_schedule_tree_n_children(tree1
);
2230 isl_schedule_tree_list
*list
;
2231 list
= isl_schedule_tree_list_from_schedule_tree(tree2
);
2232 tree1
= isl_schedule_tree_set_children(tree1
, list
);
2235 for (i
= 0; i
< n
; ++i
) {
2236 isl_schedule_tree
*child
;
2238 child
= isl_schedule_tree_get_child(tree1
, i
);
2239 child
= isl_schedule_tree_append_to_leaves(child
,
2240 isl_schedule_tree_copy(tree2
));
2241 tree1
= isl_schedule_tree_replace_child(tree1
, i
, child
);
2244 isl_schedule_tree_free(tree2
);
2247 isl_schedule_tree_free(tree1
);
2248 isl_schedule_tree_free(tree2
);
2252 /* Reset the user pointer on all identifiers of parameters and tuples
2253 * in the root of "tree".
2255 __isl_give isl_schedule_tree
*isl_schedule_tree_reset_user(
2256 __isl_take isl_schedule_tree
*tree
)
2258 if (isl_schedule_tree_is_leaf(tree
))
2261 tree
= isl_schedule_tree_cow(tree
);
2265 switch (tree
->type
) {
2266 case isl_schedule_node_error
:
2267 return isl_schedule_tree_free(tree
);
2268 case isl_schedule_node_band
:
2269 tree
->band
= isl_schedule_band_reset_user(tree
->band
);
2271 return isl_schedule_tree_free(tree
);
2273 case isl_schedule_node_context
:
2274 tree
->context
= isl_set_reset_user(tree
->context
);
2276 return isl_schedule_tree_free(tree
);
2278 case isl_schedule_node_domain
:
2279 tree
->domain
= isl_union_set_reset_user(tree
->domain
);
2281 return isl_schedule_tree_free(tree
);
2283 case isl_schedule_node_expansion
:
2285 isl_union_pw_multi_aff_reset_user(tree
->contraction
);
2286 tree
->expansion
= isl_union_map_reset_user(tree
->expansion
);
2287 if (!tree
->contraction
|| !tree
->expansion
)
2288 return isl_schedule_tree_free(tree
);
2290 case isl_schedule_node_extension
:
2291 tree
->extension
= isl_union_map_reset_user(tree
->extension
);
2292 if (!tree
->extension
)
2293 return isl_schedule_tree_free(tree
);
2295 case isl_schedule_node_filter
:
2296 tree
->filter
= isl_union_set_reset_user(tree
->filter
);
2298 return isl_schedule_tree_free(tree
);
2300 case isl_schedule_node_guard
:
2301 tree
->guard
= isl_set_reset_user(tree
->guard
);
2303 return isl_schedule_tree_free(tree
);
2305 case isl_schedule_node_leaf
:
2306 case isl_schedule_node_mark
:
2307 case isl_schedule_node_sequence
:
2308 case isl_schedule_node_set
:
2315 /* Align the parameters of the root of "tree" to those of "space".
2317 __isl_give isl_schedule_tree
*isl_schedule_tree_align_params(
2318 __isl_take isl_schedule_tree
*tree
, __isl_take isl_space
*space
)
2323 if (isl_schedule_tree_is_leaf(tree
)) {
2324 isl_space_free(space
);
2328 tree
= isl_schedule_tree_cow(tree
);
2332 switch (tree
->type
) {
2333 case isl_schedule_node_error
:
2335 case isl_schedule_node_band
:
2336 tree
->band
= isl_schedule_band_align_params(tree
->band
, space
);
2338 return isl_schedule_tree_free(tree
);
2340 case isl_schedule_node_context
:
2341 tree
->context
= isl_set_align_params(tree
->context
, space
);
2343 return isl_schedule_tree_free(tree
);
2345 case isl_schedule_node_domain
:
2346 tree
->domain
= isl_union_set_align_params(tree
->domain
, space
);
2348 return isl_schedule_tree_free(tree
);
2350 case isl_schedule_node_expansion
:
2352 isl_union_pw_multi_aff_align_params(tree
->contraction
,
2353 isl_space_copy(space
));
2354 tree
->expansion
= isl_union_map_align_params(tree
->expansion
,
2356 if (!tree
->contraction
|| !tree
->expansion
)
2357 return isl_schedule_tree_free(tree
);
2359 case isl_schedule_node_extension
:
2360 tree
->extension
= isl_union_map_align_params(tree
->extension
,
2362 if (!tree
->extension
)
2363 return isl_schedule_tree_free(tree
);
2365 case isl_schedule_node_filter
:
2366 tree
->filter
= isl_union_set_align_params(tree
->filter
, space
);
2368 return isl_schedule_tree_free(tree
);
2370 case isl_schedule_node_guard
:
2371 tree
->guard
= isl_set_align_params(tree
->guard
, space
);
2373 return isl_schedule_tree_free(tree
);
2375 case isl_schedule_node_leaf
:
2376 case isl_schedule_node_mark
:
2377 case isl_schedule_node_sequence
:
2378 case isl_schedule_node_set
:
2379 isl_space_free(space
);
2385 isl_space_free(space
);
2386 isl_schedule_tree_free(tree
);
2390 /* Does "tree" involve the iteration domain?
2391 * That is, does it need to be modified
2392 * by isl_schedule_tree_pullback_union_pw_multi_aff?
2394 static int involves_iteration_domain(__isl_keep isl_schedule_tree
*tree
)
2399 switch (tree
->type
) {
2400 case isl_schedule_node_error
:
2402 case isl_schedule_node_band
:
2403 case isl_schedule_node_domain
:
2404 case isl_schedule_node_expansion
:
2405 case isl_schedule_node_extension
:
2406 case isl_schedule_node_filter
:
2408 case isl_schedule_node_context
:
2409 case isl_schedule_node_leaf
:
2410 case isl_schedule_node_guard
:
2411 case isl_schedule_node_mark
:
2412 case isl_schedule_node_sequence
:
2413 case isl_schedule_node_set
:
2417 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
2418 "unhandled case", return -1);
2421 /* Compute the pullback of the root node of "tree" by the function
2422 * represented by "upma".
2423 * In other words, plug in "upma" in the iteration domains of
2424 * the root node of "tree".
2425 * We currently do not handle expansion nodes.
2427 * We first check if the root node involves any iteration domains.
2428 * If so, we handle the specific cases.
2430 __isl_give isl_schedule_tree
*isl_schedule_tree_pullback_union_pw_multi_aff(
2431 __isl_take isl_schedule_tree
*tree
,
2432 __isl_take isl_union_pw_multi_aff
*upma
)
2439 involves
= involves_iteration_domain(tree
);
2443 isl_union_pw_multi_aff_free(upma
);
2447 tree
= isl_schedule_tree_cow(tree
);
2451 if (tree
->type
== isl_schedule_node_band
) {
2452 tree
->band
= isl_schedule_band_pullback_union_pw_multi_aff(
2455 return isl_schedule_tree_free(tree
);
2456 } else if (tree
->type
== isl_schedule_node_domain
) {
2458 isl_union_set_preimage_union_pw_multi_aff(tree
->domain
,
2461 return isl_schedule_tree_free(tree
);
2462 } else if (tree
->type
== isl_schedule_node_expansion
) {
2463 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_unsupported
,
2464 "cannot pullback expansion node", goto error
);
2465 } else if (tree
->type
== isl_schedule_node_extension
) {
2467 isl_union_map_preimage_range_union_pw_multi_aff(
2468 tree
->extension
, upma
);
2469 if (!tree
->extension
)
2470 return isl_schedule_tree_free(tree
);
2471 } else if (tree
->type
== isl_schedule_node_filter
) {
2473 isl_union_set_preimage_union_pw_multi_aff(tree
->filter
,
2476 return isl_schedule_tree_free(tree
);
2481 isl_union_pw_multi_aff_free(upma
);
2482 isl_schedule_tree_free(tree
);
2486 /* Compute the gist of the band tree root with respect to "context".
2488 __isl_give isl_schedule_tree
*isl_schedule_tree_band_gist(
2489 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*context
)
2493 if (tree
->type
!= isl_schedule_node_band
)
2494 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2495 "not a band node", goto error
);
2496 tree
= isl_schedule_tree_cow(tree
);
2500 tree
->band
= isl_schedule_band_gist(tree
->band
, context
);
2502 return isl_schedule_tree_free(tree
);
2505 isl_union_set_free(context
);
2506 isl_schedule_tree_free(tree
);
2510 /* Are any members in "band" marked coincident?
2512 static int any_coincident(__isl_keep isl_schedule_band
*band
)
2516 n
= isl_schedule_band_n_member(band
);
2517 for (i
= 0; i
< n
; ++i
)
2518 if (isl_schedule_band_member_get_coincident(band
, i
))
2524 /* Print the band node "band" to "p".
2526 * The permutable and coincident properties are only printed if they
2527 * are different from the defaults.
2528 * The coincident property is always printed in YAML flow style.
2530 static __isl_give isl_printer
*print_tree_band(__isl_take isl_printer
*p
,
2531 __isl_keep isl_schedule_band
*band
)
2533 isl_union_set
*options
;
2536 p
= isl_printer_print_str(p
, "schedule");
2537 p
= isl_printer_yaml_next(p
);
2538 p
= isl_printer_print_str(p
, "\"");
2539 p
= isl_printer_print_multi_union_pw_aff(p
, band
->mupa
);
2540 p
= isl_printer_print_str(p
, "\"");
2541 if (isl_schedule_band_get_permutable(band
)) {
2542 p
= isl_printer_yaml_next(p
);
2543 p
= isl_printer_print_str(p
, "permutable");
2544 p
= isl_printer_yaml_next(p
);
2545 p
= isl_printer_print_int(p
, 1);
2547 if (any_coincident(band
)) {
2551 p
= isl_printer_yaml_next(p
);
2552 p
= isl_printer_print_str(p
, "coincident");
2553 p
= isl_printer_yaml_next(p
);
2554 style
= isl_printer_get_yaml_style(p
);
2555 p
= isl_printer_set_yaml_style(p
, ISL_YAML_STYLE_FLOW
);
2556 p
= isl_printer_yaml_start_sequence(p
);
2557 n
= isl_schedule_band_n_member(band
);
2558 for (i
= 0; i
< n
; ++i
) {
2559 p
= isl_printer_print_int(p
,
2560 isl_schedule_band_member_get_coincident(band
, i
));
2561 p
= isl_printer_yaml_next(p
);
2563 p
= isl_printer_yaml_end_sequence(p
);
2564 p
= isl_printer_set_yaml_style(p
, style
);
2566 options
= isl_schedule_band_get_ast_build_options(band
);
2567 empty
= isl_union_set_is_empty(options
);
2569 p
= isl_printer_free(p
);
2571 p
= isl_printer_yaml_next(p
);
2572 p
= isl_printer_print_str(p
, "options");
2573 p
= isl_printer_yaml_next(p
);
2574 p
= isl_printer_print_str(p
, "\"");
2575 p
= isl_printer_print_union_set(p
, options
);
2576 p
= isl_printer_print_str(p
, "\"");
2578 isl_union_set_free(options
);
2583 /* Print "tree" to "p".
2585 * If "n_ancestor" is non-negative, then "child_pos" contains the child
2586 * positions of a descendant of the current node that should be marked
2587 * (by the comment "YOU ARE HERE"). In particular, if "n_ancestor"
2588 * is zero, then the current node should be marked.
2589 * The marking is only printed in YAML block format.
2591 * Implicit leaf nodes are not printed, except if they correspond
2592 * to the node that should be marked.
2594 __isl_give isl_printer
*isl_printer_print_schedule_tree_mark(
2595 __isl_take isl_printer
*p
, __isl_keep isl_schedule_tree
*tree
,
2596 int n_ancestor
, int *child_pos
)
2602 block
= isl_printer_get_yaml_style(p
) == ISL_YAML_STYLE_BLOCK
;
2604 p
= isl_printer_yaml_start_mapping(p
);
2605 if (n_ancestor
== 0 && block
) {
2606 p
= isl_printer_print_str(p
, "# YOU ARE HERE");
2607 p
= isl_printer_end_line(p
);
2608 p
= isl_printer_start_line(p
);
2610 switch (tree
->type
) {
2611 case isl_schedule_node_error
:
2612 p
= isl_printer_print_str(p
, "ERROR");
2614 case isl_schedule_node_leaf
:
2615 p
= isl_printer_print_str(p
, "leaf");
2617 case isl_schedule_node_sequence
:
2618 p
= isl_printer_print_str(p
, "sequence");
2621 case isl_schedule_node_set
:
2622 p
= isl_printer_print_str(p
, "set");
2625 case isl_schedule_node_context
:
2626 p
= isl_printer_print_str(p
, "context");
2627 p
= isl_printer_yaml_next(p
);
2628 p
= isl_printer_print_str(p
, "\"");
2629 p
= isl_printer_print_set(p
, tree
->context
);
2630 p
= isl_printer_print_str(p
, "\"");
2632 case isl_schedule_node_domain
:
2633 p
= isl_printer_print_str(p
, "domain");
2634 p
= isl_printer_yaml_next(p
);
2635 p
= isl_printer_print_str(p
, "\"");
2636 p
= isl_printer_print_union_set(p
, tree
->domain
);
2637 p
= isl_printer_print_str(p
, "\"");
2639 case isl_schedule_node_expansion
:
2640 p
= isl_printer_print_str(p
, "contraction");
2641 p
= isl_printer_yaml_next(p
);
2642 p
= isl_printer_print_str(p
, "\"");
2643 p
= isl_printer_print_union_pw_multi_aff(p
, tree
->contraction
);
2644 p
= isl_printer_print_str(p
, "\"");
2645 p
= isl_printer_yaml_next(p
);
2646 p
= isl_printer_print_str(p
, "expansion");
2647 p
= isl_printer_yaml_next(p
);
2648 p
= isl_printer_print_str(p
, "\"");
2649 p
= isl_printer_print_union_map(p
, tree
->expansion
);
2650 p
= isl_printer_print_str(p
, "\"");
2652 case isl_schedule_node_extension
:
2653 p
= isl_printer_print_str(p
, "extension");
2654 p
= isl_printer_yaml_next(p
);
2655 p
= isl_printer_print_str(p
, "\"");
2656 p
= isl_printer_print_union_map(p
, tree
->extension
);
2657 p
= isl_printer_print_str(p
, "\"");
2659 case isl_schedule_node_filter
:
2660 p
= isl_printer_print_str(p
, "filter");
2661 p
= isl_printer_yaml_next(p
);
2662 p
= isl_printer_print_str(p
, "\"");
2663 p
= isl_printer_print_union_set(p
, tree
->filter
);
2664 p
= isl_printer_print_str(p
, "\"");
2666 case isl_schedule_node_guard
:
2667 p
= isl_printer_print_str(p
, "guard");
2668 p
= isl_printer_yaml_next(p
);
2669 p
= isl_printer_print_str(p
, "\"");
2670 p
= isl_printer_print_set(p
, tree
->guard
);
2671 p
= isl_printer_print_str(p
, "\"");
2673 case isl_schedule_node_mark
:
2674 p
= isl_printer_print_str(p
, "mark");
2675 p
= isl_printer_yaml_next(p
);
2676 p
= isl_printer_print_str(p
, "\"");
2677 p
= isl_printer_print_str(p
, isl_id_get_name(tree
->mark
));
2678 p
= isl_printer_print_str(p
, "\"");
2680 case isl_schedule_node_band
:
2681 p
= print_tree_band(p
, tree
->band
);
2684 p
= isl_printer_yaml_next(p
);
2686 if (!tree
->children
) {
2687 if (n_ancestor
> 0 && block
) {
2688 isl_schedule_tree
*leaf
;
2690 p
= isl_printer_print_str(p
, "child");
2691 p
= isl_printer_yaml_next(p
);
2692 leaf
= isl_schedule_tree_leaf(isl_printer_get_ctx(p
));
2693 p
= isl_printer_print_schedule_tree_mark(p
,
2695 isl_schedule_tree_free(leaf
);
2696 p
= isl_printer_yaml_next(p
);
2698 return isl_printer_yaml_end_mapping(p
);
2702 p
= isl_printer_yaml_start_sequence(p
);
2704 p
= isl_printer_print_str(p
, "child");
2705 p
= isl_printer_yaml_next(p
);
2708 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
2709 for (i
= 0; i
< n
; ++i
) {
2710 isl_schedule_tree
*t
;
2712 t
= isl_schedule_tree_get_child(tree
, i
);
2713 if (n_ancestor
> 0 && child_pos
[0] == i
)
2714 p
= isl_printer_print_schedule_tree_mark(p
, t
,
2715 n_ancestor
- 1, child_pos
+ 1);
2717 p
= isl_printer_print_schedule_tree_mark(p
, t
,
2719 isl_schedule_tree_free(t
);
2721 p
= isl_printer_yaml_next(p
);
2725 p
= isl_printer_yaml_end_sequence(p
);
2726 p
= isl_printer_yaml_end_mapping(p
);
2731 /* Print "tree" to "p".
2733 __isl_give isl_printer
*isl_printer_print_schedule_tree(
2734 __isl_take isl_printer
*p
, __isl_keep isl_schedule_tree
*tree
)
2736 return isl_printer_print_schedule_tree_mark(p
, tree
, -1, NULL
);
2739 void isl_schedule_tree_dump(__isl_keep isl_schedule_tree
*tree
)
2742 isl_printer
*printer
;
2747 ctx
= isl_schedule_tree_get_ctx(tree
);
2748 printer
= isl_printer_to_file(ctx
, stderr
);
2749 printer
= isl_printer_set_yaml_style(printer
, ISL_YAML_STYLE_BLOCK
);
2750 printer
= isl_printer_print_schedule_tree(printer
, tree
);
2752 isl_printer_free(printer
);