Makefile.am: append extra copy of CLANG_LDFLAGS to LDADD
[pet.git] / scop.c
blob43c00b76b4dde6a87cec17b66d50150e8b184df3
1 /*
2 * Copyright 2011 Leiden University. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY LEIDEN UNIVERSITY ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LEIDEN UNIVERSITY OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * The views and conclusions contained in the software and documentation
29 * are those of the authors and should not be interpreted as
30 * representing official policies, either expressed or implied, of
31 * Leiden University.
32 */
34 #include <isl/constraint.h>
35 #include <isl/union_set.h>
37 #include "scop.h"
39 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
41 static char *type_str[] = {
42 [pet_expr_access] = "access",
43 [pet_expr_call] = "call",
44 [pet_expr_double] = "double",
45 [pet_expr_unary] = "unary",
46 [pet_expr_binary] = "binary",
47 [pet_expr_ternary] = "ternary"
50 static char *op_str[] = {
51 [pet_op_add_assign] = "+=",
52 [pet_op_sub_assign] = "-=",
53 [pet_op_mul_assign] = "*=",
54 [pet_op_div_assign] = "/=",
55 [pet_op_assign] = "=",
56 [pet_op_add] = "+",
57 [pet_op_sub] = "-",
58 [pet_op_mul] = "*",
59 [pet_op_div] = "/",
60 [pet_op_eq] = "==",
61 [pet_op_le] = "<=",
62 [pet_op_lt] = "<",
63 [pet_op_gt] = ">",
64 [pet_op_minus] = "-"
67 const char *pet_op_str(enum pet_op_type op)
69 return op_str[op];
72 const char *pet_type_str(enum pet_expr_type type)
74 return type_str[type];
77 enum pet_op_type pet_str_op(const char *str)
79 int i;
81 for (i = 0; i < ARRAY_SIZE(op_str); ++i)
82 if (!strcmp(op_str[i], str))
83 return i;
85 return -1;
88 enum pet_expr_type pet_str_type(const char *str)
90 int i;
92 for (i = 0; i < ARRAY_SIZE(type_str); ++i)
93 if (!strcmp(type_str[i], str))
94 return i;
96 return -1;
99 /* Construct a pet_expr from an access relation.
100 * By default, it is considered to be a read access.
102 struct pet_expr *pet_expr_from_access(__isl_take isl_map *access)
104 isl_ctx *ctx = isl_map_get_ctx(access);
105 struct pet_expr *expr;
107 if (!access)
108 return NULL;
109 expr = isl_calloc_type(ctx, struct pet_expr);
110 if (!expr)
111 goto error;
113 expr->type = pet_expr_access;
114 expr->acc.access = access;
115 expr->acc.read = 1;
116 expr->acc.write = 0;
118 return expr;
119 error:
120 isl_map_free(access);
121 return NULL;
124 /* Construct a unary pet_expr that performs "op" on "arg".
126 struct pet_expr *pet_expr_new_unary(isl_ctx *ctx, enum pet_op_type op,
127 struct pet_expr *arg)
129 struct pet_expr *expr;
131 if (!arg)
132 goto error;
133 expr = isl_alloc_type(ctx, struct pet_expr);
134 if (!expr)
135 goto error;
137 expr->type = pet_expr_unary;
138 expr->op = op;
139 expr->n_arg = 1;
140 expr->args = isl_calloc_array(ctx, struct pet_expr *, 1);
141 if (!expr->args)
142 goto error;
143 expr->args[pet_un_arg] = arg;
145 return expr;
146 error:
147 pet_expr_free(arg);
148 return NULL;
151 /* Construct a binary pet_expr that performs "op" on "lhs" and "rhs".
153 struct pet_expr *pet_expr_new_binary(isl_ctx *ctx, enum pet_op_type op,
154 struct pet_expr *lhs, struct pet_expr *rhs)
156 struct pet_expr *expr;
158 if (!lhs || !rhs)
159 goto error;
160 expr = isl_alloc_type(ctx, struct pet_expr);
161 if (!expr)
162 goto error;
164 expr->type = pet_expr_binary;
165 expr->op = op;
166 expr->n_arg = 2;
167 expr->args = isl_calloc_array(ctx, struct pet_expr *, 2);
168 if (!expr->args)
169 goto error;
170 expr->args[pet_bin_lhs] = lhs;
171 expr->args[pet_bin_rhs] = rhs;
173 return expr;
174 error:
175 pet_expr_free(lhs);
176 pet_expr_free(rhs);
177 return NULL;
180 /* Construct a ternary pet_expr that performs "cond" ? "lhs" : "rhs".
182 struct pet_expr *pet_expr_new_ternary(isl_ctx *ctx, struct pet_expr *cond,
183 struct pet_expr *lhs, struct pet_expr *rhs)
185 struct pet_expr *expr;
187 if (!cond || !lhs || !rhs)
188 goto error;
189 expr = isl_alloc_type(ctx, struct pet_expr);
190 if (!expr)
191 goto error;
193 expr->type = pet_expr_ternary;
194 expr->n_arg = 3;
195 expr->args = isl_calloc_array(ctx, struct pet_expr *, 3);
196 if (!expr->args)
197 goto error;
198 expr->args[pet_ter_cond] = cond;
199 expr->args[pet_ter_true] = lhs;
200 expr->args[pet_ter_false] = rhs;
202 return expr;
203 error:
204 pet_expr_free(cond);
205 pet_expr_free(lhs);
206 pet_expr_free(rhs);
207 return NULL;
210 /* Construct a call pet_expr that calls function "name" with "n_arg"
211 * arguments. The caller is responsible for filling in the arguments.
213 struct pet_expr *pet_expr_new_call(isl_ctx *ctx, const char *name,
214 unsigned n_arg)
216 struct pet_expr *expr;
218 expr = isl_alloc_type(ctx, struct pet_expr);
219 if (!expr)
220 return NULL;
222 expr->type = pet_expr_call;
223 expr->n_arg = n_arg;
224 expr->name = strdup(name);
225 expr->args = isl_calloc_array(ctx, struct pet_expr *, n_arg);
226 if (!expr->name || !expr->args)
227 return pet_expr_free(expr);
229 return expr;
232 /* Construct a pet_expr that represents the double "d".
234 struct pet_expr *pet_expr_new_double(isl_ctx *ctx, double d)
236 struct pet_expr *expr;
238 expr = isl_calloc_type(ctx, struct pet_expr);
239 if (!expr)
240 return NULL;
242 expr->type = pet_expr_double;
243 expr->d = d;
245 return expr;
248 void *pet_expr_free(struct pet_expr *expr)
250 int i;
252 if (!expr)
253 return NULL;
255 for (i = 0; i < expr->n_arg; ++i)
256 pet_expr_free(expr->args[i]);
257 free(expr->args);
259 switch (expr->type) {
260 case pet_expr_access:
261 isl_map_free(expr->acc.access);
262 break;
263 case pet_expr_call:
264 free(expr->name);
265 break;
266 case pet_expr_double:
267 case pet_expr_unary:
268 case pet_expr_binary:
269 case pet_expr_ternary:
270 break;
273 free(expr);
274 return NULL;
277 static void expr_dump(struct pet_expr *expr, int indent)
279 int i;
281 if (!expr)
282 return;
284 fprintf(stderr, "%*s", indent, "");
286 switch (expr->type) {
287 case pet_expr_double:
288 fprintf(stderr, "%g\n", expr->d);
289 break;
290 case pet_expr_access:
291 isl_map_dump(expr->acc.access);
292 fprintf(stderr, "%*sread: %d\n", indent + 2,
293 "", expr->acc.read);
294 fprintf(stderr, "%*swrite: %d\n", indent + 2,
295 "", expr->acc.write);
296 for (i = 0; i < expr->n_arg; ++i)
297 expr_dump(expr->args[i], indent + 2);
298 break;
299 case pet_expr_unary:
300 fprintf(stderr, "%s\n", op_str[expr->op]);
301 expr_dump(expr->args[pet_un_arg], indent + 2);
302 break;
303 case pet_expr_binary:
304 fprintf(stderr, "%s\n", op_str[expr->op]);
305 expr_dump(expr->args[pet_bin_lhs], indent + 2);
306 expr_dump(expr->args[pet_bin_rhs], indent + 2);
307 break;
308 case pet_expr_ternary:
309 fprintf(stderr, "?:\n");
310 expr_dump(expr->args[pet_ter_cond], indent + 2);
311 expr_dump(expr->args[pet_ter_true], indent + 2);
312 expr_dump(expr->args[pet_ter_false], indent + 2);
313 break;
314 case pet_expr_call:
315 fprintf(stderr, "%s/%d\n", expr->name, expr->n_arg);
316 for (i = 0; i < expr->n_arg; ++i)
317 expr_dump(expr->args[i], indent + 2);
318 break;
322 void pet_expr_dump(struct pet_expr *expr)
324 expr_dump(expr, 0);
327 /* Return 1 if the two pet_exprs are equivalent.
329 int pet_expr_is_equal(struct pet_expr *expr1, struct pet_expr *expr2)
331 int i;
333 if (!expr1 || !expr2)
334 return 0;
336 if (expr1->type != expr2->type)
337 return 0;
338 if (expr1->n_arg != expr2->n_arg)
339 return 0;
340 for (i = 0; i < expr1->n_arg; ++i)
341 if (!pet_expr_is_equal(expr1->args[i], expr2->args[i]))
342 return 0;
343 switch (expr1->type) {
344 case pet_expr_double:
345 if (expr1->d != expr2->d)
346 return 0;
347 break;
348 case pet_expr_access:
349 if (expr1->acc.read != expr2->acc.read)
350 return 0;
351 if (expr1->acc.write != expr2->acc.write)
352 return 0;
353 if (!expr1->acc.access || !expr2->acc.access)
354 return 0;
355 if (!isl_map_is_equal(expr1->acc.access, expr2->acc.access))
356 return 0;
357 break;
358 case pet_expr_unary:
359 case pet_expr_binary:
360 case pet_expr_ternary:
361 if (expr1->op != expr2->op)
362 return 0;
363 break;
364 case pet_expr_call:
365 if (strcmp(expr1->name, expr2->name))
366 return 0;
367 break;
370 return 1;
373 /* Add extra conditions on the parameters to all access relations in "expr".
375 struct pet_expr *pet_expr_restrict(struct pet_expr *expr,
376 __isl_take isl_set *cond)
378 int i;
380 if (!expr)
381 goto error;
383 for (i = 0; i < expr->n_arg; ++i) {
384 expr->args[i] = pet_expr_restrict(expr->args[i],
385 isl_set_copy(cond));
386 if (!expr->args[i])
387 goto error;
390 if (expr->type == pet_expr_access) {
391 expr->acc.access = isl_map_intersect_params(expr->acc.access,
392 isl_set_copy(cond));
393 if (!expr->acc.access)
394 goto error;
397 isl_set_free(cond);
398 return expr;
399 error:
400 isl_set_free(cond);
401 return pet_expr_free(expr);
404 /* Modify all access relations in "expr" by calling "fn" on them.
406 static struct pet_expr *expr_foreach_access(struct pet_expr *expr,
407 __isl_give isl_map *(*fn)(__isl_take isl_map *access, void *user),
408 void *user)
410 int i;
412 if (!expr)
413 return NULL;
415 for (i = 0; i < expr->n_arg; ++i) {
416 expr->args[i] = expr_foreach_access(expr->args[i], fn, user);
417 if (!expr->args[i])
418 return pet_expr_free(expr);
421 if (expr->type == pet_expr_access) {
422 expr->acc.access = fn(expr->acc.access, user);
423 if (!expr->acc.access)
424 return pet_expr_free(expr);
427 return expr;
430 /* Modify the given access relation based on the given iteration space
431 * transformation.
432 * If the access has any arguments then the domain of the access relation
433 * is a wrapped mapping from the iteration space to the space of
434 * argument values. We only need to change the domain of this wrapped
435 * mapping, so we extend the input transformation with an identity mapping
436 * on the space of argument values.
438 static __isl_give isl_map *update_domain(__isl_take isl_map *access,
439 void *user)
441 isl_map *update = user;
442 isl_space *dim;
444 update = isl_map_copy(update);
446 dim = isl_map_get_space(access);
447 dim = isl_space_domain(dim);
448 if (!isl_space_is_wrapping(dim))
449 isl_space_free(dim);
450 else {
451 isl_map *id;
452 dim = isl_space_unwrap(dim);
453 dim = isl_space_range(dim);
454 dim = isl_space_map_from_set(dim);
455 id = isl_map_identity(dim);
456 update = isl_map_product(update, id);
459 return isl_map_apply_domain(access, update);
462 /* Modify all access relations in "expr" based on the given iteration space
463 * transformation.
465 static struct pet_expr *expr_update_domain(struct pet_expr *expr,
466 __isl_take isl_map *update)
468 expr = expr_foreach_access(expr, &update_domain, update);
469 isl_map_free(update);
470 return expr;
473 /* Construct a pet_stmt with given line number and statement
474 * number from a pet_expr.
475 * The initial iteration domain is the zero-dimensional universe.
476 * The domains of all access relations are modified to refer
477 * to the statement iteration domain.
479 struct pet_stmt *pet_stmt_from_pet_expr(isl_ctx *ctx, int line, int id,
480 struct pet_expr *expr)
482 struct pet_stmt *stmt;
483 isl_space *dim;
484 isl_set *dom;
485 isl_map *sched;
486 isl_map *add_name;
487 char name[50];
489 if (!expr)
490 return NULL;
492 stmt = isl_calloc_type(ctx, struct pet_stmt);
493 if (!stmt)
494 return pet_expr_free(expr);
496 dim = isl_space_set_alloc(ctx, 0, 0);
497 snprintf(name, sizeof(name), "S_%d", id);
498 dim = isl_space_set_tuple_name(dim, isl_dim_set, name);
499 dom = isl_set_universe(isl_space_copy(dim));
500 sched = isl_map_from_domain(isl_set_copy(dom));
502 dim = isl_space_from_range(dim);
503 add_name = isl_map_universe(dim);
504 expr = expr_update_domain(expr, add_name);
506 stmt->line = line;
507 stmt->domain = dom;
508 stmt->schedule = sched;
509 stmt->body = expr;
511 if (!stmt->domain || !stmt->schedule || !stmt->body)
512 return pet_stmt_free(stmt);
514 return stmt;
517 void *pet_stmt_free(struct pet_stmt *stmt)
519 int i;
521 if (!stmt)
522 return NULL;
524 isl_set_free(stmt->domain);
525 isl_map_free(stmt->schedule);
526 pet_expr_free(stmt->body);
528 for (i = 0; i < stmt->n_arg; ++i)
529 pet_expr_free(stmt->args[i]);
530 free(stmt->args);
532 free(stmt);
533 return NULL;
536 static void stmt_dump(struct pet_stmt *stmt, int indent)
538 int i;
540 if (!stmt)
541 return;
543 fprintf(stderr, "%*s%d\n", indent, "", stmt->line);
544 fprintf(stderr, "%*s", indent, "");
545 isl_set_dump(stmt->domain);
546 fprintf(stderr, "%*s", indent, "");
547 isl_map_dump(stmt->schedule);
548 expr_dump(stmt->body, indent);
549 for (i = 0; i < stmt->n_arg; ++i)
550 expr_dump(stmt->args[i], indent + 2);
553 void pet_stmt_dump(struct pet_stmt *stmt)
555 stmt_dump(stmt, 0);
558 void *pet_array_free(struct pet_array *array)
560 if (!array)
561 return NULL;
563 isl_set_free(array->context);
564 isl_set_free(array->extent);
565 isl_set_free(array->value_bounds);
566 free(array->element_type);
568 free(array);
569 return NULL;
572 void pet_array_dump(struct pet_array *array)
574 if (!array)
575 return;
577 isl_set_dump(array->context);
578 isl_set_dump(array->extent);
579 isl_set_dump(array->value_bounds);
580 fprintf(stderr, "%s %s\n", array->element_type,
581 array->live_out ? "live-out" : "");
584 /* Construct a pet_scop with room for n statements.
586 static struct pet_scop *scop_alloc(isl_ctx *ctx, int n)
588 isl_space *space;
589 struct pet_scop *scop;
591 scop = isl_calloc_type(ctx, struct pet_scop);
592 if (!scop)
593 return NULL;
595 space = isl_space_params_alloc(ctx, 0);
596 scop->context = isl_set_universe(isl_space_copy(space));
597 scop->context_value = isl_set_universe(space);
598 scop->stmts = isl_calloc_array(ctx, struct pet_stmt *, n);
599 if (!scop->context || !scop->stmts)
600 return pet_scop_free(scop);
602 scop->n_stmt = n;
604 return scop;
607 struct pet_scop *pet_scop_empty(isl_ctx *ctx)
609 return scop_alloc(ctx, 0);
612 /* Construct a pet_scop that contains the given pet_stmt.
614 struct pet_scop *pet_scop_from_pet_stmt(isl_ctx *ctx, struct pet_stmt *stmt)
616 struct pet_scop *scop;
618 if (!stmt)
619 return NULL;
621 scop = scop_alloc(ctx, 1);
623 scop->stmts[0] = stmt;
625 return scop;
626 error:
627 pet_stmt_free(stmt);
628 pet_scop_free(scop);
629 return NULL;
632 /* Construct a pet_scop that contains the arrays and the statements
633 * in "scop1" and "scop2".
635 struct pet_scop *pet_scop_add(isl_ctx *ctx, struct pet_scop *scop1,
636 struct pet_scop *scop2)
638 int i;
639 struct pet_scop *scop;
641 if (!scop1 || !scop2)
642 goto error;
644 if (scop1->n_stmt == 0) {
645 pet_scop_free(scop1);
646 return scop2;
649 if (scop2->n_stmt == 0) {
650 pet_scop_free(scop2);
651 return scop1;
654 scop = scop_alloc(ctx, scop1->n_stmt + scop2->n_stmt);
655 if (!scop)
656 goto error;
658 scop->arrays = isl_calloc_array(ctx, struct pet_array *,
659 scop1->n_array + scop2->n_array);
660 if (!scop->arrays)
661 goto error;
662 scop->n_array = scop1->n_array + scop2->n_array;
664 for (i = 0; i < scop1->n_stmt; ++i) {
665 scop->stmts[i] = scop1->stmts[i];
666 scop1->stmts[i] = NULL;
669 for (i = 0; i < scop2->n_stmt; ++i) {
670 scop->stmts[scop1->n_stmt + i] = scop2->stmts[i];
671 scop2->stmts[i] = NULL;
674 for (i = 0; i < scop1->n_array; ++i) {
675 scop->arrays[i] = scop1->arrays[i];
676 scop1->arrays[i] = NULL;
679 for (i = 0; i < scop2->n_array; ++i) {
680 scop->arrays[scop1->n_array + i] = scop2->arrays[i];
681 scop2->arrays[i] = NULL;
684 pet_scop_free(scop1);
685 pet_scop_free(scop2);
686 return scop;
687 error:
688 pet_scop_free(scop1);
689 pet_scop_free(scop2);
690 return NULL;
693 void *pet_scop_free(struct pet_scop *scop)
695 int i;
697 if (!scop)
698 return NULL;
699 isl_set_free(scop->context);
700 isl_set_free(scop->context_value);
701 if (scop->arrays)
702 for (i = 0; i < scop->n_array; ++i)
703 pet_array_free(scop->arrays[i]);
704 free(scop->arrays);
705 if (scop->stmts)
706 for (i = 0; i < scop->n_stmt; ++i)
707 pet_stmt_free(scop->stmts[i]);
708 free(scop->stmts);
709 free(scop);
710 return NULL;
713 void pet_scop_dump(struct pet_scop *scop)
715 int i;
717 if (!scop)
718 return;
720 isl_set_dump(scop->context);
721 isl_set_dump(scop->context_value);
722 for (i = 0; i < scop->n_array; ++i)
723 pet_array_dump(scop->arrays[i]);
724 for (i = 0; i < scop->n_stmt; ++i)
725 pet_stmt_dump(scop->stmts[i]);
728 /* Return 1 if the two pet_arrays are equivalent.
730 int pet_array_is_equal(struct pet_array *array1, struct pet_array *array2)
732 if (!array1 || !array2)
733 return 0;
735 if (!isl_set_is_equal(array1->context, array2->context))
736 return 0;
737 if (!isl_set_is_equal(array1->extent, array2->extent))
738 return 0;
739 if (!!array1->value_bounds != !!array2->value_bounds)
740 return 0;
741 if (array1->value_bounds &&
742 !isl_set_is_equal(array1->value_bounds, array2->value_bounds))
743 return 0;
744 if (strcmp(array1->element_type, array2->element_type))
745 return 0;
746 if (array1->live_out != array2->live_out)
747 return 0;
749 return 1;
752 /* Return 1 if the two pet_stmts are equivalent.
754 int pet_stmt_is_equal(struct pet_stmt *stmt1, struct pet_stmt *stmt2)
756 int i;
758 if (!stmt1 || !stmt2)
759 return 0;
761 if (stmt1->line != stmt2->line)
762 return 0;
763 if (!isl_set_is_equal(stmt1->domain, stmt2->domain))
764 return 0;
765 if (!isl_map_is_equal(stmt1->schedule, stmt2->schedule))
766 return 0;
767 if (!pet_expr_is_equal(stmt1->body, stmt2->body))
768 return 0;
769 if (stmt1->n_arg != stmt2->n_arg)
770 return 0;
771 for (i = 0; i < stmt1->n_arg; ++i) {
772 if (!pet_expr_is_equal(stmt1->args[i], stmt2->args[i]))
773 return 0;
776 return 1;
779 /* Return 1 if the two pet_scops are equivalent.
781 int pet_scop_is_equal(struct pet_scop *scop1, struct pet_scop *scop2)
783 int i;
785 if (!scop1 || !scop2)
786 return 0;
788 if (!isl_set_is_equal(scop1->context, scop2->context))
789 return 0;
790 if (!isl_set_is_equal(scop1->context_value, scop2->context_value))
791 return 0;
793 if (scop1->n_array != scop2->n_array)
794 return 0;
795 for (i = 0; i < scop1->n_array; ++i)
796 if (!pet_array_is_equal(scop1->arrays[i], scop2->arrays[i]))
797 return 0;
799 if (scop1->n_stmt != scop2->n_stmt)
800 return 0;
801 for (i = 0; i < scop1->n_stmt; ++i)
802 if (!pet_stmt_is_equal(scop1->stmts[i], scop2->stmts[i]))
803 return 0;
805 return 1;
808 /* Prefix the schedule of "stmt" with an extra dimension with constant
809 * value "pos".
811 struct pet_stmt *pet_stmt_prefix(struct pet_stmt *stmt, int pos)
813 if (!stmt)
814 return NULL;
816 stmt->schedule = isl_map_insert_dims(stmt->schedule, isl_dim_out, 0, 1);
817 stmt->schedule = isl_map_fix_si(stmt->schedule, isl_dim_out, 0, pos);
818 if (!stmt->schedule)
819 return pet_stmt_free(stmt);
821 return stmt;
824 /* Prefix the schedules of all statements in "scop" with an extra
825 * dimension with constant value "pos".
827 struct pet_scop *pet_scop_prefix(struct pet_scop *scop, int pos)
829 int i;
831 if (!scop)
832 return NULL;
834 for (i = 0; i < scop->n_stmt; ++i) {
835 scop->stmts[i] = pet_stmt_prefix(scop->stmts[i], pos);
836 if (!scop->stmts[i])
837 return pet_scop_free(scop);
840 return scop;
843 /* Data used in embed_access.
844 * extend adds an iterator to the iteration domain
845 * var_id represents the induction variable of the corresponding loop
847 struct pet_embed_access {
848 isl_map *extend;
849 isl_id *var_id;
852 /* Embed the access relation in an extra outer loop.
854 * We first update the iteration domain to insert the extra dimension.
856 * If the access refers to the induction variable, then it is
857 * turned into an access to the set of integers with index (and value)
858 * equal to the induction variable.
860 * If the induction variable appears in the constraints (as a parameter),
861 * then the parameter is equated to the newly introduced iteration
862 * domain dimension and subsequently projected out.
864 static __isl_give isl_map *embed_access(__isl_take isl_map *access,
865 void *user)
867 struct pet_embed_access *data = user;
868 isl_id *array_id = NULL;
869 int pos;
871 access = update_domain(access, data->extend);
873 if (isl_map_has_tuple_id(access, isl_dim_out))
874 array_id = isl_map_get_tuple_id(access, isl_dim_out);
875 if (array_id == data->var_id) {
876 access = isl_map_insert_dims(access, isl_dim_out, 0, 1);
877 access = isl_map_equate(access,
878 isl_dim_in, 0, isl_dim_out, 0);
880 isl_id_free(array_id);
882 pos = isl_map_find_dim_by_id(access, isl_dim_param, data->var_id);
883 if (pos >= 0) {
884 access = isl_map_equate(access,
885 isl_dim_param, pos, isl_dim_in, 0);
886 access = isl_map_project_out(access, isl_dim_param, pos, 1);
888 access = isl_map_set_dim_id(access, isl_dim_in, 0,
889 isl_id_copy(data->var_id));
891 return access;
894 /* Embed all access relations in "expr" in an extra loop.
895 * "extend" inserts an outer loop iterator in the iteration domains.
896 * "var_id" represents the induction variable.
898 static struct pet_expr *expr_embed(struct pet_expr *expr,
899 __isl_take isl_map *extend, __isl_keep isl_id *var_id)
901 struct pet_embed_access data = { .extend = extend, .var_id = var_id };
903 expr = expr_foreach_access(expr, &embed_access, &data);
904 isl_map_free(extend);
905 return expr;
908 /* Embed the given pet_stmt in an extra outer loop with iteration domain
909 * "dom" and schedule "sched". "var_id" represents the induction variable
910 * of the loop.
912 * The iteration domain and schedule of the statement are updated
913 * according to the iteration domain and schedule of the new loop.
914 * If stmt->domain is a wrapped map, then the iteration domain
915 * is the domain of this map, so we need to be careful to adjust
916 * this domain.
918 * If the induction variable appears in the constraints (as a parameter)
919 * of the current iteration domain or the schedule of the statement,
920 * then the parameter is equated to the newly introduced iteration
921 * domain dimension and subsequently projected out.
923 * Finally, all access relations are updated based on the extra loop.
925 struct pet_stmt *pet_stmt_embed(struct pet_stmt *stmt, __isl_take isl_set *dom,
926 __isl_take isl_map *sched, __isl_take isl_id *var_id)
928 int i;
929 int pos;
930 isl_id *stmt_id;
931 isl_space *dim;
932 isl_map *extend;
934 if (!stmt)
935 goto error;
937 if (isl_set_is_wrapping(stmt->domain)) {
938 isl_map *map;
939 isl_map *ext;
940 isl_space *ran_dim;
942 map = isl_set_unwrap(stmt->domain);
943 stmt_id = isl_map_get_tuple_id(map, isl_dim_in);
944 ran_dim = isl_space_range(isl_map_get_space(map));
945 ext = isl_map_from_domain_and_range(isl_set_copy(dom),
946 isl_set_universe(ran_dim));
947 map = isl_map_flat_domain_product(ext, map);
948 map = isl_map_set_tuple_id(map, isl_dim_in,
949 isl_id_copy(stmt_id));
950 dim = isl_space_domain(isl_map_get_space(map));
951 stmt->domain = isl_map_wrap(map);
952 } else {
953 stmt_id = isl_set_get_tuple_id(stmt->domain);
954 stmt->domain = isl_set_flat_product(isl_set_copy(dom),
955 stmt->domain);
956 stmt->domain = isl_set_set_tuple_id(stmt->domain,
957 isl_id_copy(stmt_id));
958 dim = isl_set_get_space(stmt->domain);
961 pos = isl_set_find_dim_by_id(stmt->domain, isl_dim_param, var_id);
962 if (pos >= 0) {
963 stmt->domain = isl_set_equate(stmt->domain,
964 isl_dim_param, pos, isl_dim_set, 0);
965 stmt->domain = isl_set_project_out(stmt->domain,
966 isl_dim_param, pos, 1);
969 stmt->schedule = isl_map_flat_product(sched, stmt->schedule);
970 stmt->schedule = isl_map_set_tuple_id(stmt->schedule,
971 isl_dim_in, stmt_id);
973 pos = isl_map_find_dim_by_id(stmt->schedule, isl_dim_param, var_id);
974 if (pos >= 0) {
975 stmt->schedule = isl_map_equate(stmt->schedule,
976 isl_dim_param, pos, isl_dim_in, 0);
977 stmt->schedule = isl_map_project_out(stmt->schedule,
978 isl_dim_param, pos, 1);
981 dim = isl_space_map_from_set(dim);
982 extend = isl_map_identity(dim);
983 extend = isl_map_remove_dims(extend, isl_dim_in, 0, 1);
984 extend = isl_map_set_tuple_id(extend, isl_dim_in,
985 isl_map_get_tuple_id(extend, isl_dim_out));
986 for (i = 0; i < stmt->n_arg; ++i)
987 stmt->args[i] = expr_embed(stmt->args[i],
988 isl_map_copy(extend), var_id);
989 stmt->body = expr_embed(stmt->body, extend, var_id);
991 isl_set_free(dom);
992 isl_id_free(var_id);
994 for (i = 0; i < stmt->n_arg; ++i)
995 if (!stmt->args[i])
996 return pet_stmt_free(stmt);
997 if (!stmt->domain || !stmt->schedule || !stmt->body)
998 return pet_stmt_free(stmt);
999 return stmt;
1000 error:
1001 isl_set_free(dom);
1002 isl_map_free(sched);
1003 isl_id_free(var_id);
1004 return NULL;
1007 /* Embed all statements in "scop" in an extra outer loop with iteration domain
1008 * "dom" and schedule "sched". "var_id" represents the induction variable
1009 * of the loop.
1011 struct pet_scop *pet_scop_embed(struct pet_scop *scop, __isl_take isl_set *dom,
1012 __isl_take isl_map *sched, __isl_take isl_id *id)
1014 int i;
1016 if (!scop)
1017 goto error;
1019 for (i = 0; i < scop->n_stmt; ++i) {
1020 scop->stmts[i] = pet_stmt_embed(scop->stmts[i],
1021 isl_set_copy(dom),
1022 isl_map_copy(sched), isl_id_copy(id));
1023 if (!scop->stmts[i])
1024 goto error;
1027 isl_set_free(dom);
1028 isl_map_free(sched);
1029 isl_id_free(id);
1030 return scop;
1031 error:
1032 isl_set_free(dom);
1033 isl_map_free(sched);
1034 isl_id_free(id);
1035 return pet_scop_free(scop);
1038 /* Add extra conditions on the parameters to iteration domain of "stmt".
1040 static struct pet_stmt *stmt_restrict(struct pet_stmt *stmt,
1041 __isl_take isl_set *cond)
1043 if (!stmt)
1044 goto error;
1046 stmt->domain = isl_set_intersect_params(stmt->domain, cond);
1048 return stmt;
1049 error:
1050 isl_set_free(cond);
1051 return pet_stmt_free(stmt);
1054 /* Add extra conditions on the parameters to all iteration domains.
1056 struct pet_scop *pet_scop_restrict(struct pet_scop *scop,
1057 __isl_take isl_set *cond)
1059 int i;
1061 if (!scop)
1062 goto error;
1064 for (i = 0; i < scop->n_stmt; ++i) {
1065 scop->stmts[i] = stmt_restrict(scop->stmts[i],
1066 isl_set_copy(cond));
1067 if (!scop->stmts[i])
1068 goto error;
1071 isl_set_free(cond);
1072 return scop;
1073 error:
1074 isl_set_free(cond);
1075 return pet_scop_free(scop);
1078 /* Make the statements "stmt" depend on the value of "test"
1079 * being equal to "satisfied" by adjusting stmt->domain.
1081 * We insert an argument corresponding to a read to "test"
1082 * from the iteration domain of "stmt" in front of the list of arguments.
1083 * We also insert a corresponding output dimension in the wrapped
1084 * map contained in stmt->domain, with value set to "satisfied".
1086 static struct pet_stmt *stmt_filter(struct pet_stmt *stmt,
1087 __isl_take isl_map *test, int satisfied)
1089 int i;
1090 isl_id *id;
1091 isl_ctx *ctx;
1092 isl_map *map;
1093 isl_set *dom;
1095 if (!stmt || !test)
1096 goto error;
1098 if (isl_set_is_wrapping(stmt->domain))
1099 map = isl_set_unwrap(stmt->domain);
1100 else
1101 map = isl_map_from_domain(stmt->domain);
1102 map = isl_map_insert_dims(map, isl_dim_out, 0, 1);
1103 id = isl_map_get_tuple_id(test, isl_dim_out);
1104 map = isl_map_set_dim_id(map, isl_dim_out, 0, id);
1105 map = isl_map_fix_si(map, isl_dim_out, 0, satisfied);
1106 dom = isl_set_universe(isl_space_domain(isl_map_get_space(map)));
1107 test = isl_map_apply_domain(test, isl_map_from_range(dom));
1109 stmt->domain = isl_map_wrap(map);
1111 ctx = isl_map_get_ctx(test);
1112 if (!stmt->args) {
1113 stmt->args = isl_calloc_array(ctx, struct pet_expr *, 1);
1114 if (!stmt->args)
1115 goto error;
1116 } else {
1117 struct pet_expr **args;
1118 args = isl_calloc_array(ctx, struct pet_expr *, 1 + stmt->n_arg);
1119 if (!args)
1120 goto error;
1121 for (i = 0; i < stmt->n_arg; ++i)
1122 args[1 + i] = stmt->args[i];
1123 free(stmt->args);
1124 stmt->args = args;
1126 stmt->n_arg++;
1127 stmt->args[0] = pet_expr_from_access(isl_map_copy(test));
1128 if (!stmt->args[0])
1129 goto error;
1131 isl_map_free(test);
1132 return stmt;
1133 error:
1134 isl_map_free(test);
1135 return pet_stmt_free(stmt);
1138 /* Make all statements in "scop" depend on the value of "test"
1139 * being equal to "satisfied" by adjusting their domains.
1141 struct pet_scop *pet_scop_filter(struct pet_scop *scop,
1142 __isl_take isl_map *test, int satisfied)
1144 int i;
1146 if (!scop)
1147 goto error;
1149 for (i = 0; i < scop->n_stmt; ++i) {
1150 scop->stmts[i] = stmt_filter(scop->stmts[i],
1151 isl_map_copy(test), satisfied);
1152 if (!scop->stmts[i])
1153 goto error;
1156 isl_map_free(test);
1157 return scop;
1158 error:
1159 isl_map_free(test);
1160 return pet_scop_free(scop);
1163 /* Add all parameters in "expr" to "dim" and return the result.
1165 static __isl_give isl_space *expr_collect_params(struct pet_expr *expr,
1166 __isl_take isl_space *dim)
1168 int i;
1170 if (!expr)
1171 goto error;
1172 for (i = 0; i < expr->n_arg; ++i)
1174 dim = expr_collect_params(expr->args[i], dim);
1176 if (expr->type == pet_expr_access)
1177 dim = isl_space_align_params(dim,
1178 isl_map_get_space(expr->acc.access));
1180 return dim;
1181 error:
1182 isl_space_free(dim);
1183 return pet_expr_free(expr);
1186 /* Add all parameters in "stmt" to "dim" and return the result.
1188 static __isl_give isl_space *stmt_collect_params(struct pet_stmt *stmt,
1189 __isl_take isl_space *dim)
1191 if (!stmt)
1192 goto error;
1194 dim = isl_space_align_params(dim, isl_set_get_space(stmt->domain));
1195 dim = isl_space_align_params(dim, isl_map_get_space(stmt->schedule));
1196 dim = expr_collect_params(stmt->body, dim);
1198 return dim;
1199 error:
1200 isl_space_free(dim);
1201 return pet_stmt_free(stmt);
1204 /* Add all parameters in "array" to "dim" and return the result.
1206 static __isl_give isl_space *array_collect_params(struct pet_array *array,
1207 __isl_take isl_space *dim)
1209 if (!array)
1210 goto error;
1212 dim = isl_space_align_params(dim, isl_set_get_space(array->context));
1213 dim = isl_space_align_params(dim, isl_set_get_space(array->extent));
1215 return dim;
1216 error:
1217 isl_space_free(dim);
1218 return pet_array_free(array);
1221 /* Add all parameters in "scop" to "dim" and return the result.
1223 static __isl_give isl_space *scop_collect_params(struct pet_scop *scop,
1224 __isl_take isl_space *dim)
1226 int i;
1228 if (!scop)
1229 goto error;
1231 for (i = 0; i < scop->n_array; ++i)
1232 dim = array_collect_params(scop->arrays[i], dim);
1234 for (i = 0; i < scop->n_stmt; ++i)
1235 dim = stmt_collect_params(scop->stmts[i], dim);
1237 return dim;
1238 error:
1239 isl_space_free(dim);
1240 return pet_scop_free(scop);
1243 /* Add all parameters in "dim" to all access relations in "expr".
1245 static struct pet_expr *expr_propagate_params(struct pet_expr *expr,
1246 __isl_take isl_space *dim)
1248 int i;
1250 if (!expr)
1251 goto error;
1253 for (i = 0; i < expr->n_arg; ++i) {
1254 expr->args[i] =
1255 expr_propagate_params(expr->args[i],
1256 isl_space_copy(dim));
1257 if (!expr->args[i])
1258 goto error;
1261 if (expr->type == pet_expr_access) {
1262 expr->acc.access = isl_map_align_params(expr->acc.access,
1263 isl_space_copy(dim));
1264 if (!expr->acc.access)
1265 goto error;
1268 isl_space_free(dim);
1269 return expr;
1270 error:
1271 isl_space_free(dim);
1272 return pet_expr_free(expr);
1275 /* Add all parameters in "dim" to the domain, schedule and
1276 * all access relations in "stmt".
1278 static struct pet_stmt *stmt_propagate_params(struct pet_stmt *stmt,
1279 __isl_take isl_space *dim)
1281 if (!stmt)
1282 goto error;
1284 stmt->domain = isl_set_align_params(stmt->domain, isl_space_copy(dim));
1285 stmt->schedule = isl_map_align_params(stmt->schedule,
1286 isl_space_copy(dim));
1287 stmt->body = expr_propagate_params(stmt->body, isl_space_copy(dim));
1289 if (!stmt->domain || !stmt->schedule || !stmt->body)
1290 goto error;
1292 isl_space_free(dim);
1293 return stmt;
1294 error:
1295 isl_space_free(dim);
1296 return pet_stmt_free(stmt);
1299 /* Add all parameters in "dim" to "array".
1301 static struct pet_array *array_propagate_params(struct pet_array *array,
1302 __isl_take isl_space *dim)
1304 if (!array)
1305 goto error;
1307 array->context = isl_set_align_params(array->context,
1308 isl_space_copy(dim));
1309 array->extent = isl_set_align_params(array->extent,
1310 isl_space_copy(dim));
1311 if (array->value_bounds) {
1312 array->value_bounds = isl_set_align_params(array->value_bounds,
1313 isl_space_copy(dim));
1314 if (!array->value_bounds)
1315 goto error;
1318 if (!array->context || !array->extent)
1319 goto error;
1321 isl_space_free(dim);
1322 return array;
1323 error:
1324 isl_space_free(dim);
1325 return pet_array_free(array);
1328 /* Add all parameters in "dim" to "scop".
1330 static struct pet_scop *scop_propagate_params(struct pet_scop *scop,
1331 __isl_take isl_space *dim)
1333 int i;
1335 if (!scop)
1336 goto error;
1338 for (i = 0; i < scop->n_array; ++i) {
1339 scop->arrays[i] = array_propagate_params(scop->arrays[i],
1340 isl_space_copy(dim));
1341 if (!scop->arrays[i])
1342 goto error;
1345 for (i = 0; i < scop->n_stmt; ++i) {
1346 scop->stmts[i] = stmt_propagate_params(scop->stmts[i],
1347 isl_space_copy(dim));
1348 if (!scop->stmts[i])
1349 goto error;
1352 isl_space_free(dim);
1353 return scop;
1354 error:
1355 isl_space_free(dim);
1356 return pet_scop_free(scop);
1359 /* Update all isl_sets and isl_maps in "scop" such that they all
1360 * have the same parameters.
1362 struct pet_scop *pet_scop_align_params(struct pet_scop *scop)
1364 isl_space *dim;
1366 if (!scop)
1367 return NULL;
1369 dim = isl_set_get_space(scop->context);
1370 dim = scop_collect_params(scop, dim);
1372 scop->context = isl_set_align_params(scop->context, isl_space_copy(dim));
1373 scop = scop_propagate_params(scop, dim);
1375 return scop;
1378 /* Check if the given access relation accesses a (0D) array that corresponds
1379 * to one of the parameters in "dim". If so, replace the array access
1380 * by an access to the set of integers with as index (and value)
1381 * that parameter.
1383 static __isl_give isl_map *access_detect_parameter(__isl_take isl_map *access,
1384 __isl_take isl_space *dim)
1386 isl_id *array_id = NULL;
1387 int pos = -1;
1389 if (isl_map_has_tuple_id(access, isl_dim_out)) {
1390 array_id = isl_map_get_tuple_id(access, isl_dim_out);
1391 pos = isl_space_find_dim_by_id(dim, isl_dim_param, array_id);
1393 isl_space_free(dim);
1395 if (pos < 0) {
1396 isl_id_free(array_id);
1397 return access;
1400 pos = isl_map_find_dim_by_id(access, isl_dim_param, array_id);
1401 if (pos < 0) {
1402 access = isl_map_insert_dims(access, isl_dim_param, 0, 1);
1403 access = isl_map_set_dim_id(access, isl_dim_param, 0, array_id);
1404 pos = 0;
1405 } else
1406 isl_id_free(array_id);
1408 access = isl_map_insert_dims(access, isl_dim_out, 0, 1);
1409 access = isl_map_equate(access, isl_dim_param, pos, isl_dim_out, 0);
1411 return access;
1414 /* Replace all accesses to (0D) arrays that correspond to one of the parameters
1415 * in "dim" by a value equal to the corresponding parameter.
1417 static struct pet_expr *expr_detect_parameter_accesses(struct pet_expr *expr,
1418 __isl_take isl_space *dim)
1420 int i;
1422 if (!expr)
1423 goto error;
1425 for (i = 0; i < expr->n_arg; ++i) {
1426 expr->args[i] =
1427 expr_detect_parameter_accesses(expr->args[i],
1428 isl_space_copy(dim));
1429 if (!expr->args[i])
1430 goto error;
1433 if (expr->type == pet_expr_access) {
1434 expr->acc.access = access_detect_parameter(expr->acc.access,
1435 isl_space_copy(dim));
1436 if (!expr->acc.access)
1437 goto error;
1440 isl_space_free(dim);
1441 return expr;
1442 error:
1443 isl_space_free(dim);
1444 return pet_expr_free(expr);
1447 /* Replace all accesses to (0D) arrays that correspond to one of the parameters
1448 * in "dim" by a value equal to the corresponding parameter.
1450 static struct pet_stmt *stmt_detect_parameter_accesses(struct pet_stmt *stmt,
1451 __isl_take isl_space *dim)
1453 if (!stmt)
1454 goto error;
1456 stmt->body = expr_detect_parameter_accesses(stmt->body,
1457 isl_space_copy(dim));
1459 if (!stmt->domain || !stmt->schedule || !stmt->body)
1460 goto error;
1462 isl_space_free(dim);
1463 return stmt;
1464 error:
1465 isl_space_free(dim);
1466 return pet_stmt_free(stmt);
1469 /* Replace all accesses to (0D) arrays that correspond to one of the parameters
1470 * in "dim" by a value equal to the corresponding parameter.
1472 static struct pet_scop *scop_detect_parameter_accesses(struct pet_scop *scop,
1473 __isl_take isl_space *dim)
1475 int i;
1477 if (!scop)
1478 goto error;
1480 for (i = 0; i < scop->n_stmt; ++i) {
1481 scop->stmts[i] = stmt_detect_parameter_accesses(scop->stmts[i],
1482 isl_space_copy(dim));
1483 if (!scop->stmts[i])
1484 goto error;
1487 isl_space_free(dim);
1488 return scop;
1489 error:
1490 isl_space_free(dim);
1491 return pet_scop_free(scop);
1494 /* Replace all accesses to (0D) arrays that correspond to any of
1495 * the parameters used in "scop" by a value equal
1496 * to the corresponding parameter.
1498 struct pet_scop *pet_scop_detect_parameter_accesses(struct pet_scop *scop)
1500 isl_space *dim;
1502 if (!scop)
1503 return NULL;
1505 dim = isl_set_get_space(scop->context);
1506 dim = scop_collect_params(scop, dim);
1508 scop = scop_detect_parameter_accesses(scop, dim);
1510 return scop;
1513 /* Add all read access relations (if "read" is set) and/or all write
1514 * access relations (if "write" is set) to "accesses" and return the result.
1516 static __isl_give isl_union_map *expr_collect_accesses(struct pet_expr *expr,
1517 int read, int write, __isl_take isl_union_map *accesses)
1519 int i;
1520 isl_id *id;
1521 isl_space *dim;
1523 if (!expr)
1524 return NULL;
1526 for (i = 0; i < expr->n_arg; ++i)
1527 accesses = expr_collect_accesses(expr->args[i],
1528 read, write, accesses);
1530 if (expr->type == pet_expr_access &&
1531 isl_map_has_tuple_id(expr->acc.access, isl_dim_out) &&
1532 ((read && expr->acc.read) || (write && expr->acc.write)))
1533 accesses = isl_union_map_add_map(accesses,
1534 isl_map_copy(expr->acc.access));
1536 return accesses;
1539 /* Collect and return all read access relations (if "read" is set)
1540 * and/or all write * access relations (if "write" is set) in "stmt".
1542 static __isl_give isl_union_map *stmt_collect_accesses(struct pet_stmt *stmt,
1543 int read, int write, __isl_take isl_space *dim)
1545 isl_union_map *accesses;
1547 if (!stmt)
1548 return NULL;
1550 accesses = isl_union_map_empty(dim);
1551 accesses = expr_collect_accesses(stmt->body, read, write, accesses);
1552 accesses = isl_union_map_intersect_domain(accesses,
1553 isl_union_set_from_set(isl_set_copy(stmt->domain)));
1555 return accesses;
1558 /* Collect and return all read access relations (if "read" is set)
1559 * and/or all write * access relations (if "write" is set) in "scop".
1561 static __isl_give isl_union_map *scop_collect_accesses(struct pet_scop *scop,
1562 int read, int write)
1564 int i;
1565 isl_union_map *accesses;
1567 if (!scop)
1568 return NULL;
1570 accesses = isl_union_map_empty(isl_set_get_space(scop->context));
1572 for (i = 0; i < scop->n_stmt; ++i) {
1573 isl_union_map *accesses_i;
1574 isl_space *dim = isl_set_get_space(scop->context);
1575 accesses_i = stmt_collect_accesses(scop->stmts[i],
1576 read, write, dim);
1577 accesses = isl_union_map_union(accesses, accesses_i);
1580 return accesses;
1583 __isl_give isl_union_map *pet_scop_collect_reads(struct pet_scop *scop)
1585 return scop_collect_accesses(scop, 1, 0);
1588 __isl_give isl_union_map *pet_scop_collect_writes(struct pet_scop *scop)
1590 return scop_collect_accesses(scop, 0, 1);
1593 /* Collect and return the union of iteration domains in "scop".
1595 __isl_give isl_union_set *pet_scop_collect_domains(struct pet_scop *scop)
1597 int i;
1598 isl_set *domain_i;
1599 isl_union_set *domain;
1601 if (!scop)
1602 return NULL;
1604 domain = isl_union_set_empty(isl_set_get_space(scop->context));
1606 for (i = 0; i < scop->n_stmt; ++i) {
1607 domain_i = isl_set_copy(scop->stmts[i]->domain);
1608 domain = isl_union_set_add_set(domain, domain_i);
1611 return domain;
1614 /* Collect and return the schedules of the statements in "scop".
1615 * The range is normalized to the maximal number of scheduling
1616 * dimensions.
1618 __isl_give isl_union_map *pet_scop_collect_schedule(struct pet_scop *scop)
1620 int i, j;
1621 isl_map *schedule_i;
1622 isl_union_map *schedule;
1623 int depth, max_depth = 0;
1625 if (!scop)
1626 return NULL;
1628 schedule = isl_union_map_empty(isl_set_get_space(scop->context));
1630 for (i = 0; i < scop->n_stmt; ++i) {
1631 depth = isl_map_dim(scop->stmts[i]->schedule, isl_dim_out);
1632 if (depth > max_depth)
1633 max_depth = depth;
1636 for (i = 0; i < scop->n_stmt; ++i) {
1637 schedule_i = isl_map_copy(scop->stmts[i]->schedule);
1638 depth = isl_map_dim(schedule_i, isl_dim_out);
1639 schedule_i = isl_map_add_dims(schedule_i, isl_dim_out,
1640 max_depth - depth);
1641 for (j = depth; j < max_depth; ++j)
1642 schedule_i = isl_map_fix_si(schedule_i,
1643 isl_dim_out, j, 0);
1644 schedule = isl_union_map_add_map(schedule, schedule_i);
1647 return schedule;