add isl_schedule_node_reset_user
[isl.git] / isl_schedule_tree.c
blobde991f3f7525edc07dd8e5f7ee30c1fadfebcd4b
1 /*
2 * Copyright 2013 Ecole Normale Superieure
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege,
7 * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
8 */
10 #include <isl/map.h>
11 #include <isl_schedule_band.h>
12 #include <isl_schedule_private.h>
14 #undef EL
15 #define EL isl_schedule_tree
17 #include <isl_list_templ.h>
19 #undef BASE
20 #define BASE schedule_tree
22 #include <isl_list_templ.c>
24 /* Is "tree" the leaf of a schedule tree?
26 int isl_schedule_tree_is_leaf(__isl_keep isl_schedule_tree *tree)
28 return isl_schedule_tree_get_type(tree) == isl_schedule_node_leaf;
31 /* Create a new schedule tree of type "type".
32 * The caller is responsible for filling in the type specific fields and
33 * the children.
35 static __isl_give isl_schedule_tree *isl_schedule_tree_alloc(isl_ctx *ctx,
36 enum isl_schedule_node_type type)
38 isl_schedule_tree *tree;
40 if (type == isl_schedule_node_error)
41 return NULL;
43 tree = isl_calloc_type(ctx, isl_schedule_tree);
44 if (!tree)
45 return NULL;
47 tree->ref = 1;
48 tree->ctx = ctx;
49 isl_ctx_ref(ctx);
50 tree->type = type;
52 return tree;
55 /* Return a fresh copy of "tree".
57 __isl_take isl_schedule_tree *isl_schedule_tree_dup(
58 __isl_keep isl_schedule_tree *tree)
60 isl_ctx *ctx;
61 isl_schedule_tree *dup;
63 if (!tree)
64 return NULL;
66 ctx = isl_schedule_tree_get_ctx(tree);
67 dup = isl_schedule_tree_alloc(ctx, tree->type);
68 if (!dup)
69 return NULL;
71 switch (tree->type) {
72 case isl_schedule_node_error:
73 isl_die(ctx, isl_error_internal,
74 "allocation should have failed",
75 isl_schedule_tree_free(dup));
76 case isl_schedule_node_band:
77 dup->band = isl_schedule_band_copy(tree->band);
78 if (!dup->band)
79 return isl_schedule_tree_free(dup);
80 break;
81 case isl_schedule_node_domain:
82 dup->domain = isl_union_set_copy(tree->domain);
83 if (!dup->domain)
84 return isl_schedule_tree_free(dup);
85 break;
86 case isl_schedule_node_filter:
87 dup->filter = isl_union_set_copy(tree->filter);
88 if (!dup->filter)
89 return isl_schedule_tree_free(dup);
90 break;
91 case isl_schedule_node_leaf:
92 case isl_schedule_node_sequence:
93 case isl_schedule_node_set:
94 break;
97 if (tree->children) {
98 dup->children = isl_schedule_tree_list_copy(tree->children);
99 if (!dup->children)
100 return isl_schedule_tree_free(dup);
103 return dup;
106 /* Return an isl_schedule_tree that is equal to "tree" and that has only
107 * a single reference.
109 * This function is called before a tree is modified.
110 * A static tree (with negative reference count) should never be modified,
111 * so it is not allowed to call this function on a static tree.
113 __isl_give isl_schedule_tree *isl_schedule_tree_cow(
114 __isl_take isl_schedule_tree *tree)
116 if (!tree)
117 return NULL;
119 if (tree->ref < 0)
120 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
121 "static trees cannot be modified",
122 return isl_schedule_tree_free(tree));
124 if (tree->ref == 1)
125 return tree;
126 tree->ref--;
127 return isl_schedule_tree_dup(tree);
130 /* Return a new reference to "tree".
132 * A static tree (with negative reference count) does not keep track
133 * of the number of references and should not be modified.
135 __isl_give isl_schedule_tree *isl_schedule_tree_copy(
136 __isl_keep isl_schedule_tree *tree)
138 if (!tree)
139 return NULL;
141 if (tree->ref < 0)
142 return tree;
144 tree->ref++;
145 return tree;
148 /* Free "tree" and return NULL.
150 __isl_null isl_schedule_tree *isl_schedule_tree_free(
151 __isl_take isl_schedule_tree *tree)
153 if (!tree)
154 return NULL;
155 if (tree->ref < 0)
156 return NULL;
157 if (--tree->ref > 0)
158 return NULL;
160 switch (tree->type) {
161 case isl_schedule_node_band:
162 isl_schedule_band_free(tree->band);
163 break;
164 case isl_schedule_node_domain:
165 isl_union_set_free(tree->domain);
166 break;
167 case isl_schedule_node_filter:
168 isl_union_set_free(tree->filter);
169 break;
170 case isl_schedule_node_sequence:
171 case isl_schedule_node_set:
172 case isl_schedule_node_error:
173 case isl_schedule_node_leaf:
174 break;
176 isl_schedule_tree_list_free(tree->children);
177 isl_ctx_deref(tree->ctx);
178 free(tree);
180 return NULL;
183 /* Create and return a new leaf schedule tree.
185 __isl_give isl_schedule_tree *isl_schedule_tree_leaf(isl_ctx *ctx)
187 return isl_schedule_tree_alloc(ctx, isl_schedule_node_leaf);
190 /* Create a new band schedule tree referring to "band"
191 * with no children.
193 __isl_give isl_schedule_tree *isl_schedule_tree_from_band(
194 __isl_take isl_schedule_band *band)
196 isl_ctx *ctx;
197 isl_schedule_tree *tree;
199 if (!band)
200 return NULL;
202 ctx = isl_schedule_band_get_ctx(band);
203 tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_band);
204 if (!tree)
205 goto error;
207 tree->band = band;
209 return tree;
210 error:
211 isl_schedule_band_free(band);
212 return NULL;
215 /* Create a new domain schedule tree with the given domain and no children.
217 __isl_give isl_schedule_tree *isl_schedule_tree_from_domain(
218 __isl_take isl_union_set *domain)
220 isl_ctx *ctx;
221 isl_schedule_tree *tree;
223 if (!domain)
224 return NULL;
226 ctx = isl_union_set_get_ctx(domain);
227 tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_domain);
228 if (!tree)
229 goto error;
231 tree->domain = domain;
233 return tree;
234 error:
235 isl_union_set_free(domain);
236 return NULL;
239 /* Create a new filter schedule tree with the given filter and no children.
241 __isl_give isl_schedule_tree *isl_schedule_tree_from_filter(
242 __isl_take isl_union_set *filter)
244 isl_ctx *ctx;
245 isl_schedule_tree *tree;
247 if (!filter)
248 return NULL;
250 ctx = isl_union_set_get_ctx(filter);
251 tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_filter);
252 if (!tree)
253 goto error;
255 tree->filter = filter;
257 return tree;
258 error:
259 isl_union_set_free(filter);
260 return NULL;
263 /* Create a new tree of the given type (isl_schedule_node_sequence or
264 * isl_schedule_node_set) with the given children.
266 __isl_give isl_schedule_tree *isl_schedule_tree_from_children(
267 enum isl_schedule_node_type type,
268 __isl_take isl_schedule_tree_list *list)
270 isl_ctx *ctx;
271 isl_schedule_tree *tree;
273 if (!list)
274 return NULL;
276 ctx = isl_schedule_tree_list_get_ctx(list);
277 tree = isl_schedule_tree_alloc(ctx, type);
278 if (!tree)
279 goto error;
281 tree->children = list;
283 return tree;
284 error:
285 isl_schedule_tree_list_free(list);
286 return NULL;
289 /* Construct a tree with a root node of type "type" and as children
290 * "tree1" and "tree2".
291 * If the root of one (or both) of the input trees is itself of type "type",
292 * then the tree is replaced by its children.
294 __isl_give isl_schedule_tree *isl_schedule_tree_from_pair(
295 enum isl_schedule_node_type type, __isl_take isl_schedule_tree *tree1,
296 __isl_take isl_schedule_tree *tree2)
298 isl_ctx *ctx;
299 isl_schedule_tree_list *list;
301 if (!tree1 || !tree2)
302 goto error;
304 ctx = isl_schedule_tree_get_ctx(tree1);
305 if (isl_schedule_tree_get_type(tree1) == type) {
306 list = isl_schedule_tree_list_copy(tree1->children);
307 isl_schedule_tree_free(tree1);
308 } else {
309 list = isl_schedule_tree_list_alloc(ctx, 2);
310 list = isl_schedule_tree_list_add(list, tree1);
312 if (isl_schedule_tree_get_type(tree2) == type) {
313 isl_schedule_tree_list *children;
315 children = isl_schedule_tree_list_copy(tree2->children);
316 list = isl_schedule_tree_list_concat(list, children);
317 isl_schedule_tree_free(tree2);
318 } else {
319 list = isl_schedule_tree_list_add(list, tree2);
322 return isl_schedule_tree_from_children(type, list);
323 error:
324 isl_schedule_tree_free(tree1);
325 isl_schedule_tree_free(tree2);
326 return NULL;
329 /* Return the isl_ctx to which "tree" belongs.
331 isl_ctx *isl_schedule_tree_get_ctx(__isl_keep isl_schedule_tree *tree)
333 return tree ? tree->ctx : NULL;
336 /* Return the type of the root of the tree or isl_schedule_node_error
337 * on error.
339 enum isl_schedule_node_type isl_schedule_tree_get_type(
340 __isl_keep isl_schedule_tree *tree)
342 return tree ? tree->type : isl_schedule_node_error;
345 /* Are "tree1" and "tree2" obviously equal to each other?
347 int isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree *tree1,
348 __isl_keep isl_schedule_tree *tree2)
350 int equal;
351 int i, n;
353 if (!tree1 || !tree2)
354 return -1;
355 if (tree1 == tree2)
356 return 1;
357 if (tree1->type != tree2->type)
358 return 0;
360 switch (tree1->type) {
361 case isl_schedule_node_band:
362 equal = isl_schedule_band_plain_is_equal(tree1->band,
363 tree2->band);
364 break;
365 case isl_schedule_node_domain:
366 equal = isl_union_set_is_equal(tree1->domain, tree2->domain);
367 break;
368 case isl_schedule_node_filter:
369 equal = isl_union_set_is_equal(tree1->filter, tree2->filter);
370 break;
371 case isl_schedule_node_leaf:
372 case isl_schedule_node_sequence:
373 case isl_schedule_node_set:
374 equal = 1;
375 break;
376 case isl_schedule_node_error:
377 equal = -1;
378 break;
381 if (equal < 0 || !equal)
382 return equal;
384 n = isl_schedule_tree_n_children(tree1);
385 if (n != isl_schedule_tree_n_children(tree2))
386 return 0;
387 for (i = 0; i < n; ++i) {
388 isl_schedule_tree *child1, *child2;
390 child1 = isl_schedule_tree_get_child(tree1, i);
391 child2 = isl_schedule_tree_get_child(tree2, i);
392 equal = isl_schedule_tree_plain_is_equal(child1, child2);
393 isl_schedule_tree_free(child1);
394 isl_schedule_tree_free(child2);
396 if (equal < 0 || !equal)
397 return equal;
400 return 1;
403 /* Does "tree" have any children, other than an implicit leaf.
405 int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree *tree)
407 if (!tree)
408 return -1;
410 return tree->children != NULL;
413 /* Return the number of children of "tree", excluding implicit leaves.
415 int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree *tree)
417 if (!tree)
418 return -1;
420 return isl_schedule_tree_list_n_schedule_tree(tree->children);
423 /* Return a copy of the (explicit) child at position "pos" of "tree".
425 __isl_give isl_schedule_tree *isl_schedule_tree_get_child(
426 __isl_keep isl_schedule_tree *tree, int pos)
428 if (!tree)
429 return NULL;
430 if (!tree->children)
431 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
432 "schedule tree has no explicit children", return NULL);
433 return isl_schedule_tree_list_get_schedule_tree(tree->children, pos);
436 /* Return a copy of the (explicit) child at position "pos" of "tree" and
437 * free "tree".
439 __isl_give isl_schedule_tree *isl_schedule_tree_child(
440 __isl_take isl_schedule_tree *tree, int pos)
442 isl_schedule_tree *child;
444 child = isl_schedule_tree_get_child(tree, pos);
445 isl_schedule_tree_free(tree);
446 return child;
449 /* Remove all (explicit) children from "tree".
451 __isl_give isl_schedule_tree *isl_schedule_tree_reset_children(
452 __isl_take isl_schedule_tree *tree)
454 tree = isl_schedule_tree_cow(tree);
455 if (!tree)
456 return NULL;
457 tree->children = isl_schedule_tree_list_free(tree->children);
458 return tree;
461 /* Replace the child at position "pos" of "tree" by "child".
463 * If the new child is a leaf, then it is not explicitly
464 * recorded in the list of children. Instead, the list of children
465 * (which is assumed to have only one element) is removed.
466 * Note that the children of set and sequence nodes are always
467 * filters, so they cannot be replaced by empty trees.
469 __isl_give isl_schedule_tree *isl_schedule_tree_replace_child(
470 __isl_take isl_schedule_tree *tree, int pos,
471 __isl_take isl_schedule_tree *child)
473 tree = isl_schedule_tree_cow(tree);
474 if (!tree || !child)
475 goto error;
477 if (isl_schedule_tree_is_leaf(child)) {
478 isl_schedule_tree_free(child);
479 if (!tree->children && pos == 0)
480 return tree;
481 if (isl_schedule_tree_n_children(tree) != 1)
482 isl_die(isl_schedule_tree_get_ctx(tree),
483 isl_error_internal,
484 "can only replace single child by leaf",
485 goto error);
486 return isl_schedule_tree_reset_children(tree);
489 if (!tree->children && pos == 0)
490 tree->children =
491 isl_schedule_tree_list_from_schedule_tree(child);
492 else
493 tree->children = isl_schedule_tree_list_set_schedule_tree(
494 tree->children, pos, child);
496 if (!tree->children)
497 return isl_schedule_tree_free(tree);
499 return tree;
500 error:
501 isl_schedule_tree_free(tree);
502 isl_schedule_tree_free(child);
503 return NULL;
506 /* Replace the (explicit) children of "tree" by "children"?
508 __isl_give isl_schedule_tree *isl_schedule_tree_set_children(
509 __isl_take isl_schedule_tree *tree,
510 __isl_take isl_schedule_tree_list *children)
512 tree = isl_schedule_tree_cow(tree);
513 if (!tree || !children)
514 goto error;
515 isl_schedule_tree_list_free(tree->children);
516 tree->children = children;
517 return tree;
518 error:
519 isl_schedule_tree_free(tree);
520 isl_schedule_tree_list_free(children);
521 return NULL;
524 /* Create a new band schedule tree referring to "band"
525 * with "tree" as single child.
527 __isl_give isl_schedule_tree *isl_schedule_tree_insert_band(
528 __isl_take isl_schedule_tree *tree, __isl_take isl_schedule_band *band)
530 isl_schedule_tree *res;
532 res = isl_schedule_tree_from_band(band);
533 return isl_schedule_tree_replace_child(res, 0, tree);
536 /* Create a new domain schedule tree with the given domain and
537 * with "tree" as single child.
539 __isl_give isl_schedule_tree *isl_schedule_tree_insert_domain(
540 __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
542 isl_schedule_tree *res;
544 res = isl_schedule_tree_from_domain(domain);
545 return isl_schedule_tree_replace_child(res, 0, tree);
548 /* Create a new filter schedule tree with the given filter and single child.
550 * If the root of "tree" is itself a filter node, then the two
551 * filter nodes are merged into one node.
553 __isl_give isl_schedule_tree *isl_schedule_tree_insert_filter(
554 __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
556 isl_schedule_tree *res;
558 if (isl_schedule_tree_get_type(tree) == isl_schedule_node_filter) {
559 isl_union_set *tree_filter;
561 tree_filter = isl_schedule_tree_filter_get_filter(tree);
562 tree_filter = isl_union_set_intersect(tree_filter, filter);
563 tree = isl_schedule_tree_filter_set_filter(tree, tree_filter);
564 return tree;
567 res = isl_schedule_tree_from_filter(filter);
568 return isl_schedule_tree_replace_child(res, 0, tree);
571 /* Insert a filter node with filter set "filter"
572 * in each of the children of "tree".
574 __isl_give isl_schedule_tree *isl_schedule_tree_children_insert_filter(
575 __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
577 int i, n;
579 if (!tree || !filter)
580 goto error;
582 n = isl_schedule_tree_n_children(tree);
583 for (i = 0; i < n; ++i) {
584 isl_schedule_tree *child;
586 child = isl_schedule_tree_get_child(tree, i);
587 child = isl_schedule_tree_insert_filter(child,
588 isl_union_set_copy(filter));
589 tree = isl_schedule_tree_replace_child(tree, i, child);
592 isl_union_set_free(filter);
593 return tree;
594 error:
595 isl_union_set_free(filter);
596 isl_schedule_tree_free(tree);
597 return NULL;
600 /* Return the number of members in the band tree root.
602 unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree *tree)
604 if (!tree)
605 return 0;
607 if (tree->type != isl_schedule_node_band)
608 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
609 "not a band node", return 0);
611 return isl_schedule_band_n_member(tree->band);
614 /* Is the band member at position "pos" of the band tree root
615 * marked coincident?
617 int isl_schedule_tree_band_member_get_coincident(
618 __isl_keep isl_schedule_tree *tree, int pos)
620 if (!tree)
621 return -1;
623 if (tree->type != isl_schedule_node_band)
624 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
625 "not a band node", return -1);
627 return isl_schedule_band_member_get_coincident(tree->band, pos);
630 /* Mark the given band member as being coincident or not
631 * according to "coincident".
633 __isl_give isl_schedule_tree *isl_schedule_tree_band_member_set_coincident(
634 __isl_take isl_schedule_tree *tree, int pos, int coincident)
636 if (!tree)
637 return NULL;
638 if (tree->type != isl_schedule_node_band)
639 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
640 "not a band node", return isl_schedule_tree_free(tree));
641 if (isl_schedule_tree_band_member_get_coincident(tree, pos) ==
642 coincident)
643 return tree;
644 tree = isl_schedule_tree_cow(tree);
645 if (!tree)
646 return NULL;
648 tree->band = isl_schedule_band_member_set_coincident(tree->band, pos,
649 coincident);
650 if (!tree->band)
651 return isl_schedule_tree_free(tree);
652 return tree;
655 /* Is the band tree root marked permutable?
657 int isl_schedule_tree_band_get_permutable(__isl_keep isl_schedule_tree *tree)
659 if (!tree)
660 return -1;
662 if (tree->type != isl_schedule_node_band)
663 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
664 "not a band node", return -1);
666 return isl_schedule_band_get_permutable(tree->band);
669 /* Mark the band tree root permutable or not according to "permutable"?
671 __isl_give isl_schedule_tree *isl_schedule_tree_band_set_permutable(
672 __isl_take isl_schedule_tree *tree, int permutable)
674 if (!tree)
675 return NULL;
676 if (tree->type != isl_schedule_node_band)
677 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
678 "not a band node", return isl_schedule_tree_free(tree));
679 if (isl_schedule_tree_band_get_permutable(tree) == permutable)
680 return tree;
681 tree = isl_schedule_tree_cow(tree);
682 if (!tree)
683 return NULL;
685 tree->band = isl_schedule_band_set_permutable(tree->band, permutable);
686 if (!tree->band)
687 return isl_schedule_tree_free(tree);
688 return tree;
691 /* Return the schedule space of the band tree root.
693 __isl_give isl_space *isl_schedule_tree_band_get_space(
694 __isl_keep isl_schedule_tree *tree)
696 if (!tree)
697 return NULL;
699 if (tree->type != isl_schedule_node_band)
700 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
701 "not a band node", return NULL);
703 return isl_schedule_band_get_space(tree->band);
706 /* Return the schedule of the band tree root in isolation.
708 __isl_give isl_multi_union_pw_aff *isl_schedule_tree_band_get_partial_schedule(
709 __isl_keep isl_schedule_tree *tree)
711 if (!tree)
712 return NULL;
714 if (tree->type != isl_schedule_node_band)
715 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
716 "not a band node", return NULL);
718 return isl_schedule_band_get_partial_schedule(tree->band);
721 /* Return the domain of the domain tree root.
723 __isl_give isl_union_set *isl_schedule_tree_domain_get_domain(
724 __isl_keep isl_schedule_tree *tree)
726 if (!tree)
727 return NULL;
729 if (tree->type != isl_schedule_node_domain)
730 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
731 "not a domain node", return NULL);
733 return isl_union_set_copy(tree->domain);
736 /* Replace the domain of domain tree root "tree" by "domain".
738 __isl_give isl_schedule_tree *isl_schedule_tree_domain_set_domain(
739 __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
741 tree = isl_schedule_tree_cow(tree);
742 if (!tree || !domain)
743 goto error;
745 if (tree->type != isl_schedule_node_domain)
746 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
747 "not a domain node", goto error);
749 isl_union_set_free(tree->domain);
750 tree->domain = domain;
752 return tree;
753 error:
754 isl_schedule_tree_free(tree);
755 isl_union_set_free(domain);
756 return NULL;
759 /* Return the filter of the filter tree root.
761 __isl_give isl_union_set *isl_schedule_tree_filter_get_filter(
762 __isl_keep isl_schedule_tree *tree)
764 if (!tree)
765 return NULL;
767 if (tree->type != isl_schedule_node_filter)
768 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
769 "not a filter node", return NULL);
771 return isl_union_set_copy(tree->filter);
774 /* Replace the filter of the filter tree root by "filter".
776 __isl_give isl_schedule_tree *isl_schedule_tree_filter_set_filter(
777 __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
779 tree = isl_schedule_tree_cow(tree);
780 if (!tree || !filter)
781 goto error;
783 if (tree->type != isl_schedule_node_filter)
784 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
785 "not a filter node", return NULL);
787 isl_union_set_free(tree->filter);
788 tree->filter = filter;
790 return tree;
791 error:
792 isl_schedule_tree_free(tree);
793 isl_union_set_free(filter);
794 return NULL;
797 /* Set dim to the range dimension of "map" and abort the search.
799 static int set_range_dim(__isl_take isl_map *map, void *user)
801 int *dim = user;
803 *dim = isl_map_dim(map, isl_dim_out);
804 isl_map_free(map);
806 return -1;
809 /* Return the dimension of the range of "umap".
810 * "umap" is assumed not to be empty and
811 * all maps inside "umap" are assumed to have the same range.
813 * We extract the range dimension from the first map in "umap".
815 static int range_dim(__isl_keep isl_union_map *umap)
817 int dim = -1;
819 if (!umap)
820 return -1;
821 if (isl_union_map_n_map(umap) == 0)
822 isl_die(isl_union_map_get_ctx(umap), isl_error_internal,
823 "unexpected empty input", return -1);
825 isl_union_map_foreach_map(umap, &set_range_dim, &dim);
827 return dim;
830 /* Append an "extra" number of zeros to the range of "umap" and
831 * return the result.
833 static __isl_give isl_union_map *append_range(__isl_take isl_union_map *umap,
834 int extra)
836 isl_union_set *dom;
837 isl_space *space;
838 isl_multi_val *mv;
839 isl_union_pw_multi_aff *suffix;
840 isl_union_map *universe;
841 isl_union_map *suffix_umap;
843 universe = isl_union_map_universe(isl_union_map_copy(umap));
844 dom = isl_union_map_domain(universe);
845 space = isl_union_set_get_space(dom);
846 space = isl_space_set_from_params(space);
847 space = isl_space_add_dims(space, isl_dim_set, extra);
848 mv = isl_multi_val_zero(space);
850 suffix = isl_union_pw_multi_aff_multi_val_on_domain(dom, mv);
851 suffix_umap = isl_union_map_from_union_pw_multi_aff(suffix);
852 umap = isl_union_map_flat_range_product(umap, suffix_umap);
854 return umap;
857 /* Move down to the first descendant of "tree" that contains any schedule
858 * information or return "leaf" if there is no such descendant.
860 __isl_give isl_schedule_tree *isl_schedule_tree_first_schedule_descendant(
861 __isl_take isl_schedule_tree *tree, __isl_keep isl_schedule_tree *leaf)
863 while (isl_schedule_tree_get_type(tree) == isl_schedule_node_band &&
864 isl_schedule_tree_band_n_member(tree) == 0) {
865 if (!isl_schedule_tree_has_children(tree)) {
866 isl_schedule_tree_free(tree);
867 return isl_schedule_tree_copy(leaf);
869 tree = isl_schedule_tree_child(tree, 0);
872 return tree;
875 static __isl_give isl_union_map *subtree_schedule_extend(
876 __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer);
878 /* Extend the schedule map "outer" with the subtree schedule
879 * of the (single) child of "tree", if any.
881 * If "tree" does not have any descendants (apart from those that
882 * do not carry any schedule information), then we simply return "outer".
883 * Otherwise, we extend the schedule map "outer" with the subtree schedule
884 * of the single child.
886 static __isl_give isl_union_map *subtree_schedule_extend_child(
887 __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
889 isl_schedule_tree *child;
890 isl_union_map *res;
892 if (!tree)
893 return isl_union_map_free(outer);
894 if (!isl_schedule_tree_has_children(tree))
895 return outer;
896 child = isl_schedule_tree_get_child(tree, 0);
897 if (!child)
898 return isl_union_map_free(outer);
899 res = subtree_schedule_extend(child, outer);
900 isl_schedule_tree_free(child);
901 return res;
904 /* Extract the parameter space from one of the children of "tree",
905 * which are assumed to be filters.
907 static __isl_give isl_space *extract_space_from_filter_child(
908 __isl_keep isl_schedule_tree *tree)
910 isl_space *space;
911 isl_union_set *dom;
912 isl_schedule_tree *child;
914 child = isl_schedule_tree_list_get_schedule_tree(tree->children, 0);
915 dom = isl_schedule_tree_filter_get_filter(child);
916 space = isl_union_set_get_space(dom);
917 isl_union_set_free(dom);
918 isl_schedule_tree_free(child);
920 return space;
923 /* Extend the schedule map "outer" with the subtree schedule
924 * of a set or sequence node.
926 * The schedule for the set or sequence node itself is composed of
927 * pieces of the form
929 * filter -> []
931 * or
933 * filter -> [index]
935 * The first form is used if there is only a single child or
936 * if the current node is a set node and the schedule_separate_components
937 * option is not set.
939 * Each of the pieces above is extended with the subtree schedule of
940 * the child of the corresponding filter, if any, padded with zeros
941 * to ensure that all pieces have the same range dimension.
943 static __isl_give isl_union_map *subtree_schedule_extend_from_children(
944 __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
946 int i, n;
947 int dim;
948 int separate;
949 isl_ctx *ctx;
950 isl_val *v = NULL;
951 isl_multi_val *mv;
952 isl_space *space;
953 isl_union_map *umap;
955 if (!tree)
956 return NULL;
958 ctx = isl_schedule_tree_get_ctx(tree);
959 if (!tree->children)
960 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
961 "missing children", return NULL);
962 n = isl_schedule_tree_list_n_schedule_tree(tree->children);
963 if (n == 0)
964 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
965 "missing children", return NULL);
967 separate = n > 1 && (tree->type == isl_schedule_node_sequence ||
968 isl_options_get_schedule_separate_components(ctx));
970 space = extract_space_from_filter_child(tree);
972 umap = isl_union_map_empty(isl_space_copy(space));
973 space = isl_space_set_from_params(space);
974 if (separate) {
975 space = isl_space_add_dims(space, isl_dim_set, 1);
976 v = isl_val_zero(ctx);
978 mv = isl_multi_val_zero(space);
980 dim = isl_multi_val_dim(mv, isl_dim_set);
981 for (i = 0; i < n; ++i) {
982 isl_union_pw_multi_aff *upma;
983 isl_union_map *umap_i;
984 isl_union_set *dom;
985 isl_schedule_tree *child;
986 int dim_i;
987 int empty;
989 child = isl_schedule_tree_list_get_schedule_tree(
990 tree->children, i);
991 dom = isl_schedule_tree_filter_get_filter(child);
993 if (separate) {
994 mv = isl_multi_val_set_val(mv, 0, isl_val_copy(v));
995 v = isl_val_add_ui(v, 1);
997 upma = isl_union_pw_multi_aff_multi_val_on_domain(dom,
998 isl_multi_val_copy(mv));
999 umap_i = isl_union_map_from_union_pw_multi_aff(upma);
1000 umap_i = isl_union_map_flat_range_product(
1001 isl_union_map_copy(outer), umap_i);
1002 umap_i = subtree_schedule_extend_child(child, umap_i);
1003 isl_schedule_tree_free(child);
1005 empty = isl_union_map_is_empty(umap_i);
1006 if (empty < 0)
1007 umap_i = isl_union_map_free(umap_i);
1008 else if (empty) {
1009 isl_union_map_free(umap_i);
1010 continue;
1013 dim_i = range_dim(umap_i);
1014 if (dim_i < 0) {
1015 umap = isl_union_map_free(umap);
1016 } else if (dim < dim_i) {
1017 umap = append_range(umap, dim_i - dim);
1018 dim = dim_i;
1019 } else if (dim_i < dim) {
1020 umap_i = append_range(umap_i, dim - dim_i);
1022 umap = isl_union_map_union(umap, umap_i);
1025 isl_val_free(v);
1026 isl_multi_val_free(mv);
1027 isl_union_map_free(outer);
1029 return umap;
1032 /* Extend the schedule map "outer" with the subtree schedule of "tree".
1034 * If the root of the tree is a set or a sequence, then we extend
1035 * the schedule map in subtree_schedule_extend_from_children.
1036 * Otherwise, we extend the schedule map with the partial schedule
1037 * corresponding to the root of the tree and then continue with
1038 * the single child of this root.
1040 static __isl_give isl_union_map *subtree_schedule_extend(
1041 __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
1043 isl_multi_union_pw_aff *mupa;
1044 isl_union_map *umap;
1045 isl_union_set *domain;
1047 if (!tree)
1048 return NULL;
1050 switch (tree->type) {
1051 case isl_schedule_node_error:
1052 return isl_union_map_free(outer);
1053 case isl_schedule_node_band:
1054 if (isl_schedule_tree_band_n_member(tree) == 0)
1055 return subtree_schedule_extend_child(tree, outer);
1056 mupa = isl_schedule_band_get_partial_schedule(tree->band);
1057 umap = isl_union_map_from_multi_union_pw_aff(mupa);
1058 outer = isl_union_map_flat_range_product(outer, umap);
1059 umap = subtree_schedule_extend_child(tree, outer);
1060 break;
1061 case isl_schedule_node_domain:
1062 domain = isl_schedule_tree_domain_get_domain(tree);
1063 umap = isl_union_map_from_domain(domain);
1064 outer = isl_union_map_flat_range_product(outer, umap);
1065 umap = subtree_schedule_extend_child(tree, outer);
1066 break;
1067 case isl_schedule_node_filter:
1068 domain = isl_schedule_tree_filter_get_filter(tree);
1069 umap = isl_union_map_from_domain(domain);
1070 outer = isl_union_map_flat_range_product(outer, umap);
1071 umap = subtree_schedule_extend_child(tree, outer);
1072 break;
1073 case isl_schedule_node_leaf:
1074 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1075 "leaf node should be handled by caller", return NULL);
1076 case isl_schedule_node_set:
1077 case isl_schedule_node_sequence:
1078 umap = subtree_schedule_extend_from_children(tree, outer);
1079 break;
1082 return umap;
1085 static __isl_give isl_union_set *initial_domain(
1086 __isl_keep isl_schedule_tree *tree);
1088 /* Extract a universe domain from the children of the tree root "tree",
1089 * which is a set or sequence, meaning that its children are filters.
1090 * In particular, return the union of the universes of the filters.
1092 static __isl_give isl_union_set *initial_domain_from_children(
1093 __isl_keep isl_schedule_tree *tree)
1095 int i, n;
1096 isl_space *space;
1097 isl_union_set *domain;
1099 if (!tree->children)
1100 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1101 "missing children", return NULL);
1102 n = isl_schedule_tree_list_n_schedule_tree(tree->children);
1103 if (n == 0)
1104 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1105 "missing children", return NULL);
1107 space = extract_space_from_filter_child(tree);
1108 domain = isl_union_set_empty(space);
1110 for (i = 0; i < n; ++i) {
1111 isl_schedule_tree *child;
1112 isl_union_set *domain_i;
1114 child = isl_schedule_tree_get_child(tree, i);
1115 domain_i = initial_domain(child);
1116 domain = isl_union_set_union(domain, domain_i);
1117 isl_schedule_tree_free(child);
1120 return domain;
1123 /* Extract a universe domain from the tree root "tree".
1124 * The caller is responsible for making sure that this node
1125 * would not be skipped by isl_schedule_tree_first_schedule_descendant
1126 * and that it is not a leaf node.
1128 static __isl_give isl_union_set *initial_domain(
1129 __isl_keep isl_schedule_tree *tree)
1131 isl_multi_union_pw_aff *mupa;
1132 isl_union_set *domain;
1134 if (!tree)
1135 return NULL;
1137 switch (tree->type) {
1138 case isl_schedule_node_error:
1139 return NULL;
1140 case isl_schedule_node_band:
1141 if (isl_schedule_tree_band_n_member(tree) == 0)
1142 isl_die(isl_schedule_tree_get_ctx(tree),
1143 isl_error_internal,
1144 "0D band should be handled by caller",
1145 return NULL);
1146 mupa = isl_schedule_band_get_partial_schedule(tree->band);
1147 domain = isl_multi_union_pw_aff_domain(mupa);
1148 domain = isl_union_set_universe(domain);
1149 break;
1150 case isl_schedule_node_domain:
1151 domain = isl_schedule_tree_domain_get_domain(tree);
1152 domain = isl_union_set_universe(domain);
1153 break;
1154 case isl_schedule_node_filter:
1155 domain = isl_schedule_tree_filter_get_filter(tree);
1156 domain = isl_union_set_universe(domain);
1157 break;
1158 case isl_schedule_node_leaf:
1159 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1160 "leaf node should be handled by caller", return NULL);
1161 case isl_schedule_node_set:
1162 case isl_schedule_node_sequence:
1163 domain = initial_domain_from_children(tree);
1164 break;
1167 return domain;
1170 /* Return the subtree schedule of a node that contains some schedule
1171 * information, i.e., a node that would not be skipped by
1172 * isl_schedule_tree_first_schedule_descendant and that is not a leaf.
1174 * We start with an initial zero-dimensional subtree schedule based
1175 * on the domain information in the root node and then extend it
1176 * based on the schedule information in the root node and its descendants.
1178 __isl_give isl_union_map *isl_schedule_tree_get_subtree_schedule_union_map(
1179 __isl_keep isl_schedule_tree *tree)
1181 isl_union_set *domain;
1182 isl_union_map *umap;
1184 domain = initial_domain(tree);
1185 umap = isl_union_map_from_domain(domain);
1186 return subtree_schedule_extend(tree, umap);
1189 /* Multiply the partial schedule of the band root node of "tree"
1190 * with the factors in "mv".
1192 __isl_give isl_schedule_tree *isl_schedule_tree_band_scale(
1193 __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
1195 if (!tree || !mv)
1196 goto error;
1197 if (tree->type != isl_schedule_node_band)
1198 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1199 "not a band node", goto error);
1201 tree = isl_schedule_tree_cow(tree);
1202 if (!tree)
1203 goto error;
1205 tree->band = isl_schedule_band_scale(tree->band, mv);
1206 if (!tree->band)
1207 return isl_schedule_tree_free(tree);
1209 return tree;
1210 error:
1211 isl_schedule_tree_free(tree);
1212 isl_multi_val_free(mv);
1213 return NULL;
1216 /* Divide the partial schedule of the band root node of "tree"
1217 * by the factors in "mv".
1219 __isl_give isl_schedule_tree *isl_schedule_tree_band_scale_down(
1220 __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
1222 if (!tree || !mv)
1223 goto error;
1224 if (tree->type != isl_schedule_node_band)
1225 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1226 "not a band node", goto error);
1228 tree = isl_schedule_tree_cow(tree);
1229 if (!tree)
1230 goto error;
1232 tree->band = isl_schedule_band_scale_down(tree->band, mv);
1233 if (!tree->band)
1234 return isl_schedule_tree_free(tree);
1236 return tree;
1237 error:
1238 isl_schedule_tree_free(tree);
1239 isl_multi_val_free(mv);
1240 return NULL;
1243 /* Tile the band root node of "tree" with tile sizes "sizes".
1245 * We duplicate the band node, change the schedule of one of them
1246 * to the tile schedule and the other to the point schedule and then
1247 * attach the point band as a child to the tile band.
1249 __isl_give isl_schedule_tree *isl_schedule_tree_band_tile(
1250 __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *sizes)
1252 isl_schedule_tree *child = NULL;
1254 if (!tree || !sizes)
1255 goto error;
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 child = isl_schedule_tree_copy(tree);
1261 tree = isl_schedule_tree_cow(tree);
1262 child = isl_schedule_tree_cow(child);
1263 if (!tree || !child)
1264 goto error;
1266 tree->band = isl_schedule_band_tile(tree->band,
1267 isl_multi_val_copy(sizes));
1268 if (!tree->band)
1269 goto error;
1270 child->band = isl_schedule_band_point(child->band, tree->band, sizes);
1271 if (!child->band)
1272 child = isl_schedule_tree_free(child);
1274 tree = isl_schedule_tree_replace_child(tree, 0, child);
1276 return tree;
1277 error:
1278 isl_schedule_tree_free(child);
1279 isl_schedule_tree_free(tree);
1280 isl_multi_val_free(sizes);
1281 return NULL;
1284 /* Split the band root node of "tree" into two nested band nodes,
1285 * one with the first "pos" dimensions and
1286 * one with the remaining dimensions.
1288 __isl_give isl_schedule_tree *isl_schedule_tree_band_split(
1289 __isl_take isl_schedule_tree *tree, int pos)
1291 int n;
1292 isl_schedule_tree *child;
1294 if (!tree)
1295 return NULL;
1296 if (tree->type != isl_schedule_node_band)
1297 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1298 "not a band node", return isl_schedule_tree_free(tree));
1300 n = isl_schedule_tree_band_n_member(tree);
1301 if (pos < 0 || pos > n)
1302 isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1303 "position out of bounds",
1304 return isl_schedule_tree_free(tree));
1306 child = isl_schedule_tree_copy(tree);
1307 tree = isl_schedule_tree_cow(tree);
1308 child = isl_schedule_tree_cow(child);
1309 if (!tree || !child)
1310 goto error;
1312 child->band = isl_schedule_band_drop(child->band, 0, pos);
1313 tree->band = isl_schedule_band_drop(tree->band, pos, n - pos);
1314 if (!child->band || !tree->band)
1315 goto error;
1317 tree = isl_schedule_tree_replace_child(tree, 0, child);
1319 return tree;
1320 error:
1321 isl_schedule_tree_free(child);
1322 isl_schedule_tree_free(tree);
1323 return NULL;
1326 /* Attach "tree2" at each of the leaves of "tree1".
1328 * If "tree1" does not have any explicit children, then make "tree2"
1329 * its single child. Otherwise, attach "tree2" to the leaves of
1330 * each of the children of "tree1".
1332 __isl_give isl_schedule_tree *isl_schedule_tree_append_to_leaves(
1333 __isl_take isl_schedule_tree *tree1,
1334 __isl_take isl_schedule_tree *tree2)
1336 int i, n;
1338 if (!tree1 || !tree2)
1339 goto error;
1340 n = isl_schedule_tree_n_children(tree1);
1341 if (n == 0) {
1342 isl_schedule_tree_list *list;
1343 list = isl_schedule_tree_list_from_schedule_tree(tree2);
1344 tree1 = isl_schedule_tree_set_children(tree1, list);
1345 return tree1;
1347 for (i = 0; i < n; ++i) {
1348 isl_schedule_tree *child;
1350 child = isl_schedule_tree_get_child(tree1, i);
1351 child = isl_schedule_tree_append_to_leaves(child,
1352 isl_schedule_tree_copy(tree2));
1353 tree1 = isl_schedule_tree_replace_child(tree1, i, child);
1356 isl_schedule_tree_free(tree2);
1357 return tree1;
1358 error:
1359 isl_schedule_tree_free(tree1);
1360 isl_schedule_tree_free(tree2);
1361 return NULL;
1364 /* Reset the user pointer on all identifiers of parameters and tuples
1365 * in the root of "tree".
1367 __isl_give isl_schedule_tree *isl_schedule_tree_reset_user(
1368 __isl_take isl_schedule_tree *tree)
1370 if (isl_schedule_tree_is_leaf(tree))
1371 return tree;
1373 tree = isl_schedule_tree_cow(tree);
1374 if (!tree)
1375 return NULL;
1377 switch (tree->type) {
1378 case isl_schedule_node_error:
1379 return isl_schedule_tree_free(tree);
1380 case isl_schedule_node_band:
1381 tree->band = isl_schedule_band_reset_user(tree->band);
1382 if (!tree->band)
1383 return isl_schedule_tree_free(tree);
1384 break;
1385 case isl_schedule_node_domain:
1386 tree->domain = isl_union_set_reset_user(tree->domain);
1387 if (!tree->domain)
1388 return isl_schedule_tree_free(tree);
1389 break;
1390 case isl_schedule_node_filter:
1391 tree->filter = isl_union_set_reset_user(tree->filter);
1392 if (!tree->filter)
1393 return isl_schedule_tree_free(tree);
1394 break;
1395 case isl_schedule_node_leaf:
1396 case isl_schedule_node_sequence:
1397 case isl_schedule_node_set:
1398 break;
1401 return tree;
1404 /* Are any members in "band" marked coincident?
1406 static int any_coincident(__isl_keep isl_schedule_band *band)
1408 int i, n;
1410 n = isl_schedule_band_n_member(band);
1411 for (i = 0; i < n; ++i)
1412 if (isl_schedule_band_member_get_coincident(band, i))
1413 return 1;
1415 return 0;
1418 /* Print the band node "band" to "p".
1420 * The permutable and coincident properties are only printed if they
1421 * are different from the defaults.
1422 * The coincident property is always printed in YAML flow style.
1424 static __isl_give isl_printer *print_tree_band(__isl_take isl_printer *p,
1425 __isl_keep isl_schedule_band *band)
1427 p = isl_printer_print_str(p, "schedule");
1428 p = isl_printer_yaml_next(p);
1429 p = isl_printer_print_str(p, "\"");
1430 p = isl_printer_print_multi_union_pw_aff(p, band->mupa);
1431 p = isl_printer_print_str(p, "\"");
1432 if (isl_schedule_band_get_permutable(band)) {
1433 p = isl_printer_yaml_next(p);
1434 p = isl_printer_print_str(p, "permutable");
1435 p = isl_printer_yaml_next(p);
1436 p = isl_printer_print_int(p, 1);
1438 if (any_coincident(band)) {
1439 int i, n;
1440 int style;
1442 p = isl_printer_yaml_next(p);
1443 p = isl_printer_print_str(p, "coincident");
1444 p = isl_printer_yaml_next(p);
1445 style = isl_printer_get_yaml_style(p);
1446 p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
1447 p = isl_printer_yaml_start_sequence(p);
1448 n = isl_schedule_band_n_member(band);
1449 for (i = 0; i < n; ++i) {
1450 p = isl_printer_print_int(p,
1451 isl_schedule_band_member_get_coincident(band, i));
1452 p = isl_printer_yaml_next(p);
1454 p = isl_printer_yaml_end_sequence(p);
1455 p = isl_printer_set_yaml_style(p, style);
1458 return p;
1461 /* Print "tree" to "p".
1463 * If "n_ancestor" is non-negative, then "child_pos" contains the child
1464 * positions of a descendant of the current node that should be marked
1465 * (by the comment "YOU ARE HERE"). In particular, if "n_ancestor"
1466 * is zero, then the current node should be marked.
1467 * The marking is only printed in YAML block format.
1469 * Implicit leaf nodes are not printed, except if they correspond
1470 * to the node that should be marked.
1472 __isl_give isl_printer *isl_printer_print_schedule_tree_mark(
1473 __isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree,
1474 int n_ancestor, int *child_pos)
1476 int i, n;
1477 int sequence = 0;
1478 int block;
1480 block = isl_printer_get_yaml_style(p) == ISL_YAML_STYLE_BLOCK;
1482 p = isl_printer_yaml_start_mapping(p);
1483 if (n_ancestor == 0 && block) {
1484 p = isl_printer_print_str(p, "# YOU ARE HERE");
1485 p = isl_printer_end_line(p);
1486 p = isl_printer_start_line(p);
1488 switch (tree->type) {
1489 case isl_schedule_node_error:
1490 p = isl_printer_print_str(p, "ERROR");
1491 break;
1492 case isl_schedule_node_leaf:
1493 p = isl_printer_print_str(p, "leaf");
1494 break;
1495 case isl_schedule_node_sequence:
1496 p = isl_printer_print_str(p, "sequence");
1497 sequence = 1;
1498 break;
1499 case isl_schedule_node_set:
1500 p = isl_printer_print_str(p, "set");
1501 sequence = 1;
1502 break;
1503 case isl_schedule_node_domain:
1504 p = isl_printer_print_str(p, "domain");
1505 p = isl_printer_yaml_next(p);
1506 p = isl_printer_print_str(p, "\"");
1507 p = isl_printer_print_union_set(p, tree->domain);
1508 p = isl_printer_print_str(p, "\"");
1509 break;
1510 case isl_schedule_node_filter:
1511 p = isl_printer_print_str(p, "filter");
1512 p = isl_printer_yaml_next(p);
1513 p = isl_printer_print_str(p, "\"");
1514 p = isl_printer_print_union_set(p, tree->filter);
1515 p = isl_printer_print_str(p, "\"");
1516 break;
1517 case isl_schedule_node_band:
1518 p = print_tree_band(p, tree->band);
1519 break;
1521 p = isl_printer_yaml_next(p);
1523 if (!tree->children) {
1524 if (n_ancestor > 0 && block) {
1525 isl_schedule_tree *leaf;
1527 p = isl_printer_print_str(p, "child");
1528 p = isl_printer_yaml_next(p);
1529 leaf = isl_schedule_tree_leaf(isl_printer_get_ctx(p));
1530 p = isl_printer_print_schedule_tree_mark(p,
1531 leaf, 0, NULL);
1532 isl_schedule_tree_free(leaf);
1533 p = isl_printer_yaml_next(p);
1535 return isl_printer_yaml_end_mapping(p);
1538 if (sequence) {
1539 p = isl_printer_yaml_start_sequence(p);
1540 } else {
1541 p = isl_printer_print_str(p, "child");
1542 p = isl_printer_yaml_next(p);
1545 n = isl_schedule_tree_list_n_schedule_tree(tree->children);
1546 for (i = 0; i < n; ++i) {
1547 isl_schedule_tree *t;
1549 t = isl_schedule_tree_get_child(tree, i);
1550 if (n_ancestor > 0 && child_pos[0] == i)
1551 p = isl_printer_print_schedule_tree_mark(p, t,
1552 n_ancestor - 1, child_pos + 1);
1553 else
1554 p = isl_printer_print_schedule_tree_mark(p, t,
1555 -1, NULL);
1556 isl_schedule_tree_free(t);
1558 p = isl_printer_yaml_next(p);
1561 if (sequence)
1562 p = isl_printer_yaml_end_sequence(p);
1563 p = isl_printer_yaml_end_mapping(p);
1565 return p;
1568 /* Print "tree" to "p".
1570 __isl_give isl_printer *isl_printer_print_schedule_tree(
1571 __isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree)
1573 return isl_printer_print_schedule_tree_mark(p, tree, -1, NULL);
1576 void isl_schedule_tree_dump(__isl_keep isl_schedule_tree *tree)
1578 isl_ctx *ctx;
1579 isl_printer *printer;
1581 if (!tree)
1582 return;
1584 ctx = isl_schedule_tree_get_ctx(tree);
1585 printer = isl_printer_to_file(ctx, stderr);
1586 printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_BLOCK);
1587 printer = isl_printer_print_schedule_tree(printer, tree);
1589 isl_printer_free(printer);