2 * Copyright 2013-2014 Ecole Normale Superieure
3 * Copyright 2014 INRIA Rocquencourt
4 * Copyright 2016 INRIA Paris
6 * Use of this software is governed by the MIT license
8 * Written by Sven Verdoolaege,
9 * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
10 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
11 * B.P. 105 - 78153 Le Chesnay, France
12 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
13 * CS 42112, 75589 Paris Cedex 12, France
18 #include <isl/space.h>
20 #include <isl_schedule_band.h>
21 #include <isl_schedule_private.h>
24 #define EL isl_schedule_tree
26 #include <isl_list_templ.h>
29 #define BASE schedule_tree
31 #include <isl_list_templ.c>
33 /* Is "tree" the leaf of a schedule tree?
35 int isl_schedule_tree_is_leaf(__isl_keep isl_schedule_tree
*tree
)
37 return isl_schedule_tree_get_type(tree
) == isl_schedule_node_leaf
;
40 /* Create a new schedule tree of type "type".
41 * The caller is responsible for filling in the type specific fields and
44 * By default, the single node tree does not have any anchored nodes.
45 * The caller is responsible for updating the anchored field if needed.
47 static __isl_give isl_schedule_tree
*isl_schedule_tree_alloc(isl_ctx
*ctx
,
48 enum isl_schedule_node_type type
)
50 isl_schedule_tree
*tree
;
52 if (type
== isl_schedule_node_error
)
55 tree
= isl_calloc_type(ctx
, isl_schedule_tree
);
68 /* Return a fresh copy of "tree".
70 __isl_take isl_schedule_tree
*isl_schedule_tree_dup(
71 __isl_keep isl_schedule_tree
*tree
)
74 isl_schedule_tree
*dup
;
79 ctx
= isl_schedule_tree_get_ctx(tree
);
80 dup
= isl_schedule_tree_alloc(ctx
, tree
->type
);
85 case isl_schedule_node_error
:
86 isl_die(ctx
, isl_error_internal
,
87 "allocation should have failed",
88 return isl_schedule_tree_free(dup
));
89 case isl_schedule_node_band
:
90 dup
->band
= isl_schedule_band_copy(tree
->band
);
92 return isl_schedule_tree_free(dup
);
94 case isl_schedule_node_context
:
95 dup
->context
= isl_set_copy(tree
->context
);
97 return isl_schedule_tree_free(dup
);
99 case isl_schedule_node_domain
:
100 dup
->domain
= isl_union_set_copy(tree
->domain
);
102 return isl_schedule_tree_free(dup
);
104 case isl_schedule_node_expansion
:
106 isl_union_pw_multi_aff_copy(tree
->contraction
);
107 dup
->expansion
= isl_union_map_copy(tree
->expansion
);
108 if (!dup
->contraction
|| !dup
->expansion
)
109 return isl_schedule_tree_free(dup
);
111 case isl_schedule_node_extension
:
112 dup
->extension
= isl_union_map_copy(tree
->extension
);
114 return isl_schedule_tree_free(dup
);
116 case isl_schedule_node_filter
:
117 dup
->filter
= isl_union_set_copy(tree
->filter
);
119 return isl_schedule_tree_free(dup
);
121 case isl_schedule_node_guard
:
122 dup
->guard
= isl_set_copy(tree
->guard
);
124 return isl_schedule_tree_free(dup
);
126 case isl_schedule_node_mark
:
127 dup
->mark
= isl_id_copy(tree
->mark
);
129 return isl_schedule_tree_free(dup
);
131 case isl_schedule_node_leaf
:
132 case isl_schedule_node_sequence
:
133 case isl_schedule_node_set
:
137 if (tree
->children
) {
138 dup
->children
= isl_schedule_tree_list_copy(tree
->children
);
140 return isl_schedule_tree_free(dup
);
142 dup
->anchored
= tree
->anchored
;
147 /* Return an isl_schedule_tree that is equal to "tree" and that has only
148 * a single reference.
150 __isl_give isl_schedule_tree
*isl_schedule_tree_cow(
151 __isl_take isl_schedule_tree
*tree
)
159 return isl_schedule_tree_dup(tree
);
162 /* Return a new reference to "tree".
164 __isl_give isl_schedule_tree
*isl_schedule_tree_copy(
165 __isl_keep isl_schedule_tree
*tree
)
174 /* Free "tree" and return NULL.
176 __isl_null isl_schedule_tree
*isl_schedule_tree_free(
177 __isl_take isl_schedule_tree
*tree
)
184 switch (tree
->type
) {
185 case isl_schedule_node_band
:
186 isl_schedule_band_free(tree
->band
);
188 case isl_schedule_node_context
:
189 isl_set_free(tree
->context
);
191 case isl_schedule_node_domain
:
192 isl_union_set_free(tree
->domain
);
194 case isl_schedule_node_expansion
:
195 isl_union_pw_multi_aff_free(tree
->contraction
);
196 isl_union_map_free(tree
->expansion
);
198 case isl_schedule_node_extension
:
199 isl_union_map_free(tree
->extension
);
201 case isl_schedule_node_filter
:
202 isl_union_set_free(tree
->filter
);
204 case isl_schedule_node_guard
:
205 isl_set_free(tree
->guard
);
207 case isl_schedule_node_mark
:
208 isl_id_free(tree
->mark
);
210 case isl_schedule_node_sequence
:
211 case isl_schedule_node_set
:
212 case isl_schedule_node_error
:
213 case isl_schedule_node_leaf
:
216 isl_schedule_tree_list_free(tree
->children
);
217 isl_ctx_deref(tree
->ctx
);
223 /* Create and return a new leaf schedule tree.
225 __isl_give isl_schedule_tree
*isl_schedule_tree_leaf(isl_ctx
*ctx
)
227 return isl_schedule_tree_alloc(ctx
, isl_schedule_node_leaf
);
230 /* Create a new band schedule tree referring to "band"
233 __isl_give isl_schedule_tree
*isl_schedule_tree_from_band(
234 __isl_take isl_schedule_band
*band
)
237 isl_schedule_tree
*tree
;
242 ctx
= isl_schedule_band_get_ctx(band
);
243 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_band
);
248 tree
->anchored
= isl_schedule_band_is_anchored(band
);
252 isl_schedule_band_free(band
);
256 /* Create a new context schedule tree with the given context and no children.
257 * Since the context references the outer schedule dimension,
258 * the tree is anchored.
260 __isl_give isl_schedule_tree
*isl_schedule_tree_from_context(
261 __isl_take isl_set
*context
)
264 isl_schedule_tree
*tree
;
269 ctx
= isl_set_get_ctx(context
);
270 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_context
);
274 tree
->context
= context
;
279 isl_set_free(context
);
283 /* Create a new domain schedule tree with the given domain and no children.
285 __isl_give isl_schedule_tree
*isl_schedule_tree_from_domain(
286 __isl_take isl_union_set
*domain
)
289 isl_schedule_tree
*tree
;
294 ctx
= isl_union_set_get_ctx(domain
);
295 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_domain
);
299 tree
->domain
= domain
;
303 isl_union_set_free(domain
);
307 /* Create a new expansion schedule tree with the given contraction and
308 * expansion and no children.
310 __isl_give isl_schedule_tree
*isl_schedule_tree_from_expansion(
311 __isl_take isl_union_pw_multi_aff
*contraction
,
312 __isl_take isl_union_map
*expansion
)
315 isl_schedule_tree
*tree
;
317 if (!contraction
|| !expansion
)
320 ctx
= isl_union_map_get_ctx(expansion
);
321 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_expansion
);
325 tree
->contraction
= contraction
;
326 tree
->expansion
= expansion
;
330 isl_union_pw_multi_aff_free(contraction
);
331 isl_union_map_free(expansion
);
335 /* Create a new extension schedule tree with the given extension and
337 * Since the domain of the extension refers to the outer schedule dimension,
338 * the tree is anchored.
340 __isl_give isl_schedule_tree
*isl_schedule_tree_from_extension(
341 __isl_take isl_union_map
*extension
)
344 isl_schedule_tree
*tree
;
349 ctx
= isl_union_map_get_ctx(extension
);
350 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_extension
);
354 tree
->extension
= extension
;
359 isl_union_map_free(extension
);
363 /* Create a new filter schedule tree with the given filter and no children.
365 __isl_give isl_schedule_tree
*isl_schedule_tree_from_filter(
366 __isl_take isl_union_set
*filter
)
369 isl_schedule_tree
*tree
;
374 ctx
= isl_union_set_get_ctx(filter
);
375 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_filter
);
379 tree
->filter
= filter
;
383 isl_union_set_free(filter
);
387 /* Create a new guard schedule tree with the given guard and no children.
388 * Since the guard references the outer schedule dimension,
389 * the tree is anchored.
391 __isl_give isl_schedule_tree
*isl_schedule_tree_from_guard(
392 __isl_take isl_set
*guard
)
395 isl_schedule_tree
*tree
;
400 ctx
= isl_set_get_ctx(guard
);
401 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_guard
);
414 /* Create a new mark schedule tree with the given mark identifier and
417 __isl_give isl_schedule_tree
*isl_schedule_tree_from_mark(
418 __isl_take isl_id
*mark
)
421 isl_schedule_tree
*tree
;
426 ctx
= isl_id_get_ctx(mark
);
427 tree
= isl_schedule_tree_alloc(ctx
, isl_schedule_node_mark
);
439 /* Does "tree" have any node that depends on its position
440 * in the complete schedule tree?
442 isl_bool
isl_schedule_tree_is_subtree_anchored(
443 __isl_keep isl_schedule_tree
*tree
)
445 return tree
? tree
->anchored
: isl_bool_error
;
448 /* Does the root node of "tree" depend on its position in the complete
450 * Band nodes may be anchored depending on the associated AST build options.
451 * Context, extension and guard nodes are always anchored.
453 int isl_schedule_tree_is_anchored(__isl_keep isl_schedule_tree
*tree
)
458 switch (isl_schedule_tree_get_type(tree
)) {
459 case isl_schedule_node_error
:
461 case isl_schedule_node_band
:
462 return isl_schedule_band_is_anchored(tree
->band
);
463 case isl_schedule_node_context
:
464 case isl_schedule_node_extension
:
465 case isl_schedule_node_guard
:
467 case isl_schedule_node_domain
:
468 case isl_schedule_node_expansion
:
469 case isl_schedule_node_filter
:
470 case isl_schedule_node_leaf
:
471 case isl_schedule_node_mark
:
472 case isl_schedule_node_sequence
:
473 case isl_schedule_node_set
:
477 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
478 "unhandled case", return -1);
481 /* Update the anchored field of "tree" based on whether the root node
482 * itself in anchored and the anchored fields of the children.
484 * This function should be called whenever the children of a tree node
485 * are changed or the anchoredness of the tree root itself changes.
487 __isl_give isl_schedule_tree
*isl_schedule_tree_update_anchored(
488 __isl_take isl_schedule_tree
*tree
)
493 anchored
= isl_schedule_tree_is_anchored(tree
);
494 n
= isl_schedule_tree_n_children(tree
);
495 if (anchored
< 0 || n
< 0)
496 return isl_schedule_tree_free(tree
);
498 for (i
= 0; !anchored
&& i
< n
; ++i
) {
499 isl_schedule_tree
*child
;
501 child
= isl_schedule_tree_get_child(tree
, i
);
503 return isl_schedule_tree_free(tree
);
504 anchored
= child
->anchored
;
505 isl_schedule_tree_free(child
);
508 if (anchored
== tree
->anchored
)
510 tree
= isl_schedule_tree_cow(tree
);
513 tree
->anchored
= anchored
;
517 /* Create a new tree of the given type (isl_schedule_node_sequence or
518 * isl_schedule_node_set) with the given children.
520 __isl_give isl_schedule_tree
*isl_schedule_tree_from_children(
521 enum isl_schedule_node_type type
,
522 __isl_take isl_schedule_tree_list
*list
)
525 isl_schedule_tree
*tree
;
530 ctx
= isl_schedule_tree_list_get_ctx(list
);
531 tree
= isl_schedule_tree_alloc(ctx
, type
);
535 tree
->children
= list
;
536 tree
= isl_schedule_tree_update_anchored(tree
);
540 isl_schedule_tree_list_free(list
);
544 /* Construct a tree with a root node of type "type" and as children
545 * "tree1" and "tree2".
546 * If the root of one (or both) of the input trees is itself of type "type",
547 * then the tree is replaced by its children.
549 __isl_give isl_schedule_tree
*isl_schedule_tree_from_pair(
550 enum isl_schedule_node_type type
, __isl_take isl_schedule_tree
*tree1
,
551 __isl_take isl_schedule_tree
*tree2
)
554 isl_schedule_tree_list
*list
;
556 if (!tree1
|| !tree2
)
559 ctx
= isl_schedule_tree_get_ctx(tree1
);
560 if (isl_schedule_tree_get_type(tree1
) == type
) {
561 list
= isl_schedule_tree_list_copy(tree1
->children
);
562 isl_schedule_tree_free(tree1
);
564 list
= isl_schedule_tree_list_alloc(ctx
, 2);
565 list
= isl_schedule_tree_list_add(list
, tree1
);
567 if (isl_schedule_tree_get_type(tree2
) == type
) {
568 isl_schedule_tree_list
*children
;
570 children
= isl_schedule_tree_list_copy(tree2
->children
);
571 list
= isl_schedule_tree_list_concat(list
, children
);
572 isl_schedule_tree_free(tree2
);
574 list
= isl_schedule_tree_list_add(list
, tree2
);
577 return isl_schedule_tree_from_children(type
, list
);
579 isl_schedule_tree_free(tree1
);
580 isl_schedule_tree_free(tree2
);
584 /* Construct a tree with a sequence root node and as children
585 * "tree1" and "tree2".
586 * If the root of one (or both) of the input trees is itself a sequence,
587 * then the tree is replaced by its children.
589 __isl_give isl_schedule_tree
*isl_schedule_tree_sequence_pair(
590 __isl_take isl_schedule_tree
*tree1
,
591 __isl_take isl_schedule_tree
*tree2
)
593 return isl_schedule_tree_from_pair(isl_schedule_node_sequence
,
597 /* Construct a tree with a set root node and as children
598 * "tree1" and "tree2".
599 * If the root of one (or both) of the input trees is itself a set,
600 * then the tree is replaced by its children.
602 __isl_give isl_schedule_tree
*isl_schedule_tree_set_pair(
603 __isl_take isl_schedule_tree
*tree1
,
604 __isl_take isl_schedule_tree
*tree2
)
606 return isl_schedule_tree_from_pair(isl_schedule_node_set
, tree1
, tree2
);
609 /* Return the isl_ctx to which "tree" belongs.
611 isl_ctx
*isl_schedule_tree_get_ctx(__isl_keep isl_schedule_tree
*tree
)
613 return tree
? tree
->ctx
: NULL
;
616 /* Return the type of the root of the tree or isl_schedule_node_error
619 enum isl_schedule_node_type
isl_schedule_tree_get_type(
620 __isl_keep isl_schedule_tree
*tree
)
622 return tree
? tree
->type
: isl_schedule_node_error
;
625 /* Are "tree1" and "tree2" obviously equal to each other?
627 isl_bool
isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree
*tree1
,
628 __isl_keep isl_schedule_tree
*tree2
)
633 if (!tree1
|| !tree2
)
634 return isl_bool_error
;
636 return isl_bool_true
;
637 if (tree1
->type
!= tree2
->type
)
638 return isl_bool_false
;
640 switch (tree1
->type
) {
641 case isl_schedule_node_band
:
642 equal
= isl_schedule_band_plain_is_equal(tree1
->band
,
645 case isl_schedule_node_context
:
646 equal
= isl_set_is_equal(tree1
->context
, tree2
->context
);
648 case isl_schedule_node_domain
:
649 equal
= isl_union_set_is_equal(tree1
->domain
, tree2
->domain
);
651 case isl_schedule_node_expansion
:
652 equal
= isl_union_map_is_equal(tree1
->expansion
,
654 if (equal
>= 0 && equal
)
655 equal
= isl_union_pw_multi_aff_plain_is_equal(
656 tree1
->contraction
, tree2
->contraction
);
658 case isl_schedule_node_extension
:
659 equal
= isl_union_map_is_equal(tree1
->extension
,
662 case isl_schedule_node_filter
:
663 equal
= isl_union_set_is_equal(tree1
->filter
, tree2
->filter
);
665 case isl_schedule_node_guard
:
666 equal
= isl_set_is_equal(tree1
->guard
, tree2
->guard
);
668 case isl_schedule_node_mark
:
669 equal
= tree1
->mark
== tree2
->mark
;
671 case isl_schedule_node_leaf
:
672 case isl_schedule_node_sequence
:
673 case isl_schedule_node_set
:
674 equal
= isl_bool_true
;
676 case isl_schedule_node_error
:
677 equal
= isl_bool_error
;
681 if (equal
< 0 || !equal
)
684 n
= isl_schedule_tree_n_children(tree1
);
685 if (n
!= isl_schedule_tree_n_children(tree2
))
686 return isl_bool_false
;
687 for (i
= 0; i
< n
; ++i
) {
688 isl_schedule_tree
*child1
, *child2
;
690 child1
= isl_schedule_tree_get_child(tree1
, i
);
691 child2
= isl_schedule_tree_get_child(tree2
, i
);
692 equal
= isl_schedule_tree_plain_is_equal(child1
, child2
);
693 isl_schedule_tree_free(child1
);
694 isl_schedule_tree_free(child2
);
696 if (equal
< 0 || !equal
)
700 return isl_bool_true
;
703 /* Does "tree" have any children, other than an implicit leaf.
705 int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree
*tree
)
710 return tree
->children
!= NULL
;
713 /* Return the number of children of "tree", excluding implicit leaves.
714 * The "children" field is NULL if there are
715 * no children (except for the implicit leaves).
717 int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree
*tree
)
724 return isl_schedule_tree_list_n_schedule_tree(tree
->children
);
727 /* Return a copy of the (explicit) child at position "pos" of "tree".
729 __isl_give isl_schedule_tree
*isl_schedule_tree_get_child(
730 __isl_keep isl_schedule_tree
*tree
, int pos
)
735 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
736 "schedule tree has no explicit children", return NULL
);
737 return isl_schedule_tree_list_get_schedule_tree(tree
->children
, pos
);
740 /* Return a copy of the (explicit) child at position "pos" of "tree" and
743 __isl_give isl_schedule_tree
*isl_schedule_tree_child(
744 __isl_take isl_schedule_tree
*tree
, int pos
)
746 isl_schedule_tree
*child
;
748 child
= isl_schedule_tree_get_child(tree
, pos
);
749 isl_schedule_tree_free(tree
);
753 /* Remove all (explicit) children from "tree".
755 __isl_give isl_schedule_tree
*isl_schedule_tree_reset_children(
756 __isl_take isl_schedule_tree
*tree
)
758 tree
= isl_schedule_tree_cow(tree
);
761 tree
->children
= isl_schedule_tree_list_free(tree
->children
);
765 /* Remove the child at position "pos" from the children of "tree".
766 * If there was only one child to begin with, then remove all children.
768 __isl_give isl_schedule_tree
*isl_schedule_tree_drop_child(
769 __isl_take isl_schedule_tree
*tree
, int pos
)
773 tree
= isl_schedule_tree_cow(tree
);
775 n
= isl_schedule_tree_n_children(tree
);
777 return isl_schedule_tree_free(tree
);
779 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
780 "tree does not have any explicit children",
781 return isl_schedule_tree_free(tree
));
782 if (pos
< 0 || pos
>= n
)
783 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
784 "position out of bounds",
785 return isl_schedule_tree_free(tree
));
787 return isl_schedule_tree_reset_children(tree
);
789 tree
->children
= isl_schedule_tree_list_drop(tree
->children
, pos
, 1);
791 return isl_schedule_tree_free(tree
);
796 /* Replace the child at position "pos" of "tree" by "child".
798 * If the new child is a leaf, then it is not explicitly
799 * recorded in the list of children. Instead, the list of children
800 * (which is assumed to have only one element) is removed.
801 * Note that the children of set and sequence nodes are always
802 * filters, so they cannot be replaced by empty trees.
804 __isl_give isl_schedule_tree
*isl_schedule_tree_replace_child(
805 __isl_take isl_schedule_tree
*tree
, int pos
,
806 __isl_take isl_schedule_tree
*child
)
808 tree
= isl_schedule_tree_cow(tree
);
812 if (isl_schedule_tree_is_leaf(child
)) {
813 isl_schedule_tree_free(child
);
814 if (!tree
->children
&& pos
== 0)
816 if (isl_schedule_tree_n_children(tree
) != 1)
817 isl_die(isl_schedule_tree_get_ctx(tree
),
819 "can only replace single child by leaf",
821 return isl_schedule_tree_reset_children(tree
);
824 if (!tree
->children
&& pos
== 0)
826 isl_schedule_tree_list_from_schedule_tree(child
);
828 tree
->children
= isl_schedule_tree_list_set_schedule_tree(
829 tree
->children
, pos
, child
);
832 return isl_schedule_tree_free(tree
);
833 tree
= isl_schedule_tree_update_anchored(tree
);
837 isl_schedule_tree_free(tree
);
838 isl_schedule_tree_free(child
);
842 /* Replace the (explicit) children of "tree" by "children"?
844 __isl_give isl_schedule_tree
*isl_schedule_tree_set_children(
845 __isl_take isl_schedule_tree
*tree
,
846 __isl_take isl_schedule_tree_list
*children
)
848 tree
= isl_schedule_tree_cow(tree
);
849 if (!tree
|| !children
)
851 isl_schedule_tree_list_free(tree
->children
);
852 tree
->children
= children
;
855 isl_schedule_tree_free(tree
);
856 isl_schedule_tree_list_free(children
);
860 /* Create a new band schedule tree referring to "band"
861 * with "tree" as single child.
863 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_band(
864 __isl_take isl_schedule_tree
*tree
, __isl_take isl_schedule_band
*band
)
866 isl_schedule_tree
*res
;
868 res
= isl_schedule_tree_from_band(band
);
869 return isl_schedule_tree_replace_child(res
, 0, tree
);
872 /* Create a new context schedule tree with the given context and
873 * with "tree" as single child.
875 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_context(
876 __isl_take isl_schedule_tree
*tree
, __isl_take isl_set
*context
)
878 isl_schedule_tree
*res
;
880 res
= isl_schedule_tree_from_context(context
);
881 return isl_schedule_tree_replace_child(res
, 0, tree
);
884 /* Create a new domain schedule tree with the given domain and
885 * with "tree" as single child.
887 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_domain(
888 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
890 isl_schedule_tree
*res
;
892 res
= isl_schedule_tree_from_domain(domain
);
893 return isl_schedule_tree_replace_child(res
, 0, tree
);
896 /* Create a new expansion schedule tree with the given contraction and
897 * expansion and with "tree" as single child.
899 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_expansion(
900 __isl_take isl_schedule_tree
*tree
,
901 __isl_take isl_union_pw_multi_aff
*contraction
,
902 __isl_take isl_union_map
*expansion
)
904 isl_schedule_tree
*res
;
906 res
= isl_schedule_tree_from_expansion(contraction
, expansion
);
907 return isl_schedule_tree_replace_child(res
, 0, tree
);
910 /* Create a new extension schedule tree with the given extension and
911 * with "tree" as single child.
913 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_extension(
914 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_map
*extension
)
916 isl_schedule_tree
*res
;
918 res
= isl_schedule_tree_from_extension(extension
);
919 return isl_schedule_tree_replace_child(res
, 0, tree
);
922 /* Create a new filter schedule tree with the given filter and single child.
924 * If the root of "tree" is itself a filter node, then the two
925 * filter nodes are merged into one node.
927 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_filter(
928 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
930 isl_schedule_tree
*res
;
932 if (isl_schedule_tree_get_type(tree
) == isl_schedule_node_filter
) {
933 isl_union_set
*tree_filter
;
935 tree_filter
= isl_schedule_tree_filter_get_filter(tree
);
936 tree_filter
= isl_union_set_intersect(tree_filter
, filter
);
937 tree
= isl_schedule_tree_filter_set_filter(tree
, tree_filter
);
941 res
= isl_schedule_tree_from_filter(filter
);
942 return isl_schedule_tree_replace_child(res
, 0, tree
);
945 /* Insert a filter node with filter set "filter"
946 * in each of the children of "tree".
948 __isl_give isl_schedule_tree
*isl_schedule_tree_children_insert_filter(
949 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
953 if (!tree
|| !filter
)
956 n
= isl_schedule_tree_n_children(tree
);
957 for (i
= 0; i
< n
; ++i
) {
958 isl_schedule_tree
*child
;
960 child
= isl_schedule_tree_get_child(tree
, i
);
961 child
= isl_schedule_tree_insert_filter(child
,
962 isl_union_set_copy(filter
));
963 tree
= isl_schedule_tree_replace_child(tree
, i
, child
);
966 isl_union_set_free(filter
);
969 isl_union_set_free(filter
);
970 isl_schedule_tree_free(tree
);
974 /* Create a new guard schedule tree with the given guard and
975 * with "tree" as single child.
977 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_guard(
978 __isl_take isl_schedule_tree
*tree
, __isl_take isl_set
*guard
)
980 isl_schedule_tree
*res
;
982 res
= isl_schedule_tree_from_guard(guard
);
983 return isl_schedule_tree_replace_child(res
, 0, tree
);
986 /* Create a new mark schedule tree with the given mark identifier and
989 __isl_give isl_schedule_tree
*isl_schedule_tree_insert_mark(
990 __isl_take isl_schedule_tree
*tree
, __isl_take isl_id
*mark
)
992 isl_schedule_tree
*res
;
994 res
= isl_schedule_tree_from_mark(mark
);
995 return isl_schedule_tree_replace_child(res
, 0, tree
);
998 /* Return the number of members in the band tree root.
1000 unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree
*tree
)
1005 if (tree
->type
!= isl_schedule_node_band
)
1006 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1007 "not a band node", return 0);
1009 return isl_schedule_band_n_member(tree
->band
);
1012 /* Is the band member at position "pos" of the band tree root
1013 * marked coincident?
1015 isl_bool
isl_schedule_tree_band_member_get_coincident(
1016 __isl_keep isl_schedule_tree
*tree
, int pos
)
1019 return isl_bool_error
;
1021 if (tree
->type
!= isl_schedule_node_band
)
1022 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1023 "not a band node", return isl_bool_error
);
1025 return isl_schedule_band_member_get_coincident(tree
->band
, pos
);
1028 /* Mark the given band member as being coincident or not
1029 * according to "coincident".
1031 __isl_give isl_schedule_tree
*isl_schedule_tree_band_member_set_coincident(
1032 __isl_take isl_schedule_tree
*tree
, int pos
, int coincident
)
1036 if (tree
->type
!= isl_schedule_node_band
)
1037 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1038 "not a band node", return isl_schedule_tree_free(tree
));
1039 if (isl_schedule_tree_band_member_get_coincident(tree
, pos
) ==
1042 tree
= isl_schedule_tree_cow(tree
);
1046 tree
->band
= isl_schedule_band_member_set_coincident(tree
->band
, pos
,
1049 return isl_schedule_tree_free(tree
);
1053 /* Is the band tree root marked permutable?
1055 isl_bool
isl_schedule_tree_band_get_permutable(
1056 __isl_keep isl_schedule_tree
*tree
)
1059 return isl_bool_error
;
1061 if (tree
->type
!= isl_schedule_node_band
)
1062 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1063 "not a band node", return isl_bool_error
);
1065 return isl_schedule_band_get_permutable(tree
->band
);
1068 /* Mark the band tree root permutable or not according to "permutable"?
1070 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_permutable(
1071 __isl_take isl_schedule_tree
*tree
, int permutable
)
1075 if (tree
->type
!= isl_schedule_node_band
)
1076 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1077 "not a band node", return isl_schedule_tree_free(tree
));
1078 if (isl_schedule_tree_band_get_permutable(tree
) == permutable
)
1080 tree
= isl_schedule_tree_cow(tree
);
1084 tree
->band
= isl_schedule_band_set_permutable(tree
->band
, permutable
);
1086 return isl_schedule_tree_free(tree
);
1090 /* Return the schedule space of the band tree root.
1092 __isl_give isl_space
*isl_schedule_tree_band_get_space(
1093 __isl_keep isl_schedule_tree
*tree
)
1098 if (tree
->type
!= isl_schedule_node_band
)
1099 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1100 "not a band node", return NULL
);
1102 return isl_schedule_band_get_space(tree
->band
);
1105 /* Intersect the domain of the band schedule of the band tree root
1108 __isl_give isl_schedule_tree
*isl_schedule_tree_band_intersect_domain(
1109 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
1111 if (!tree
|| !domain
)
1114 if (tree
->type
!= isl_schedule_node_band
)
1115 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1116 "not a band node", goto error
);
1118 tree
->band
= isl_schedule_band_intersect_domain(tree
->band
, domain
);
1120 return isl_schedule_tree_free(tree
);
1124 isl_schedule_tree_free(tree
);
1125 isl_union_set_free(domain
);
1129 /* Return the schedule of the band tree root in isolation.
1131 __isl_give isl_multi_union_pw_aff
*isl_schedule_tree_band_get_partial_schedule(
1132 __isl_keep isl_schedule_tree
*tree
)
1137 if (tree
->type
!= isl_schedule_node_band
)
1138 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1139 "not a band node", return NULL
);
1141 return isl_schedule_band_get_partial_schedule(tree
->band
);
1144 /* Replace the schedule of the band tree root by "schedule".
1146 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_partial_schedule(
1147 __isl_take isl_schedule_tree
*tree
,
1148 __isl_take isl_multi_union_pw_aff
*schedule
)
1150 tree
= isl_schedule_tree_cow(tree
);
1151 if (!tree
|| !schedule
)
1154 if (tree
->type
!= isl_schedule_node_band
)
1155 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1156 "not a band node", return NULL
);
1157 tree
->band
= isl_schedule_band_set_partial_schedule(tree
->band
,
1162 isl_schedule_tree_free(tree
);
1163 isl_multi_union_pw_aff_free(schedule
);
1167 /* Return the loop AST generation type for the band member
1168 * of the band tree root at position "pos".
1170 enum isl_ast_loop_type
isl_schedule_tree_band_member_get_ast_loop_type(
1171 __isl_keep isl_schedule_tree
*tree
, int pos
)
1174 return isl_ast_loop_error
;
1176 if (tree
->type
!= isl_schedule_node_band
)
1177 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1178 "not a band node", return isl_ast_loop_error
);
1180 return isl_schedule_band_member_get_ast_loop_type(tree
->band
, pos
);
1183 /* Set the loop AST generation type for the band member of the band tree root
1184 * at position "pos" to "type".
1186 __isl_give isl_schedule_tree
*isl_schedule_tree_band_member_set_ast_loop_type(
1187 __isl_take isl_schedule_tree
*tree
, int pos
,
1188 enum isl_ast_loop_type type
)
1190 tree
= isl_schedule_tree_cow(tree
);
1194 if (tree
->type
!= isl_schedule_node_band
)
1195 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1196 "not a band node", return isl_schedule_tree_free(tree
));
1198 tree
->band
= isl_schedule_band_member_set_ast_loop_type(tree
->band
,
1201 return isl_schedule_tree_free(tree
);
1206 /* Return the loop AST generation type for the band member
1207 * of the band tree root at position "pos" for the isolated part.
1209 enum isl_ast_loop_type
isl_schedule_tree_band_member_get_isolate_ast_loop_type(
1210 __isl_keep isl_schedule_tree
*tree
, int pos
)
1213 return isl_ast_loop_error
;
1215 if (tree
->type
!= isl_schedule_node_band
)
1216 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1217 "not a band node", return isl_ast_loop_error
);
1219 return isl_schedule_band_member_get_isolate_ast_loop_type(tree
->band
,
1223 /* Set the loop AST generation type for the band member of the band tree root
1224 * at position "pos" for the isolated part to "type".
1226 __isl_give isl_schedule_tree
*
1227 isl_schedule_tree_band_member_set_isolate_ast_loop_type(
1228 __isl_take isl_schedule_tree
*tree
, int pos
,
1229 enum isl_ast_loop_type type
)
1231 tree
= isl_schedule_tree_cow(tree
);
1235 if (tree
->type
!= isl_schedule_node_band
)
1236 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1237 "not a band node", return isl_schedule_tree_free(tree
));
1239 tree
->band
= isl_schedule_band_member_set_isolate_ast_loop_type(
1240 tree
->band
, pos
, type
);
1242 return isl_schedule_tree_free(tree
);
1247 /* Return the AST build options associated to the band tree root.
1249 __isl_give isl_union_set
*isl_schedule_tree_band_get_ast_build_options(
1250 __isl_keep isl_schedule_tree
*tree
)
1255 if (tree
->type
!= isl_schedule_node_band
)
1256 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1257 "not a band node", return NULL
);
1259 return isl_schedule_band_get_ast_build_options(tree
->band
);
1262 /* Replace the AST build options associated to band tree root by "options".
1263 * Updated the anchored field if the anchoredness of the root node itself
1266 __isl_give isl_schedule_tree
*isl_schedule_tree_band_set_ast_build_options(
1267 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*options
)
1271 tree
= isl_schedule_tree_cow(tree
);
1272 if (!tree
|| !options
)
1275 if (tree
->type
!= isl_schedule_node_band
)
1276 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1277 "not a band node", goto error
);
1279 was_anchored
= isl_schedule_tree_is_anchored(tree
);
1280 tree
->band
= isl_schedule_band_set_ast_build_options(tree
->band
,
1283 return isl_schedule_tree_free(tree
);
1284 if (isl_schedule_tree_is_anchored(tree
) != was_anchored
)
1285 tree
= isl_schedule_tree_update_anchored(tree
);
1289 isl_schedule_tree_free(tree
);
1290 isl_union_set_free(options
);
1294 /* Return the "isolate" option associated to the band tree root of "tree",
1295 * which is assumed to appear at schedule depth "depth".
1297 __isl_give isl_set
*isl_schedule_tree_band_get_ast_isolate_option(
1298 __isl_keep isl_schedule_tree
*tree
, int depth
)
1303 if (tree
->type
!= isl_schedule_node_band
)
1304 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1305 "not a band node", return NULL
);
1307 return isl_schedule_band_get_ast_isolate_option(tree
->band
, depth
);
1310 /* Return the context of the context tree root.
1312 __isl_give isl_set
*isl_schedule_tree_context_get_context(
1313 __isl_keep isl_schedule_tree
*tree
)
1318 if (tree
->type
!= isl_schedule_node_context
)
1319 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1320 "not a context node", return NULL
);
1322 return isl_set_copy(tree
->context
);
1325 /* Return the domain of the domain tree root.
1327 __isl_give isl_union_set
*isl_schedule_tree_domain_get_domain(
1328 __isl_keep isl_schedule_tree
*tree
)
1333 if (tree
->type
!= isl_schedule_node_domain
)
1334 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1335 "not a domain node", return NULL
);
1337 return isl_union_set_copy(tree
->domain
);
1340 /* Replace the domain of domain tree root "tree" by "domain".
1342 __isl_give isl_schedule_tree
*isl_schedule_tree_domain_set_domain(
1343 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*domain
)
1345 tree
= isl_schedule_tree_cow(tree
);
1346 if (!tree
|| !domain
)
1349 if (tree
->type
!= isl_schedule_node_domain
)
1350 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1351 "not a domain node", goto error
);
1353 isl_union_set_free(tree
->domain
);
1354 tree
->domain
= domain
;
1358 isl_schedule_tree_free(tree
);
1359 isl_union_set_free(domain
);
1363 /* Return the contraction of the expansion tree root.
1365 __isl_give isl_union_pw_multi_aff
*isl_schedule_tree_expansion_get_contraction(
1366 __isl_keep isl_schedule_tree
*tree
)
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 return isl_union_pw_multi_aff_copy(tree
->contraction
);
1378 /* Return the expansion of the expansion tree root.
1380 __isl_give isl_union_map
*isl_schedule_tree_expansion_get_expansion(
1381 __isl_keep isl_schedule_tree
*tree
)
1386 if (tree
->type
!= isl_schedule_node_expansion
)
1387 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1388 "not an expansion node", return NULL
);
1390 return isl_union_map_copy(tree
->expansion
);
1393 /* Replace the contraction and the expansion of the expansion tree root "tree"
1394 * by "contraction" and "expansion".
1396 __isl_give isl_schedule_tree
*
1397 isl_schedule_tree_expansion_set_contraction_and_expansion(
1398 __isl_take isl_schedule_tree
*tree
,
1399 __isl_take isl_union_pw_multi_aff
*contraction
,
1400 __isl_take isl_union_map
*expansion
)
1402 tree
= isl_schedule_tree_cow(tree
);
1403 if (!tree
|| !contraction
|| !expansion
)
1406 if (tree
->type
!= isl_schedule_node_expansion
)
1407 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1408 "not an expansion node", return NULL
);
1410 isl_union_pw_multi_aff_free(tree
->contraction
);
1411 tree
->contraction
= contraction
;
1412 isl_union_map_free(tree
->expansion
);
1413 tree
->expansion
= expansion
;
1417 isl_schedule_tree_free(tree
);
1418 isl_union_pw_multi_aff_free(contraction
);
1419 isl_union_map_free(expansion
);
1423 /* Return the extension of the extension tree root.
1425 __isl_give isl_union_map
*isl_schedule_tree_extension_get_extension(
1426 __isl_take isl_schedule_tree
*tree
)
1431 if (tree
->type
!= isl_schedule_node_extension
)
1432 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1433 "not an extension node", return NULL
);
1435 return isl_union_map_copy(tree
->extension
);
1438 /* Replace the extension of extension tree root "tree" by "extension".
1440 __isl_give isl_schedule_tree
*isl_schedule_tree_extension_set_extension(
1441 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_map
*extension
)
1443 tree
= isl_schedule_tree_cow(tree
);
1444 if (!tree
|| !extension
)
1447 if (tree
->type
!= isl_schedule_node_extension
)
1448 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1449 "not an extension node", return NULL
);
1450 isl_union_map_free(tree
->extension
);
1451 tree
->extension
= extension
;
1455 isl_schedule_tree_free(tree
);
1456 isl_union_map_free(extension
);
1460 /* Return the filter of the filter tree root.
1462 __isl_give isl_union_set
*isl_schedule_tree_filter_get_filter(
1463 __isl_keep isl_schedule_tree
*tree
)
1468 if (tree
->type
!= isl_schedule_node_filter
)
1469 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1470 "not a filter node", return NULL
);
1472 return isl_union_set_copy(tree
->filter
);
1475 /* Replace the filter of the filter tree root by "filter".
1477 __isl_give isl_schedule_tree
*isl_schedule_tree_filter_set_filter(
1478 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*filter
)
1480 tree
= isl_schedule_tree_cow(tree
);
1481 if (!tree
|| !filter
)
1484 if (tree
->type
!= isl_schedule_node_filter
)
1485 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1486 "not a filter node", return NULL
);
1488 isl_union_set_free(tree
->filter
);
1489 tree
->filter
= filter
;
1493 isl_schedule_tree_free(tree
);
1494 isl_union_set_free(filter
);
1498 /* Return the guard of the guard tree root.
1500 __isl_give isl_set
*isl_schedule_tree_guard_get_guard(
1501 __isl_take isl_schedule_tree
*tree
)
1506 if (tree
->type
!= isl_schedule_node_guard
)
1507 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1508 "not a guard node", return NULL
);
1510 return isl_set_copy(tree
->guard
);
1513 /* Return the mark identifier of the mark tree root "tree".
1515 __isl_give isl_id
*isl_schedule_tree_mark_get_id(
1516 __isl_keep isl_schedule_tree
*tree
)
1521 if (tree
->type
!= isl_schedule_node_mark
)
1522 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1523 "not a mark node", return NULL
);
1525 return isl_id_copy(tree
->mark
);
1528 /* Set dim to the range dimension of "map" and abort the search.
1530 static isl_stat
set_range_dim(__isl_take isl_map
*map
, void *user
)
1534 *dim
= isl_map_dim(map
, isl_dim_out
);
1537 return isl_stat_error
;
1540 /* Return the dimension of the range of "umap".
1541 * "umap" is assumed not to be empty and
1542 * all maps inside "umap" are assumed to have the same range.
1544 * We extract the range dimension from the first map in "umap".
1546 static int range_dim(__isl_keep isl_union_map
*umap
)
1552 if (isl_union_map_n_map(umap
) == 0)
1553 isl_die(isl_union_map_get_ctx(umap
), isl_error_internal
,
1554 "unexpected empty input", return -1);
1556 isl_union_map_foreach_map(umap
, &set_range_dim
, &dim
);
1561 /* Append an "extra" number of zeros to the range of "umap" and
1562 * return the result.
1564 static __isl_give isl_union_map
*append_range(__isl_take isl_union_map
*umap
,
1570 isl_union_pw_multi_aff
*suffix
;
1571 isl_union_map
*universe
;
1572 isl_union_map
*suffix_umap
;
1574 universe
= isl_union_map_universe(isl_union_map_copy(umap
));
1575 dom
= isl_union_map_domain(universe
);
1576 space
= isl_union_set_get_space(dom
);
1577 space
= isl_space_set_from_params(space
);
1578 space
= isl_space_add_dims(space
, isl_dim_set
, extra
);
1579 mv
= isl_multi_val_zero(space
);
1581 suffix
= isl_union_pw_multi_aff_multi_val_on_domain(dom
, mv
);
1582 suffix_umap
= isl_union_map_from_union_pw_multi_aff(suffix
);
1583 umap
= isl_union_map_flat_range_product(umap
, suffix_umap
);
1588 /* Should we skip the root of "tree" while looking for the first
1589 * descendant with schedule information?
1590 * That is, is it impossible to derive any information about
1591 * the iteration domain from this node?
1593 * We do not want to skip leaf or error nodes because there is
1594 * no point in looking any deeper from these nodes.
1595 * We can only extract partial iteration domain information
1596 * from an extension node, but extension nodes are not supported
1597 * by the caller and it will error out on them.
1599 static int domain_less(__isl_keep isl_schedule_tree
*tree
)
1601 enum isl_schedule_node_type type
;
1603 type
= isl_schedule_tree_get_type(tree
);
1605 case isl_schedule_node_band
:
1606 return isl_schedule_tree_band_n_member(tree
) == 0;
1607 case isl_schedule_node_context
:
1608 case isl_schedule_node_guard
:
1609 case isl_schedule_node_mark
:
1611 case isl_schedule_node_leaf
:
1612 case isl_schedule_node_error
:
1613 case isl_schedule_node_domain
:
1614 case isl_schedule_node_expansion
:
1615 case isl_schedule_node_extension
:
1616 case isl_schedule_node_filter
:
1617 case isl_schedule_node_set
:
1618 case isl_schedule_node_sequence
:
1622 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1623 "unhandled case", return 0);
1626 /* Move down to the first descendant of "tree" that contains any schedule
1627 * information or return "leaf" if there is no such descendant.
1629 __isl_give isl_schedule_tree
*isl_schedule_tree_first_schedule_descendant(
1630 __isl_take isl_schedule_tree
*tree
, __isl_keep isl_schedule_tree
*leaf
)
1632 while (domain_less(tree
)) {
1633 if (!isl_schedule_tree_has_children(tree
)) {
1634 isl_schedule_tree_free(tree
);
1635 return isl_schedule_tree_copy(leaf
);
1637 tree
= isl_schedule_tree_child(tree
, 0);
1643 static __isl_give isl_union_map
*subtree_schedule_extend(
1644 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
);
1646 /* Extend the schedule map "outer" with the subtree schedule
1647 * of the (single) child of "tree", if any.
1649 * If "tree" does not have any descendants (apart from those that
1650 * do not carry any schedule information), then we simply return "outer".
1651 * Otherwise, we extend the schedule map "outer" with the subtree schedule
1652 * of the single child.
1654 static __isl_give isl_union_map
*subtree_schedule_extend_child(
1655 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1657 isl_schedule_tree
*child
;
1661 return isl_union_map_free(outer
);
1662 if (!isl_schedule_tree_has_children(tree
))
1664 child
= isl_schedule_tree_get_child(tree
, 0);
1666 return isl_union_map_free(outer
);
1667 res
= subtree_schedule_extend(child
, outer
);
1668 isl_schedule_tree_free(child
);
1672 /* Extract the parameter space from one of the children of "tree",
1673 * which are assumed to be filters.
1675 static __isl_give isl_space
*extract_space_from_filter_child(
1676 __isl_keep isl_schedule_tree
*tree
)
1680 isl_schedule_tree
*child
;
1682 child
= isl_schedule_tree_list_get_schedule_tree(tree
->children
, 0);
1683 dom
= isl_schedule_tree_filter_get_filter(child
);
1684 space
= isl_union_set_get_space(dom
);
1685 isl_union_set_free(dom
);
1686 isl_schedule_tree_free(child
);
1691 /* Extend the schedule map "outer" with the subtree schedule
1692 * of a set or sequence node.
1694 * The schedule for the set or sequence node itself is composed of
1695 * pieces of the form
1703 * The first form is used if there is only a single child or
1704 * if the current node is a set node and the schedule_separate_components
1705 * option is not set.
1707 * Each of the pieces above is extended with the subtree schedule of
1708 * the child of the corresponding filter, if any, padded with zeros
1709 * to ensure that all pieces have the same range dimension.
1711 static __isl_give isl_union_map
*subtree_schedule_extend_from_children(
1712 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1721 isl_union_map
*umap
;
1723 n
= isl_schedule_tree_n_children(tree
);
1725 return isl_union_map_free(outer
);
1727 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1728 "missing children", return isl_union_map_free(outer
));
1730 ctx
= isl_schedule_tree_get_ctx(tree
);
1731 separate
= n
> 1 && (tree
->type
== isl_schedule_node_sequence
||
1732 isl_options_get_schedule_separate_components(ctx
));
1734 space
= isl_space_params_alloc(ctx
, 0);
1736 umap
= isl_union_map_empty(isl_space_copy(space
));
1737 space
= isl_space_set_from_params(space
);
1739 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
1740 v
= isl_val_zero(ctx
);
1742 mv
= isl_multi_val_zero(space
);
1744 dim
= isl_multi_val_dim(mv
, isl_dim_set
);
1745 for (i
= 0; i
< n
; ++i
) {
1746 isl_multi_val
*mv_copy
;
1747 isl_union_pw_multi_aff
*upma
;
1748 isl_union_map
*umap_i
;
1750 isl_schedule_tree
*child
;
1754 child
= isl_schedule_tree_list_get_schedule_tree(
1756 dom
= isl_schedule_tree_filter_get_filter(child
);
1759 mv
= isl_multi_val_set_val(mv
, 0, isl_val_copy(v
));
1760 v
= isl_val_add_ui(v
, 1);
1762 mv_copy
= isl_multi_val_copy(mv
);
1763 space
= isl_union_set_get_space(dom
);
1764 mv_copy
= isl_multi_val_align_params(mv_copy
, space
);
1765 upma
= isl_union_pw_multi_aff_multi_val_on_domain(dom
, mv_copy
);
1766 umap_i
= isl_union_map_from_union_pw_multi_aff(upma
);
1767 umap_i
= isl_union_map_flat_range_product(
1768 isl_union_map_copy(outer
), umap_i
);
1769 umap_i
= subtree_schedule_extend_child(child
, umap_i
);
1770 isl_schedule_tree_free(child
);
1772 empty
= isl_union_map_is_empty(umap_i
);
1774 umap_i
= isl_union_map_free(umap_i
);
1776 isl_union_map_free(umap_i
);
1780 dim_i
= range_dim(umap_i
);
1782 umap
= isl_union_map_free(umap
);
1783 } else if (dim
< dim_i
) {
1784 umap
= append_range(umap
, dim_i
- dim
);
1786 } else if (dim_i
< dim
) {
1787 umap_i
= append_range(umap_i
, dim
- dim_i
);
1789 umap
= isl_union_map_union(umap
, umap_i
);
1793 isl_multi_val_free(mv
);
1794 isl_union_map_free(outer
);
1799 /* Extend the schedule map "outer" with the subtree schedule of "tree".
1801 * If the root of the tree is a set or a sequence, then we extend
1802 * the schedule map in subtree_schedule_extend_from_children.
1803 * Otherwise, we extend the schedule map with the partial schedule
1804 * corresponding to the root of the tree and then continue with
1805 * the single child of this root.
1806 * In the special case of an expansion, the schedule map is "extended"
1807 * by applying the expansion to the domain of the schedule map.
1809 static __isl_give isl_union_map
*subtree_schedule_extend(
1810 __isl_keep isl_schedule_tree
*tree
, __isl_take isl_union_map
*outer
)
1812 isl_multi_union_pw_aff
*mupa
;
1813 isl_union_map
*umap
;
1814 isl_union_set
*domain
;
1819 switch (tree
->type
) {
1820 case isl_schedule_node_error
:
1821 return isl_union_map_free(outer
);
1822 case isl_schedule_node_extension
:
1823 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1824 "cannot construct subtree schedule of tree "
1825 "with extension nodes",
1826 return isl_union_map_free(outer
));
1827 case isl_schedule_node_context
:
1828 case isl_schedule_node_guard
:
1829 case isl_schedule_node_mark
:
1830 return subtree_schedule_extend_child(tree
, outer
);
1831 case isl_schedule_node_band
:
1832 if (isl_schedule_tree_band_n_member(tree
) == 0)
1833 return subtree_schedule_extend_child(tree
, outer
);
1834 mupa
= isl_schedule_band_get_partial_schedule(tree
->band
);
1835 umap
= isl_union_map_from_multi_union_pw_aff(mupa
);
1836 outer
= isl_union_map_flat_range_product(outer
, umap
);
1837 umap
= subtree_schedule_extend_child(tree
, outer
);
1839 case isl_schedule_node_domain
:
1840 domain
= isl_schedule_tree_domain_get_domain(tree
);
1841 umap
= isl_union_map_from_domain(domain
);
1842 outer
= isl_union_map_flat_range_product(outer
, umap
);
1843 umap
= subtree_schedule_extend_child(tree
, outer
);
1845 case isl_schedule_node_expansion
:
1846 umap
= isl_schedule_tree_expansion_get_expansion(tree
);
1847 outer
= isl_union_map_apply_domain(outer
, umap
);
1848 umap
= subtree_schedule_extend_child(tree
, outer
);
1850 case isl_schedule_node_filter
:
1851 domain
= isl_schedule_tree_filter_get_filter(tree
);
1852 umap
= isl_union_map_from_domain(domain
);
1853 outer
= isl_union_map_flat_range_product(outer
, umap
);
1854 umap
= subtree_schedule_extend_child(tree
, outer
);
1856 case isl_schedule_node_leaf
:
1857 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1858 "leaf node should be handled by caller", return NULL
);
1859 case isl_schedule_node_set
:
1860 case isl_schedule_node_sequence
:
1861 umap
= subtree_schedule_extend_from_children(tree
, outer
);
1868 static __isl_give isl_union_set
*initial_domain(
1869 __isl_keep isl_schedule_tree
*tree
);
1871 /* Extract a universe domain from the children of the tree root "tree",
1872 * which is a set or sequence, meaning that its children are filters.
1873 * In particular, return the union of the universes of the filters.
1875 static __isl_give isl_union_set
*initial_domain_from_children(
1876 __isl_keep isl_schedule_tree
*tree
)
1880 isl_union_set
*domain
;
1882 n
= isl_schedule_tree_n_children(tree
);
1886 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1887 "missing children", return NULL
);
1889 space
= extract_space_from_filter_child(tree
);
1890 domain
= isl_union_set_empty(space
);
1892 for (i
= 0; i
< n
; ++i
) {
1893 isl_schedule_tree
*child
;
1894 isl_union_set
*domain_i
;
1896 child
= isl_schedule_tree_get_child(tree
, i
);
1897 domain_i
= initial_domain(child
);
1898 domain
= isl_union_set_union(domain
, domain_i
);
1899 isl_schedule_tree_free(child
);
1905 /* Extract a universe domain from the tree root "tree".
1906 * The caller is responsible for making sure that this node
1907 * would not be skipped by isl_schedule_tree_first_schedule_descendant
1908 * and that it is not a leaf node.
1910 static __isl_give isl_union_set
*initial_domain(
1911 __isl_keep isl_schedule_tree
*tree
)
1913 isl_multi_union_pw_aff
*mupa
;
1914 isl_union_set
*domain
;
1920 switch (tree
->type
) {
1921 case isl_schedule_node_error
:
1923 case isl_schedule_node_context
:
1924 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1925 "context node should be handled by caller",
1927 case isl_schedule_node_guard
:
1928 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1929 "guard node should be handled by caller",
1931 case isl_schedule_node_mark
:
1932 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1933 "mark node should be handled by caller",
1935 case isl_schedule_node_extension
:
1936 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
1937 "cannot construct subtree schedule of tree "
1938 "with extension nodes", return NULL
);
1939 case isl_schedule_node_band
:
1940 if (isl_schedule_tree_band_n_member(tree
) == 0)
1941 isl_die(isl_schedule_tree_get_ctx(tree
),
1943 "0D band should be handled by caller",
1945 mupa
= isl_schedule_band_get_partial_schedule(tree
->band
);
1946 domain
= isl_multi_union_pw_aff_domain(mupa
);
1947 domain
= isl_union_set_universe(domain
);
1949 case isl_schedule_node_domain
:
1950 domain
= isl_schedule_tree_domain_get_domain(tree
);
1951 domain
= isl_union_set_universe(domain
);
1953 case isl_schedule_node_expansion
:
1954 exp
= isl_schedule_tree_expansion_get_expansion(tree
);
1955 exp
= isl_union_map_universe(exp
);
1956 domain
= isl_union_map_domain(exp
);
1958 case isl_schedule_node_filter
:
1959 domain
= isl_schedule_tree_filter_get_filter(tree
);
1960 domain
= isl_union_set_universe(domain
);
1962 case isl_schedule_node_leaf
:
1963 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
1964 "leaf node should be handled by caller", return NULL
);
1965 case isl_schedule_node_set
:
1966 case isl_schedule_node_sequence
:
1967 domain
= initial_domain_from_children(tree
);
1974 /* Return the subtree schedule of a node that contains some schedule
1975 * information, i.e., a node that would not be skipped by
1976 * isl_schedule_tree_first_schedule_descendant and that is not a leaf.
1978 * If the tree contains any expansions, then the returned subtree
1979 * schedule is formulated in terms of the expanded domains.
1980 * The tree is not allowed to contain any extension nodes.
1982 * We start with an initial zero-dimensional subtree schedule based
1983 * on the domain information in the root node and then extend it
1984 * based on the schedule information in the root node and its descendants.
1986 __isl_give isl_union_map
*isl_schedule_tree_get_subtree_schedule_union_map(
1987 __isl_keep isl_schedule_tree
*tree
)
1989 isl_union_set
*domain
;
1990 isl_union_map
*umap
;
1992 domain
= initial_domain(tree
);
1993 umap
= isl_union_map_from_domain(domain
);
1994 return subtree_schedule_extend(tree
, umap
);
1997 /* Multiply the partial schedule of the band root node of "tree"
1998 * with the factors in "mv".
2000 __isl_give isl_schedule_tree
*isl_schedule_tree_band_scale(
2001 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
2005 if (tree
->type
!= isl_schedule_node_band
)
2006 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2007 "not a band node", goto error
);
2009 tree
= isl_schedule_tree_cow(tree
);
2013 tree
->band
= isl_schedule_band_scale(tree
->band
, mv
);
2015 return isl_schedule_tree_free(tree
);
2019 isl_schedule_tree_free(tree
);
2020 isl_multi_val_free(mv
);
2024 /* Divide the partial schedule of the band root node of "tree"
2025 * by the factors in "mv".
2027 __isl_give isl_schedule_tree
*isl_schedule_tree_band_scale_down(
2028 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
2032 if (tree
->type
!= isl_schedule_node_band
)
2033 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2034 "not a band node", goto error
);
2036 tree
= isl_schedule_tree_cow(tree
);
2040 tree
->band
= isl_schedule_band_scale_down(tree
->band
, mv
);
2042 return isl_schedule_tree_free(tree
);
2046 isl_schedule_tree_free(tree
);
2047 isl_multi_val_free(mv
);
2051 /* Reduce the partial schedule of the band root node of "tree"
2052 * modulo the factors in "mv".
2054 __isl_give isl_schedule_tree
*isl_schedule_tree_band_mod(
2055 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*mv
)
2059 if (tree
->type
!= isl_schedule_node_band
)
2060 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2061 "not a band node", goto error
);
2063 tree
= isl_schedule_tree_cow(tree
);
2067 tree
->band
= isl_schedule_band_mod(tree
->band
, mv
);
2069 return isl_schedule_tree_free(tree
);
2073 isl_schedule_tree_free(tree
);
2074 isl_multi_val_free(mv
);
2078 /* Shift the partial schedule of the band root node of "tree" by "shift".
2080 __isl_give isl_schedule_tree
*isl_schedule_tree_band_shift(
2081 __isl_take isl_schedule_tree
*tree
,
2082 __isl_take isl_multi_union_pw_aff
*shift
)
2084 if (!tree
|| !shift
)
2086 if (tree
->type
!= isl_schedule_node_band
)
2087 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2088 "not a band node", goto error
);
2090 tree
= isl_schedule_tree_cow(tree
);
2094 tree
->band
= isl_schedule_band_shift(tree
->band
, shift
);
2096 return isl_schedule_tree_free(tree
);
2100 isl_schedule_tree_free(tree
);
2101 isl_multi_union_pw_aff_free(shift
);
2105 /* Given two trees with sequence roots, replace the child at position
2106 * "pos" of "tree" with the children of "child".
2108 __isl_give isl_schedule_tree
*isl_schedule_tree_sequence_splice(
2109 __isl_take isl_schedule_tree
*tree
, int pos
,
2110 __isl_take isl_schedule_tree
*child
)
2113 isl_schedule_tree_list
*list1
, *list2
;
2115 tree
= isl_schedule_tree_cow(tree
);
2116 if (!tree
|| !child
)
2118 if (isl_schedule_tree_get_type(tree
) != isl_schedule_node_sequence
)
2119 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2120 "not a sequence node", goto error
);
2121 n
= isl_schedule_tree_n_children(tree
);
2122 if (pos
< 0 || pos
>= n
)
2123 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2124 "position out of bounds", goto error
);
2125 if (isl_schedule_tree_get_type(child
) != isl_schedule_node_sequence
)
2126 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2127 "not a sequence node", goto error
);
2129 list1
= isl_schedule_tree_list_copy(tree
->children
);
2130 list1
= isl_schedule_tree_list_drop(list1
, pos
, n
- pos
);
2131 list2
= isl_schedule_tree_list_copy(tree
->children
);
2132 list2
= isl_schedule_tree_list_drop(list2
, 0, pos
+ 1);
2133 list1
= isl_schedule_tree_list_concat(list1
,
2134 isl_schedule_tree_list_copy(child
->children
));
2135 list1
= isl_schedule_tree_list_concat(list1
, list2
);
2137 isl_schedule_tree_free(tree
);
2138 isl_schedule_tree_free(child
);
2139 return isl_schedule_tree_from_children(isl_schedule_node_sequence
,
2142 isl_schedule_tree_free(tree
);
2143 isl_schedule_tree_free(child
);
2147 /* Tile the band root node of "tree" with tile sizes "sizes".
2149 * We duplicate the band node, change the schedule of one of them
2150 * to the tile schedule and the other to the point schedule and then
2151 * attach the point band as a child to the tile band.
2153 __isl_give isl_schedule_tree
*isl_schedule_tree_band_tile(
2154 __isl_take isl_schedule_tree
*tree
, __isl_take isl_multi_val
*sizes
)
2156 isl_schedule_tree
*child
= NULL
;
2158 if (!tree
|| !sizes
)
2160 if (tree
->type
!= isl_schedule_node_band
)
2161 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2162 "not a band node", goto error
);
2164 child
= isl_schedule_tree_copy(tree
);
2165 tree
= isl_schedule_tree_cow(tree
);
2166 child
= isl_schedule_tree_cow(child
);
2167 if (!tree
|| !child
)
2170 tree
->band
= isl_schedule_band_tile(tree
->band
,
2171 isl_multi_val_copy(sizes
));
2174 child
->band
= isl_schedule_band_point(child
->band
, tree
->band
, sizes
);
2176 child
= isl_schedule_tree_free(child
);
2178 tree
= isl_schedule_tree_replace_child(tree
, 0, child
);
2182 isl_schedule_tree_free(child
);
2183 isl_schedule_tree_free(tree
);
2184 isl_multi_val_free(sizes
);
2188 /* Given an isolate AST generation option "isolate" for a band of size pos + n,
2189 * return the corresponding option for a band covering the first "pos"
2192 * The input isolate option is of the form
2194 * isolate[[flattened outer bands] -> [pos; n]]
2196 * The output isolate option is of the form
2198 * isolate[[flattened outer bands] -> [pos]]
2200 static __isl_give isl_set
*isolate_initial(__isl_keep isl_set
*isolate
,
2206 isolate
= isl_set_copy(isolate
);
2207 id
= isl_set_get_tuple_id(isolate
);
2208 map
= isl_set_unwrap(isolate
);
2209 map
= isl_map_project_out(map
, isl_dim_out
, pos
, n
);
2210 isolate
= isl_map_wrap(map
);
2211 isolate
= isl_set_set_tuple_id(isolate
, id
);
2216 /* Given an isolate AST generation option "isolate" for a band of size pos + n,
2217 * return the corresponding option for a band covering the final "n"
2218 * members within a band covering the first "pos" members.
2220 * The input isolate option is of the form
2222 * isolate[[flattened outer bands] -> [pos; n]]
2224 * The output isolate option is of the form
2226 * isolate[[flattened outer bands; pos] -> [n]]
2229 * The range is first split into
2231 * isolate[[flattened outer bands] -> [[pos] -> [n]]]
2233 * and then the first pos members are moved to the domain
2235 * isolate[[[flattened outer bands] -> [pos]] -> [n]]
2237 * after which the domain is flattened to obtain the desired output.
2239 static __isl_give isl_set
*isolate_final(__isl_keep isl_set
*isolate
,
2244 isl_multi_aff
*ma1
, *ma2
;
2247 isolate
= isl_set_copy(isolate
);
2248 id
= isl_set_get_tuple_id(isolate
);
2249 map
= isl_set_unwrap(isolate
);
2250 space
= isl_space_range(isl_map_get_space(map
));
2251 ma1
= isl_multi_aff_project_out_map(isl_space_copy(space
),
2252 isl_dim_set
, pos
, n
);
2253 ma2
= isl_multi_aff_project_out_map(space
, isl_dim_set
, 0, pos
);
2254 ma1
= isl_multi_aff_range_product(ma1
, ma2
);
2255 map
= isl_map_apply_range(map
, isl_map_from_multi_aff(ma1
));
2256 map
= isl_map_uncurry(map
);
2257 map
= isl_map_flatten_domain(map
);
2258 isolate
= isl_map_wrap(map
);
2259 isolate
= isl_set_set_tuple_id(isolate
, id
);
2264 /* Split the band root node of "tree" into two nested band nodes,
2265 * one with the first "pos" dimensions and
2266 * one with the remaining dimensions.
2267 * The tree is itself positioned at schedule depth "depth".
2269 * The loop AST generation type options and the isolate option
2270 * are split over the two band nodes.
2272 __isl_give isl_schedule_tree
*isl_schedule_tree_band_split(
2273 __isl_take isl_schedule_tree
*tree
, int pos
, int depth
)
2276 isl_set
*isolate
, *tree_isolate
, *child_isolate
;
2277 isl_schedule_tree
*child
;
2281 if (tree
->type
!= isl_schedule_node_band
)
2282 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2283 "not a band node", return isl_schedule_tree_free(tree
));
2285 n
= isl_schedule_tree_band_n_member(tree
);
2286 if (pos
< 0 || pos
> n
)
2287 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2288 "position out of bounds",
2289 return isl_schedule_tree_free(tree
));
2291 child
= isl_schedule_tree_copy(tree
);
2292 tree
= isl_schedule_tree_cow(tree
);
2293 child
= isl_schedule_tree_cow(child
);
2294 if (!tree
|| !child
)
2297 isolate
= isl_schedule_tree_band_get_ast_isolate_option(tree
, depth
);
2298 tree_isolate
= isolate_initial(isolate
, pos
, n
- pos
);
2299 child_isolate
= isolate_final(isolate
, pos
, n
- pos
);
2300 child
->band
= isl_schedule_band_drop(child
->band
, 0, pos
);
2301 child
->band
= isl_schedule_band_replace_ast_build_option(child
->band
,
2302 isl_set_copy(isolate
), child_isolate
);
2303 tree
->band
= isl_schedule_band_drop(tree
->band
, pos
, n
- pos
);
2304 tree
->band
= isl_schedule_band_replace_ast_build_option(tree
->band
,
2305 isl_set_copy(isolate
), tree_isolate
);
2306 isl_set_free(isolate
);
2307 if (!child
->band
|| !tree
->band
)
2310 tree
= isl_schedule_tree_replace_child(tree
, 0, child
);
2314 isl_schedule_tree_free(child
);
2315 isl_schedule_tree_free(tree
);
2319 /* Attach "tree2" at each of the leaves of "tree1".
2321 * If "tree1" does not have any explicit children, then make "tree2"
2322 * its single child. Otherwise, attach "tree2" to the leaves of
2323 * each of the children of "tree1".
2325 __isl_give isl_schedule_tree
*isl_schedule_tree_append_to_leaves(
2326 __isl_take isl_schedule_tree
*tree1
,
2327 __isl_take isl_schedule_tree
*tree2
)
2331 if (!tree1
|| !tree2
)
2333 n
= isl_schedule_tree_n_children(tree1
);
2335 isl_schedule_tree_list
*list
;
2336 list
= isl_schedule_tree_list_from_schedule_tree(tree2
);
2337 tree1
= isl_schedule_tree_set_children(tree1
, list
);
2340 for (i
= 0; i
< n
; ++i
) {
2341 isl_schedule_tree
*child
;
2343 child
= isl_schedule_tree_get_child(tree1
, i
);
2344 child
= isl_schedule_tree_append_to_leaves(child
,
2345 isl_schedule_tree_copy(tree2
));
2346 tree1
= isl_schedule_tree_replace_child(tree1
, i
, child
);
2349 isl_schedule_tree_free(tree2
);
2352 isl_schedule_tree_free(tree1
);
2353 isl_schedule_tree_free(tree2
);
2357 /* Reset the user pointer on all identifiers of parameters and tuples
2358 * in the root of "tree".
2360 __isl_give isl_schedule_tree
*isl_schedule_tree_reset_user(
2361 __isl_take isl_schedule_tree
*tree
)
2363 if (isl_schedule_tree_is_leaf(tree
))
2366 tree
= isl_schedule_tree_cow(tree
);
2370 switch (tree
->type
) {
2371 case isl_schedule_node_error
:
2372 return isl_schedule_tree_free(tree
);
2373 case isl_schedule_node_band
:
2374 tree
->band
= isl_schedule_band_reset_user(tree
->band
);
2376 return isl_schedule_tree_free(tree
);
2378 case isl_schedule_node_context
:
2379 tree
->context
= isl_set_reset_user(tree
->context
);
2381 return isl_schedule_tree_free(tree
);
2383 case isl_schedule_node_domain
:
2384 tree
->domain
= isl_union_set_reset_user(tree
->domain
);
2386 return isl_schedule_tree_free(tree
);
2388 case isl_schedule_node_expansion
:
2390 isl_union_pw_multi_aff_reset_user(tree
->contraction
);
2391 tree
->expansion
= isl_union_map_reset_user(tree
->expansion
);
2392 if (!tree
->contraction
|| !tree
->expansion
)
2393 return isl_schedule_tree_free(tree
);
2395 case isl_schedule_node_extension
:
2396 tree
->extension
= isl_union_map_reset_user(tree
->extension
);
2397 if (!tree
->extension
)
2398 return isl_schedule_tree_free(tree
);
2400 case isl_schedule_node_filter
:
2401 tree
->filter
= isl_union_set_reset_user(tree
->filter
);
2403 return isl_schedule_tree_free(tree
);
2405 case isl_schedule_node_guard
:
2406 tree
->guard
= isl_set_reset_user(tree
->guard
);
2408 return isl_schedule_tree_free(tree
);
2410 case isl_schedule_node_leaf
:
2411 case isl_schedule_node_mark
:
2412 case isl_schedule_node_sequence
:
2413 case isl_schedule_node_set
:
2420 /* Align the parameters of the root of "tree" to those of "space".
2422 __isl_give isl_schedule_tree
*isl_schedule_tree_align_params(
2423 __isl_take isl_schedule_tree
*tree
, __isl_take isl_space
*space
)
2428 if (isl_schedule_tree_is_leaf(tree
)) {
2429 isl_space_free(space
);
2433 tree
= isl_schedule_tree_cow(tree
);
2437 switch (tree
->type
) {
2438 case isl_schedule_node_error
:
2440 case isl_schedule_node_band
:
2441 tree
->band
= isl_schedule_band_align_params(tree
->band
, space
);
2443 return isl_schedule_tree_free(tree
);
2445 case isl_schedule_node_context
:
2446 tree
->context
= isl_set_align_params(tree
->context
, space
);
2448 return isl_schedule_tree_free(tree
);
2450 case isl_schedule_node_domain
:
2451 tree
->domain
= isl_union_set_align_params(tree
->domain
, space
);
2453 return isl_schedule_tree_free(tree
);
2455 case isl_schedule_node_expansion
:
2457 isl_union_pw_multi_aff_align_params(tree
->contraction
,
2458 isl_space_copy(space
));
2459 tree
->expansion
= isl_union_map_align_params(tree
->expansion
,
2461 if (!tree
->contraction
|| !tree
->expansion
)
2462 return isl_schedule_tree_free(tree
);
2464 case isl_schedule_node_extension
:
2465 tree
->extension
= isl_union_map_align_params(tree
->extension
,
2467 if (!tree
->extension
)
2468 return isl_schedule_tree_free(tree
);
2470 case isl_schedule_node_filter
:
2471 tree
->filter
= isl_union_set_align_params(tree
->filter
, space
);
2473 return isl_schedule_tree_free(tree
);
2475 case isl_schedule_node_guard
:
2476 tree
->guard
= isl_set_align_params(tree
->guard
, space
);
2478 return isl_schedule_tree_free(tree
);
2480 case isl_schedule_node_leaf
:
2481 case isl_schedule_node_mark
:
2482 case isl_schedule_node_sequence
:
2483 case isl_schedule_node_set
:
2484 isl_space_free(space
);
2490 isl_space_free(space
);
2491 isl_schedule_tree_free(tree
);
2495 /* Does "tree" involve the iteration domain?
2496 * That is, does it need to be modified
2497 * by isl_schedule_tree_pullback_union_pw_multi_aff?
2499 static int involves_iteration_domain(__isl_keep isl_schedule_tree
*tree
)
2504 switch (tree
->type
) {
2505 case isl_schedule_node_error
:
2507 case isl_schedule_node_band
:
2508 case isl_schedule_node_domain
:
2509 case isl_schedule_node_expansion
:
2510 case isl_schedule_node_extension
:
2511 case isl_schedule_node_filter
:
2513 case isl_schedule_node_context
:
2514 case isl_schedule_node_leaf
:
2515 case isl_schedule_node_guard
:
2516 case isl_schedule_node_mark
:
2517 case isl_schedule_node_sequence
:
2518 case isl_schedule_node_set
:
2522 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_internal
,
2523 "unhandled case", return -1);
2526 /* Compute the pullback of the root node of "tree" by the function
2527 * represented by "upma".
2528 * In other words, plug in "upma" in the iteration domains of
2529 * the root node of "tree".
2530 * We currently do not handle expansion nodes.
2532 * We first check if the root node involves any iteration domains.
2533 * If so, we handle the specific cases.
2535 __isl_give isl_schedule_tree
*isl_schedule_tree_pullback_union_pw_multi_aff(
2536 __isl_take isl_schedule_tree
*tree
,
2537 __isl_take isl_union_pw_multi_aff
*upma
)
2544 involves
= involves_iteration_domain(tree
);
2548 isl_union_pw_multi_aff_free(upma
);
2552 tree
= isl_schedule_tree_cow(tree
);
2556 if (tree
->type
== isl_schedule_node_band
) {
2557 tree
->band
= isl_schedule_band_pullback_union_pw_multi_aff(
2560 return isl_schedule_tree_free(tree
);
2561 } else if (tree
->type
== isl_schedule_node_domain
) {
2563 isl_union_set_preimage_union_pw_multi_aff(tree
->domain
,
2566 return isl_schedule_tree_free(tree
);
2567 } else if (tree
->type
== isl_schedule_node_expansion
) {
2568 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_unsupported
,
2569 "cannot pullback expansion node", goto error
);
2570 } else if (tree
->type
== isl_schedule_node_extension
) {
2572 isl_union_map_preimage_range_union_pw_multi_aff(
2573 tree
->extension
, upma
);
2574 if (!tree
->extension
)
2575 return isl_schedule_tree_free(tree
);
2576 } else if (tree
->type
== isl_schedule_node_filter
) {
2578 isl_union_set_preimage_union_pw_multi_aff(tree
->filter
,
2581 return isl_schedule_tree_free(tree
);
2586 isl_union_pw_multi_aff_free(upma
);
2587 isl_schedule_tree_free(tree
);
2591 /* Compute the gist of the band tree root with respect to "context".
2593 __isl_give isl_schedule_tree
*isl_schedule_tree_band_gist(
2594 __isl_take isl_schedule_tree
*tree
, __isl_take isl_union_set
*context
)
2598 if (tree
->type
!= isl_schedule_node_band
)
2599 isl_die(isl_schedule_tree_get_ctx(tree
), isl_error_invalid
,
2600 "not a band node", goto error
);
2601 tree
= isl_schedule_tree_cow(tree
);
2605 tree
->band
= isl_schedule_band_gist(tree
->band
, context
);
2607 return isl_schedule_tree_free(tree
);
2610 isl_union_set_free(context
);
2611 isl_schedule_tree_free(tree
);
2615 /* Are any members in "band" marked coincident?
2617 static isl_bool
any_coincident(__isl_keep isl_schedule_band
*band
)
2621 n
= isl_schedule_band_n_member(band
);
2622 for (i
= 0; i
< n
; ++i
) {
2623 isl_bool coincident
;
2625 coincident
= isl_schedule_band_member_get_coincident(band
, i
);
2626 if (coincident
< 0 || coincident
)
2630 return isl_bool_false
;
2633 /* Print the band node "band" to "p".
2635 * The permutable and coincident properties are only printed if they
2636 * are different from the defaults.
2637 * The coincident property is always printed in YAML flow style.
2639 static __isl_give isl_printer
*print_tree_band(__isl_take isl_printer
*p
,
2640 __isl_keep isl_schedule_band
*band
)
2642 isl_union_set
*options
;
2644 isl_bool coincident
;
2646 p
= isl_printer_print_str(p
, "schedule");
2647 p
= isl_printer_yaml_next(p
);
2648 p
= isl_printer_print_str(p
, "\"");
2649 p
= isl_printer_print_multi_union_pw_aff(p
, band
->mupa
);
2650 p
= isl_printer_print_str(p
, "\"");
2651 if (isl_schedule_band_get_permutable(band
)) {
2652 p
= isl_printer_yaml_next(p
);
2653 p
= isl_printer_print_str(p
, "permutable");
2654 p
= isl_printer_yaml_next(p
);
2655 p
= isl_printer_print_int(p
, 1);
2657 coincident
= any_coincident(band
);
2659 return isl_printer_free(p
);
2664 p
= isl_printer_yaml_next(p
);
2665 p
= isl_printer_print_str(p
, "coincident");
2666 p
= isl_printer_yaml_next(p
);
2667 style
= isl_printer_get_yaml_style(p
);
2668 p
= isl_printer_set_yaml_style(p
, ISL_YAML_STYLE_FLOW
);
2669 p
= isl_printer_yaml_start_sequence(p
);
2670 n
= isl_schedule_band_n_member(band
);
2671 for (i
= 0; i
< n
; ++i
) {
2672 p
= isl_printer_print_int(p
,
2673 isl_schedule_band_member_get_coincident(band
, i
));
2674 p
= isl_printer_yaml_next(p
);
2676 p
= isl_printer_yaml_end_sequence(p
);
2677 p
= isl_printer_set_yaml_style(p
, style
);
2679 options
= isl_schedule_band_get_ast_build_options(band
);
2680 empty
= isl_union_set_is_empty(options
);
2682 p
= isl_printer_free(p
);
2684 p
= isl_printer_yaml_next(p
);
2685 p
= isl_printer_print_str(p
, "options");
2686 p
= isl_printer_yaml_next(p
);
2687 p
= isl_printer_print_str(p
, "\"");
2688 p
= isl_printer_print_union_set(p
, options
);
2689 p
= isl_printer_print_str(p
, "\"");
2691 isl_union_set_free(options
);
2696 /* Print "tree" to "p".
2698 * If "n_ancestor" is non-negative, then "child_pos" contains the child
2699 * positions of a descendant of the current node that should be marked
2700 * (by the comment "YOU ARE HERE"). In particular, if "n_ancestor"
2701 * is zero, then the current node should be marked.
2702 * The marking is only printed in YAML block format.
2704 * Implicit leaf nodes are not printed, except if they correspond
2705 * to the node that should be marked.
2707 __isl_give isl_printer
*isl_printer_print_schedule_tree_mark(
2708 __isl_take isl_printer
*p
, __isl_keep isl_schedule_tree
*tree
,
2709 int n_ancestor
, int *child_pos
)
2715 block
= isl_printer_get_yaml_style(p
) == ISL_YAML_STYLE_BLOCK
;
2717 p
= isl_printer_yaml_start_mapping(p
);
2718 if (n_ancestor
== 0 && block
) {
2719 p
= isl_printer_print_str(p
, "# YOU ARE HERE");
2720 p
= isl_printer_end_line(p
);
2721 p
= isl_printer_start_line(p
);
2723 switch (tree
->type
) {
2724 case isl_schedule_node_error
:
2725 p
= isl_printer_print_str(p
, "ERROR");
2727 case isl_schedule_node_leaf
:
2728 p
= isl_printer_print_str(p
, "leaf");
2730 case isl_schedule_node_sequence
:
2731 p
= isl_printer_print_str(p
, "sequence");
2734 case isl_schedule_node_set
:
2735 p
= isl_printer_print_str(p
, "set");
2738 case isl_schedule_node_context
:
2739 p
= isl_printer_print_str(p
, "context");
2740 p
= isl_printer_yaml_next(p
);
2741 p
= isl_printer_print_str(p
, "\"");
2742 p
= isl_printer_print_set(p
, tree
->context
);
2743 p
= isl_printer_print_str(p
, "\"");
2745 case isl_schedule_node_domain
:
2746 p
= isl_printer_print_str(p
, "domain");
2747 p
= isl_printer_yaml_next(p
);
2748 p
= isl_printer_print_str(p
, "\"");
2749 p
= isl_printer_print_union_set(p
, tree
->domain
);
2750 p
= isl_printer_print_str(p
, "\"");
2752 case isl_schedule_node_expansion
:
2753 p
= isl_printer_print_str(p
, "contraction");
2754 p
= isl_printer_yaml_next(p
);
2755 p
= isl_printer_print_str(p
, "\"");
2756 p
= isl_printer_print_union_pw_multi_aff(p
, tree
->contraction
);
2757 p
= isl_printer_print_str(p
, "\"");
2758 p
= isl_printer_yaml_next(p
);
2759 p
= isl_printer_print_str(p
, "expansion");
2760 p
= isl_printer_yaml_next(p
);
2761 p
= isl_printer_print_str(p
, "\"");
2762 p
= isl_printer_print_union_map(p
, tree
->expansion
);
2763 p
= isl_printer_print_str(p
, "\"");
2765 case isl_schedule_node_extension
:
2766 p
= isl_printer_print_str(p
, "extension");
2767 p
= isl_printer_yaml_next(p
);
2768 p
= isl_printer_print_str(p
, "\"");
2769 p
= isl_printer_print_union_map(p
, tree
->extension
);
2770 p
= isl_printer_print_str(p
, "\"");
2772 case isl_schedule_node_filter
:
2773 p
= isl_printer_print_str(p
, "filter");
2774 p
= isl_printer_yaml_next(p
);
2775 p
= isl_printer_print_str(p
, "\"");
2776 p
= isl_printer_print_union_set(p
, tree
->filter
);
2777 p
= isl_printer_print_str(p
, "\"");
2779 case isl_schedule_node_guard
:
2780 p
= isl_printer_print_str(p
, "guard");
2781 p
= isl_printer_yaml_next(p
);
2782 p
= isl_printer_print_str(p
, "\"");
2783 p
= isl_printer_print_set(p
, tree
->guard
);
2784 p
= isl_printer_print_str(p
, "\"");
2786 case isl_schedule_node_mark
:
2787 p
= isl_printer_print_str(p
, "mark");
2788 p
= isl_printer_yaml_next(p
);
2789 p
= isl_printer_print_str(p
, "\"");
2790 p
= isl_printer_print_str(p
, isl_id_get_name(tree
->mark
));
2791 p
= isl_printer_print_str(p
, "\"");
2793 case isl_schedule_node_band
:
2794 p
= print_tree_band(p
, tree
->band
);
2797 p
= isl_printer_yaml_next(p
);
2799 n
= isl_schedule_tree_n_children(tree
);
2801 return isl_printer_free(p
);
2803 if (n_ancestor
> 0 && block
) {
2804 isl_schedule_tree
*leaf
;
2806 p
= isl_printer_print_str(p
, "child");
2807 p
= isl_printer_yaml_next(p
);
2808 leaf
= isl_schedule_tree_leaf(isl_printer_get_ctx(p
));
2809 p
= isl_printer_print_schedule_tree_mark(p
,
2811 isl_schedule_tree_free(leaf
);
2812 p
= isl_printer_yaml_next(p
);
2814 return isl_printer_yaml_end_mapping(p
);
2818 p
= isl_printer_yaml_start_sequence(p
);
2820 p
= isl_printer_print_str(p
, "child");
2821 p
= isl_printer_yaml_next(p
);
2824 for (i
= 0; i
< n
; ++i
) {
2825 isl_schedule_tree
*t
;
2827 t
= isl_schedule_tree_get_child(tree
, i
);
2828 if (n_ancestor
> 0 && child_pos
[0] == i
)
2829 p
= isl_printer_print_schedule_tree_mark(p
, t
,
2830 n_ancestor
- 1, child_pos
+ 1);
2832 p
= isl_printer_print_schedule_tree_mark(p
, t
,
2834 isl_schedule_tree_free(t
);
2836 p
= isl_printer_yaml_next(p
);
2840 p
= isl_printer_yaml_end_sequence(p
);
2841 p
= isl_printer_yaml_end_mapping(p
);
2846 /* Print "tree" to "p".
2848 __isl_give isl_printer
*isl_printer_print_schedule_tree(
2849 __isl_take isl_printer
*p
, __isl_keep isl_schedule_tree
*tree
)
2851 return isl_printer_print_schedule_tree_mark(p
, tree
, -1, NULL
);
2854 void isl_schedule_tree_dump(__isl_keep isl_schedule_tree
*tree
)
2857 isl_printer
*printer
;
2862 ctx
= isl_schedule_tree_get_ctx(tree
);
2863 printer
= isl_printer_to_file(ctx
, stderr
);
2864 printer
= isl_printer_set_yaml_style(printer
, ISL_YAML_STYLE_BLOCK
);
2865 printer
= isl_printer_print_schedule_tree(printer
, tree
);
2867 isl_printer_free(printer
);