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_filter
:
106 dup
->filter
= isl_union_set_copy(tree
->filter
);
108 return isl_schedule_tree_free(dup
);
110 case isl_schedule_node_mark
:
111 dup
->mark
= isl_id_copy(tree
->mark
);
113 return isl_schedule_tree_free(dup
);
115 case isl_schedule_node_leaf
:
116 case isl_schedule_node_sequence
:
117 case isl_schedule_node_set
:
121 if (tree
->children
) {
122 dup
->children
= isl_schedule_tree_list_copy(tree
->children
);
124 return isl_schedule_tree_free(dup
);
126 dup
->anchored
= tree
->anchored
;
131 /* Return an isl_schedule_tree that is equal to "tree" and that has only
132 * a single reference.
134 * This function is called before a tree is modified.
135 * A static tree (with negative reference count) should never be modified,
136 * so it is not allowed to call this function on a static tree.
138 __isl_give isl_schedule_tree
*isl_schedule_tree_cow(
139 __isl_take isl_schedule_tree
*tree
)
145 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
146 "static trees cannot be modified",
147 return isl_schedule_tree_free(tree
));
152 return isl_schedule_tree_dup(tree
);
155 /* Return a new reference to "tree".
157 * A static tree (with negative reference count) does not keep track
158 * of the number of references and should not be modified.
160 __isl_give isl_schedule_tree
*isl_schedule_tree_copy(
161 __isl_keep isl_schedule_tree
*tree
)
173 /* Free "tree" and return NULL.
175 __isl_null isl_schedule_tree
*isl_schedule_tree_free(
176 __isl_take isl_schedule_tree
*tree
)
185 switch (tree
->type
) {
186 case isl_schedule_node_band
:
187 isl_schedule_band_free(tree
->band
);
189 case isl_schedule_node_context
:
190 isl_set_free(tree
->context
);
192 case isl_schedule_node_domain
:
193 isl_union_set_free(tree
->domain
);
195 case isl_schedule_node_expansion
:
196 isl_union_pw_multi_aff_free(tree
->contraction
);
197 isl_union_map_free(tree
->expansion
);
199 case isl_schedule_node_filter
:
200 isl_union_set_free(tree
->filter
);
202 case isl_schedule_node_mark
:
203 isl_id_free(tree
->mark
);
205 case isl_schedule_node_sequence
:
206 case isl_schedule_node_set
:
207 case isl_schedule_node_error
:
208 case isl_schedule_node_leaf
:
211 isl_schedule_tree_list_free(tree
->children
);
212 isl_ctx_deref(tree
->ctx
);
218 /* Create and return a new leaf schedule tree.
220 __isl_give isl_schedule_tree
*isl_schedule_tree_leaf(isl_ctx
*ctx
)
222 return isl_schedule_tree_alloc(ctx
, isl_schedule_node_leaf
);
225 /* Create a new band schedule tree referring to "band"
228 __isl_give isl_schedule_tree
*isl_schedule_tree_from_band(
229 __isl_take isl_schedule_band
*band
)
232 isl_schedule_tree
*tree
;
237 ctx
= isl_schedule_band_get_ctx(band
);
238 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_band
);
243 tree
->anchored
= isl_schedule_band_is_anchored(band
);
247 isl_schedule_band_free(band
);
251 /* Create a new context schedule tree with the given context and no children.
252 * Since the context references the outer schedule dimension,
253 * the tree is anchored.
255 __isl_give isl_schedule_tree
*isl_schedule_tree_from_context(
256 __isl_take isl_set
*context
)
259 isl_schedule_tree
*tree
;
264 ctx
= isl_set_get_ctx(context
);
265 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_context
);
269 tree
->context
= context
;
274 isl_set_free(context
);
278 /* Create a new domain schedule tree with the given domain and no children.
280 __isl_give isl_schedule_tree
*isl_schedule_tree_from_domain(
281 __isl_take isl_union_set
*domain
)
284 isl_schedule_tree
*tree
;
289 ctx
= isl_union_set_get_ctx(domain
);
290 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_domain
);
294 tree
->domain
= domain
;
298 isl_union_set_free(domain
);
302 /* Create a new expansion schedule tree with the given contraction and
303 * expansion and no children.
305 __isl_give isl_schedule_tree
*isl_schedule_tree_from_expansion(
306 __isl_take isl_union_pw_multi_aff
*contraction
,
307 __isl_take isl_union_map
*expansion
)
310 isl_schedule_tree
*tree
;
312 if (!contraction
|| !expansion
)
315 ctx
= isl_union_map_get_ctx(expansion
);
316 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_expansion
);
320 tree
->contraction
= contraction
;
321 tree
->expansion
= expansion
;
325 isl_union_pw_multi_aff_free(contraction
);
326 isl_union_map_free(expansion
);
330 /* Create a new filter schedule tree with the given filter and no children.
332 __isl_give isl_schedule_tree
*isl_schedule_tree_from_filter(
333 __isl_take isl_union_set
*filter
)
336 isl_schedule_tree
*tree
;
341 ctx
= isl_union_set_get_ctx(filter
);
342 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_filter
);
346 tree
->filter
= filter
;
350 isl_union_set_free(filter
);
354 /* Create a new mark schedule tree with the given mark identifier and
357 __isl_give isl_schedule_tree
*isl_schedule_tree_from_mark(
358 __isl_take isl_id
*mark
)
361 isl_schedule_tree
*tree
;
366 ctx
= isl_id_get_ctx(mark
);
367 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_mark
);
379 /* Does "tree" have any node that depends on its position
380 * in the complete schedule tree?
382 int isl_schedule_tree_is_subtree_anchored(__isl_keep isl_schedule_tree
*tree
)
384 return tree
? tree
->anchored
: -1;
387 /* Does the root node of "tree" depend on its position in the complete
389 * Band nodes may be anchored depending on the associated AST build options.
390 * Context nodes are always anchored.
392 int isl_schedule_tree_is_anchored(__isl_keep isl_schedule_tree
*tree
)
397 switch (isl_schedule_tree_get_type(tree
)) {
398 case isl_schedule_node_error
:
400 case isl_schedule_node_band
:
401 return isl_schedule_band_is_anchored(tree
->band
);
402 case isl_schedule_node_context
:
404 case isl_schedule_node_domain
:
405 case isl_schedule_node_expansion
:
406 case isl_schedule_node_filter
:
407 case isl_schedule_node_leaf
:
408 case isl_schedule_node_mark
:
409 case isl_schedule_node_sequence
:
410 case isl_schedule_node_set
:
415 /* Update the anchored field of "tree" based on whether the root node
416 * itself in anchored and the anchored fields of the children.
418 * This function should be called whenever the children of a tree node
419 * are changed or the anchoredness of the tree root itself changes.
421 __isl_give isl_schedule_tree
*isl_schedule_tree_update_anchored(
422 __isl_take isl_schedule_tree
*tree
)
430 anchored
= isl_schedule_tree_is_anchored(tree
);
432 return isl_schedule_tree_free(tree
);
434 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
435 for (i
= 0; !anchored
&& i
< n
; ++i
) {
436 isl_schedule_tree
*child
;
438 child
= isl_schedule_tree_get_child(tree
, i
);
440 return isl_schedule_tree_free(tree
);
441 anchored
= child
->anchored
;
442 isl_schedule_tree_free(child
);
445 if (anchored
== tree
->anchored
)
447 tree
= isl_schedule_tree_cow(tree
);
450 tree
->anchored
= anchored
;
454 /* Create a new tree of the given type (isl_schedule_node_sequence or
455 * isl_schedule_node_set) with the given children.
457 __isl_give isl_schedule_tree
*isl_schedule_tree_from_children(
458 enum isl_schedule_node_type type
,
459 __isl_take isl_schedule_tree_list
*list
)
462 isl_schedule_tree
*tree
;
467 ctx
= isl_schedule_tree_list_get_ctx(list
);
468 tree
= isl_schedule_tree_alloc(ctx
, type
);
472 tree
->children
= list
;
473 tree
= isl_schedule_tree_update_anchored(tree
);
477 isl_schedule_tree_list_free(list
);
481 /* Construct a tree with a root node of type "type" and as children
482 * "tree1" and "tree2".
483 * If the root of one (or both) of the input trees is itself of type "type",
484 * then the tree is replaced by its children.
486 __isl_give isl_schedule_tree
*isl_schedule_tree_from_pair(
487 enum isl_schedule_node_type type
, __isl_take isl_schedule_tree
*tree1
,
488 __isl_take isl_schedule_tree
*tree2
)
491 isl_schedule_tree_list
*list
;
493 if (!tree1
|| !tree2
)
496 ctx
= isl_schedule_tree_get_ctx(tree1
);
497 if (isl_schedule_tree_get_type(tree1
) == type
) {
498 list
= isl_schedule_tree_list_copy(tree1
->children
);
499 isl_schedule_tree_free(tree1
);
501 list
= isl_schedule_tree_list_alloc(ctx
, 2);
502 list
= isl_schedule_tree_list_add(list
, tree1
);
504 if (isl_schedule_tree_get_type(tree2
) == type
) {
505 isl_schedule_tree_list
*children
;
507 children
= isl_schedule_tree_list_copy(tree2
->children
);
508 list
= isl_schedule_tree_list_concat(list
, children
);
509 isl_schedule_tree_free(tree2
);
511 list
= isl_schedule_tree_list_add(list
, tree2
);
514 return isl_schedule_tree_from_children(type
, list
);
516 isl_schedule_tree_free(tree1
);
517 isl_schedule_tree_free(tree2
);
521 /* Return the isl_ctx to which "tree" belongs.
523 isl_ctx
*isl_schedule_tree_get_ctx(__isl_keep isl_schedule_tree
*tree
)
525 return tree
? tree
->ctx
: NULL
;
528 /* Return the type of the root of the tree or isl_schedule_node_error
531 enum isl_schedule_node_type
isl_schedule_tree_get_type(
532 __isl_keep isl_schedule_tree
*tree
)
534 return tree
? tree
->type
: isl_schedule_node_error
;
537 /* Are "tree1" and "tree2" obviously equal to each other?
539 int isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree
*tree1
,
540 __isl_keep isl_schedule_tree
*tree2
)
545 if (!tree1
|| !tree2
)
549 if (tree1
->type
!= tree2
->type
)
552 switch (tree1
->type
) {
553 case isl_schedule_node_band
:
554 equal
= isl_schedule_band_plain_is_equal(tree1
->band
,
557 case isl_schedule_node_context
:
558 equal
= isl_set_is_equal(tree1
->context
, tree2
->context
);
560 case isl_schedule_node_domain
:
561 equal
= isl_union_set_is_equal(tree1
->domain
, tree2
->domain
);
563 case isl_schedule_node_expansion
:
564 equal
= isl_union_map_is_equal(tree1
->expansion
,
566 if (equal
>= 0 && equal
)
567 equal
= isl_union_pw_multi_aff_plain_is_equal(
568 tree1
->contraction
, tree2
->contraction
);
570 case isl_schedule_node_filter
:
571 equal
= isl_union_set_is_equal(tree1
->filter
, tree2
->filter
);
573 case isl_schedule_node_mark
:
574 equal
= tree1
->mark
== tree2
->mark
;
576 case isl_schedule_node_leaf
:
577 case isl_schedule_node_sequence
:
578 case isl_schedule_node_set
:
581 case isl_schedule_node_error
:
586 if (equal
< 0 || !equal
)
589 n
= isl_schedule_tree_n_children(tree1
);
590 if (n
!= isl_schedule_tree_n_children(tree2
))
592 for (i
= 0; i
< n
; ++i
) {
593 isl_schedule_tree
*child1
, *child2
;
595 child1
= isl_schedule_tree_get_child(tree1
, i
);
596 child2
= isl_schedule_tree_get_child(tree2
, i
);
597 equal
= isl_schedule_tree_plain_is_equal(child1
, child2
);
598 isl_schedule_tree_free(child1
);
599 isl_schedule_tree_free(child2
);
601 if (equal
< 0 || !equal
)
608 /* Does "tree" have any children, other than an implicit leaf.
610 int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree
*tree
)
615 return tree
->children
!= NULL
;
618 /* Return the number of children of "tree", excluding implicit leaves.
620 int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree
*tree
)
625 return isl_schedule_tree_list_n_schedule_tree(tree
->children
);
628 /* Return a copy of the (explicit) child at position "pos" of "tree".
630 __isl_give isl_schedule_tree
*isl_schedule_tree_get_child(
631 __isl_keep isl_schedule_tree
*tree
, int pos
)
636 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
637 "schedule tree has no explicit children", return NULL
);
638 return isl_schedule_tree_list_get_schedule_tree(tree
->children
, pos
);
641 /* Return a copy of the (explicit) child at position "pos" of "tree" and
644 __isl_give isl_schedule_tree
*isl_schedule_tree_child(
645 __isl_take isl_schedule_tree
*tree
, int pos
)
647 isl_schedule_tree
*child
;
649 child
= isl_schedule_tree_get_child(tree
, pos
);
650 isl_schedule_tree_free(tree
);
654 /* Remove all (explicit) children from "tree".
656 __isl_give isl_schedule_tree
*isl_schedule_tree_reset_children(
657 __isl_take isl_schedule_tree
*tree
)
659 tree
= isl_schedule_tree_cow(tree
);
662 tree
->children
= isl_schedule_tree_list_free(tree
->children
);
666 /* Remove the child at position "pos" from the children of "tree".
667 * If there was only one child to begin with, then remove all children.
669 __isl_give isl_schedule_tree
*isl_schedule_tree_drop_child(
670 __isl_take isl_schedule_tree
*tree
, int pos
)
674 tree
= isl_schedule_tree_cow(tree
);
678 if (!isl_schedule_tree_has_children(tree
))
679 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
680 "tree does not have any explicit children",
681 return isl_schedule_tree_free(tree
));
682 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
683 if (pos
< 0 || pos
>= n
)
684 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
685 "position out of bounds",
686 return isl_schedule_tree_free(tree
));
688 return isl_schedule_tree_reset_children(tree
);
690 tree
->children
= isl_schedule_tree_list_drop(tree
->children
, pos
, 1);
692 return isl_schedule_tree_free(tree
);
697 /* Replace the child at position "pos" of "tree" by "child".
699 * If the new child is a leaf, then it is not explicitly
700 * recorded in the list of children. Instead, the list of children
701 * (which is assumed to have only one element) is removed.
702 * Note that the children of set and sequence nodes are always
703 * filters, so they cannot be replaced by empty trees.
705 __isl_give isl_schedule_tree
*isl_schedule_tree_replace_child(
706 __isl_take isl_schedule_tree
*tree
, int pos
,
707 __isl_take isl_schedule_tree
*child
)
709 tree
= isl_schedule_tree_cow(tree
);
713 if (isl_schedule_tree_is_leaf(child
)) {
714 isl_schedule_tree_free(child
);
715 if (!tree
->children
&& pos
== 0)
717 if (isl_schedule_tree_n_children(tree
) != 1)
718 isl_die(isl_schedule_tree_get_ctx(tree
),
720 "can only replace single child by leaf",
722 return isl_schedule_tree_reset_children(tree
);
725 if (!tree
->children
&& pos
== 0)
727 isl_schedule_tree_list_from_schedule_tree(child
);
729 tree
->children
= isl_schedule_tree_list_set_schedule_tree(
730 tree
->children
, pos
, child
);
733 return isl_schedule_tree_free(tree
);
734 tree
= isl_schedule_tree_update_anchored(tree
);
738 isl_schedule_tree_free(tree
);
739 isl_schedule_tree_free(child
);
743 /* Replace the (explicit) children of "tree" by "children"?
745 __isl_give isl_schedule_tree
*isl_schedule_tree_set_children(
746 __isl_take isl_schedule_tree
*tree
,
747 __isl_take isl_schedule_tree_list
*children
)
749 tree
= isl_schedule_tree_cow(tree
);
750 if (!tree
|| !children
)
752 isl_schedule_tree_list_free(tree
->children
);
753 tree
->children
= children
;
756 isl_schedule_tree_free(tree
);
757 isl_schedule_tree_list_free(children
);
761 /* Create a new band schedule tree referring to "band"
762 * with "tree" as single child.
764 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_band(
765 __isl_take isl_schedule_tree
*tree
, __isl_take isl_schedule_band
*band
)
767 isl_schedule_tree
*res
;
769 res
= isl_schedule_tree_from_band(band
);
770 return isl_schedule_tree_replace_child(res
, 0, tree
);
773 /* Create a new context schedule tree with the given context and
774 * with "tree" as single child.
776 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_context(
777 __isl_take isl_schedule_tree
*tree
, __isl_take isl_set
*context
)
779 isl_schedule_tree
*res
;
781 res
= isl_schedule_tree_from_context(context
);
782 return isl_schedule_tree_replace_child(res
, 0, tree
);
785 /* Create a new domain schedule tree with the given domain and
786 * with "tree" as single child.
788 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_domain(
789 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
791 isl_schedule_tree
*res
;
793 res
= isl_schedule_tree_from_domain(domain
);
794 return isl_schedule_tree_replace_child(res
, 0, tree
);
797 /* Create a new expansion schedule tree with the given contraction and
798 * expansion and with "tree" as single child.
800 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_expansion(
801 __isl_take isl_schedule_tree
*tree
,
802 __isl_take isl_union_pw_multi_aff
*contraction
,
803 __isl_take isl_union_map
*expansion
)
805 isl_schedule_tree
*res
;
807 res
= isl_schedule_tree_from_expansion(contraction
, expansion
);
808 return isl_schedule_tree_replace_child(res
, 0, tree
);
811 /* Create a new filter schedule tree with the given filter and single child.
813 * If the root of "tree" is itself a filter node, then the two
814 * filter nodes are merged into one node.
816 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_filter(
817 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
819 isl_schedule_tree
*res
;
821 if (isl_schedule_tree_get_type(tree
) == isl_schedule_node_filter
) {
822 isl_union_set
*tree_filter
;
824 tree_filter
= isl_schedule_tree_filter_get_filter(tree
);
825 tree_filter
= isl_union_set_intersect(tree_filter
, filter
);
826 tree
= isl_schedule_tree_filter_set_filter(tree
, tree_filter
);
830 res
= isl_schedule_tree_from_filter(filter
);
831 return isl_schedule_tree_replace_child(res
, 0, tree
);
834 /* Insert a filter node with filter set "filter"
835 * in each of the children of "tree".
837 __isl_give isl_schedule_tree
*isl_schedule_tree_children_insert_filter(
838 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
842 if (!tree
|| !filter
)
845 n
= isl_schedule_tree_n_children(tree
);
846 for (i
= 0; i
< n
; ++i
) {
847 isl_schedule_tree
*child
;
849 child
= isl_schedule_tree_get_child(tree
, i
);
850 child
= isl_schedule_tree_insert_filter(child
,
851 isl_union_set_copy(filter
));
852 tree
= isl_schedule_tree_replace_child(tree
, i
, child
);
855 isl_union_set_free(filter
);
858 isl_union_set_free(filter
);
859 isl_schedule_tree_free(tree
);
863 /* Create a new mark schedule tree with the given mark identifier and
866 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_mark(
867 __isl_take isl_schedule_tree
*tree
, __isl_take isl_id
*mark
)
869 isl_schedule_tree
*res
;
871 res
= isl_schedule_tree_from_mark(mark
);
872 return isl_schedule_tree_replace_child(res
, 0, tree
);
875 /* Return the number of members in the band tree root.
877 unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree
*tree
)
882 if (tree
->type
!= isl_schedule_node_band
)
883 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
884 "not a band node", return 0);
886 return isl_schedule_band_n_member(tree
->band
);
889 /* Is the band member at position "pos" of the band tree root
892 int isl_schedule_tree_band_member_get_coincident(
893 __isl_keep isl_schedule_tree
*tree
, int pos
)
898 if (tree
->type
!= isl_schedule_node_band
)
899 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
900 "not a band node", return -1);
902 return isl_schedule_band_member_get_coincident(tree
->band
, pos
);
905 /* Mark the given band member as being coincident or not
906 * according to "coincident".
908 __isl_give isl_schedule_tree
*isl_schedule_tree_band_member_set_coincident(
909 __isl_take isl_schedule_tree
*tree
, int pos
, int coincident
)
913 if (tree
->type
!= isl_schedule_node_band
)
914 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
915 "not a band node", return isl_schedule_tree_free(tree
));
916 if (isl_schedule_tree_band_member_get_coincident(tree
, pos
) ==
919 tree
= isl_schedule_tree_cow(tree
);
923 tree
->band
= isl_schedule_band_member_set_coincident(tree
->band
, pos
,
926 return isl_schedule_tree_free(tree
);
930 /* Is the band tree root marked permutable?
932 int isl_schedule_tree_band_get_permutable(__isl_keep isl_schedule_tree
*tree
)
937 if (tree
->type
!= isl_schedule_node_band
)
938 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
939 "not a band node", return -1);
941 return isl_schedule_band_get_permutable(tree
->band
);
944 /* Mark the band tree root permutable or not according to "permutable"?
946 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_permutable(
947 __isl_take isl_schedule_tree
*tree
, int permutable
)
951 if (tree
->type
!= isl_schedule_node_band
)
952 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
953 "not a band node", return isl_schedule_tree_free(tree
));
954 if (isl_schedule_tree_band_get_permutable(tree
) == permutable
)
956 tree
= isl_schedule_tree_cow(tree
);
960 tree
->band
= isl_schedule_band_set_permutable(tree
->band
, permutable
);
962 return isl_schedule_tree_free(tree
);
966 /* Return the schedule space of the band tree root.
968 __isl_give isl_space
*isl_schedule_tree_band_get_space(
969 __isl_keep isl_schedule_tree
*tree
)
974 if (tree
->type
!= isl_schedule_node_band
)
975 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
976 "not a band node", return NULL
);
978 return isl_schedule_band_get_space(tree
->band
);
981 /* Intersect the domain of the band schedule of the band tree root
984 __isl_give isl_schedule_tree
*isl_schedule_tree_band_intersect_domain(
985 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
987 if (!tree
|| !domain
)
990 if (tree
->type
!= isl_schedule_node_band
)
991 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
992 "not a band node", goto error
);
994 tree
->band
= isl_schedule_band_intersect_domain(tree
->band
, domain
);
996 return isl_schedule_tree_free(tree
);
1000 isl_schedule_tree_free(tree
);
1001 isl_union_set_free(domain
);
1005 /* Return the schedule of the band tree root in isolation.
1007 __isl_give isl_multi_union_pw_aff
*isl_schedule_tree_band_get_partial_schedule(
1008 __isl_keep isl_schedule_tree
*tree
)
1013 if (tree
->type
!= isl_schedule_node_band
)
1014 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1015 "not a band node", return NULL
);
1017 return isl_schedule_band_get_partial_schedule(tree
->band
);
1020 /* Replace the schedule of the band tree root by "schedule".
1022 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_partial_schedule(
1023 __isl_take isl_schedule_tree
*tree
,
1024 __isl_take isl_multi_union_pw_aff
*schedule
)
1026 tree
= isl_schedule_tree_cow(tree
);
1027 if (!tree
|| !schedule
)
1030 if (tree
->type
!= isl_schedule_node_band
)
1031 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1032 "not a band node", return NULL
);
1033 tree
->band
= isl_schedule_band_set_partial_schedule(tree
->band
,
1038 isl_schedule_tree_free(tree
);
1039 isl_multi_union_pw_aff_free(schedule
);
1043 /* Return the loop AST generation type for the band member
1044 * of the band tree root at position "pos".
1046 enum isl_ast_loop_type
isl_schedule_tree_band_member_get_ast_loop_type(
1047 __isl_keep isl_schedule_tree
*tree
, int pos
)
1050 return isl_ast_loop_error
;
1052 if (tree
->type
!= isl_schedule_node_band
)
1053 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1054 "not a band node", return isl_ast_loop_error
);
1056 return isl_schedule_band_member_get_ast_loop_type(tree
->band
, pos
);
1059 /* Set the loop AST generation type for the band member of the band tree root
1060 * at position "pos" to "type".
1062 __isl_give isl_schedule_tree
*isl_schedule_tree_band_member_set_ast_loop_type(
1063 __isl_take isl_schedule_tree
*tree
, int pos
,
1064 enum isl_ast_loop_type type
)
1066 tree
= isl_schedule_tree_cow(tree
);
1070 if (tree
->type
!= isl_schedule_node_band
)
1071 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1072 "not a band node", return isl_schedule_tree_free(tree
));
1074 tree
->band
= isl_schedule_band_member_set_ast_loop_type(tree
->band
,
1077 return isl_schedule_tree_free(tree
);
1082 /* Return the loop AST generation type for the band member
1083 * of the band tree root at position "pos" for the isolated part.
1085 enum isl_ast_loop_type
isl_schedule_tree_band_member_get_isolate_ast_loop_type(
1086 __isl_keep isl_schedule_tree
*tree
, int pos
)
1089 return isl_ast_loop_error
;
1091 if (tree
->type
!= isl_schedule_node_band
)
1092 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1093 "not a band node", return isl_ast_loop_error
);
1095 return isl_schedule_band_member_get_isolate_ast_loop_type(tree
->band
,
1099 /* Set the loop AST generation type for the band member of the band tree root
1100 * at position "pos" for the isolated part to "type".
1102 __isl_give isl_schedule_tree
*
1103 isl_schedule_tree_band_member_set_isolate_ast_loop_type(
1104 __isl_take isl_schedule_tree
*tree
, int pos
,
1105 enum isl_ast_loop_type type
)
1107 tree
= isl_schedule_tree_cow(tree
);
1111 if (tree
->type
!= isl_schedule_node_band
)
1112 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1113 "not a band node", return isl_schedule_tree_free(tree
));
1115 tree
->band
= isl_schedule_band_member_set_isolate_ast_loop_type(
1116 tree
->band
, pos
, type
);
1118 return isl_schedule_tree_free(tree
);
1123 /* Return the AST build options associated to the band tree root.
1125 __isl_give isl_union_set
*isl_schedule_tree_band_get_ast_build_options(
1126 __isl_keep isl_schedule_tree
*tree
)
1131 if (tree
->type
!= isl_schedule_node_band
)
1132 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1133 "not a band node", return NULL
);
1135 return isl_schedule_band_get_ast_build_options(tree
->band
);
1138 /* Replace the AST build options associated to band tree root by "options".
1139 * Updated the anchored field if the anchoredness of the root node itself
1142 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_ast_build_options(
1143 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*options
)
1147 tree
= isl_schedule_tree_cow(tree
);
1148 if (!tree
|| !options
)
1151 if (tree
->type
!= isl_schedule_node_band
)
1152 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1153 "not a band node", goto error
);
1155 was_anchored
= isl_schedule_tree_is_anchored(tree
);
1156 tree
->band
= isl_schedule_band_set_ast_build_options(tree
->band
,
1159 return isl_schedule_tree_free(tree
);
1160 if (isl_schedule_tree_is_anchored(tree
) != was_anchored
)
1161 tree
= isl_schedule_tree_update_anchored(tree
);
1165 isl_schedule_tree_free(tree
);
1166 isl_union_set_free(options
);
1170 /* Return the context of the context tree root.
1172 __isl_give isl_set
*isl_schedule_tree_context_get_context(
1173 __isl_keep isl_schedule_tree
*tree
)
1178 if (tree
->type
!= isl_schedule_node_context
)
1179 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1180 "not a context node", return NULL
);
1182 return isl_set_copy(tree
->context
);
1185 /* Return the domain of the domain tree root.
1187 __isl_give isl_union_set
*isl_schedule_tree_domain_get_domain(
1188 __isl_keep isl_schedule_tree
*tree
)
1193 if (tree
->type
!= isl_schedule_node_domain
)
1194 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1195 "not a domain node", return NULL
);
1197 return isl_union_set_copy(tree
->domain
);
1200 /* Replace the domain of domain tree root "tree" by "domain".
1202 __isl_give isl_schedule_tree
*isl_schedule_tree_domain_set_domain(
1203 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
1205 tree
= isl_schedule_tree_cow(tree
);
1206 if (!tree
|| !domain
)
1209 if (tree
->type
!= isl_schedule_node_domain
)
1210 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1211 "not a domain node", goto error
);
1213 isl_union_set_free(tree
->domain
);
1214 tree
->domain
= domain
;
1218 isl_schedule_tree_free(tree
);
1219 isl_union_set_free(domain
);
1223 /* Return the contraction of the expansion tree root.
1225 __isl_give isl_union_pw_multi_aff
*isl_schedule_tree_expansion_get_contraction(
1226 __isl_keep isl_schedule_tree
*tree
)
1231 if (tree
->type
!= isl_schedule_node_expansion
)
1232 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1233 "not an expansion node", return NULL
);
1235 return isl_union_pw_multi_aff_copy(tree
->contraction
);
1238 /* Return the expansion of the expansion tree root.
1240 __isl_give isl_union_map
*isl_schedule_tree_expansion_get_expansion(
1241 __isl_keep isl_schedule_tree
*tree
)
1246 if (tree
->type
!= isl_schedule_node_expansion
)
1247 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1248 "not an expansion node", return NULL
);
1250 return isl_union_map_copy(tree
->expansion
);
1253 /* Replace the contraction and the expansion of the expansion tree root "tree"
1254 * by "contraction" and "expansion".
1256 __isl_give isl_schedule_tree
*
1257 isl_schedule_tree_expansion_set_contraction_and_expansion(
1258 __isl_take isl_schedule_tree
*tree
,
1259 __isl_take isl_union_pw_multi_aff
*contraction
,
1260 __isl_take isl_union_map
*expansion
)
1262 tree
= isl_schedule_tree_cow(tree
);
1263 if (!tree
|| !contraction
|| !expansion
)
1266 if (tree
->type
!= isl_schedule_node_expansion
)
1267 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1268 "not an expansion node", return NULL
);
1270 isl_union_pw_multi_aff_free(tree
->contraction
);
1271 tree
->contraction
= contraction
;
1272 isl_union_map_free(tree
->expansion
);
1273 tree
->expansion
= expansion
;
1277 isl_schedule_tree_free(tree
);
1278 isl_union_pw_multi_aff_free(contraction
);
1279 isl_union_map_free(expansion
);
1283 /* Return the filter of the filter tree root.
1285 __isl_give isl_union_set
*isl_schedule_tree_filter_get_filter(
1286 __isl_keep isl_schedule_tree
*tree
)
1291 if (tree
->type
!= isl_schedule_node_filter
)
1292 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1293 "not a filter node", return NULL
);
1295 return isl_union_set_copy(tree
->filter
);
1298 /* Replace the filter of the filter tree root by "filter".
1300 __isl_give isl_schedule_tree
*isl_schedule_tree_filter_set_filter(
1301 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
1303 tree
= isl_schedule_tree_cow(tree
);
1304 if (!tree
|| !filter
)
1307 if (tree
->type
!= isl_schedule_node_filter
)
1308 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1309 "not a filter node", return NULL
);
1311 isl_union_set_free(tree
->filter
);
1312 tree
->filter
= filter
;
1316 isl_schedule_tree_free(tree
);
1317 isl_union_set_free(filter
);
1321 /* Return the mark identifier of the mark tree root "tree".
1323 __isl_give isl_id
*isl_schedule_tree_mark_get_id(
1324 __isl_keep isl_schedule_tree
*tree
)
1329 if (tree
->type
!= isl_schedule_node_mark
)
1330 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1331 "not a mark node", return NULL
);
1333 return isl_id_copy(tree
->mark
);
1336 /* Set dim to the range dimension of "map" and abort the search.
1338 static int set_range_dim(__isl_take isl_map
*map
, void *user
)
1342 *dim
= isl_map_dim(map
, isl_dim_out
);
1348 /* Return the dimension of the range of "umap".
1349 * "umap" is assumed not to be empty and
1350 * all maps inside "umap" are assumed to have the same range.
1352 * We extract the range dimension from the first map in "umap".
1354 static int range_dim(__isl_keep isl_union_map
*umap
)
1360 if (isl_union_map_n_map(umap
) == 0)
1361 isl_die(isl_union_map_get_ctx(umap
), isl_error_internal
,
1362 "unexpected empty input", return -1);
1364 isl_union_map_foreach_map(umap
, &set_range_dim
, &dim
);
1369 /* Append an "extra" number of zeros to the range of "umap" and
1370 * return the result.
1372 static __isl_give isl_union_map
*append_range(__isl_take isl_union_map
*umap
,
1378 isl_union_pw_multi_aff
*suffix
;
1379 isl_union_map
*universe
;
1380 isl_union_map
*suffix_umap
;
1382 universe
= isl_union_map_universe(isl_union_map_copy(umap
));
1383 dom
= isl_union_map_domain(universe
);
1384 space
= isl_union_set_get_space(dom
);
1385 space
= isl_space_set_from_params(space
);
1386 space
= isl_space_add_dims(space
, isl_dim_set
, extra
);
1387 mv
= isl_multi_val_zero(space
);
1389 suffix
= isl_union_pw_multi_aff_multi_val_on_domain(dom
, mv
);
1390 suffix_umap
= isl_union_map_from_union_pw_multi_aff(suffix
);
1391 umap
= isl_union_map_flat_range_product(umap
, suffix_umap
);
1396 /* Should we skip the root of "tree" while looking for the first
1397 * descendant with schedule information?
1398 * That is, is it impossible to derive any information about
1399 * the iteration domain from this node?
1401 * We do not want to skip leaf or error nodes because there is
1402 * no point in looking any deeper from these nodes.
1404 static int domain_less(__isl_keep isl_schedule_tree
*tree
)
1406 enum isl_schedule_node_type type
;
1408 type
= isl_schedule_tree_get_type(tree
);
1410 case isl_schedule_node_band
:
1411 return isl_schedule_tree_band_n_member(tree
) == 0;
1412 case isl_schedule_node_context
:
1413 case isl_schedule_node_mark
:
1415 case isl_schedule_node_leaf
:
1416 case isl_schedule_node_error
:
1417 case isl_schedule_node_domain
:
1418 case isl_schedule_node_expansion
:
1419 case isl_schedule_node_filter
:
1420 case isl_schedule_node_set
:
1421 case isl_schedule_node_sequence
:
1426 /* Move down to the first descendant of "tree" that contains any schedule
1427 * information or return "leaf" if there is no such descendant.
1429 __isl_give isl_schedule_tree
*isl_schedule_tree_first_schedule_descendant(
1430 __isl_take isl_schedule_tree
*tree
, __isl_keep isl_schedule_tree
*leaf
)
1432 while (domain_less(tree
)) {
1433 if (!isl_schedule_tree_has_children(tree
)) {
1434 isl_schedule_tree_free(tree
);
1435 return isl_schedule_tree_copy(leaf
);
1437 tree
= isl_schedule_tree_child(tree
, 0);
1443 static __isl_give isl_union_map
*subtree_schedule_extend(
1444 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
);
1446 /* Extend the schedule map "outer" with the subtree schedule
1447 * of the (single) child of "tree", if any.
1449 * If "tree" does not have any descendants (apart from those that
1450 * do not carry any schedule information), then we simply return "outer".
1451 * Otherwise, we extend the schedule map "outer" with the subtree schedule
1452 * of the single child.
1454 static __isl_give isl_union_map
*subtree_schedule_extend_child(
1455 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1457 isl_schedule_tree
*child
;
1461 return isl_union_map_free(outer
);
1462 if (!isl_schedule_tree_has_children(tree
))
1464 child
= isl_schedule_tree_get_child(tree
, 0);
1466 return isl_union_map_free(outer
);
1467 res
= subtree_schedule_extend(child
, outer
);
1468 isl_schedule_tree_free(child
);
1472 /* Extract the parameter space from one of the children of "tree",
1473 * which are assumed to be filters.
1475 static __isl_give isl_space
*extract_space_from_filter_child(
1476 __isl_keep isl_schedule_tree
*tree
)
1480 isl_schedule_tree
*child
;
1482 child
= isl_schedule_tree_list_get_schedule_tree(tree
->children
, 0);
1483 dom
= isl_schedule_tree_filter_get_filter(child
);
1484 space
= isl_union_set_get_space(dom
);
1485 isl_union_set_free(dom
);
1486 isl_schedule_tree_free(child
);
1491 /* Extend the schedule map "outer" with the subtree schedule
1492 * of a set or sequence node.
1494 * The schedule for the set or sequence node itself is composed of
1495 * pieces of the form
1503 * The first form is used if there is only a single child or
1504 * if the current node is a set node and the schedule_separate_components
1505 * option is not set.
1507 * Each of the pieces above is extended with the subtree schedule of
1508 * the child of the corresponding filter, if any, padded with zeros
1509 * to ensure that all pieces have the same range dimension.
1511 static __isl_give isl_union_map
*subtree_schedule_extend_from_children(
1512 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1521 isl_union_map
*umap
;
1526 ctx
= isl_schedule_tree_get_ctx(tree
);
1527 if (!tree
->children
)
1528 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1529 "missing children", return NULL
);
1530 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
1532 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1533 "missing children", return NULL
);
1535 separate
= n
> 1 && (tree
->type
== isl_schedule_node_sequence
||
1536 isl_options_get_schedule_separate_components(ctx
));
1538 space
= extract_space_from_filter_child(tree
);
1540 umap
= isl_union_map_empty(isl_space_copy(space
));
1541 space
= isl_space_set_from_params(space
);
1543 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
1544 v
= isl_val_zero(ctx
);
1546 mv
= isl_multi_val_zero(space
);
1548 dim
= isl_multi_val_dim(mv
, isl_dim_set
);
1549 for (i
= 0; i
< n
; ++i
) {
1550 isl_union_pw_multi_aff
*upma
;
1551 isl_union_map
*umap_i
;
1553 isl_schedule_tree
*child
;
1557 child
= isl_schedule_tree_list_get_schedule_tree(
1559 dom
= isl_schedule_tree_filter_get_filter(child
);
1562 mv
= isl_multi_val_set_val(mv
, 0, isl_val_copy(v
));
1563 v
= isl_val_add_ui(v
, 1);
1565 upma
= isl_union_pw_multi_aff_multi_val_on_domain(dom
,
1566 isl_multi_val_copy(mv
));
1567 umap_i
= isl_union_map_from_union_pw_multi_aff(upma
);
1568 umap_i
= isl_union_map_flat_range_product(
1569 isl_union_map_copy(outer
), umap_i
);
1570 umap_i
= subtree_schedule_extend_child(child
, umap_i
);
1571 isl_schedule_tree_free(child
);
1573 empty
= isl_union_map_is_empty(umap_i
);
1575 umap_i
= isl_union_map_free(umap_i
);
1577 isl_union_map_free(umap_i
);
1581 dim_i
= range_dim(umap_i
);
1583 umap
= isl_union_map_free(umap
);
1584 } else if (dim
< dim_i
) {
1585 umap
= append_range(umap
, dim_i
- dim
);
1587 } else if (dim_i
< dim
) {
1588 umap_i
= append_range(umap_i
, dim
- dim_i
);
1590 umap
= isl_union_map_union(umap
, umap_i
);
1594 isl_multi_val_free(mv
);
1595 isl_union_map_free(outer
);
1600 /* Extend the schedule map "outer" with the subtree schedule of "tree".
1602 * If the root of the tree is a set or a sequence, then we extend
1603 * the schedule map in subtree_schedule_extend_from_children.
1604 * Otherwise, we extend the schedule map with the partial schedule
1605 * corresponding to the root of the tree and then continue with
1606 * the single child of this root.
1607 * In the special case of an expansion, the schedule map is "extended"
1608 * by applying the expansion to the domain of the schedule map.
1610 static __isl_give isl_union_map
*subtree_schedule_extend(
1611 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1613 isl_multi_union_pw_aff
*mupa
;
1614 isl_union_map
*umap
;
1615 isl_union_set
*domain
;
1620 switch (tree
->type
) {
1621 case isl_schedule_node_error
:
1622 return isl_union_map_free(outer
);
1623 case isl_schedule_node_context
:
1624 case isl_schedule_node_mark
:
1625 return subtree_schedule_extend_child(tree
, outer
);
1626 case isl_schedule_node_band
:
1627 if (isl_schedule_tree_band_n_member(tree
) == 0)
1628 return subtree_schedule_extend_child(tree
, outer
);
1629 mupa
= isl_schedule_band_get_partial_schedule(tree
->band
);
1630 umap
= isl_union_map_from_multi_union_pw_aff(mupa
);
1631 outer
= isl_union_map_flat_range_product(outer
, umap
);
1632 umap
= subtree_schedule_extend_child(tree
, outer
);
1634 case isl_schedule_node_domain
:
1635 domain
= isl_schedule_tree_domain_get_domain(tree
);
1636 umap
= isl_union_map_from_domain(domain
);
1637 outer
= isl_union_map_flat_range_product(outer
, umap
);
1638 umap
= subtree_schedule_extend_child(tree
, outer
);
1640 case isl_schedule_node_expansion
:
1641 umap
= isl_schedule_tree_expansion_get_expansion(tree
);
1642 outer
= isl_union_map_apply_domain(outer
, umap
);
1643 umap
= subtree_schedule_extend_child(tree
, outer
);
1645 case isl_schedule_node_filter
:
1646 domain
= isl_schedule_tree_filter_get_filter(tree
);
1647 umap
= isl_union_map_from_domain(domain
);
1648 outer
= isl_union_map_flat_range_product(outer
, umap
);
1649 umap
= subtree_schedule_extend_child(tree
, outer
);
1651 case isl_schedule_node_leaf
:
1652 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1653 "leaf node should be handled by caller", return NULL
);
1654 case isl_schedule_node_set
:
1655 case isl_schedule_node_sequence
:
1656 umap
= subtree_schedule_extend_from_children(tree
, outer
);
1663 static __isl_give isl_union_set
*initial_domain(
1664 __isl_keep isl_schedule_tree
*tree
);
1666 /* Extract a universe domain from the children of the tree root "tree",
1667 * which is a set or sequence, meaning that its children are filters.
1668 * In particular, return the union of the universes of the filters.
1670 static __isl_give isl_union_set
*initial_domain_from_children(
1671 __isl_keep isl_schedule_tree
*tree
)
1675 isl_union_set
*domain
;
1677 if (!tree
->children
)
1678 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1679 "missing children", return NULL
);
1680 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
1682 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1683 "missing children", return NULL
);
1685 space
= extract_space_from_filter_child(tree
);
1686 domain
= isl_union_set_empty(space
);
1688 for (i
= 0; i
< n
; ++i
) {
1689 isl_schedule_tree
*child
;
1690 isl_union_set
*domain_i
;
1692 child
= isl_schedule_tree_get_child(tree
, i
);
1693 domain_i
= initial_domain(child
);
1694 domain
= isl_union_set_union(domain
, domain_i
);
1695 isl_schedule_tree_free(child
);
1701 /* Extract a universe domain from the tree root "tree".
1702 * The caller is responsible for making sure that this node
1703 * would not be skipped by isl_schedule_tree_first_schedule_descendant
1704 * and that it is not a leaf node.
1706 static __isl_give isl_union_set
*initial_domain(
1707 __isl_keep isl_schedule_tree
*tree
)
1709 isl_multi_union_pw_aff
*mupa
;
1710 isl_union_set
*domain
;
1716 switch (tree
->type
) {
1717 case isl_schedule_node_error
:
1719 case isl_schedule_node_context
:
1720 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1721 "context node should be handled by caller",
1723 case isl_schedule_node_mark
:
1724 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1725 "mark node should be handled by caller",
1727 case isl_schedule_node_band
:
1728 if (isl_schedule_tree_band_n_member(tree
) == 0)
1729 isl_die(isl_schedule_tree_get_ctx(tree
),
1731 "0D band should be handled by caller",
1733 mupa
= isl_schedule_band_get_partial_schedule(tree
->band
);
1734 domain
= isl_multi_union_pw_aff_domain(mupa
);
1735 domain
= isl_union_set_universe(domain
);
1737 case isl_schedule_node_domain
:
1738 domain
= isl_schedule_tree_domain_get_domain(tree
);
1739 domain
= isl_union_set_universe(domain
);
1741 case isl_schedule_node_expansion
:
1742 exp
= isl_schedule_tree_expansion_get_expansion(tree
);
1743 exp
= isl_union_map_universe(exp
);
1744 domain
= isl_union_map_domain(exp
);
1746 case isl_schedule_node_filter
:
1747 domain
= isl_schedule_tree_filter_get_filter(tree
);
1748 domain
= isl_union_set_universe(domain
);
1750 case isl_schedule_node_leaf
:
1751 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1752 "leaf node should be handled by caller", return NULL
);
1753 case isl_schedule_node_set
:
1754 case isl_schedule_node_sequence
:
1755 domain
= initial_domain_from_children(tree
);
1762 /* Return the subtree schedule of a node that contains some schedule
1763 * information, i.e., a node that would not be skipped by
1764 * isl_schedule_tree_first_schedule_descendant and that is not a leaf.
1766 * If the tree contains any expansions, then the returned subtree
1767 * schedule is formulated in terms of the expanded domains.
1769 * We start with an initial zero-dimensional subtree schedule based
1770 * on the domain information in the root node and then extend it
1771 * based on the schedule information in the root node and its descendants.
1773 __isl_give isl_union_map
*isl_schedule_tree_get_subtree_schedule_union_map(
1774 __isl_keep isl_schedule_tree
*tree
)
1776 isl_union_set
*domain
;
1777 isl_union_map
*umap
;
1779 domain
= initial_domain(tree
);
1780 umap
= isl_union_map_from_domain(domain
);
1781 return subtree_schedule_extend(tree
, umap
);
1784 /* Multiply the partial schedule of the band root node of "tree"
1785 * with the factors in "mv".
1787 __isl_give isl_schedule_tree
*isl_schedule_tree_band_scale(
1788 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
1792 if (tree
->type
!= isl_schedule_node_band
)
1793 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1794 "not a band node", goto error
);
1796 tree
= isl_schedule_tree_cow(tree
);
1800 tree
->band
= isl_schedule_band_scale(tree
->band
, mv
);
1802 return isl_schedule_tree_free(tree
);
1806 isl_schedule_tree_free(tree
);
1807 isl_multi_val_free(mv
);
1811 /* Divide the partial schedule of the band root node of "tree"
1812 * by the factors in "mv".
1814 __isl_give isl_schedule_tree
*isl_schedule_tree_band_scale_down(
1815 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
1819 if (tree
->type
!= isl_schedule_node_band
)
1820 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1821 "not a band node", goto error
);
1823 tree
= isl_schedule_tree_cow(tree
);
1827 tree
->band
= isl_schedule_band_scale_down(tree
->band
, mv
);
1829 return isl_schedule_tree_free(tree
);
1833 isl_schedule_tree_free(tree
);
1834 isl_multi_val_free(mv
);
1838 /* Tile the band root node of "tree" with tile sizes "sizes".
1840 * We duplicate the band node, change the schedule of one of them
1841 * to the tile schedule and the other to the point schedule and then
1842 * attach the point band as a child to the tile band.
1844 __isl_give isl_schedule_tree
*isl_schedule_tree_band_tile(
1845 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*sizes
)
1847 isl_schedule_tree
*child
= NULL
;
1849 if (!tree
|| !sizes
)
1851 if (tree
->type
!= isl_schedule_node_band
)
1852 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1853 "not a band node", goto error
);
1855 child
= isl_schedule_tree_copy(tree
);
1856 tree
= isl_schedule_tree_cow(tree
);
1857 child
= isl_schedule_tree_cow(child
);
1858 if (!tree
|| !child
)
1861 tree
->band
= isl_schedule_band_tile(tree
->band
,
1862 isl_multi_val_copy(sizes
));
1865 child
->band
= isl_schedule_band_point(child
->band
, tree
->band
, sizes
);
1867 child
= isl_schedule_tree_free(child
);
1869 tree
= isl_schedule_tree_replace_child(tree
, 0, child
);
1873 isl_schedule_tree_free(child
);
1874 isl_schedule_tree_free(tree
);
1875 isl_multi_val_free(sizes
);
1879 /* Split the band root node of "tree" into two nested band nodes,
1880 * one with the first "pos" dimensions and
1881 * one with the remaining dimensions.
1883 __isl_give isl_schedule_tree
*isl_schedule_tree_band_split(
1884 __isl_take isl_schedule_tree
*tree
, int pos
)
1887 isl_schedule_tree
*child
;
1891 if (tree
->type
!= isl_schedule_node_band
)
1892 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1893 "not a band node", return isl_schedule_tree_free(tree
));
1895 n
= isl_schedule_tree_band_n_member(tree
);
1896 if (pos
< 0 || pos
> n
)
1897 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1898 "position out of bounds",
1899 return isl_schedule_tree_free(tree
));
1901 child
= isl_schedule_tree_copy(tree
);
1902 tree
= isl_schedule_tree_cow(tree
);
1903 child
= isl_schedule_tree_cow(child
);
1904 if (!tree
|| !child
)
1907 child
->band
= isl_schedule_band_drop(child
->band
, 0, pos
);
1908 tree
->band
= isl_schedule_band_drop(tree
->band
, pos
, n
- pos
);
1909 if (!child
->band
|| !tree
->band
)
1912 tree
= isl_schedule_tree_replace_child(tree
, 0, child
);
1916 isl_schedule_tree_free(child
);
1917 isl_schedule_tree_free(tree
);
1921 /* Attach "tree2" at each of the leaves of "tree1".
1923 * If "tree1" does not have any explicit children, then make "tree2"
1924 * its single child. Otherwise, attach "tree2" to the leaves of
1925 * each of the children of "tree1".
1927 __isl_give isl_schedule_tree
*isl_schedule_tree_append_to_leaves(
1928 __isl_take isl_schedule_tree
*tree1
,
1929 __isl_take isl_schedule_tree
*tree2
)
1933 if (!tree1
|| !tree2
)
1935 n
= isl_schedule_tree_n_children(tree1
);
1937 isl_schedule_tree_list
*list
;
1938 list
= isl_schedule_tree_list_from_schedule_tree(tree2
);
1939 tree1
= isl_schedule_tree_set_children(tree1
, list
);
1942 for (i
= 0; i
< n
; ++i
) {
1943 isl_schedule_tree
*child
;
1945 child
= isl_schedule_tree_get_child(tree1
, i
);
1946 child
= isl_schedule_tree_append_to_leaves(child
,
1947 isl_schedule_tree_copy(tree2
));
1948 tree1
= isl_schedule_tree_replace_child(tree1
, i
, child
);
1951 isl_schedule_tree_free(tree2
);
1954 isl_schedule_tree_free(tree1
);
1955 isl_schedule_tree_free(tree2
);
1959 /* Reset the user pointer on all identifiers of parameters and tuples
1960 * in the root of "tree".
1962 __isl_give isl_schedule_tree
*isl_schedule_tree_reset_user(
1963 __isl_take isl_schedule_tree
*tree
)
1965 if (isl_schedule_tree_is_leaf(tree
))
1968 tree
= isl_schedule_tree_cow(tree
);
1972 switch (tree
->type
) {
1973 case isl_schedule_node_error
:
1974 return isl_schedule_tree_free(tree
);
1975 case isl_schedule_node_band
:
1976 tree
->band
= isl_schedule_band_reset_user(tree
->band
);
1978 return isl_schedule_tree_free(tree
);
1980 case isl_schedule_node_context
:
1981 tree
->context
= isl_set_reset_user(tree
->context
);
1983 return isl_schedule_tree_free(tree
);
1985 case isl_schedule_node_domain
:
1986 tree
->domain
= isl_union_set_reset_user(tree
->domain
);
1988 return isl_schedule_tree_free(tree
);
1990 case isl_schedule_node_expansion
:
1992 isl_union_pw_multi_aff_reset_user(tree
->contraction
);
1993 tree
->expansion
= isl_union_map_reset_user(tree
->expansion
);
1994 if (!tree
->contraction
|| !tree
->expansion
)
1995 return isl_schedule_tree_free(tree
);
1997 case isl_schedule_node_filter
:
1998 tree
->filter
= isl_union_set_reset_user(tree
->filter
);
2000 return isl_schedule_tree_free(tree
);
2002 case isl_schedule_node_leaf
:
2003 case isl_schedule_node_mark
:
2004 case isl_schedule_node_sequence
:
2005 case isl_schedule_node_set
:
2012 /* Align the parameters of the root of "tree" to those of "space".
2014 __isl_give isl_schedule_tree
*isl_schedule_tree_align_params(
2015 __isl_take isl_schedule_tree
*tree
, __isl_take isl_space
*space
)
2020 if (isl_schedule_tree_is_leaf(tree
)) {
2021 isl_space_free(space
);
2025 tree
= isl_schedule_tree_cow(tree
);
2029 switch (tree
->type
) {
2030 case isl_schedule_node_error
:
2032 case isl_schedule_node_band
:
2033 tree
->band
= isl_schedule_band_align_params(tree
->band
, space
);
2035 return isl_schedule_tree_free(tree
);
2037 case isl_schedule_node_context
:
2038 tree
->context
= isl_set_align_params(tree
->context
, space
);
2040 return isl_schedule_tree_free(tree
);
2042 case isl_schedule_node_domain
:
2043 tree
->domain
= isl_union_set_align_params(tree
->domain
, space
);
2045 return isl_schedule_tree_free(tree
);
2047 case isl_schedule_node_expansion
:
2049 isl_union_pw_multi_aff_align_params(tree
->contraction
,
2050 isl_space_copy(space
));
2051 tree
->expansion
= isl_union_map_align_params(tree
->expansion
,
2053 if (!tree
->contraction
|| !tree
->expansion
)
2054 return isl_schedule_tree_free(tree
);
2056 case isl_schedule_node_filter
:
2057 tree
->filter
= isl_union_set_align_params(tree
->filter
, space
);
2059 return isl_schedule_tree_free(tree
);
2061 case isl_schedule_node_leaf
:
2062 case isl_schedule_node_mark
:
2063 case isl_schedule_node_sequence
:
2064 case isl_schedule_node_set
:
2065 isl_space_free(space
);
2071 isl_space_free(space
);
2072 isl_schedule_tree_free(tree
);
2076 /* Does "tree" involve the iteration domain?
2077 * That is, does it need to be modified
2078 * by isl_schedule_tree_pullback_union_pw_multi_aff?
2080 static int involves_iteration_domain(__isl_keep isl_schedule_tree
*tree
)
2085 switch (tree
->type
) {
2086 case isl_schedule_node_error
:
2088 case isl_schedule_node_band
:
2089 case isl_schedule_node_domain
:
2090 case isl_schedule_node_expansion
:
2091 case isl_schedule_node_filter
:
2093 case isl_schedule_node_context
:
2094 case isl_schedule_node_leaf
:
2095 case isl_schedule_node_mark
:
2096 case isl_schedule_node_sequence
:
2097 case isl_schedule_node_set
:
2102 /* Compute the pullback of the root node of "tree" by the function
2103 * represented by "upma".
2104 * In other words, plug in "upma" in the iteration domains of
2105 * the root node of "tree".
2106 * We currently do not handle expansion nodes.
2108 * We first check if the root node involves any iteration domains.
2109 * If so, we handle the specific cases.
2111 __isl_give isl_schedule_tree
*isl_schedule_tree_pullback_union_pw_multi_aff(
2112 __isl_take isl_schedule_tree
*tree
,
2113 __isl_take isl_union_pw_multi_aff
*upma
)
2120 involves
= involves_iteration_domain(tree
);
2124 isl_union_pw_multi_aff_free(upma
);
2128 tree
= isl_schedule_tree_cow(tree
);
2132 if (tree
->type
== isl_schedule_node_band
) {
2133 tree
->band
= isl_schedule_band_pullback_union_pw_multi_aff(
2136 return isl_schedule_tree_free(tree
);
2137 } else if (tree
->type
== isl_schedule_node_domain
) {
2139 isl_union_set_preimage_union_pw_multi_aff(tree
->domain
,
2142 return isl_schedule_tree_free(tree
);
2143 } else if (tree
->type
== isl_schedule_node_expansion
) {
2144 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_unsupported
,
2145 "cannot pullback expansion node", goto error
);
2146 } else if (tree
->type
== isl_schedule_node_filter
) {
2148 isl_union_set_preimage_union_pw_multi_aff(tree
->filter
,
2151 return isl_schedule_tree_free(tree
);
2156 isl_union_pw_multi_aff_free(upma
);
2157 isl_schedule_tree_free(tree
);
2161 /* Compute the gist of the band tree root with respect to "context".
2163 __isl_give isl_schedule_tree
*isl_schedule_tree_band_gist(
2164 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*context
)
2168 if (tree
->type
!= isl_schedule_node_band
)
2169 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2170 "not a band node", goto error
);
2171 tree
= isl_schedule_tree_cow(tree
);
2175 tree
->band
= isl_schedule_band_gist(tree
->band
, context
);
2177 return isl_schedule_tree_free(tree
);
2180 isl_union_set_free(context
);
2181 isl_schedule_tree_free(tree
);
2185 /* Are any members in "band" marked coincident?
2187 static int any_coincident(__isl_keep isl_schedule_band
*band
)
2191 n
= isl_schedule_band_n_member(band
);
2192 for (i
= 0; i
< n
; ++i
)
2193 if (isl_schedule_band_member_get_coincident(band
, i
))
2199 /* Print the band node "band" to "p".
2201 * The permutable and coincident properties are only printed if they
2202 * are different from the defaults.
2203 * The coincident property is always printed in YAML flow style.
2205 static __isl_give isl_printer
*print_tree_band(__isl_take isl_printer
*p
,
2206 __isl_keep isl_schedule_band
*band
)
2208 isl_union_set
*options
;
2211 p
= isl_printer_print_str(p
, "schedule");
2212 p
= isl_printer_yaml_next(p
);
2213 p
= isl_printer_print_str(p
, "\"");
2214 p
= isl_printer_print_multi_union_pw_aff(p
, band
->mupa
);
2215 p
= isl_printer_print_str(p
, "\"");
2216 if (isl_schedule_band_get_permutable(band
)) {
2217 p
= isl_printer_yaml_next(p
);
2218 p
= isl_printer_print_str(p
, "permutable");
2219 p
= isl_printer_yaml_next(p
);
2220 p
= isl_printer_print_int(p
, 1);
2222 if (any_coincident(band
)) {
2226 p
= isl_printer_yaml_next(p
);
2227 p
= isl_printer_print_str(p
, "coincident");
2228 p
= isl_printer_yaml_next(p
);
2229 style
= isl_printer_get_yaml_style(p
);
2230 p
= isl_printer_set_yaml_style(p
, ISL_YAML_STYLE_FLOW
);
2231 p
= isl_printer_yaml_start_sequence(p
);
2232 n
= isl_schedule_band_n_member(band
);
2233 for (i
= 0; i
< n
; ++i
) {
2234 p
= isl_printer_print_int(p
,
2235 isl_schedule_band_member_get_coincident(band
, i
));
2236 p
= isl_printer_yaml_next(p
);
2238 p
= isl_printer_yaml_end_sequence(p
);
2239 p
= isl_printer_set_yaml_style(p
, style
);
2241 options
= isl_schedule_band_get_ast_build_options(band
);
2242 empty
= isl_union_set_is_empty(options
);
2244 p
= isl_printer_free(p
);
2246 p
= isl_printer_yaml_next(p
);
2247 p
= isl_printer_print_str(p
, "options");
2248 p
= isl_printer_yaml_next(p
);
2249 p
= isl_printer_print_str(p
, "\"");
2250 p
= isl_printer_print_union_set(p
, options
);
2251 p
= isl_printer_print_str(p
, "\"");
2253 isl_union_set_free(options
);
2258 /* Print "tree" to "p".
2260 * If "n_ancestor" is non-negative, then "child_pos" contains the child
2261 * positions of a descendant of the current node that should be marked
2262 * (by the comment "YOU ARE HERE"). In particular, if "n_ancestor"
2263 * is zero, then the current node should be marked.
2264 * The marking is only printed in YAML block format.
2266 * Implicit leaf nodes are not printed, except if they correspond
2267 * to the node that should be marked.
2269 __isl_give isl_printer
*isl_printer_print_schedule_tree_mark(
2270 __isl_take isl_printer
*p
, __isl_keep isl_schedule_tree
*tree
,
2271 int n_ancestor
, int *child_pos
)
2277 block
= isl_printer_get_yaml_style(p
) == ISL_YAML_STYLE_BLOCK
;
2279 p
= isl_printer_yaml_start_mapping(p
);
2280 if (n_ancestor
== 0 && block
) {
2281 p
= isl_printer_print_str(p
, "# YOU ARE HERE");
2282 p
= isl_printer_end_line(p
);
2283 p
= isl_printer_start_line(p
);
2285 switch (tree
->type
) {
2286 case isl_schedule_node_error
:
2287 p
= isl_printer_print_str(p
, "ERROR");
2289 case isl_schedule_node_leaf
:
2290 p
= isl_printer_print_str(p
, "leaf");
2292 case isl_schedule_node_sequence
:
2293 p
= isl_printer_print_str(p
, "sequence");
2296 case isl_schedule_node_set
:
2297 p
= isl_printer_print_str(p
, "set");
2300 case isl_schedule_node_context
:
2301 p
= isl_printer_print_str(p
, "context");
2302 p
= isl_printer_yaml_next(p
);
2303 p
= isl_printer_print_str(p
, "\"");
2304 p
= isl_printer_print_set(p
, tree
->context
);
2305 p
= isl_printer_print_str(p
, "\"");
2307 case isl_schedule_node_domain
:
2308 p
= isl_printer_print_str(p
, "domain");
2309 p
= isl_printer_yaml_next(p
);
2310 p
= isl_printer_print_str(p
, "\"");
2311 p
= isl_printer_print_union_set(p
, tree
->domain
);
2312 p
= isl_printer_print_str(p
, "\"");
2314 case isl_schedule_node_expansion
:
2315 p
= isl_printer_print_str(p
, "contraction");
2316 p
= isl_printer_yaml_next(p
);
2317 p
= isl_printer_print_str(p
, "\"");
2318 p
= isl_printer_print_union_pw_multi_aff(p
, tree
->contraction
);
2319 p
= isl_printer_print_str(p
, "\"");
2320 p
= isl_printer_yaml_next(p
);
2321 p
= isl_printer_print_str(p
, "expansion");
2322 p
= isl_printer_yaml_next(p
);
2323 p
= isl_printer_print_str(p
, "\"");
2324 p
= isl_printer_print_union_map(p
, tree
->expansion
);
2325 p
= isl_printer_print_str(p
, "\"");
2327 case isl_schedule_node_filter
:
2328 p
= isl_printer_print_str(p
, "filter");
2329 p
= isl_printer_yaml_next(p
);
2330 p
= isl_printer_print_str(p
, "\"");
2331 p
= isl_printer_print_union_set(p
, tree
->filter
);
2332 p
= isl_printer_print_str(p
, "\"");
2334 case isl_schedule_node_mark
:
2335 p
= isl_printer_print_str(p
, "mark");
2336 p
= isl_printer_yaml_next(p
);
2337 p
= isl_printer_print_str(p
, "\"");
2338 p
= isl_printer_print_str(p
, isl_id_get_name(tree
->mark
));
2339 p
= isl_printer_print_str(p
, "\"");
2341 case isl_schedule_node_band
:
2342 p
= print_tree_band(p
, tree
->band
);
2345 p
= isl_printer_yaml_next(p
);
2347 if (!tree
->children
) {
2348 if (n_ancestor
> 0 && block
) {
2349 isl_schedule_tree
*leaf
;
2351 p
= isl_printer_print_str(p
, "child");
2352 p
= isl_printer_yaml_next(p
);
2353 leaf
= isl_schedule_tree_leaf(isl_printer_get_ctx(p
));
2354 p
= isl_printer_print_schedule_tree_mark(p
,
2356 isl_schedule_tree_free(leaf
);
2357 p
= isl_printer_yaml_next(p
);
2359 return isl_printer_yaml_end_mapping(p
);
2363 p
= isl_printer_yaml_start_sequence(p
);
2365 p
= isl_printer_print_str(p
, "child");
2366 p
= isl_printer_yaml_next(p
);
2369 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
2370 for (i
= 0; i
< n
; ++i
) {
2371 isl_schedule_tree
*t
;
2373 t
= isl_schedule_tree_get_child(tree
, i
);
2374 if (n_ancestor
> 0 && child_pos
[0] == i
)
2375 p
= isl_printer_print_schedule_tree_mark(p
, t
,
2376 n_ancestor
- 1, child_pos
+ 1);
2378 p
= isl_printer_print_schedule_tree_mark(p
, t
,
2380 isl_schedule_tree_free(t
);
2382 p
= isl_printer_yaml_next(p
);
2386 p
= isl_printer_yaml_end_sequence(p
);
2387 p
= isl_printer_yaml_end_mapping(p
);
2392 /* Print "tree" to "p".
2394 __isl_give isl_printer
*isl_printer_print_schedule_tree(
2395 __isl_take isl_printer
*p
, __isl_keep isl_schedule_tree
*tree
)
2397 return isl_printer_print_schedule_tree_mark(p
, tree
, -1, NULL
);
2400 void isl_schedule_tree_dump(__isl_keep isl_schedule_tree
*tree
)
2403 isl_printer
*printer
;
2408 ctx
= isl_schedule_tree_get_ctx(tree
);
2409 printer
= isl_printer_to_file(ctx
, stderr
);
2410 printer
= isl_printer_set_yaml_style(printer
, ISL_YAML_STYLE_BLOCK
);
2411 printer
= isl_printer_print_schedule_tree(printer
, tree
);
2413 isl_printer_free(printer
);