isl_schedule.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. /*
  2. * Copyright 2011 INRIA Saclay
  3. * Copyright 2012-2014 Ecole Normale Superieure
  4. * Copyright 2016 Sven Verdoolaege
  5. *
  6. * Use of this software is governed by the MIT license
  7. *
  8. * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
  9. * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
  10. * 91893 Orsay, France
  11. * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
  12. */
  13. #include <isl/ctx.h>
  14. #include <isl/val.h>
  15. #include <isl_aff_private.h>
  16. #include <isl/map.h>
  17. #include <isl/set.h>
  18. #include <isl/schedule.h>
  19. #include <isl/schedule_node.h>
  20. #include <isl_sort.h>
  21. #include <isl/printer.h>
  22. #include <isl_schedule_private.h>
  23. #include <isl_schedule_tree.h>
  24. #include <isl_schedule_node_private.h>
  25. /* Return a schedule encapsulating the given schedule tree.
  26. *
  27. * We currently only allow schedule trees with a domain or extension as root.
  28. *
  29. * The leaf field is initialized as a leaf node so that it can be
  30. * used to represent leaves in the constructed schedule.
  31. * The reference count is set to -1 since the isl_schedule_tree
  32. * should never be freed. It is up to the (internal) users of
  33. * these leaves to ensure that they are only used while the schedule
  34. * is still alive.
  35. */
  36. __isl_give isl_schedule *isl_schedule_from_schedule_tree(isl_ctx *ctx,
  37. __isl_take isl_schedule_tree *tree)
  38. {
  39. enum isl_schedule_node_type type;
  40. isl_schedule *schedule;
  41. if (!tree)
  42. return NULL;
  43. type = isl_schedule_tree_get_type(tree);
  44. if (type != isl_schedule_node_domain &&
  45. type != isl_schedule_node_extension)
  46. isl_die(isl_schedule_tree_get_ctx(tree), isl_error_unsupported,
  47. "root of schedule tree should be a domain or extension",
  48. goto error);
  49. schedule = isl_calloc_type(ctx, isl_schedule);
  50. if (!schedule)
  51. goto error;
  52. schedule->ref = 1;
  53. schedule->root = tree;
  54. schedule->leaf = isl_schedule_tree_leaf(ctx);
  55. if (!schedule->leaf)
  56. return isl_schedule_free(schedule);
  57. return schedule;
  58. error:
  59. isl_schedule_tree_free(tree);
  60. return NULL;
  61. }
  62. /* Return a pointer to a schedule with as single node
  63. * a domain node with the given domain.
  64. */
  65. __isl_give isl_schedule *isl_schedule_from_domain(
  66. __isl_take isl_union_set *domain)
  67. {
  68. isl_ctx *ctx;
  69. isl_schedule_tree *tree;
  70. ctx = isl_union_set_get_ctx(domain);
  71. tree = isl_schedule_tree_from_domain(domain);
  72. return isl_schedule_from_schedule_tree(ctx, tree);
  73. }
  74. /* Return a pointer to a schedule with as single node
  75. * a domain node with an empty domain.
  76. */
  77. __isl_give isl_schedule *isl_schedule_empty(__isl_take isl_space *space)
  78. {
  79. return isl_schedule_from_domain(isl_union_set_empty(space));
  80. }
  81. /* Return a new reference to "sched".
  82. */
  83. __isl_give isl_schedule *isl_schedule_copy(__isl_keep isl_schedule *sched)
  84. {
  85. if (!sched)
  86. return NULL;
  87. sched->ref++;
  88. return sched;
  89. }
  90. /* Return an isl_schedule that is equal to "schedule" and that has only
  91. * a single reference.
  92. */
  93. __isl_give isl_schedule *isl_schedule_cow(__isl_take isl_schedule *schedule)
  94. {
  95. isl_ctx *ctx;
  96. isl_schedule_tree *tree;
  97. if (!schedule)
  98. return NULL;
  99. if (schedule->ref == 1)
  100. return schedule;
  101. ctx = isl_schedule_get_ctx(schedule);
  102. schedule->ref--;
  103. tree = isl_schedule_tree_copy(schedule->root);
  104. return isl_schedule_from_schedule_tree(ctx, tree);
  105. }
  106. __isl_null isl_schedule *isl_schedule_free(__isl_take isl_schedule *sched)
  107. {
  108. if (!sched)
  109. return NULL;
  110. if (--sched->ref > 0)
  111. return NULL;
  112. isl_schedule_tree_free(sched->root);
  113. isl_schedule_tree_free(sched->leaf);
  114. free(sched);
  115. return NULL;
  116. }
  117. /* Replace the root of "schedule" by "tree".
  118. */
  119. __isl_give isl_schedule *isl_schedule_set_root(
  120. __isl_take isl_schedule *schedule, __isl_take isl_schedule_tree *tree)
  121. {
  122. if (!schedule || !tree)
  123. goto error;
  124. if (schedule->root == tree) {
  125. isl_schedule_tree_free(tree);
  126. return schedule;
  127. }
  128. schedule = isl_schedule_cow(schedule);
  129. if (!schedule)
  130. goto error;
  131. isl_schedule_tree_free(schedule->root);
  132. schedule->root = tree;
  133. return schedule;
  134. error:
  135. isl_schedule_free(schedule);
  136. isl_schedule_tree_free(tree);
  137. return NULL;
  138. }
  139. isl_ctx *isl_schedule_get_ctx(__isl_keep isl_schedule *schedule)
  140. {
  141. return schedule ? isl_schedule_tree_get_ctx(schedule->leaf) : NULL;
  142. }
  143. /* Return a pointer to the leaf of "schedule".
  144. */
  145. __isl_keep isl_schedule_tree *isl_schedule_peek_leaf(
  146. __isl_keep isl_schedule *schedule)
  147. {
  148. return schedule ? schedule->leaf : NULL;
  149. }
  150. /* Are "schedule1" and "schedule2" obviously equal to each other?
  151. */
  152. isl_bool isl_schedule_plain_is_equal(__isl_keep isl_schedule *schedule1,
  153. __isl_keep isl_schedule *schedule2)
  154. {
  155. if (!schedule1 || !schedule2)
  156. return isl_bool_error;
  157. if (schedule1 == schedule2)
  158. return isl_bool_true;
  159. return isl_schedule_tree_plain_is_equal(schedule1->root,
  160. schedule2->root);
  161. }
  162. /* Return the (parameter) space of the schedule, i.e., the space
  163. * of the root domain.
  164. */
  165. __isl_give isl_space *isl_schedule_get_space(
  166. __isl_keep isl_schedule *schedule)
  167. {
  168. enum isl_schedule_node_type type;
  169. isl_space *space;
  170. isl_union_set *domain;
  171. if (!schedule)
  172. return NULL;
  173. type = isl_schedule_tree_get_type(schedule->root);
  174. if (type != isl_schedule_node_domain)
  175. isl_die(isl_schedule_get_ctx(schedule), isl_error_internal,
  176. "root node not a domain node", return NULL);
  177. domain = isl_schedule_tree_domain_get_domain(schedule->root);
  178. space = isl_union_set_get_space(domain);
  179. isl_union_set_free(domain);
  180. return space;
  181. }
  182. /* Return a pointer to the root of "schedule".
  183. */
  184. __isl_give isl_schedule_node *isl_schedule_get_root(
  185. __isl_keep isl_schedule *schedule)
  186. {
  187. isl_ctx *ctx;
  188. isl_schedule_tree *tree;
  189. isl_schedule_tree_list *ancestors;
  190. if (!schedule)
  191. return NULL;
  192. ctx = isl_schedule_get_ctx(schedule);
  193. tree = isl_schedule_tree_copy(schedule->root);
  194. schedule = isl_schedule_copy(schedule);
  195. ancestors = isl_schedule_tree_list_alloc(ctx, 0);
  196. return isl_schedule_node_alloc(schedule, tree, ancestors, NULL);
  197. }
  198. /* Return the domain of the root domain node of "schedule".
  199. */
  200. __isl_give isl_union_set *isl_schedule_get_domain(
  201. __isl_keep isl_schedule *schedule)
  202. {
  203. if (!schedule)
  204. return NULL;
  205. return isl_schedule_tree_domain_get_domain(schedule->root);
  206. }
  207. /* Traverse all nodes of "sched" in depth first preorder.
  208. *
  209. * If "fn" returns -1 on any of the nodes, then the traversal is aborted.
  210. * If "fn" returns 0 on any of the nodes, then the subtree rooted
  211. * at that node is skipped.
  212. *
  213. * Return 0 on success and -1 on failure.
  214. */
  215. isl_stat isl_schedule_foreach_schedule_node_top_down(
  216. __isl_keep isl_schedule *sched,
  217. isl_bool (*fn)(__isl_keep isl_schedule_node *node, void *user),
  218. void *user)
  219. {
  220. isl_schedule_node *node;
  221. isl_stat r;
  222. if (!sched)
  223. return isl_stat_error;
  224. node = isl_schedule_get_root(sched);
  225. r = isl_schedule_node_foreach_descendant_top_down(node, fn, user);
  226. isl_schedule_node_free(node);
  227. return r;
  228. }
  229. /* Traverse the node of "sched" in depth first postorder,
  230. * allowing the user to modify the visited node.
  231. * The traversal continues from the node returned by the callback function.
  232. * It is the responsibility of the user to ensure that this does not
  233. * lead to an infinite loop. It is safest to always return a pointer
  234. * to the same position (same ancestors and child positions) as the input node.
  235. */
  236. __isl_give isl_schedule *isl_schedule_map_schedule_node_bottom_up(
  237. __isl_take isl_schedule *schedule,
  238. __isl_give isl_schedule_node *(*fn)(
  239. __isl_take isl_schedule_node *node, void *user), void *user)
  240. {
  241. isl_schedule_node *node;
  242. node = isl_schedule_get_root(schedule);
  243. isl_schedule_free(schedule);
  244. node = isl_schedule_node_map_descendant_bottom_up(node, fn, user);
  245. schedule = isl_schedule_node_get_schedule(node);
  246. isl_schedule_node_free(node);
  247. return schedule;
  248. }
  249. /* Wrapper around isl_schedule_node_reset_user for use as
  250. * an isl_schedule_map_schedule_node_bottom_up callback.
  251. */
  252. static __isl_give isl_schedule_node *reset_user(
  253. __isl_take isl_schedule_node *node, void *user)
  254. {
  255. return isl_schedule_node_reset_user(node);
  256. }
  257. /* Reset the user pointer on all identifiers of parameters and tuples
  258. * in the schedule "schedule".
  259. */
  260. __isl_give isl_schedule *isl_schedule_reset_user(
  261. __isl_take isl_schedule *schedule)
  262. {
  263. return isl_schedule_map_schedule_node_bottom_up(schedule, &reset_user,
  264. NULL);
  265. }
  266. /* Wrapper around isl_schedule_node_align_params for use as
  267. * an isl_schedule_map_schedule_node_bottom_up callback.
  268. */
  269. static __isl_give isl_schedule_node *align_params(
  270. __isl_take isl_schedule_node *node, void *user)
  271. {
  272. isl_space *space = user;
  273. return isl_schedule_node_align_params(node, isl_space_copy(space));
  274. }
  275. /* Align the parameters of all nodes in schedule "schedule"
  276. * to those of "space".
  277. */
  278. __isl_give isl_schedule *isl_schedule_align_params(
  279. __isl_take isl_schedule *schedule, __isl_take isl_space *space)
  280. {
  281. schedule = isl_schedule_map_schedule_node_bottom_up(schedule,
  282. &align_params, space);
  283. isl_space_free(space);
  284. return schedule;
  285. }
  286. /* Wrapper around isl_schedule_node_pullback_union_pw_multi_aff for use as
  287. * an isl_schedule_map_schedule_node_bottom_up callback.
  288. */
  289. static __isl_give isl_schedule_node *pullback_upma(
  290. __isl_take isl_schedule_node *node, void *user)
  291. {
  292. isl_union_pw_multi_aff *upma = user;
  293. return isl_schedule_node_pullback_union_pw_multi_aff(node,
  294. isl_union_pw_multi_aff_copy(upma));
  295. }
  296. /* Compute the pullback of "schedule" by the function represented by "upma".
  297. * In other words, plug in "upma" in the iteration domains of "schedule".
  298. *
  299. * The schedule tree is not allowed to contain any expansion nodes.
  300. */
  301. __isl_give isl_schedule *isl_schedule_pullback_union_pw_multi_aff(
  302. __isl_take isl_schedule *schedule,
  303. __isl_take isl_union_pw_multi_aff *upma)
  304. {
  305. schedule = isl_schedule_map_schedule_node_bottom_up(schedule,
  306. &pullback_upma, upma);
  307. isl_union_pw_multi_aff_free(upma);
  308. return schedule;
  309. }
  310. /* Expand the schedule "schedule" by extending all leaves
  311. * with an expansion node with as subtree the tree of "expansion".
  312. * The expansion of the expansion node is determined by "contraction"
  313. * and the domain of "expansion". That is, the domain of "expansion"
  314. * is contracted according to "contraction".
  315. *
  316. * Call isl_schedule_node_expand after extracting the required
  317. * information from "expansion".
  318. */
  319. __isl_give isl_schedule *isl_schedule_expand(__isl_take isl_schedule *schedule,
  320. __isl_take isl_union_pw_multi_aff *contraction,
  321. __isl_take isl_schedule *expansion)
  322. {
  323. isl_union_set *domain;
  324. isl_schedule_node *node;
  325. isl_schedule_tree *tree;
  326. domain = isl_schedule_get_domain(expansion);
  327. node = isl_schedule_get_root(expansion);
  328. node = isl_schedule_node_child(node, 0);
  329. tree = isl_schedule_node_get_tree(node);
  330. isl_schedule_node_free(node);
  331. isl_schedule_free(expansion);
  332. node = isl_schedule_get_root(schedule);
  333. isl_schedule_free(schedule);
  334. node = isl_schedule_node_expand(node, contraction, domain, tree);
  335. schedule = isl_schedule_node_get_schedule(node);
  336. isl_schedule_node_free(node);
  337. return schedule;
  338. }
  339. /* Intersect the domain of the schedule "schedule" with "domain".
  340. * The root of "schedule" is required to be a domain node.
  341. */
  342. __isl_give isl_schedule *isl_schedule_intersect_domain(
  343. __isl_take isl_schedule *schedule, __isl_take isl_union_set *domain)
  344. {
  345. enum isl_schedule_node_type root_type;
  346. isl_schedule_node *node;
  347. if (!schedule || !domain)
  348. goto error;
  349. root_type = isl_schedule_tree_get_type(schedule->root);
  350. if (root_type != isl_schedule_node_domain)
  351. isl_die(isl_schedule_get_ctx(schedule), isl_error_invalid,
  352. "root node must be a domain node", goto error);
  353. node = isl_schedule_get_root(schedule);
  354. isl_schedule_free(schedule);
  355. node = isl_schedule_node_domain_intersect_domain(node, domain);
  356. schedule = isl_schedule_node_get_schedule(node);
  357. isl_schedule_node_free(node);
  358. return schedule;
  359. error:
  360. isl_schedule_free(schedule);
  361. isl_union_set_free(domain);
  362. return NULL;
  363. }
  364. /* Replace the domain of the schedule "schedule" with the gist
  365. * of the original domain with respect to the parameter domain "context".
  366. */
  367. __isl_give isl_schedule *isl_schedule_gist_domain_params(
  368. __isl_take isl_schedule *schedule, __isl_take isl_set *context)
  369. {
  370. enum isl_schedule_node_type root_type;
  371. isl_schedule_node *node;
  372. if (!schedule || !context)
  373. goto error;
  374. root_type = isl_schedule_tree_get_type(schedule->root);
  375. if (root_type != isl_schedule_node_domain)
  376. isl_die(isl_schedule_get_ctx(schedule), isl_error_invalid,
  377. "root node must be a domain node", goto error);
  378. node = isl_schedule_get_root(schedule);
  379. isl_schedule_free(schedule);
  380. node = isl_schedule_node_domain_gist_params(node, context);
  381. schedule = isl_schedule_node_get_schedule(node);
  382. isl_schedule_node_free(node);
  383. return schedule;
  384. error:
  385. isl_schedule_free(schedule);
  386. isl_set_free(context);
  387. return NULL;
  388. }
  389. /* Return an isl_union_map representation of the schedule. In particular,
  390. * return an isl_union_map corresponding to the subtree schedule of the child
  391. * of the root domain node. That is, we do not intersect the domain
  392. * of the returned isl_union_map with the domain constraints.
  393. */
  394. __isl_give isl_union_map *isl_schedule_get_map(__isl_keep isl_schedule *sched)
  395. {
  396. enum isl_schedule_node_type type;
  397. isl_schedule_node *node;
  398. isl_union_map *umap;
  399. if (!sched)
  400. return NULL;
  401. type = isl_schedule_tree_get_type(sched->root);
  402. if (type != isl_schedule_node_domain)
  403. isl_die(isl_schedule_get_ctx(sched), isl_error_internal,
  404. "root node not a domain node", return NULL);
  405. node = isl_schedule_get_root(sched);
  406. node = isl_schedule_node_child(node, 0);
  407. umap = isl_schedule_node_get_subtree_schedule_union_map(node);
  408. isl_schedule_node_free(node);
  409. return umap;
  410. }
  411. /* Insert a band node with partial schedule "partial" between the domain
  412. * root node of "schedule" and its single child.
  413. * Return a pointer to the updated schedule.
  414. *
  415. * If any of the nodes in the tree depend on the set of outer band nodes
  416. * then we refuse to insert the band node.
  417. */
  418. __isl_give isl_schedule *isl_schedule_insert_partial_schedule(
  419. __isl_take isl_schedule *schedule,
  420. __isl_take isl_multi_union_pw_aff *partial)
  421. {
  422. isl_schedule_node *node;
  423. int anchored;
  424. node = isl_schedule_get_root(schedule);
  425. isl_schedule_free(schedule);
  426. if (!node)
  427. goto error;
  428. if (isl_schedule_node_get_type(node) != isl_schedule_node_domain)
  429. isl_die(isl_schedule_node_get_ctx(node), isl_error_internal,
  430. "root node not a domain node", goto error);
  431. node = isl_schedule_node_child(node, 0);
  432. anchored = isl_schedule_node_is_subtree_anchored(node);
  433. if (anchored < 0)
  434. goto error;
  435. if (anchored)
  436. isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
  437. "cannot insert band node in anchored subtree",
  438. goto error);
  439. node = isl_schedule_node_insert_partial_schedule(node, partial);
  440. schedule = isl_schedule_node_get_schedule(node);
  441. isl_schedule_node_free(node);
  442. return schedule;
  443. error:
  444. isl_schedule_node_free(node);
  445. isl_multi_union_pw_aff_free(partial);
  446. return NULL;
  447. }
  448. /* Insert a context node with constraints "context" between the domain
  449. * root node of "schedule" and its single child.
  450. * Return a pointer to the updated schedule.
  451. */
  452. __isl_give isl_schedule *isl_schedule_insert_context(
  453. __isl_take isl_schedule *schedule, __isl_take isl_set *context)
  454. {
  455. isl_schedule_node *node;
  456. node = isl_schedule_get_root(schedule);
  457. isl_schedule_free(schedule);
  458. node = isl_schedule_node_child(node, 0);
  459. node = isl_schedule_node_insert_context(node, context);
  460. schedule = isl_schedule_node_get_schedule(node);
  461. isl_schedule_node_free(node);
  462. return schedule;
  463. }
  464. /* Insert a guard node with constraints "guard" between the domain
  465. * root node of "schedule" and its single child.
  466. * Return a pointer to the updated schedule.
  467. */
  468. __isl_give isl_schedule *isl_schedule_insert_guard(
  469. __isl_take isl_schedule *schedule, __isl_take isl_set *guard)
  470. {
  471. isl_schedule_node *node;
  472. node = isl_schedule_get_root(schedule);
  473. isl_schedule_free(schedule);
  474. node = isl_schedule_node_child(node, 0);
  475. node = isl_schedule_node_insert_guard(node, guard);
  476. schedule = isl_schedule_node_get_schedule(node);
  477. isl_schedule_node_free(node);
  478. return schedule;
  479. }
  480. /* Return a tree with as top-level node a filter corresponding to "filter" and
  481. * as child, the (single) child of "tree".
  482. * However, if this single child is of type "type", then the filter is inserted
  483. * in the children of this single child instead.
  484. */
  485. static __isl_give isl_schedule_tree *insert_filter_in_child_of_type(
  486. __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter,
  487. enum isl_schedule_node_type type)
  488. {
  489. if (!isl_schedule_tree_has_children(tree)) {
  490. isl_schedule_tree_free(tree);
  491. return isl_schedule_tree_from_filter(filter);
  492. } else {
  493. tree = isl_schedule_tree_child(tree, 0);
  494. }
  495. if (isl_schedule_tree_get_type(tree) == type)
  496. tree = isl_schedule_tree_children_insert_filter(tree, filter);
  497. else
  498. tree = isl_schedule_tree_insert_filter(tree, filter);
  499. return tree;
  500. }
  501. /* Construct a schedule that combines the schedules "schedule1" and "schedule2"
  502. * with a top-level node (underneath the domain node) of type "type",
  503. * either isl_schedule_node_sequence or isl_schedule_node_set.
  504. * The domains of the two schedules are assumed to be disjoint.
  505. *
  506. * The new schedule has as domain the union of the domains of the two
  507. * schedules. The child of the domain node is a node of type "type"
  508. * with two filters corresponding to the domains of the input schedules.
  509. * If one (or both) of the top-level nodes of the two schedules is itself
  510. * of type "type", then the filter is pushed into the children of that
  511. * node and the sequence or set is flattened.
  512. */
  513. __isl_give isl_schedule *isl_schedule_pair(enum isl_schedule_node_type type,
  514. __isl_take isl_schedule *schedule1, __isl_take isl_schedule *schedule2)
  515. {
  516. int disjoint;
  517. isl_ctx *ctx;
  518. enum isl_schedule_node_type root_type;
  519. isl_schedule_tree *tree1, *tree2;
  520. isl_union_set *filter1, *filter2, *domain;
  521. if (!schedule1 || !schedule2)
  522. goto error;
  523. root_type = isl_schedule_tree_get_type(schedule1->root);
  524. if (root_type != isl_schedule_node_domain)
  525. isl_die(isl_schedule_get_ctx(schedule1), isl_error_internal,
  526. "root node not a domain node", goto error);
  527. root_type = isl_schedule_tree_get_type(schedule2->root);
  528. if (root_type != isl_schedule_node_domain)
  529. isl_die(isl_schedule_get_ctx(schedule1), isl_error_internal,
  530. "root node not a domain node", goto error);
  531. ctx = isl_schedule_get_ctx(schedule1);
  532. tree1 = isl_schedule_tree_copy(schedule1->root);
  533. filter1 = isl_schedule_tree_domain_get_domain(tree1);
  534. tree2 = isl_schedule_tree_copy(schedule2->root);
  535. filter2 = isl_schedule_tree_domain_get_domain(tree2);
  536. isl_schedule_free(schedule1);
  537. isl_schedule_free(schedule2);
  538. disjoint = isl_union_set_is_disjoint(filter1, filter2);
  539. if (disjoint < 0)
  540. filter1 = isl_union_set_free(filter1);
  541. if (!disjoint)
  542. isl_die(ctx, isl_error_invalid,
  543. "schedule domains not disjoint",
  544. filter1 = isl_union_set_free(filter1));
  545. domain = isl_union_set_union(isl_union_set_copy(filter1),
  546. isl_union_set_copy(filter2));
  547. filter1 = isl_union_set_gist(filter1, isl_union_set_copy(domain));
  548. filter2 = isl_union_set_gist(filter2, isl_union_set_copy(domain));
  549. tree1 = insert_filter_in_child_of_type(tree1, filter1, type);
  550. tree2 = insert_filter_in_child_of_type(tree2, filter2, type);
  551. tree1 = isl_schedule_tree_from_pair(type, tree1, tree2);
  552. tree1 = isl_schedule_tree_insert_domain(tree1, domain);
  553. return isl_schedule_from_schedule_tree(ctx, tree1);
  554. error:
  555. isl_schedule_free(schedule1);
  556. isl_schedule_free(schedule2);
  557. return NULL;
  558. }
  559. /* Construct a schedule that combines the schedules "schedule1" and "schedule2"
  560. * through a sequence node.
  561. * The domains of the input schedules are assumed to be disjoint.
  562. */
  563. __isl_give isl_schedule *isl_schedule_sequence(
  564. __isl_take isl_schedule *schedule1, __isl_take isl_schedule *schedule2)
  565. {
  566. return isl_schedule_pair(isl_schedule_node_sequence,
  567. schedule1, schedule2);
  568. }
  569. /* Construct a schedule that combines the schedules "schedule1" and "schedule2"
  570. * through a set node.
  571. * The domains of the input schedules are assumed to be disjoint.
  572. */
  573. __isl_give isl_schedule *isl_schedule_set(
  574. __isl_take isl_schedule *schedule1, __isl_take isl_schedule *schedule2)
  575. {
  576. return isl_schedule_pair(isl_schedule_node_set, schedule1, schedule2);
  577. }
  578. /* Print "schedule" to "p".
  579. */
  580. __isl_give isl_printer *isl_printer_print_schedule(__isl_take isl_printer *p,
  581. __isl_keep isl_schedule *schedule)
  582. {
  583. if (!schedule)
  584. return isl_printer_free(p);
  585. return isl_printer_print_schedule_tree(p, schedule->root);
  586. }
  587. #undef BASE
  588. #define BASE schedule
  589. #include <print_templ_yaml.c>