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 __isl_give isl_schedule_tree
*isl_schedule_tree_cow(
145 __isl_take isl_schedule_tree
*tree
)
153 return isl_schedule_tree_dup(tree
);
156 /* Return a new reference to "tree".
158 __isl_give isl_schedule_tree
*isl_schedule_tree_copy(
159 __isl_keep isl_schedule_tree
*tree
)
168 /* Free "tree" and return NULL.
170 __isl_null isl_schedule_tree
*isl_schedule_tree_free(
171 __isl_take isl_schedule_tree
*tree
)
178 switch (tree
->type
) {
179 case isl_schedule_node_band
:
180 isl_schedule_band_free(tree
->band
);
182 case isl_schedule_node_context
:
183 isl_set_free(tree
->context
);
185 case isl_schedule_node_domain
:
186 isl_union_set_free(tree
->domain
);
188 case isl_schedule_node_expansion
:
189 isl_union_pw_multi_aff_free(tree
->contraction
);
190 isl_union_map_free(tree
->expansion
);
192 case isl_schedule_node_extension
:
193 isl_union_map_free(tree
->extension
);
195 case isl_schedule_node_filter
:
196 isl_union_set_free(tree
->filter
);
198 case isl_schedule_node_guard
:
199 isl_set_free(tree
->guard
);
201 case isl_schedule_node_mark
:
202 isl_id_free(tree
->mark
);
204 case isl_schedule_node_sequence
:
205 case isl_schedule_node_set
:
206 case isl_schedule_node_error
:
207 case isl_schedule_node_leaf
:
210 isl_schedule_tree_list_free(tree
->children
);
211 isl_ctx_deref(tree
->ctx
);
217 /* Create and return a new leaf schedule tree.
219 __isl_give isl_schedule_tree
*isl_schedule_tree_leaf(isl_ctx
*ctx
)
221 return isl_schedule_tree_alloc(ctx
, isl_schedule_node_leaf
);
224 /* Create a new band schedule tree referring to "band"
227 __isl_give isl_schedule_tree
*isl_schedule_tree_from_band(
228 __isl_take isl_schedule_band
*band
)
231 isl_schedule_tree
*tree
;
236 ctx
= isl_schedule_band_get_ctx(band
);
237 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_band
);
242 tree
->anchored
= isl_schedule_band_is_anchored(band
);
246 isl_schedule_band_free(band
);
250 /* Create a new context schedule tree with the given context and no children.
251 * Since the context references the outer schedule dimension,
252 * the tree is anchored.
254 __isl_give isl_schedule_tree
*isl_schedule_tree_from_context(
255 __isl_take isl_set
*context
)
258 isl_schedule_tree
*tree
;
263 ctx
= isl_set_get_ctx(context
);
264 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_context
);
268 tree
->context
= context
;
273 isl_set_free(context
);
277 /* Create a new domain schedule tree with the given domain and no children.
279 __isl_give isl_schedule_tree
*isl_schedule_tree_from_domain(
280 __isl_take isl_union_set
*domain
)
283 isl_schedule_tree
*tree
;
288 ctx
= isl_union_set_get_ctx(domain
);
289 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_domain
);
293 tree
->domain
= domain
;
297 isl_union_set_free(domain
);
301 /* Create a new expansion schedule tree with the given contraction and
302 * expansion and no children.
304 __isl_give isl_schedule_tree
*isl_schedule_tree_from_expansion(
305 __isl_take isl_union_pw_multi_aff
*contraction
,
306 __isl_take isl_union_map
*expansion
)
309 isl_schedule_tree
*tree
;
311 if (!contraction
|| !expansion
)
314 ctx
= isl_union_map_get_ctx(expansion
);
315 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_expansion
);
319 tree
->contraction
= contraction
;
320 tree
->expansion
= expansion
;
324 isl_union_pw_multi_aff_free(contraction
);
325 isl_union_map_free(expansion
);
329 /* Create a new extension schedule tree with the given extension and
331 * Since the domain of the extension refers to the outer schedule dimension,
332 * the tree is anchored.
334 __isl_give isl_schedule_tree
*isl_schedule_tree_from_extension(
335 __isl_take isl_union_map
*extension
)
338 isl_schedule_tree
*tree
;
343 ctx
= isl_union_map_get_ctx(extension
);
344 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_extension
);
348 tree
->extension
= extension
;
353 isl_union_map_free(extension
);
357 /* Create a new filter schedule tree with the given filter and no children.
359 __isl_give isl_schedule_tree
*isl_schedule_tree_from_filter(
360 __isl_take isl_union_set
*filter
)
363 isl_schedule_tree
*tree
;
368 ctx
= isl_union_set_get_ctx(filter
);
369 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_filter
);
373 tree
->filter
= filter
;
377 isl_union_set_free(filter
);
381 /* Create a new guard schedule tree with the given guard and no children.
382 * Since the guard references the outer schedule dimension,
383 * the tree is anchored.
385 __isl_give isl_schedule_tree
*isl_schedule_tree_from_guard(
386 __isl_take isl_set
*guard
)
389 isl_schedule_tree
*tree
;
394 ctx
= isl_set_get_ctx(guard
);
395 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_guard
);
408 /* Create a new mark schedule tree with the given mark identifier and
411 __isl_give isl_schedule_tree
*isl_schedule_tree_from_mark(
412 __isl_take isl_id
*mark
)
415 isl_schedule_tree
*tree
;
420 ctx
= isl_id_get_ctx(mark
);
421 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_mark
);
433 /* Does "tree" have any node that depends on its position
434 * in the complete schedule tree?
436 isl_bool
isl_schedule_tree_is_subtree_anchored(
437 __isl_keep isl_schedule_tree
*tree
)
439 return tree
? tree
->anchored
: isl_bool_error
;
442 /* Does the root node of "tree" depend on its position in the complete
444 * Band nodes may be anchored depending on the associated AST build options.
445 * Context, extension and guard nodes are always anchored.
447 int isl_schedule_tree_is_anchored(__isl_keep isl_schedule_tree
*tree
)
452 switch (isl_schedule_tree_get_type(tree
)) {
453 case isl_schedule_node_error
:
455 case isl_schedule_node_band
:
456 return isl_schedule_band_is_anchored(tree
->band
);
457 case isl_schedule_node_context
:
458 case isl_schedule_node_extension
:
459 case isl_schedule_node_guard
:
461 case isl_schedule_node_domain
:
462 case isl_schedule_node_expansion
:
463 case isl_schedule_node_filter
:
464 case isl_schedule_node_leaf
:
465 case isl_schedule_node_mark
:
466 case isl_schedule_node_sequence
:
467 case isl_schedule_node_set
:
471 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
472 "unhandled case", return -1);
475 /* Update the anchored field of "tree" based on whether the root node
476 * itself in anchored and the anchored fields of the children.
478 * This function should be called whenever the children of a tree node
479 * are changed or the anchoredness of the tree root itself changes.
481 __isl_give isl_schedule_tree
*isl_schedule_tree_update_anchored(
482 __isl_take isl_schedule_tree
*tree
)
490 anchored
= isl_schedule_tree_is_anchored(tree
);
492 return isl_schedule_tree_free(tree
);
494 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
495 for (i
= 0; !anchored
&& i
< n
; ++i
) {
496 isl_schedule_tree
*child
;
498 child
= isl_schedule_tree_get_child(tree
, i
);
500 return isl_schedule_tree_free(tree
);
501 anchored
= child
->anchored
;
502 isl_schedule_tree_free(child
);
505 if (anchored
== tree
->anchored
)
507 tree
= isl_schedule_tree_cow(tree
);
510 tree
->anchored
= anchored
;
514 /* Create a new tree of the given type (isl_schedule_node_sequence or
515 * isl_schedule_node_set) with the given children.
517 __isl_give isl_schedule_tree
*isl_schedule_tree_from_children(
518 enum isl_schedule_node_type type
,
519 __isl_take isl_schedule_tree_list
*list
)
522 isl_schedule_tree
*tree
;
527 ctx
= isl_schedule_tree_list_get_ctx(list
);
528 tree
= isl_schedule_tree_alloc(ctx
, type
);
532 tree
->children
= list
;
533 tree
= isl_schedule_tree_update_anchored(tree
);
537 isl_schedule_tree_list_free(list
);
541 /* Construct a tree with a root node of type "type" and as children
542 * "tree1" and "tree2".
543 * If the root of one (or both) of the input trees is itself of type "type",
544 * then the tree is replaced by its children.
546 __isl_give isl_schedule_tree
*isl_schedule_tree_from_pair(
547 enum isl_schedule_node_type type
, __isl_take isl_schedule_tree
*tree1
,
548 __isl_take isl_schedule_tree
*tree2
)
551 isl_schedule_tree_list
*list
;
553 if (!tree1
|| !tree2
)
556 ctx
= isl_schedule_tree_get_ctx(tree1
);
557 if (isl_schedule_tree_get_type(tree1
) == type
) {
558 list
= isl_schedule_tree_list_copy(tree1
->children
);
559 isl_schedule_tree_free(tree1
);
561 list
= isl_schedule_tree_list_alloc(ctx
, 2);
562 list
= isl_schedule_tree_list_add(list
, tree1
);
564 if (isl_schedule_tree_get_type(tree2
) == type
) {
565 isl_schedule_tree_list
*children
;
567 children
= isl_schedule_tree_list_copy(tree2
->children
);
568 list
= isl_schedule_tree_list_concat(list
, children
);
569 isl_schedule_tree_free(tree2
);
571 list
= isl_schedule_tree_list_add(list
, tree2
);
574 return isl_schedule_tree_from_children(type
, list
);
576 isl_schedule_tree_free(tree1
);
577 isl_schedule_tree_free(tree2
);
581 /* Construct a tree with a sequence root node and as children
582 * "tree1" and "tree2".
583 * If the root of one (or both) of the input trees is itself a sequence,
584 * then the tree is replaced by its children.
586 __isl_give isl_schedule_tree
*isl_schedule_tree_sequence_pair(
587 __isl_take isl_schedule_tree
*tree1
,
588 __isl_take isl_schedule_tree
*tree2
)
590 return isl_schedule_tree_from_pair(isl_schedule_node_sequence
,
594 /* Return the isl_ctx to which "tree" belongs.
596 isl_ctx
*isl_schedule_tree_get_ctx(__isl_keep isl_schedule_tree
*tree
)
598 return tree
? tree
->ctx
: NULL
;
601 /* Return the type of the root of the tree or isl_schedule_node_error
604 enum isl_schedule_node_type
isl_schedule_tree_get_type(
605 __isl_keep isl_schedule_tree
*tree
)
607 return tree
? tree
->type
: isl_schedule_node_error
;
610 /* Are "tree1" and "tree2" obviously equal to each other?
612 isl_bool
isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree
*tree1
,
613 __isl_keep isl_schedule_tree
*tree2
)
618 if (!tree1
|| !tree2
)
619 return isl_bool_error
;
621 return isl_bool_true
;
622 if (tree1
->type
!= tree2
->type
)
623 return isl_bool_false
;
625 switch (tree1
->type
) {
626 case isl_schedule_node_band
:
627 equal
= isl_schedule_band_plain_is_equal(tree1
->band
,
630 case isl_schedule_node_context
:
631 equal
= isl_set_is_equal(tree1
->context
, tree2
->context
);
633 case isl_schedule_node_domain
:
634 equal
= isl_union_set_is_equal(tree1
->domain
, tree2
->domain
);
636 case isl_schedule_node_expansion
:
637 equal
= isl_union_map_is_equal(tree1
->expansion
,
639 if (equal
>= 0 && equal
)
640 equal
= isl_union_pw_multi_aff_plain_is_equal(
641 tree1
->contraction
, tree2
->contraction
);
643 case isl_schedule_node_extension
:
644 equal
= isl_union_map_is_equal(tree1
->extension
,
647 case isl_schedule_node_filter
:
648 equal
= isl_union_set_is_equal(tree1
->filter
, tree2
->filter
);
650 case isl_schedule_node_guard
:
651 equal
= isl_set_is_equal(tree1
->guard
, tree2
->guard
);
653 case isl_schedule_node_mark
:
654 equal
= tree1
->mark
== tree2
->mark
;
656 case isl_schedule_node_leaf
:
657 case isl_schedule_node_sequence
:
658 case isl_schedule_node_set
:
659 equal
= isl_bool_true
;
661 case isl_schedule_node_error
:
662 equal
= isl_bool_error
;
666 if (equal
< 0 || !equal
)
669 n
= isl_schedule_tree_n_children(tree1
);
670 if (n
!= isl_schedule_tree_n_children(tree2
))
671 return isl_bool_false
;
672 for (i
= 0; i
< n
; ++i
) {
673 isl_schedule_tree
*child1
, *child2
;
675 child1
= isl_schedule_tree_get_child(tree1
, i
);
676 child2
= isl_schedule_tree_get_child(tree2
, i
);
677 equal
= isl_schedule_tree_plain_is_equal(child1
, child2
);
678 isl_schedule_tree_free(child1
);
679 isl_schedule_tree_free(child2
);
681 if (equal
< 0 || !equal
)
685 return isl_bool_true
;
688 /* Does "tree" have any children, other than an implicit leaf.
690 int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree
*tree
)
695 return tree
->children
!= NULL
;
698 /* Return the number of children of "tree", excluding implicit leaves.
700 int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree
*tree
)
705 return isl_schedule_tree_list_n_schedule_tree(tree
->children
);
708 /* Return a copy of the (explicit) child at position "pos" of "tree".
710 __isl_give isl_schedule_tree
*isl_schedule_tree_get_child(
711 __isl_keep isl_schedule_tree
*tree
, int pos
)
716 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
717 "schedule tree has no explicit children", return NULL
);
718 return isl_schedule_tree_list_get_schedule_tree(tree
->children
, pos
);
721 /* Return a copy of the (explicit) child at position "pos" of "tree" and
724 __isl_give isl_schedule_tree
*isl_schedule_tree_child(
725 __isl_take isl_schedule_tree
*tree
, int pos
)
727 isl_schedule_tree
*child
;
729 child
= isl_schedule_tree_get_child(tree
, pos
);
730 isl_schedule_tree_free(tree
);
734 /* Remove all (explicit) children from "tree".
736 __isl_give isl_schedule_tree
*isl_schedule_tree_reset_children(
737 __isl_take isl_schedule_tree
*tree
)
739 tree
= isl_schedule_tree_cow(tree
);
742 tree
->children
= isl_schedule_tree_list_free(tree
->children
);
746 /* Remove the child at position "pos" from the children of "tree".
747 * If there was only one child to begin with, then remove all children.
749 __isl_give isl_schedule_tree
*isl_schedule_tree_drop_child(
750 __isl_take isl_schedule_tree
*tree
, int pos
)
754 tree
= isl_schedule_tree_cow(tree
);
758 if (!isl_schedule_tree_has_children(tree
))
759 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
760 "tree does not have any explicit children",
761 return isl_schedule_tree_free(tree
));
762 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
763 if (pos
< 0 || pos
>= n
)
764 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
765 "position out of bounds",
766 return isl_schedule_tree_free(tree
));
768 return isl_schedule_tree_reset_children(tree
);
770 tree
->children
= isl_schedule_tree_list_drop(tree
->children
, pos
, 1);
772 return isl_schedule_tree_free(tree
);
777 /* Replace the child at position "pos" of "tree" by "child".
779 * If the new child is a leaf, then it is not explicitly
780 * recorded in the list of children. Instead, the list of children
781 * (which is assumed to have only one element) is removed.
782 * Note that the children of set and sequence nodes are always
783 * filters, so they cannot be replaced by empty trees.
785 __isl_give isl_schedule_tree
*isl_schedule_tree_replace_child(
786 __isl_take isl_schedule_tree
*tree
, int pos
,
787 __isl_take isl_schedule_tree
*child
)
789 tree
= isl_schedule_tree_cow(tree
);
793 if (isl_schedule_tree_is_leaf(child
)) {
794 isl_schedule_tree_free(child
);
795 if (!tree
->children
&& pos
== 0)
797 if (isl_schedule_tree_n_children(tree
) != 1)
798 isl_die(isl_schedule_tree_get_ctx(tree
),
800 "can only replace single child by leaf",
802 return isl_schedule_tree_reset_children(tree
);
805 if (!tree
->children
&& pos
== 0)
807 isl_schedule_tree_list_from_schedule_tree(child
);
809 tree
->children
= isl_schedule_tree_list_set_schedule_tree(
810 tree
->children
, pos
, child
);
813 return isl_schedule_tree_free(tree
);
814 tree
= isl_schedule_tree_update_anchored(tree
);
818 isl_schedule_tree_free(tree
);
819 isl_schedule_tree_free(child
);
823 /* Replace the (explicit) children of "tree" by "children"?
825 __isl_give isl_schedule_tree
*isl_schedule_tree_set_children(
826 __isl_take isl_schedule_tree
*tree
,
827 __isl_take isl_schedule_tree_list
*children
)
829 tree
= isl_schedule_tree_cow(tree
);
830 if (!tree
|| !children
)
832 isl_schedule_tree_list_free(tree
->children
);
833 tree
->children
= children
;
836 isl_schedule_tree_free(tree
);
837 isl_schedule_tree_list_free(children
);
841 /* Create a new band schedule tree referring to "band"
842 * with "tree" as single child.
844 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_band(
845 __isl_take isl_schedule_tree
*tree
, __isl_take isl_schedule_band
*band
)
847 isl_schedule_tree
*res
;
849 res
= isl_schedule_tree_from_band(band
);
850 return isl_schedule_tree_replace_child(res
, 0, tree
);
853 /* Create a new context schedule tree with the given context and
854 * with "tree" as single child.
856 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_context(
857 __isl_take isl_schedule_tree
*tree
, __isl_take isl_set
*context
)
859 isl_schedule_tree
*res
;
861 res
= isl_schedule_tree_from_context(context
);
862 return isl_schedule_tree_replace_child(res
, 0, tree
);
865 /* Create a new domain schedule tree with the given domain and
866 * with "tree" as single child.
868 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_domain(
869 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
871 isl_schedule_tree
*res
;
873 res
= isl_schedule_tree_from_domain(domain
);
874 return isl_schedule_tree_replace_child(res
, 0, tree
);
877 /* Create a new expansion schedule tree with the given contraction and
878 * expansion and with "tree" as single child.
880 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_expansion(
881 __isl_take isl_schedule_tree
*tree
,
882 __isl_take isl_union_pw_multi_aff
*contraction
,
883 __isl_take isl_union_map
*expansion
)
885 isl_schedule_tree
*res
;
887 res
= isl_schedule_tree_from_expansion(contraction
, expansion
);
888 return isl_schedule_tree_replace_child(res
, 0, tree
);
891 /* Create a new extension schedule tree with the given extension and
892 * with "tree" as single child.
894 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_extension(
895 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_map
*extension
)
897 isl_schedule_tree
*res
;
899 res
= isl_schedule_tree_from_extension(extension
);
900 return isl_schedule_tree_replace_child(res
, 0, tree
);
903 /* Create a new filter schedule tree with the given filter and single child.
905 * If the root of "tree" is itself a filter node, then the two
906 * filter nodes are merged into one node.
908 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_filter(
909 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
911 isl_schedule_tree
*res
;
913 if (isl_schedule_tree_get_type(tree
) == isl_schedule_node_filter
) {
914 isl_union_set
*tree_filter
;
916 tree_filter
= isl_schedule_tree_filter_get_filter(tree
);
917 tree_filter
= isl_union_set_intersect(tree_filter
, filter
);
918 tree
= isl_schedule_tree_filter_set_filter(tree
, tree_filter
);
922 res
= isl_schedule_tree_from_filter(filter
);
923 return isl_schedule_tree_replace_child(res
, 0, tree
);
926 /* Insert a filter node with filter set "filter"
927 * in each of the children of "tree".
929 __isl_give isl_schedule_tree
*isl_schedule_tree_children_insert_filter(
930 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
934 if (!tree
|| !filter
)
937 n
= isl_schedule_tree_n_children(tree
);
938 for (i
= 0; i
< n
; ++i
) {
939 isl_schedule_tree
*child
;
941 child
= isl_schedule_tree_get_child(tree
, i
);
942 child
= isl_schedule_tree_insert_filter(child
,
943 isl_union_set_copy(filter
));
944 tree
= isl_schedule_tree_replace_child(tree
, i
, child
);
947 isl_union_set_free(filter
);
950 isl_union_set_free(filter
);
951 isl_schedule_tree_free(tree
);
955 /* Create a new guard schedule tree with the given guard and
956 * with "tree" as single child.
958 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_guard(
959 __isl_take isl_schedule_tree
*tree
, __isl_take isl_set
*guard
)
961 isl_schedule_tree
*res
;
963 res
= isl_schedule_tree_from_guard(guard
);
964 return isl_schedule_tree_replace_child(res
, 0, tree
);
967 /* Create a new mark schedule tree with the given mark identifier and
970 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_mark(
971 __isl_take isl_schedule_tree
*tree
, __isl_take isl_id
*mark
)
973 isl_schedule_tree
*res
;
975 res
= isl_schedule_tree_from_mark(mark
);
976 return isl_schedule_tree_replace_child(res
, 0, tree
);
979 /* Return the number of members in the band tree root.
981 unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree
*tree
)
986 if (tree
->type
!= isl_schedule_node_band
)
987 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
988 "not a band node", return 0);
990 return isl_schedule_band_n_member(tree
->band
);
993 /* Is the band member at position "pos" of the band tree root
996 isl_bool
isl_schedule_tree_band_member_get_coincident(
997 __isl_keep isl_schedule_tree
*tree
, int pos
)
1000 return isl_bool_error
;
1002 if (tree
->type
!= isl_schedule_node_band
)
1003 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1004 "not a band node", return isl_bool_error
);
1006 return isl_schedule_band_member_get_coincident(tree
->band
, pos
);
1009 /* Mark the given band member as being coincident or not
1010 * according to "coincident".
1012 __isl_give isl_schedule_tree
*isl_schedule_tree_band_member_set_coincident(
1013 __isl_take isl_schedule_tree
*tree
, int pos
, int coincident
)
1017 if (tree
->type
!= isl_schedule_node_band
)
1018 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1019 "not a band node", return isl_schedule_tree_free(tree
));
1020 if (isl_schedule_tree_band_member_get_coincident(tree
, pos
) ==
1023 tree
= isl_schedule_tree_cow(tree
);
1027 tree
->band
= isl_schedule_band_member_set_coincident(tree
->band
, pos
,
1030 return isl_schedule_tree_free(tree
);
1034 /* Is the band tree root marked permutable?
1036 isl_bool
isl_schedule_tree_band_get_permutable(
1037 __isl_keep isl_schedule_tree
*tree
)
1040 return isl_bool_error
;
1042 if (tree
->type
!= isl_schedule_node_band
)
1043 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1044 "not a band node", return isl_bool_error
);
1046 return isl_schedule_band_get_permutable(tree
->band
);
1049 /* Mark the band tree root permutable or not according to "permutable"?
1051 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_permutable(
1052 __isl_take isl_schedule_tree
*tree
, int permutable
)
1056 if (tree
->type
!= isl_schedule_node_band
)
1057 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1058 "not a band node", return isl_schedule_tree_free(tree
));
1059 if (isl_schedule_tree_band_get_permutable(tree
) == permutable
)
1061 tree
= isl_schedule_tree_cow(tree
);
1065 tree
->band
= isl_schedule_band_set_permutable(tree
->band
, permutable
);
1067 return isl_schedule_tree_free(tree
);
1071 /* Return the schedule space of the band tree root.
1073 __isl_give isl_space
*isl_schedule_tree_band_get_space(
1074 __isl_keep isl_schedule_tree
*tree
)
1079 if (tree
->type
!= isl_schedule_node_band
)
1080 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1081 "not a band node", return NULL
);
1083 return isl_schedule_band_get_space(tree
->band
);
1086 /* Intersect the domain of the band schedule of the band tree root
1089 __isl_give isl_schedule_tree
*isl_schedule_tree_band_intersect_domain(
1090 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
1092 if (!tree
|| !domain
)
1095 if (tree
->type
!= isl_schedule_node_band
)
1096 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1097 "not a band node", goto error
);
1099 tree
->band
= isl_schedule_band_intersect_domain(tree
->band
, domain
);
1101 return isl_schedule_tree_free(tree
);
1105 isl_schedule_tree_free(tree
);
1106 isl_union_set_free(domain
);
1110 /* Return the schedule of the band tree root in isolation.
1112 __isl_give isl_multi_union_pw_aff
*isl_schedule_tree_band_get_partial_schedule(
1113 __isl_keep isl_schedule_tree
*tree
)
1118 if (tree
->type
!= isl_schedule_node_band
)
1119 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1120 "not a band node", return NULL
);
1122 return isl_schedule_band_get_partial_schedule(tree
->band
);
1125 /* Replace the schedule of the band tree root by "schedule".
1127 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_partial_schedule(
1128 __isl_take isl_schedule_tree
*tree
,
1129 __isl_take isl_multi_union_pw_aff
*schedule
)
1131 tree
= isl_schedule_tree_cow(tree
);
1132 if (!tree
|| !schedule
)
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
);
1138 tree
->band
= isl_schedule_band_set_partial_schedule(tree
->band
,
1143 isl_schedule_tree_free(tree
);
1144 isl_multi_union_pw_aff_free(schedule
);
1148 /* Return the loop AST generation type for the band member
1149 * of the band tree root at position "pos".
1151 enum isl_ast_loop_type
isl_schedule_tree_band_member_get_ast_loop_type(
1152 __isl_keep isl_schedule_tree
*tree
, int pos
)
1155 return isl_ast_loop_error
;
1157 if (tree
->type
!= isl_schedule_node_band
)
1158 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1159 "not a band node", return isl_ast_loop_error
);
1161 return isl_schedule_band_member_get_ast_loop_type(tree
->band
, pos
);
1164 /* Set the loop AST generation type for the band member of the band tree root
1165 * at position "pos" to "type".
1167 __isl_give isl_schedule_tree
*isl_schedule_tree_band_member_set_ast_loop_type(
1168 __isl_take isl_schedule_tree
*tree
, int pos
,
1169 enum isl_ast_loop_type type
)
1171 tree
= isl_schedule_tree_cow(tree
);
1175 if (tree
->type
!= isl_schedule_node_band
)
1176 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1177 "not a band node", return isl_schedule_tree_free(tree
));
1179 tree
->band
= isl_schedule_band_member_set_ast_loop_type(tree
->band
,
1182 return isl_schedule_tree_free(tree
);
1187 /* Return the loop AST generation type for the band member
1188 * of the band tree root at position "pos" for the isolated part.
1190 enum isl_ast_loop_type
isl_schedule_tree_band_member_get_isolate_ast_loop_type(
1191 __isl_keep isl_schedule_tree
*tree
, int pos
)
1194 return isl_ast_loop_error
;
1196 if (tree
->type
!= isl_schedule_node_band
)
1197 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1198 "not a band node", return isl_ast_loop_error
);
1200 return isl_schedule_band_member_get_isolate_ast_loop_type(tree
->band
,
1204 /* Set the loop AST generation type for the band member of the band tree root
1205 * at position "pos" for the isolated part to "type".
1207 __isl_give isl_schedule_tree
*
1208 isl_schedule_tree_band_member_set_isolate_ast_loop_type(
1209 __isl_take isl_schedule_tree
*tree
, int pos
,
1210 enum isl_ast_loop_type type
)
1212 tree
= isl_schedule_tree_cow(tree
);
1216 if (tree
->type
!= isl_schedule_node_band
)
1217 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1218 "not a band node", return isl_schedule_tree_free(tree
));
1220 tree
->band
= isl_schedule_band_member_set_isolate_ast_loop_type(
1221 tree
->band
, pos
, type
);
1223 return isl_schedule_tree_free(tree
);
1228 /* Return the AST build options associated to the band tree root.
1230 __isl_give isl_union_set
*isl_schedule_tree_band_get_ast_build_options(
1231 __isl_keep isl_schedule_tree
*tree
)
1236 if (tree
->type
!= isl_schedule_node_band
)
1237 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1238 "not a band node", return NULL
);
1240 return isl_schedule_band_get_ast_build_options(tree
->band
);
1243 /* Replace the AST build options associated to band tree root by "options".
1244 * Updated the anchored field if the anchoredness of the root node itself
1247 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_ast_build_options(
1248 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*options
)
1252 tree
= isl_schedule_tree_cow(tree
);
1253 if (!tree
|| !options
)
1256 if (tree
->type
!= isl_schedule_node_band
)
1257 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1258 "not a band node", goto error
);
1260 was_anchored
= isl_schedule_tree_is_anchored(tree
);
1261 tree
->band
= isl_schedule_band_set_ast_build_options(tree
->band
,
1264 return isl_schedule_tree_free(tree
);
1265 if (isl_schedule_tree_is_anchored(tree
) != was_anchored
)
1266 tree
= isl_schedule_tree_update_anchored(tree
);
1270 isl_schedule_tree_free(tree
);
1271 isl_union_set_free(options
);
1275 /* Return the context of the context tree root.
1277 __isl_give isl_set
*isl_schedule_tree_context_get_context(
1278 __isl_keep isl_schedule_tree
*tree
)
1283 if (tree
->type
!= isl_schedule_node_context
)
1284 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1285 "not a context node", return NULL
);
1287 return isl_set_copy(tree
->context
);
1290 /* Return the domain of the domain tree root.
1292 __isl_give isl_union_set
*isl_schedule_tree_domain_get_domain(
1293 __isl_keep isl_schedule_tree
*tree
)
1298 if (tree
->type
!= isl_schedule_node_domain
)
1299 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1300 "not a domain node", return NULL
);
1302 return isl_union_set_copy(tree
->domain
);
1305 /* Replace the domain of domain tree root "tree" by "domain".
1307 __isl_give isl_schedule_tree
*isl_schedule_tree_domain_set_domain(
1308 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
1310 tree
= isl_schedule_tree_cow(tree
);
1311 if (!tree
|| !domain
)
1314 if (tree
->type
!= isl_schedule_node_domain
)
1315 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1316 "not a domain node", goto error
);
1318 isl_union_set_free(tree
->domain
);
1319 tree
->domain
= domain
;
1323 isl_schedule_tree_free(tree
);
1324 isl_union_set_free(domain
);
1328 /* Return the contraction of the expansion tree root.
1330 __isl_give isl_union_pw_multi_aff
*isl_schedule_tree_expansion_get_contraction(
1331 __isl_keep isl_schedule_tree
*tree
)
1336 if (tree
->type
!= isl_schedule_node_expansion
)
1337 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1338 "not an expansion node", return NULL
);
1340 return isl_union_pw_multi_aff_copy(tree
->contraction
);
1343 /* Return the expansion of the expansion tree root.
1345 __isl_give isl_union_map
*isl_schedule_tree_expansion_get_expansion(
1346 __isl_keep isl_schedule_tree
*tree
)
1351 if (tree
->type
!= isl_schedule_node_expansion
)
1352 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1353 "not an expansion node", return NULL
);
1355 return isl_union_map_copy(tree
->expansion
);
1358 /* Replace the contraction and the expansion of the expansion tree root "tree"
1359 * by "contraction" and "expansion".
1361 __isl_give isl_schedule_tree
*
1362 isl_schedule_tree_expansion_set_contraction_and_expansion(
1363 __isl_take isl_schedule_tree
*tree
,
1364 __isl_take isl_union_pw_multi_aff
*contraction
,
1365 __isl_take isl_union_map
*expansion
)
1367 tree
= isl_schedule_tree_cow(tree
);
1368 if (!tree
|| !contraction
|| !expansion
)
1371 if (tree
->type
!= isl_schedule_node_expansion
)
1372 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1373 "not an expansion node", return NULL
);
1375 isl_union_pw_multi_aff_free(tree
->contraction
);
1376 tree
->contraction
= contraction
;
1377 isl_union_map_free(tree
->expansion
);
1378 tree
->expansion
= expansion
;
1382 isl_schedule_tree_free(tree
);
1383 isl_union_pw_multi_aff_free(contraction
);
1384 isl_union_map_free(expansion
);
1388 /* Return the extension of the extension tree root.
1390 __isl_give isl_union_map
*isl_schedule_tree_extension_get_extension(
1391 __isl_take isl_schedule_tree
*tree
)
1396 if (tree
->type
!= isl_schedule_node_extension
)
1397 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1398 "not an extension node", return NULL
);
1400 return isl_union_map_copy(tree
->extension
);
1403 /* Replace the extension of extension tree root "tree" by "extension".
1405 __isl_give isl_schedule_tree
*isl_schedule_tree_extension_set_extension(
1406 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_map
*extension
)
1408 tree
= isl_schedule_tree_cow(tree
);
1409 if (!tree
|| !extension
)
1412 if (tree
->type
!= isl_schedule_node_extension
)
1413 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1414 "not an extension node", return NULL
);
1415 isl_union_map_free(tree
->extension
);
1416 tree
->extension
= extension
;
1420 isl_schedule_tree_free(tree
);
1421 isl_union_map_free(extension
);
1425 /* Return the filter of the filter tree root.
1427 __isl_give isl_union_set
*isl_schedule_tree_filter_get_filter(
1428 __isl_keep isl_schedule_tree
*tree
)
1433 if (tree
->type
!= isl_schedule_node_filter
)
1434 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1435 "not a filter node", return NULL
);
1437 return isl_union_set_copy(tree
->filter
);
1440 /* Replace the filter of the filter tree root by "filter".
1442 __isl_give isl_schedule_tree
*isl_schedule_tree_filter_set_filter(
1443 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
1445 tree
= isl_schedule_tree_cow(tree
);
1446 if (!tree
|| !filter
)
1449 if (tree
->type
!= isl_schedule_node_filter
)
1450 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1451 "not a filter node", return NULL
);
1453 isl_union_set_free(tree
->filter
);
1454 tree
->filter
= filter
;
1458 isl_schedule_tree_free(tree
);
1459 isl_union_set_free(filter
);
1463 /* Return the guard of the guard tree root.
1465 __isl_give isl_set
*isl_schedule_tree_guard_get_guard(
1466 __isl_take isl_schedule_tree
*tree
)
1471 if (tree
->type
!= isl_schedule_node_guard
)
1472 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1473 "not a guard node", return NULL
);
1475 return isl_set_copy(tree
->guard
);
1478 /* Return the mark identifier of the mark tree root "tree".
1480 __isl_give isl_id
*isl_schedule_tree_mark_get_id(
1481 __isl_keep isl_schedule_tree
*tree
)
1486 if (tree
->type
!= isl_schedule_node_mark
)
1487 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1488 "not a mark node", return NULL
);
1490 return isl_id_copy(tree
->mark
);
1493 /* Set dim to the range dimension of "map" and abort the search.
1495 static isl_stat
set_range_dim(__isl_take isl_map
*map
, void *user
)
1499 *dim
= isl_map_dim(map
, isl_dim_out
);
1502 return isl_stat_error
;
1505 /* Return the dimension of the range of "umap".
1506 * "umap" is assumed not to be empty and
1507 * all maps inside "umap" are assumed to have the same range.
1509 * We extract the range dimension from the first map in "umap".
1511 static int range_dim(__isl_keep isl_union_map
*umap
)
1517 if (isl_union_map_n_map(umap
) == 0)
1518 isl_die(isl_union_map_get_ctx(umap
), isl_error_internal
,
1519 "unexpected empty input", return -1);
1521 isl_union_map_foreach_map(umap
, &set_range_dim
, &dim
);
1526 /* Append an "extra" number of zeros to the range of "umap" and
1527 * return the result.
1529 static __isl_give isl_union_map
*append_range(__isl_take isl_union_map
*umap
,
1535 isl_union_pw_multi_aff
*suffix
;
1536 isl_union_map
*universe
;
1537 isl_union_map
*suffix_umap
;
1539 universe
= isl_union_map_universe(isl_union_map_copy(umap
));
1540 dom
= isl_union_map_domain(universe
);
1541 space
= isl_union_set_get_space(dom
);
1542 space
= isl_space_set_from_params(space
);
1543 space
= isl_space_add_dims(space
, isl_dim_set
, extra
);
1544 mv
= isl_multi_val_zero(space
);
1546 suffix
= isl_union_pw_multi_aff_multi_val_on_domain(dom
, mv
);
1547 suffix_umap
= isl_union_map_from_union_pw_multi_aff(suffix
);
1548 umap
= isl_union_map_flat_range_product(umap
, suffix_umap
);
1553 /* Should we skip the root of "tree" while looking for the first
1554 * descendant with schedule information?
1555 * That is, is it impossible to derive any information about
1556 * the iteration domain from this node?
1558 * We do not want to skip leaf or error nodes because there is
1559 * no point in looking any deeper from these nodes.
1560 * We can only extract partial iteration domain information
1561 * from an extension node, but extension nodes are not supported
1562 * by the caller and it will error out on them.
1564 static int domain_less(__isl_keep isl_schedule_tree
*tree
)
1566 enum isl_schedule_node_type type
;
1568 type
= isl_schedule_tree_get_type(tree
);
1570 case isl_schedule_node_band
:
1571 return isl_schedule_tree_band_n_member(tree
) == 0;
1572 case isl_schedule_node_context
:
1573 case isl_schedule_node_guard
:
1574 case isl_schedule_node_mark
:
1576 case isl_schedule_node_leaf
:
1577 case isl_schedule_node_error
:
1578 case isl_schedule_node_domain
:
1579 case isl_schedule_node_expansion
:
1580 case isl_schedule_node_extension
:
1581 case isl_schedule_node_filter
:
1582 case isl_schedule_node_set
:
1583 case isl_schedule_node_sequence
:
1587 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1588 "unhandled case", return 0);
1591 /* Move down to the first descendant of "tree" that contains any schedule
1592 * information or return "leaf" if there is no such descendant.
1594 __isl_give isl_schedule_tree
*isl_schedule_tree_first_schedule_descendant(
1595 __isl_take isl_schedule_tree
*tree
, __isl_keep isl_schedule_tree
*leaf
)
1597 while (domain_less(tree
)) {
1598 if (!isl_schedule_tree_has_children(tree
)) {
1599 isl_schedule_tree_free(tree
);
1600 return isl_schedule_tree_copy(leaf
);
1602 tree
= isl_schedule_tree_child(tree
, 0);
1608 static __isl_give isl_union_map
*subtree_schedule_extend(
1609 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
);
1611 /* Extend the schedule map "outer" with the subtree schedule
1612 * of the (single) child of "tree", if any.
1614 * If "tree" does not have any descendants (apart from those that
1615 * do not carry any schedule information), then we simply return "outer".
1616 * Otherwise, we extend the schedule map "outer" with the subtree schedule
1617 * of the single child.
1619 static __isl_give isl_union_map
*subtree_schedule_extend_child(
1620 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1622 isl_schedule_tree
*child
;
1626 return isl_union_map_free(outer
);
1627 if (!isl_schedule_tree_has_children(tree
))
1629 child
= isl_schedule_tree_get_child(tree
, 0);
1631 return isl_union_map_free(outer
);
1632 res
= subtree_schedule_extend(child
, outer
);
1633 isl_schedule_tree_free(child
);
1637 /* Extract the parameter space from one of the children of "tree",
1638 * which are assumed to be filters.
1640 static __isl_give isl_space
*extract_space_from_filter_child(
1641 __isl_keep isl_schedule_tree
*tree
)
1645 isl_schedule_tree
*child
;
1647 child
= isl_schedule_tree_list_get_schedule_tree(tree
->children
, 0);
1648 dom
= isl_schedule_tree_filter_get_filter(child
);
1649 space
= isl_union_set_get_space(dom
);
1650 isl_union_set_free(dom
);
1651 isl_schedule_tree_free(child
);
1656 /* Extend the schedule map "outer" with the subtree schedule
1657 * of a set or sequence node.
1659 * The schedule for the set or sequence node itself is composed of
1660 * pieces of the form
1668 * The first form is used if there is only a single child or
1669 * if the current node is a set node and the schedule_separate_components
1670 * option is not set.
1672 * Each of the pieces above is extended with the subtree schedule of
1673 * the child of the corresponding filter, if any, padded with zeros
1674 * to ensure that all pieces have the same range dimension.
1676 static __isl_give isl_union_map
*subtree_schedule_extend_from_children(
1677 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1686 isl_union_map
*umap
;
1691 ctx
= isl_schedule_tree_get_ctx(tree
);
1692 if (!tree
->children
)
1693 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1694 "missing children", return NULL
);
1695 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
1697 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1698 "missing children", return NULL
);
1700 separate
= n
> 1 && (tree
->type
== isl_schedule_node_sequence
||
1701 isl_options_get_schedule_separate_components(ctx
));
1703 space
= extract_space_from_filter_child(tree
);
1705 umap
= isl_union_map_empty(isl_space_copy(space
));
1706 space
= isl_space_set_from_params(space
);
1708 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
1709 v
= isl_val_zero(ctx
);
1711 mv
= isl_multi_val_zero(space
);
1713 dim
= isl_multi_val_dim(mv
, isl_dim_set
);
1714 for (i
= 0; i
< n
; ++i
) {
1715 isl_union_pw_multi_aff
*upma
;
1716 isl_union_map
*umap_i
;
1718 isl_schedule_tree
*child
;
1722 child
= isl_schedule_tree_list_get_schedule_tree(
1724 dom
= isl_schedule_tree_filter_get_filter(child
);
1727 mv
= isl_multi_val_set_val(mv
, 0, isl_val_copy(v
));
1728 v
= isl_val_add_ui(v
, 1);
1730 upma
= isl_union_pw_multi_aff_multi_val_on_domain(dom
,
1731 isl_multi_val_copy(mv
));
1732 umap_i
= isl_union_map_from_union_pw_multi_aff(upma
);
1733 umap_i
= isl_union_map_flat_range_product(
1734 isl_union_map_copy(outer
), umap_i
);
1735 umap_i
= subtree_schedule_extend_child(child
, umap_i
);
1736 isl_schedule_tree_free(child
);
1738 empty
= isl_union_map_is_empty(umap_i
);
1740 umap_i
= isl_union_map_free(umap_i
);
1742 isl_union_map_free(umap_i
);
1746 dim_i
= range_dim(umap_i
);
1748 umap
= isl_union_map_free(umap
);
1749 } else if (dim
< dim_i
) {
1750 umap
= append_range(umap
, dim_i
- dim
);
1752 } else if (dim_i
< dim
) {
1753 umap_i
= append_range(umap_i
, dim
- dim_i
);
1755 umap
= isl_union_map_union(umap
, umap_i
);
1759 isl_multi_val_free(mv
);
1760 isl_union_map_free(outer
);
1765 /* Extend the schedule map "outer" with the subtree schedule of "tree".
1767 * If the root of the tree is a set or a sequence, then we extend
1768 * the schedule map in subtree_schedule_extend_from_children.
1769 * Otherwise, we extend the schedule map with the partial schedule
1770 * corresponding to the root of the tree and then continue with
1771 * the single child of this root.
1772 * In the special case of an expansion, the schedule map is "extended"
1773 * by applying the expansion to the domain of the schedule map.
1775 static __isl_give isl_union_map
*subtree_schedule_extend(
1776 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1778 isl_multi_union_pw_aff
*mupa
;
1779 isl_union_map
*umap
;
1780 isl_union_set
*domain
;
1785 switch (tree
->type
) {
1786 case isl_schedule_node_error
:
1787 return isl_union_map_free(outer
);
1788 case isl_schedule_node_extension
:
1789 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1790 "cannot construct subtree schedule of tree "
1791 "with extension nodes",
1792 return isl_union_map_free(outer
));
1793 case isl_schedule_node_context
:
1794 case isl_schedule_node_guard
:
1795 case isl_schedule_node_mark
:
1796 return subtree_schedule_extend_child(tree
, outer
);
1797 case isl_schedule_node_band
:
1798 if (isl_schedule_tree_band_n_member(tree
) == 0)
1799 return subtree_schedule_extend_child(tree
, outer
);
1800 mupa
= isl_schedule_band_get_partial_schedule(tree
->band
);
1801 umap
= isl_union_map_from_multi_union_pw_aff(mupa
);
1802 outer
= isl_union_map_flat_range_product(outer
, umap
);
1803 umap
= subtree_schedule_extend_child(tree
, outer
);
1805 case isl_schedule_node_domain
:
1806 domain
= isl_schedule_tree_domain_get_domain(tree
);
1807 umap
= isl_union_map_from_domain(domain
);
1808 outer
= isl_union_map_flat_range_product(outer
, umap
);
1809 umap
= subtree_schedule_extend_child(tree
, outer
);
1811 case isl_schedule_node_expansion
:
1812 umap
= isl_schedule_tree_expansion_get_expansion(tree
);
1813 outer
= isl_union_map_apply_domain(outer
, umap
);
1814 umap
= subtree_schedule_extend_child(tree
, outer
);
1816 case isl_schedule_node_filter
:
1817 domain
= isl_schedule_tree_filter_get_filter(tree
);
1818 umap
= isl_union_map_from_domain(domain
);
1819 outer
= isl_union_map_flat_range_product(outer
, umap
);
1820 umap
= subtree_schedule_extend_child(tree
, outer
);
1822 case isl_schedule_node_leaf
:
1823 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1824 "leaf node should be handled by caller", return NULL
);
1825 case isl_schedule_node_set
:
1826 case isl_schedule_node_sequence
:
1827 umap
= subtree_schedule_extend_from_children(tree
, outer
);
1834 static __isl_give isl_union_set
*initial_domain(
1835 __isl_keep isl_schedule_tree
*tree
);
1837 /* Extract a universe domain from the children of the tree root "tree",
1838 * which is a set or sequence, meaning that its children are filters.
1839 * In particular, return the union of the universes of the filters.
1841 static __isl_give isl_union_set
*initial_domain_from_children(
1842 __isl_keep isl_schedule_tree
*tree
)
1846 isl_union_set
*domain
;
1848 if (!tree
->children
)
1849 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1850 "missing children", return NULL
);
1851 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
1853 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1854 "missing children", return NULL
);
1856 space
= extract_space_from_filter_child(tree
);
1857 domain
= isl_union_set_empty(space
);
1859 for (i
= 0; i
< n
; ++i
) {
1860 isl_schedule_tree
*child
;
1861 isl_union_set
*domain_i
;
1863 child
= isl_schedule_tree_get_child(tree
, i
);
1864 domain_i
= initial_domain(child
);
1865 domain
= isl_union_set_union(domain
, domain_i
);
1866 isl_schedule_tree_free(child
);
1872 /* Extract a universe domain from the tree root "tree".
1873 * The caller is responsible for making sure that this node
1874 * would not be skipped by isl_schedule_tree_first_schedule_descendant
1875 * and that it is not a leaf node.
1877 static __isl_give isl_union_set
*initial_domain(
1878 __isl_keep isl_schedule_tree
*tree
)
1880 isl_multi_union_pw_aff
*mupa
;
1881 isl_union_set
*domain
;
1887 switch (tree
->type
) {
1888 case isl_schedule_node_error
:
1890 case isl_schedule_node_context
:
1891 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1892 "context node should be handled by caller",
1894 case isl_schedule_node_guard
:
1895 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1896 "guard node should be handled by caller",
1898 case isl_schedule_node_mark
:
1899 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1900 "mark node should be handled by caller",
1902 case isl_schedule_node_extension
:
1903 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1904 "cannot construct subtree schedule of tree "
1905 "with extension nodes", return NULL
);
1906 case isl_schedule_node_band
:
1907 if (isl_schedule_tree_band_n_member(tree
) == 0)
1908 isl_die(isl_schedule_tree_get_ctx(tree
),
1910 "0D band should be handled by caller",
1912 mupa
= isl_schedule_band_get_partial_schedule(tree
->band
);
1913 domain
= isl_multi_union_pw_aff_domain(mupa
);
1914 domain
= isl_union_set_universe(domain
);
1916 case isl_schedule_node_domain
:
1917 domain
= isl_schedule_tree_domain_get_domain(tree
);
1918 domain
= isl_union_set_universe(domain
);
1920 case isl_schedule_node_expansion
:
1921 exp
= isl_schedule_tree_expansion_get_expansion(tree
);
1922 exp
= isl_union_map_universe(exp
);
1923 domain
= isl_union_map_domain(exp
);
1925 case isl_schedule_node_filter
:
1926 domain
= isl_schedule_tree_filter_get_filter(tree
);
1927 domain
= isl_union_set_universe(domain
);
1929 case isl_schedule_node_leaf
:
1930 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1931 "leaf node should be handled by caller", return NULL
);
1932 case isl_schedule_node_set
:
1933 case isl_schedule_node_sequence
:
1934 domain
= initial_domain_from_children(tree
);
1941 /* Return the subtree schedule of a node that contains some schedule
1942 * information, i.e., a node that would not be skipped by
1943 * isl_schedule_tree_first_schedule_descendant and that is not a leaf.
1945 * If the tree contains any expansions, then the returned subtree
1946 * schedule is formulated in terms of the expanded domains.
1947 * The tree is not allowed to contain any extension nodes.
1949 * We start with an initial zero-dimensional subtree schedule based
1950 * on the domain information in the root node and then extend it
1951 * based on the schedule information in the root node and its descendants.
1953 __isl_give isl_union_map
*isl_schedule_tree_get_subtree_schedule_union_map(
1954 __isl_keep isl_schedule_tree
*tree
)
1956 isl_union_set
*domain
;
1957 isl_union_map
*umap
;
1959 domain
= initial_domain(tree
);
1960 umap
= isl_union_map_from_domain(domain
);
1961 return subtree_schedule_extend(tree
, umap
);
1964 /* Multiply the partial schedule of the band root node of "tree"
1965 * with the factors in "mv".
1967 __isl_give isl_schedule_tree
*isl_schedule_tree_band_scale(
1968 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
1972 if (tree
->type
!= isl_schedule_node_band
)
1973 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1974 "not a band node", goto error
);
1976 tree
= isl_schedule_tree_cow(tree
);
1980 tree
->band
= isl_schedule_band_scale(tree
->band
, mv
);
1982 return isl_schedule_tree_free(tree
);
1986 isl_schedule_tree_free(tree
);
1987 isl_multi_val_free(mv
);
1991 /* Divide the partial schedule of the band root node of "tree"
1992 * by the factors in "mv".
1994 __isl_give isl_schedule_tree
*isl_schedule_tree_band_scale_down(
1995 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
1999 if (tree
->type
!= isl_schedule_node_band
)
2000 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2001 "not a band node", goto error
);
2003 tree
= isl_schedule_tree_cow(tree
);
2007 tree
->band
= isl_schedule_band_scale_down(tree
->band
, mv
);
2009 return isl_schedule_tree_free(tree
);
2013 isl_schedule_tree_free(tree
);
2014 isl_multi_val_free(mv
);
2018 /* Reduce the partial schedule of the band root node of "tree"
2019 * modulo the factors in "mv".
2021 __isl_give isl_schedule_tree
*isl_schedule_tree_band_mod(
2022 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
2026 if (tree
->type
!= isl_schedule_node_band
)
2027 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2028 "not a band node", goto error
);
2030 tree
= isl_schedule_tree_cow(tree
);
2034 tree
->band
= isl_schedule_band_mod(tree
->band
, mv
);
2036 return isl_schedule_tree_free(tree
);
2040 isl_schedule_tree_free(tree
);
2041 isl_multi_val_free(mv
);
2045 /* Shift the partial schedule of the band root node of "tree" by "shift".
2047 __isl_give isl_schedule_tree
*isl_schedule_tree_band_shift(
2048 __isl_take isl_schedule_tree
*tree
,
2049 __isl_take isl_multi_union_pw_aff
*shift
)
2051 if (!tree
|| !shift
)
2053 if (tree
->type
!= isl_schedule_node_band
)
2054 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2055 "not a band node", goto error
);
2057 tree
= isl_schedule_tree_cow(tree
);
2061 tree
->band
= isl_schedule_band_shift(tree
->band
, shift
);
2063 return isl_schedule_tree_free(tree
);
2067 isl_schedule_tree_free(tree
);
2068 isl_multi_union_pw_aff_free(shift
);
2072 /* Given two trees with sequence roots, replace the child at position
2073 * "pos" of "tree" with the children of "child".
2075 __isl_give isl_schedule_tree
*isl_schedule_tree_sequence_splice(
2076 __isl_take isl_schedule_tree
*tree
, int pos
,
2077 __isl_take isl_schedule_tree
*child
)
2080 isl_schedule_tree_list
*list1
, *list2
;
2082 tree
= isl_schedule_tree_cow(tree
);
2083 if (!tree
|| !child
)
2085 if (isl_schedule_tree_get_type(tree
) != isl_schedule_node_sequence
)
2086 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2087 "not a sequence node", goto error
);
2088 n
= isl_schedule_tree_n_children(tree
);
2089 if (pos
< 0 || pos
>= n
)
2090 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2091 "position out of bounds", goto error
);
2092 if (isl_schedule_tree_get_type(child
) != isl_schedule_node_sequence
)
2093 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2094 "not a sequence node", goto error
);
2096 list1
= isl_schedule_tree_list_copy(tree
->children
);
2097 list1
= isl_schedule_tree_list_drop(list1
, pos
, n
- pos
);
2098 list2
= isl_schedule_tree_list_copy(tree
->children
);
2099 list2
= isl_schedule_tree_list_drop(list2
, 0, pos
+ 1);
2100 list1
= isl_schedule_tree_list_concat(list1
,
2101 isl_schedule_tree_list_copy(child
->children
));
2102 list1
= isl_schedule_tree_list_concat(list1
, list2
);
2104 isl_schedule_tree_free(tree
);
2105 isl_schedule_tree_free(child
);
2106 return isl_schedule_tree_from_children(isl_schedule_node_sequence
,
2109 isl_schedule_tree_free(tree
);
2110 isl_schedule_tree_free(child
);
2114 /* Tile the band root node of "tree" with tile sizes "sizes".
2116 * We duplicate the band node, change the schedule of one of them
2117 * to the tile schedule and the other to the point schedule and then
2118 * attach the point band as a child to the tile band.
2120 __isl_give isl_schedule_tree
*isl_schedule_tree_band_tile(
2121 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*sizes
)
2123 isl_schedule_tree
*child
= NULL
;
2125 if (!tree
|| !sizes
)
2127 if (tree
->type
!= isl_schedule_node_band
)
2128 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2129 "not a band node", goto error
);
2131 child
= isl_schedule_tree_copy(tree
);
2132 tree
= isl_schedule_tree_cow(tree
);
2133 child
= isl_schedule_tree_cow(child
);
2134 if (!tree
|| !child
)
2137 tree
->band
= isl_schedule_band_tile(tree
->band
,
2138 isl_multi_val_copy(sizes
));
2141 child
->band
= isl_schedule_band_point(child
->band
, tree
->band
, sizes
);
2143 child
= isl_schedule_tree_free(child
);
2145 tree
= isl_schedule_tree_replace_child(tree
, 0, child
);
2149 isl_schedule_tree_free(child
);
2150 isl_schedule_tree_free(tree
);
2151 isl_multi_val_free(sizes
);
2155 /* Split the band root node of "tree" into two nested band nodes,
2156 * one with the first "pos" dimensions and
2157 * one with the remaining dimensions.
2159 __isl_give isl_schedule_tree
*isl_schedule_tree_band_split(
2160 __isl_take isl_schedule_tree
*tree
, int pos
)
2163 isl_schedule_tree
*child
;
2167 if (tree
->type
!= isl_schedule_node_band
)
2168 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2169 "not a band node", return isl_schedule_tree_free(tree
));
2171 n
= isl_schedule_tree_band_n_member(tree
);
2172 if (pos
< 0 || pos
> n
)
2173 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2174 "position out of bounds",
2175 return isl_schedule_tree_free(tree
));
2177 child
= isl_schedule_tree_copy(tree
);
2178 tree
= isl_schedule_tree_cow(tree
);
2179 child
= isl_schedule_tree_cow(child
);
2180 if (!tree
|| !child
)
2183 child
->band
= isl_schedule_band_drop(child
->band
, 0, pos
);
2184 tree
->band
= isl_schedule_band_drop(tree
->band
, pos
, n
- pos
);
2185 if (!child
->band
|| !tree
->band
)
2188 tree
= isl_schedule_tree_replace_child(tree
, 0, child
);
2192 isl_schedule_tree_free(child
);
2193 isl_schedule_tree_free(tree
);
2197 /* Attach "tree2" at each of the leaves of "tree1".
2199 * If "tree1" does not have any explicit children, then make "tree2"
2200 * its single child. Otherwise, attach "tree2" to the leaves of
2201 * each of the children of "tree1".
2203 __isl_give isl_schedule_tree
*isl_schedule_tree_append_to_leaves(
2204 __isl_take isl_schedule_tree
*tree1
,
2205 __isl_take isl_schedule_tree
*tree2
)
2209 if (!tree1
|| !tree2
)
2211 n
= isl_schedule_tree_n_children(tree1
);
2213 isl_schedule_tree_list
*list
;
2214 list
= isl_schedule_tree_list_from_schedule_tree(tree2
);
2215 tree1
= isl_schedule_tree_set_children(tree1
, list
);
2218 for (i
= 0; i
< n
; ++i
) {
2219 isl_schedule_tree
*child
;
2221 child
= isl_schedule_tree_get_child(tree1
, i
);
2222 child
= isl_schedule_tree_append_to_leaves(child
,
2223 isl_schedule_tree_copy(tree2
));
2224 tree1
= isl_schedule_tree_replace_child(tree1
, i
, child
);
2227 isl_schedule_tree_free(tree2
);
2230 isl_schedule_tree_free(tree1
);
2231 isl_schedule_tree_free(tree2
);
2235 /* Reset the user pointer on all identifiers of parameters and tuples
2236 * in the root of "tree".
2238 __isl_give isl_schedule_tree
*isl_schedule_tree_reset_user(
2239 __isl_take isl_schedule_tree
*tree
)
2241 if (isl_schedule_tree_is_leaf(tree
))
2244 tree
= isl_schedule_tree_cow(tree
);
2248 switch (tree
->type
) {
2249 case isl_schedule_node_error
:
2250 return isl_schedule_tree_free(tree
);
2251 case isl_schedule_node_band
:
2252 tree
->band
= isl_schedule_band_reset_user(tree
->band
);
2254 return isl_schedule_tree_free(tree
);
2256 case isl_schedule_node_context
:
2257 tree
->context
= isl_set_reset_user(tree
->context
);
2259 return isl_schedule_tree_free(tree
);
2261 case isl_schedule_node_domain
:
2262 tree
->domain
= isl_union_set_reset_user(tree
->domain
);
2264 return isl_schedule_tree_free(tree
);
2266 case isl_schedule_node_expansion
:
2268 isl_union_pw_multi_aff_reset_user(tree
->contraction
);
2269 tree
->expansion
= isl_union_map_reset_user(tree
->expansion
);
2270 if (!tree
->contraction
|| !tree
->expansion
)
2271 return isl_schedule_tree_free(tree
);
2273 case isl_schedule_node_extension
:
2274 tree
->extension
= isl_union_map_reset_user(tree
->extension
);
2275 if (!tree
->extension
)
2276 return isl_schedule_tree_free(tree
);
2278 case isl_schedule_node_filter
:
2279 tree
->filter
= isl_union_set_reset_user(tree
->filter
);
2281 return isl_schedule_tree_free(tree
);
2283 case isl_schedule_node_guard
:
2284 tree
->guard
= isl_set_reset_user(tree
->guard
);
2286 return isl_schedule_tree_free(tree
);
2288 case isl_schedule_node_leaf
:
2289 case isl_schedule_node_mark
:
2290 case isl_schedule_node_sequence
:
2291 case isl_schedule_node_set
:
2298 /* Align the parameters of the root of "tree" to those of "space".
2300 __isl_give isl_schedule_tree
*isl_schedule_tree_align_params(
2301 __isl_take isl_schedule_tree
*tree
, __isl_take isl_space
*space
)
2306 if (isl_schedule_tree_is_leaf(tree
)) {
2307 isl_space_free(space
);
2311 tree
= isl_schedule_tree_cow(tree
);
2315 switch (tree
->type
) {
2316 case isl_schedule_node_error
:
2318 case isl_schedule_node_band
:
2319 tree
->band
= isl_schedule_band_align_params(tree
->band
, space
);
2321 return isl_schedule_tree_free(tree
);
2323 case isl_schedule_node_context
:
2324 tree
->context
= isl_set_align_params(tree
->context
, space
);
2326 return isl_schedule_tree_free(tree
);
2328 case isl_schedule_node_domain
:
2329 tree
->domain
= isl_union_set_align_params(tree
->domain
, space
);
2331 return isl_schedule_tree_free(tree
);
2333 case isl_schedule_node_expansion
:
2335 isl_union_pw_multi_aff_align_params(tree
->contraction
,
2336 isl_space_copy(space
));
2337 tree
->expansion
= isl_union_map_align_params(tree
->expansion
,
2339 if (!tree
->contraction
|| !tree
->expansion
)
2340 return isl_schedule_tree_free(tree
);
2342 case isl_schedule_node_extension
:
2343 tree
->extension
= isl_union_map_align_params(tree
->extension
,
2345 if (!tree
->extension
)
2346 return isl_schedule_tree_free(tree
);
2348 case isl_schedule_node_filter
:
2349 tree
->filter
= isl_union_set_align_params(tree
->filter
, space
);
2351 return isl_schedule_tree_free(tree
);
2353 case isl_schedule_node_guard
:
2354 tree
->guard
= isl_set_align_params(tree
->guard
, space
);
2356 return isl_schedule_tree_free(tree
);
2358 case isl_schedule_node_leaf
:
2359 case isl_schedule_node_mark
:
2360 case isl_schedule_node_sequence
:
2361 case isl_schedule_node_set
:
2362 isl_space_free(space
);
2368 isl_space_free(space
);
2369 isl_schedule_tree_free(tree
);
2373 /* Does "tree" involve the iteration domain?
2374 * That is, does it need to be modified
2375 * by isl_schedule_tree_pullback_union_pw_multi_aff?
2377 static int involves_iteration_domain(__isl_keep isl_schedule_tree
*tree
)
2382 switch (tree
->type
) {
2383 case isl_schedule_node_error
:
2385 case isl_schedule_node_band
:
2386 case isl_schedule_node_domain
:
2387 case isl_schedule_node_expansion
:
2388 case isl_schedule_node_extension
:
2389 case isl_schedule_node_filter
:
2391 case isl_schedule_node_context
:
2392 case isl_schedule_node_leaf
:
2393 case isl_schedule_node_guard
:
2394 case isl_schedule_node_mark
:
2395 case isl_schedule_node_sequence
:
2396 case isl_schedule_node_set
:
2400 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
2401 "unhandled case", return -1);
2404 /* Compute the pullback of the root node of "tree" by the function
2405 * represented by "upma".
2406 * In other words, plug in "upma" in the iteration domains of
2407 * the root node of "tree".
2408 * We currently do not handle expansion nodes.
2410 * We first check if the root node involves any iteration domains.
2411 * If so, we handle the specific cases.
2413 __isl_give isl_schedule_tree
*isl_schedule_tree_pullback_union_pw_multi_aff(
2414 __isl_take isl_schedule_tree
*tree
,
2415 __isl_take isl_union_pw_multi_aff
*upma
)
2422 involves
= involves_iteration_domain(tree
);
2426 isl_union_pw_multi_aff_free(upma
);
2430 tree
= isl_schedule_tree_cow(tree
);
2434 if (tree
->type
== isl_schedule_node_band
) {
2435 tree
->band
= isl_schedule_band_pullback_union_pw_multi_aff(
2438 return isl_schedule_tree_free(tree
);
2439 } else if (tree
->type
== isl_schedule_node_domain
) {
2441 isl_union_set_preimage_union_pw_multi_aff(tree
->domain
,
2444 return isl_schedule_tree_free(tree
);
2445 } else if (tree
->type
== isl_schedule_node_expansion
) {
2446 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_unsupported
,
2447 "cannot pullback expansion node", goto error
);
2448 } else if (tree
->type
== isl_schedule_node_extension
) {
2450 isl_union_map_preimage_range_union_pw_multi_aff(
2451 tree
->extension
, upma
);
2452 if (!tree
->extension
)
2453 return isl_schedule_tree_free(tree
);
2454 } else if (tree
->type
== isl_schedule_node_filter
) {
2456 isl_union_set_preimage_union_pw_multi_aff(tree
->filter
,
2459 return isl_schedule_tree_free(tree
);
2464 isl_union_pw_multi_aff_free(upma
);
2465 isl_schedule_tree_free(tree
);
2469 /* Compute the gist of the band tree root with respect to "context".
2471 __isl_give isl_schedule_tree
*isl_schedule_tree_band_gist(
2472 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*context
)
2476 if (tree
->type
!= isl_schedule_node_band
)
2477 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2478 "not a band node", goto error
);
2479 tree
= isl_schedule_tree_cow(tree
);
2483 tree
->band
= isl_schedule_band_gist(tree
->band
, context
);
2485 return isl_schedule_tree_free(tree
);
2488 isl_union_set_free(context
);
2489 isl_schedule_tree_free(tree
);
2493 /* Are any members in "band" marked coincident?
2495 static int any_coincident(__isl_keep isl_schedule_band
*band
)
2499 n
= isl_schedule_band_n_member(band
);
2500 for (i
= 0; i
< n
; ++i
)
2501 if (isl_schedule_band_member_get_coincident(band
, i
))
2507 /* Print the band node "band" to "p".
2509 * The permutable and coincident properties are only printed if they
2510 * are different from the defaults.
2511 * The coincident property is always printed in YAML flow style.
2513 static __isl_give isl_printer
*print_tree_band(__isl_take isl_printer
*p
,
2514 __isl_keep isl_schedule_band
*band
)
2516 isl_union_set
*options
;
2519 p
= isl_printer_print_str(p
, "schedule");
2520 p
= isl_printer_yaml_next(p
);
2521 p
= isl_printer_print_str(p
, "\"");
2522 p
= isl_printer_print_multi_union_pw_aff(p
, band
->mupa
);
2523 p
= isl_printer_print_str(p
, "\"");
2524 if (isl_schedule_band_get_permutable(band
)) {
2525 p
= isl_printer_yaml_next(p
);
2526 p
= isl_printer_print_str(p
, "permutable");
2527 p
= isl_printer_yaml_next(p
);
2528 p
= isl_printer_print_int(p
, 1);
2530 if (any_coincident(band
)) {
2534 p
= isl_printer_yaml_next(p
);
2535 p
= isl_printer_print_str(p
, "coincident");
2536 p
= isl_printer_yaml_next(p
);
2537 style
= isl_printer_get_yaml_style(p
);
2538 p
= isl_printer_set_yaml_style(p
, ISL_YAML_STYLE_FLOW
);
2539 p
= isl_printer_yaml_start_sequence(p
);
2540 n
= isl_schedule_band_n_member(band
);
2541 for (i
= 0; i
< n
; ++i
) {
2542 p
= isl_printer_print_int(p
,
2543 isl_schedule_band_member_get_coincident(band
, i
));
2544 p
= isl_printer_yaml_next(p
);
2546 p
= isl_printer_yaml_end_sequence(p
);
2547 p
= isl_printer_set_yaml_style(p
, style
);
2549 options
= isl_schedule_band_get_ast_build_options(band
);
2550 empty
= isl_union_set_is_empty(options
);
2552 p
= isl_printer_free(p
);
2554 p
= isl_printer_yaml_next(p
);
2555 p
= isl_printer_print_str(p
, "options");
2556 p
= isl_printer_yaml_next(p
);
2557 p
= isl_printer_print_str(p
, "\"");
2558 p
= isl_printer_print_union_set(p
, options
);
2559 p
= isl_printer_print_str(p
, "\"");
2561 isl_union_set_free(options
);
2566 /* Print "tree" to "p".
2568 * If "n_ancestor" is non-negative, then "child_pos" contains the child
2569 * positions of a descendant of the current node that should be marked
2570 * (by the comment "YOU ARE HERE"). In particular, if "n_ancestor"
2571 * is zero, then the current node should be marked.
2572 * The marking is only printed in YAML block format.
2574 * Implicit leaf nodes are not printed, except if they correspond
2575 * to the node that should be marked.
2577 __isl_give isl_printer
*isl_printer_print_schedule_tree_mark(
2578 __isl_take isl_printer
*p
, __isl_keep isl_schedule_tree
*tree
,
2579 int n_ancestor
, int *child_pos
)
2585 block
= isl_printer_get_yaml_style(p
) == ISL_YAML_STYLE_BLOCK
;
2587 p
= isl_printer_yaml_start_mapping(p
);
2588 if (n_ancestor
== 0 && block
) {
2589 p
= isl_printer_print_str(p
, "# YOU ARE HERE");
2590 p
= isl_printer_end_line(p
);
2591 p
= isl_printer_start_line(p
);
2593 switch (tree
->type
) {
2594 case isl_schedule_node_error
:
2595 p
= isl_printer_print_str(p
, "ERROR");
2597 case isl_schedule_node_leaf
:
2598 p
= isl_printer_print_str(p
, "leaf");
2600 case isl_schedule_node_sequence
:
2601 p
= isl_printer_print_str(p
, "sequence");
2604 case isl_schedule_node_set
:
2605 p
= isl_printer_print_str(p
, "set");
2608 case isl_schedule_node_context
:
2609 p
= isl_printer_print_str(p
, "context");
2610 p
= isl_printer_yaml_next(p
);
2611 p
= isl_printer_print_str(p
, "\"");
2612 p
= isl_printer_print_set(p
, tree
->context
);
2613 p
= isl_printer_print_str(p
, "\"");
2615 case isl_schedule_node_domain
:
2616 p
= isl_printer_print_str(p
, "domain");
2617 p
= isl_printer_yaml_next(p
);
2618 p
= isl_printer_print_str(p
, "\"");
2619 p
= isl_printer_print_union_set(p
, tree
->domain
);
2620 p
= isl_printer_print_str(p
, "\"");
2622 case isl_schedule_node_expansion
:
2623 p
= isl_printer_print_str(p
, "contraction");
2624 p
= isl_printer_yaml_next(p
);
2625 p
= isl_printer_print_str(p
, "\"");
2626 p
= isl_printer_print_union_pw_multi_aff(p
, tree
->contraction
);
2627 p
= isl_printer_print_str(p
, "\"");
2628 p
= isl_printer_yaml_next(p
);
2629 p
= isl_printer_print_str(p
, "expansion");
2630 p
= isl_printer_yaml_next(p
);
2631 p
= isl_printer_print_str(p
, "\"");
2632 p
= isl_printer_print_union_map(p
, tree
->expansion
);
2633 p
= isl_printer_print_str(p
, "\"");
2635 case isl_schedule_node_extension
:
2636 p
= isl_printer_print_str(p
, "extension");
2637 p
= isl_printer_yaml_next(p
);
2638 p
= isl_printer_print_str(p
, "\"");
2639 p
= isl_printer_print_union_map(p
, tree
->extension
);
2640 p
= isl_printer_print_str(p
, "\"");
2642 case isl_schedule_node_filter
:
2643 p
= isl_printer_print_str(p
, "filter");
2644 p
= isl_printer_yaml_next(p
);
2645 p
= isl_printer_print_str(p
, "\"");
2646 p
= isl_printer_print_union_set(p
, tree
->filter
);
2647 p
= isl_printer_print_str(p
, "\"");
2649 case isl_schedule_node_guard
:
2650 p
= isl_printer_print_str(p
, "guard");
2651 p
= isl_printer_yaml_next(p
);
2652 p
= isl_printer_print_str(p
, "\"");
2653 p
= isl_printer_print_set(p
, tree
->guard
);
2654 p
= isl_printer_print_str(p
, "\"");
2656 case isl_schedule_node_mark
:
2657 p
= isl_printer_print_str(p
, "mark");
2658 p
= isl_printer_yaml_next(p
);
2659 p
= isl_printer_print_str(p
, "\"");
2660 p
= isl_printer_print_str(p
, isl_id_get_name(tree
->mark
));
2661 p
= isl_printer_print_str(p
, "\"");
2663 case isl_schedule_node_band
:
2664 p
= print_tree_band(p
, tree
->band
);
2667 p
= isl_printer_yaml_next(p
);
2669 if (!tree
->children
) {
2670 if (n_ancestor
> 0 && block
) {
2671 isl_schedule_tree
*leaf
;
2673 p
= isl_printer_print_str(p
, "child");
2674 p
= isl_printer_yaml_next(p
);
2675 leaf
= isl_schedule_tree_leaf(isl_printer_get_ctx(p
));
2676 p
= isl_printer_print_schedule_tree_mark(p
,
2678 isl_schedule_tree_free(leaf
);
2679 p
= isl_printer_yaml_next(p
);
2681 return isl_printer_yaml_end_mapping(p
);
2685 p
= isl_printer_yaml_start_sequence(p
);
2687 p
= isl_printer_print_str(p
, "child");
2688 p
= isl_printer_yaml_next(p
);
2691 n
= isl_schedule_tree_list_n_schedule_tree(tree
->children
);
2692 for (i
= 0; i
< n
; ++i
) {
2693 isl_schedule_tree
*t
;
2695 t
= isl_schedule_tree_get_child(tree
, i
);
2696 if (n_ancestor
> 0 && child_pos
[0] == i
)
2697 p
= isl_printer_print_schedule_tree_mark(p
, t
,
2698 n_ancestor
- 1, child_pos
+ 1);
2700 p
= isl_printer_print_schedule_tree_mark(p
, t
,
2702 isl_schedule_tree_free(t
);
2704 p
= isl_printer_yaml_next(p
);
2708 p
= isl_printer_yaml_end_sequence(p
);
2709 p
= isl_printer_yaml_end_mapping(p
);
2714 /* Print "tree" to "p".
2716 __isl_give isl_printer
*isl_printer_print_schedule_tree(
2717 __isl_take isl_printer
*p
, __isl_keep isl_schedule_tree
*tree
)
2719 return isl_printer_print_schedule_tree_mark(p
, tree
, -1, NULL
);
2722 void isl_schedule_tree_dump(__isl_keep isl_schedule_tree
*tree
)
2725 isl_printer
*printer
;
2730 ctx
= isl_schedule_tree_get_ctx(tree
);
2731 printer
= isl_printer_to_file(ctx
, stderr
);
2732 printer
= isl_printer_set_yaml_style(printer
, ISL_YAML_STYLE_BLOCK
);
2733 printer
= isl_printer_print_schedule_tree(printer
, tree
);
2735 isl_printer_free(printer
);