scan.cc: scop_add_array: rename "dim" variable to "space"
[pet.git] / expr.c
blob18d1b848c1cbde121d55675af3cfe3f762c1670f
1 /*
2 * Copyright 2011 Leiden University. All rights reserved.
3 * Copyright 2012-2014 Ecole Normale Superieure. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY LEIDEN UNIVERSITY ''AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LEIDEN UNIVERSITY OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and documentation
30 * are those of the authors and should not be interpreted as
31 * representing official policies, either expressed or implied, of
32 * Leiden University.
35 #include <string.h>
37 #include "expr.h"
38 #include "filter.h"
39 #include "value_bounds.h"
41 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
43 static char *type_str[] = {
44 [pet_expr_access] = "access",
45 [pet_expr_call] = "call",
46 [pet_expr_cast] = "cast",
47 [pet_expr_double] = "double",
48 [pet_expr_int] = "int",
49 [pet_expr_op] = "op",
52 static char *op_str[] = {
53 [pet_op_add_assign] = "+=",
54 [pet_op_sub_assign] = "-=",
55 [pet_op_mul_assign] = "*=",
56 [pet_op_div_assign] = "/=",
57 [pet_op_assign] = "=",
58 [pet_op_add] = "+",
59 [pet_op_sub] = "-",
60 [pet_op_mul] = "*",
61 [pet_op_div] = "/",
62 [pet_op_mod] = "%",
63 [pet_op_shl] = "<<",
64 [pet_op_shr] = ">>",
65 [pet_op_eq] = "==",
66 [pet_op_ne] = "!=",
67 [pet_op_le] = "<=",
68 [pet_op_ge] = ">=",
69 [pet_op_lt] = "<",
70 [pet_op_gt] = ">",
71 [pet_op_minus] = "-",
72 [pet_op_post_inc] = "++",
73 [pet_op_post_dec] = "--",
74 [pet_op_pre_inc] = "++",
75 [pet_op_pre_dec] = "--",
76 [pet_op_address_of] = "&",
77 [pet_op_and] = "&",
78 [pet_op_xor] = "^",
79 [pet_op_or] = "|",
80 [pet_op_not] = "~",
81 [pet_op_land] = "&&",
82 [pet_op_lor] = "||",
83 [pet_op_lnot] = "!",
84 [pet_op_cond] = "?:",
85 [pet_op_assume] = "assume",
86 [pet_op_kill] = "kill"
89 const char *pet_op_str(enum pet_op_type op)
91 return op_str[op];
94 int pet_op_is_inc_dec(enum pet_op_type op)
96 return op == pet_op_post_inc || op == pet_op_post_dec ||
97 op == pet_op_pre_inc || op == pet_op_pre_dec;
100 const char *pet_type_str(enum pet_expr_type type)
102 return type_str[type];
105 enum pet_op_type pet_str_op(const char *str)
107 int i;
109 for (i = 0; i < ARRAY_SIZE(op_str); ++i)
110 if (!strcmp(op_str[i], str))
111 return i;
113 return -1;
116 enum pet_expr_type pet_str_type(const char *str)
118 int i;
120 for (i = 0; i < ARRAY_SIZE(type_str); ++i)
121 if (!strcmp(type_str[i], str))
122 return i;
124 return -1;
127 /* Construct a pet_expr of the given type.
129 __isl_give pet_expr *pet_expr_alloc(isl_ctx *ctx, enum pet_expr_type type)
131 pet_expr *expr;
133 expr = isl_calloc_type(ctx, struct pet_expr);
134 if (!expr)
135 return NULL;
137 expr->ctx = ctx;
138 isl_ctx_ref(ctx);
139 expr->type = type;
140 expr->ref = 1;
142 return expr;
145 /* Construct an access pet_expr from an access relation and an index expression.
146 * By default, it is considered to be a read access.
148 __isl_give pet_expr *pet_expr_from_access_and_index( __isl_take isl_map *access,
149 __isl_take isl_multi_pw_aff *index)
151 isl_ctx *ctx = isl_map_get_ctx(access);
152 pet_expr *expr;
154 if (!index || !access)
155 goto error;
156 expr = pet_expr_alloc(ctx, pet_expr_access);
157 if (!expr)
158 goto error;
160 expr->acc.access = access;
161 expr->acc.index = index;
162 expr->acc.read = 1;
163 expr->acc.write = 0;
165 return expr;
166 error:
167 isl_map_free(access);
168 isl_multi_pw_aff_free(index);
169 return NULL;
172 /* Construct an access pet_expr from an index expression.
173 * By default, the access is considered to be a read access.
175 __isl_give pet_expr *pet_expr_from_index(__isl_take isl_multi_pw_aff *index)
177 isl_map *access;
179 access = isl_map_from_multi_pw_aff(isl_multi_pw_aff_copy(index));
180 return pet_expr_from_access_and_index(access, index);
183 /* Extend the range of "access" with "n" dimensions, retaining
184 * the tuple identifier on this range.
186 * If "access" represents a member access, then extend the range
187 * of the member.
189 static __isl_give isl_map *extend_range(__isl_take isl_map *access, int n)
191 isl_id *id;
193 id = isl_map_get_tuple_id(access, isl_dim_out);
195 if (!isl_map_range_is_wrapping(access)) {
196 access = isl_map_add_dims(access, isl_dim_out, n);
197 } else {
198 isl_map *domain;
200 domain = isl_map_copy(access);
201 domain = isl_map_range_factor_domain(domain);
202 access = isl_map_range_factor_range(access);
203 access = extend_range(access, n);
204 access = isl_map_range_product(domain, access);
207 access = isl_map_set_tuple_id(access, isl_dim_out, id);
209 return access;
212 /* Construct an access pet_expr from the number of bits needed to
213 * represent the type of the expression (may be zero if unknown or
214 * if the type is not an integer) an index expression and
215 * the depth of the accessed array.
216 * By default, the access is considered to be a read access.
218 * If the number of indices is smaller than the depth of the array,
219 * then we assume that all elements of the remaining dimensions
220 * are accessed.
222 __isl_give pet_expr *pet_expr_from_index_and_depth(int type_size,
223 __isl_take isl_multi_pw_aff *index, int depth)
225 isl_map *access;
226 int dim;
227 pet_expr *expr;
229 access = isl_map_from_multi_pw_aff(isl_multi_pw_aff_copy(index));
230 if (!access)
231 goto error;
232 dim = isl_map_dim(access, isl_dim_out);
233 if (dim > depth)
234 isl_die(isl_map_get_ctx(access), isl_error_internal,
235 "number of indices greater than depth",
236 access = isl_map_free(access));
238 if (dim != depth)
239 access = extend_range(access, depth - dim);
241 expr = pet_expr_from_access_and_index(access, index);
242 if (!expr)
243 return NULL;
245 expr->type_size = type_size;
247 return expr;
248 error:
249 isl_multi_pw_aff_free(index);
250 return NULL;
253 /* Construct a pet_expr that kills the elements specified by
254 * the index expression "index" and the access relation "access".
256 __isl_give pet_expr *pet_expr_kill_from_access_and_index(
257 __isl_take isl_map *access, __isl_take isl_multi_pw_aff *index)
259 pet_expr *expr;
261 if (!access || !index)
262 goto error;
264 expr = pet_expr_from_access_and_index(access, index);
265 expr = pet_expr_access_set_read(expr, 0);
266 return pet_expr_new_unary(pet_op_kill, expr);
267 error:
268 isl_map_free(access);
269 isl_multi_pw_aff_free(index);
270 return NULL;
273 /* Construct a unary pet_expr that performs "op" on "arg".
275 __isl_give pet_expr *pet_expr_new_unary(enum pet_op_type op,
276 __isl_take pet_expr *arg)
278 isl_ctx *ctx;
279 pet_expr *expr;
281 if (!arg)
282 return NULL;
283 ctx = pet_expr_get_ctx(arg);
284 expr = pet_expr_alloc(ctx, pet_expr_op);
285 expr = pet_expr_set_n_arg(expr, 1);
286 if (!expr)
287 goto error;
289 expr->op = op;
290 expr->args[pet_un_arg] = arg;
292 return expr;
293 error:
294 pet_expr_free(arg);
295 return NULL;
298 /* Construct a binary pet_expr that performs "op" on "lhs" and "rhs",
299 * where the result is represented using a type of "type_size" bits
300 * (may be zero if unknown or if the type is not an integer).
302 __isl_give pet_expr *pet_expr_new_binary(int type_size, enum pet_op_type op,
303 __isl_take pet_expr *lhs, __isl_take pet_expr *rhs)
305 isl_ctx *ctx;
306 pet_expr *expr;
308 if (!lhs || !rhs)
309 goto error;
310 ctx = pet_expr_get_ctx(lhs);
311 expr = pet_expr_alloc(ctx, pet_expr_op);
312 expr = pet_expr_set_n_arg(expr, 2);
313 if (!expr)
314 goto error;
316 expr->op = op;
317 expr->type_size = type_size;
318 expr->args[pet_bin_lhs] = lhs;
319 expr->args[pet_bin_rhs] = rhs;
321 return expr;
322 error:
323 pet_expr_free(lhs);
324 pet_expr_free(rhs);
325 return NULL;
328 /* Construct a ternary pet_expr that performs "cond" ? "lhs" : "rhs".
330 __isl_give pet_expr *pet_expr_new_ternary(__isl_take pet_expr *cond,
331 __isl_take pet_expr *lhs, __isl_take pet_expr *rhs)
333 isl_ctx *ctx;
334 pet_expr *expr;
336 if (!cond || !lhs || !rhs)
337 goto error;
338 ctx = pet_expr_get_ctx(cond);
339 expr = pet_expr_alloc(ctx, pet_expr_op);
340 expr = pet_expr_set_n_arg(expr, 3);
341 if (!expr)
342 goto error;
344 expr->op = pet_op_cond;
345 expr->args[pet_ter_cond] = cond;
346 expr->args[pet_ter_true] = lhs;
347 expr->args[pet_ter_false] = rhs;
349 return expr;
350 error:
351 pet_expr_free(cond);
352 pet_expr_free(lhs);
353 pet_expr_free(rhs);
354 return NULL;
357 /* Construct a call pet_expr that calls function "name" with "n_arg"
358 * arguments. The caller is responsible for filling in the arguments.
360 __isl_give pet_expr *pet_expr_new_call(isl_ctx *ctx, const char *name,
361 unsigned n_arg)
363 pet_expr *expr;
365 expr = pet_expr_alloc(ctx, pet_expr_call);
366 expr = pet_expr_set_n_arg(expr, n_arg);
367 if (!expr)
368 return NULL;
370 expr->name = strdup(name);
371 if (!expr->name)
372 return pet_expr_free(expr);
374 return expr;
377 /* Construct a pet_expr that represents the cast of "arg" to "type_name".
379 __isl_give pet_expr *pet_expr_new_cast(const char *type_name,
380 __isl_take pet_expr *arg)
382 isl_ctx *ctx;
383 pet_expr *expr;
385 if (!arg)
386 return NULL;
388 ctx = pet_expr_get_ctx(arg);
389 expr = pet_expr_alloc(ctx, pet_expr_cast);
390 expr = pet_expr_set_n_arg(expr, 1);
391 if (!expr)
392 goto error;
394 expr->type_name = strdup(type_name);
395 if (!expr->type_name)
396 goto error;
398 expr->args[0] = arg;
400 return expr;
401 error:
402 pet_expr_free(arg);
403 pet_expr_free(expr);
404 return NULL;
407 /* Construct a pet_expr that represents the double "d".
409 __isl_give pet_expr *pet_expr_new_double(isl_ctx *ctx,
410 double val, const char *s)
412 pet_expr *expr;
414 expr = pet_expr_alloc(ctx, pet_expr_double);
415 if (!expr)
416 return NULL;
418 expr->d.val = val;
419 expr->d.s = strdup(s);
420 if (!expr->d.s)
421 return pet_expr_free(expr);
423 return expr;
426 /* Construct a pet_expr that represents the integer value "v".
428 __isl_give pet_expr *pet_expr_new_int(__isl_take isl_val *v)
430 isl_ctx *ctx;
431 pet_expr *expr;
433 if (!v)
434 return NULL;
436 ctx = isl_val_get_ctx(v);
437 expr = pet_expr_alloc(ctx, pet_expr_int);
438 if (!expr)
439 goto error;
441 expr->i = v;
443 return expr;
444 error:
445 isl_val_free(v);
446 return NULL;
449 static __isl_give pet_expr *pet_expr_dup(__isl_keep pet_expr *expr)
451 int i;
452 pet_expr *dup;
454 if (!expr)
455 return NULL;
457 dup = pet_expr_alloc(expr->ctx, expr->type);
458 dup = pet_expr_set_type_size(dup, expr->type_size);
459 dup = pet_expr_set_n_arg(dup, expr->n_arg);
460 for (i = 0; i < expr->n_arg; ++i)
461 dup = pet_expr_set_arg(dup, i, pet_expr_copy(expr->args[i]));
463 switch (expr->type) {
464 case pet_expr_access:
465 if (expr->acc.ref_id)
466 dup = pet_expr_access_set_ref_id(dup,
467 isl_id_copy(expr->acc.ref_id));
468 dup = pet_expr_access_set_access(dup,
469 isl_map_copy(expr->acc.access));
470 dup = pet_expr_access_set_index(dup,
471 isl_multi_pw_aff_copy(expr->acc.index));
472 dup = pet_expr_access_set_read(dup, expr->acc.read);
473 dup = pet_expr_access_set_write(dup, expr->acc.write);
474 break;
475 case pet_expr_call:
476 dup = pet_expr_call_set_name(dup, expr->name);
477 break;
478 case pet_expr_cast:
479 dup = pet_expr_cast_set_type_name(dup, expr->type_name);
480 break;
481 case pet_expr_double:
482 dup = pet_expr_double_set(dup, expr->d.val, expr->d.s);
483 break;
484 case pet_expr_int:
485 dup = pet_expr_int_set_val(dup, isl_val_copy(expr->i));
486 break;
487 case pet_expr_op:
488 dup = pet_expr_op_set_type(dup, expr->op);
489 break;
490 case pet_expr_error:
491 dup = pet_expr_free(dup);
492 break;
495 return dup;
498 __isl_give pet_expr *pet_expr_cow(__isl_take pet_expr *expr)
500 if (!expr)
501 return NULL;
503 if (expr->ref == 1)
504 return expr;
505 expr->ref--;
506 return pet_expr_dup(expr);
509 __isl_null pet_expr *pet_expr_free(__isl_take pet_expr *expr)
511 int i;
513 if (!expr)
514 return NULL;
515 if (--expr->ref > 0)
516 return NULL;
518 for (i = 0; i < expr->n_arg; ++i)
519 pet_expr_free(expr->args[i]);
520 free(expr->args);
522 switch (expr->type) {
523 case pet_expr_access:
524 isl_id_free(expr->acc.ref_id);
525 isl_map_free(expr->acc.access);
526 isl_multi_pw_aff_free(expr->acc.index);
527 break;
528 case pet_expr_call:
529 free(expr->name);
530 break;
531 case pet_expr_cast:
532 free(expr->type_name);
533 break;
534 case pet_expr_double:
535 free(expr->d.s);
536 break;
537 case pet_expr_int:
538 isl_val_free(expr->i);
539 break;
540 case pet_expr_op:
541 case pet_expr_error:
542 break;
545 isl_ctx_deref(expr->ctx);
546 free(expr);
547 return NULL;
550 /* Return an additional reference to "expr".
552 __isl_give pet_expr *pet_expr_copy(__isl_keep pet_expr *expr)
554 if (!expr)
555 return NULL;
557 expr->ref++;
558 return expr;
561 /* Return the isl_ctx in which "expr" was created.
563 isl_ctx *pet_expr_get_ctx(__isl_keep pet_expr *expr)
565 return expr ? expr->ctx : NULL;
568 /* Return the type of "expr".
570 enum pet_expr_type pet_expr_get_type(__isl_keep pet_expr *expr)
572 if (!expr)
573 return pet_expr_error;
574 return expr->type;
577 /* Return the number of arguments of "expr".
579 int pet_expr_get_n_arg(__isl_keep pet_expr *expr)
581 if (!expr)
582 return -1;
584 return expr->n_arg;
587 /* Set the number of arguments of "expr" to "n".
589 * If "expr" originally had more arguments, then remove the extra arguments.
590 * If "expr" originally had fewer arguments, then create space for
591 * the extra arguments ans initialize them to NULL.
593 __isl_give pet_expr *pet_expr_set_n_arg(__isl_take pet_expr *expr, int n)
595 int i;
596 pet_expr **args;
598 if (!expr)
599 return NULL;
600 if (expr->n_arg == n)
601 return expr;
602 expr = pet_expr_cow(expr);
603 if (!expr)
604 return NULL;
606 if (n < expr->n_arg) {
607 for (i = n; i < expr->n_arg; ++i)
608 pet_expr_free(expr->args[i]);
609 expr->n_arg = n;
610 return expr;
613 args = isl_realloc_array(expr->ctx, expr->args, pet_expr *, n);
614 if (!args)
615 return pet_expr_free(expr);
616 expr->args = args;
617 for (i = expr->n_arg; i < n; ++i)
618 expr->args[i] = NULL;
619 expr->n_arg = n;
621 return expr;
624 /* Return the argument of "expr" at position "pos".
626 __isl_give pet_expr *pet_expr_get_arg(__isl_keep pet_expr *expr, int pos)
628 if (!expr)
629 return NULL;
630 if (pos < 0 || pos >= expr->n_arg)
631 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
632 "position out of bounds", return NULL);
634 return pet_expr_copy(expr->args[pos]);
637 /* Replace the argument of "expr" at position "pos" by "arg".
639 __isl_give pet_expr *pet_expr_set_arg(__isl_take pet_expr *expr, int pos,
640 __isl_take pet_expr *arg)
642 if (!expr || !arg)
643 goto error;
644 if (pos < 0 || pos >= expr->n_arg)
645 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
646 "position out of bounds", goto error);
647 if (expr->args[pos] == arg) {
648 pet_expr_free(arg);
649 return expr;
652 expr = pet_expr_cow(expr);
653 if (!expr)
654 goto error;
656 pet_expr_free(expr->args[pos]);
657 expr->args[pos] = arg;
659 return expr;
660 error:
661 pet_expr_free(expr);
662 pet_expr_free(arg);
663 return NULL;
666 /* Does "expr" represent an access to an unnamed space, i.e.,
667 * does it represent an affine expression?
669 int pet_expr_is_affine(__isl_keep pet_expr *expr)
671 int has_id;
673 if (!expr)
674 return -1;
675 if (expr->type != pet_expr_access)
676 return 0;
678 has_id = isl_map_has_tuple_id(expr->acc.access, isl_dim_out);
679 if (has_id < 0)
680 return -1;
682 return !has_id;
685 /* Does "expr" represent an access to a scalar, i.e., zero-dimensional array?
687 int pet_expr_is_scalar_access(__isl_keep pet_expr *expr)
689 if (!expr)
690 return -1;
691 if (expr->type != pet_expr_access)
692 return 0;
694 return isl_map_dim(expr->acc.access, isl_dim_out) == 0;
697 /* Return 1 if the two pet_exprs are equivalent.
699 int pet_expr_is_equal(__isl_keep pet_expr *expr1, __isl_keep pet_expr *expr2)
701 int i;
703 if (!expr1 || !expr2)
704 return 0;
706 if (expr1->type != expr2->type)
707 return 0;
708 if (expr1->n_arg != expr2->n_arg)
709 return 0;
710 for (i = 0; i < expr1->n_arg; ++i)
711 if (!pet_expr_is_equal(expr1->args[i], expr2->args[i]))
712 return 0;
713 switch (expr1->type) {
714 case pet_expr_error:
715 return -1;
716 case pet_expr_double:
717 if (strcmp(expr1->d.s, expr2->d.s))
718 return 0;
719 if (expr1->d.val != expr2->d.val)
720 return 0;
721 break;
722 case pet_expr_int:
723 if (!isl_val_eq(expr1->i, expr2->i))
724 return 0;
725 break;
726 case pet_expr_access:
727 if (expr1->acc.read != expr2->acc.read)
728 return 0;
729 if (expr1->acc.write != expr2->acc.write)
730 return 0;
731 if (expr1->acc.ref_id != expr2->acc.ref_id)
732 return 0;
733 if (!expr1->acc.access || !expr2->acc.access)
734 return 0;
735 if (!isl_map_is_equal(expr1->acc.access, expr2->acc.access))
736 return 0;
737 if (!expr1->acc.index || !expr2->acc.index)
738 return 0;
739 if (!isl_multi_pw_aff_plain_is_equal(expr1->acc.index,
740 expr2->acc.index))
741 return 0;
742 break;
743 case pet_expr_op:
744 if (expr1->op != expr2->op)
745 return 0;
746 break;
747 case pet_expr_call:
748 if (strcmp(expr1->name, expr2->name))
749 return 0;
750 break;
751 case pet_expr_cast:
752 if (strcmp(expr1->type_name, expr2->type_name))
753 return 0;
754 break;
757 return 1;
760 /* Does the access expression "expr" read the accessed elements?
762 int pet_expr_access_is_read(__isl_keep pet_expr *expr)
764 if (!expr)
765 return -1;
766 if (expr->type != pet_expr_access)
767 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
768 "not an access expression", return -1);
770 return expr->acc.read;
773 /* Does the access expression "expr" write to the accessed elements?
775 int pet_expr_access_is_write(__isl_keep pet_expr *expr)
777 if (!expr)
778 return -1;
779 if (expr->type != pet_expr_access)
780 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
781 "not an access expression", return -1);
783 return expr->acc.write;
786 /* Return the identifier of the array accessed by "expr".
788 * If "expr" represents a member access, then return the identifier
789 * of the outer structure array.
791 __isl_give isl_id *pet_expr_access_get_id(__isl_keep pet_expr *expr)
793 if (!expr)
794 return NULL;
795 if (expr->type != pet_expr_access)
796 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
797 "not an access expression", return NULL);
799 if (isl_map_range_is_wrapping(expr->acc.access)) {
800 isl_space *space;
801 isl_id *id;
803 space = isl_map_get_space(expr->acc.access);
804 space = isl_space_range(space);
805 while (space && isl_space_is_wrapping(space))
806 space = isl_space_domain(isl_space_unwrap(space));
807 id = isl_space_get_tuple_id(space, isl_dim_set);
808 isl_space_free(space);
810 return id;
813 return isl_map_get_tuple_id(expr->acc.access, isl_dim_out);
816 /* Return the parameter space of "expr".
818 __isl_give isl_space *pet_expr_access_get_parameter_space(
819 __isl_keep pet_expr *expr)
821 isl_space *space;
823 if (!expr)
824 return NULL;
825 if (expr->type != pet_expr_access)
826 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
827 "not an access expression", return NULL);
829 space = isl_multi_pw_aff_get_space(expr->acc.index);
830 space = isl_space_params(space);
832 return space;
835 /* Return the space of the data accessed by "expr".
837 __isl_give isl_space *pet_expr_access_get_data_space(__isl_keep pet_expr *expr)
839 isl_space *space;
841 if (!expr)
842 return NULL;
843 if (expr->type != pet_expr_access)
844 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
845 "not an access expression", return NULL);
847 space = isl_multi_pw_aff_get_space(expr->acc.index);
848 space = isl_space_range(space);
850 return space;
853 /* Modify all expressions of type pet_expr_access in "expr"
854 * by calling "fn" on them.
856 __isl_give pet_expr *pet_expr_map_access(__isl_take pet_expr *expr,
857 __isl_give pet_expr *(*fn)(__isl_take pet_expr *expr, void *user),
858 void *user)
860 int i, n;
862 n = pet_expr_get_n_arg(expr);
863 for (i = 0; i < n; ++i) {
864 pet_expr *arg = pet_expr_get_arg(expr, i);
865 arg = pet_expr_map_access(arg, fn, user);
866 expr = pet_expr_set_arg(expr, i, arg);
869 if (!expr)
870 return NULL;
872 if (expr->type == pet_expr_access)
873 expr = fn(expr, user);
875 return expr;
878 /* Call "fn" on each of the subexpressions of "expr" of type "type".
880 * Return -1 on error (where fn returning a negative value is treated as
881 * an error).
882 * Otherwise return 0.
884 int pet_expr_foreach_expr_of_type(__isl_keep pet_expr *expr,
885 enum pet_expr_type type,
886 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
888 int i;
890 if (!expr)
891 return -1;
893 for (i = 0; i < expr->n_arg; ++i)
894 if (pet_expr_foreach_expr_of_type(expr->args[i],
895 type, fn, user) < 0)
896 return -1;
898 if (expr->type == type)
899 return fn(expr, user);
901 return 0;
904 /* Call "fn" on each of the subexpressions of "expr" of type pet_expr_access.
906 * Return -1 on error (where fn returning a negative value is treated as
907 * an error).
908 * Otherwise return 0.
910 int pet_expr_foreach_access_expr(__isl_keep pet_expr *expr,
911 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
913 return pet_expr_foreach_expr_of_type(expr, pet_expr_access, fn, user);
916 /* Call "fn" on each of the subexpressions of "expr" of type pet_expr_call.
918 * Return -1 on error (where fn returning a negative value is treated as
919 * an error).
920 * Otherwise return 0.
922 int pet_expr_foreach_call_expr(__isl_keep pet_expr *expr,
923 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
925 return pet_expr_foreach_expr_of_type(expr, pet_expr_call, fn, user);
928 /* Internal data structure for pet_expr_writes.
929 * "id" is the identifier that we are looking for.
930 * "found" is set if we have found the identifier being written to.
932 struct pet_expr_writes_data {
933 isl_id *id;
934 int found;
937 /* Given an access expression, check if it writes to data->id.
938 * If so, set data->found and abort the search.
940 static int writes(__isl_keep pet_expr *expr, void *user)
942 struct pet_expr_writes_data *data = user;
943 isl_id *write_id;
945 if (!expr->acc.write)
946 return 0;
947 if (pet_expr_is_affine(expr))
948 return 0;
950 write_id = pet_expr_access_get_id(expr);
951 isl_id_free(write_id);
953 if (!write_id)
954 return -1;
956 if (write_id != data->id)
957 return 0;
959 data->found = 1;
960 return -1;
963 /* Does expression "expr" write to "id"?
965 int pet_expr_writes(__isl_keep pet_expr *expr, __isl_keep isl_id *id)
967 struct pet_expr_writes_data data;
969 data.id = id;
970 data.found = 0;
971 if (pet_expr_foreach_access_expr(expr, &writes, &data) < 0 &&
972 !data.found)
973 return -1;
975 return data.found;
978 /* Move the "n" dimensions of "src_type" starting at "src_pos" of
979 * index expression and access relation of "expr"
980 * to dimensions of "dst_type" at "dst_pos".
982 __isl_give pet_expr *pet_expr_access_move_dims(__isl_take pet_expr *expr,
983 enum isl_dim_type dst_type, unsigned dst_pos,
984 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
986 expr = pet_expr_cow(expr);
987 if (!expr)
988 return NULL;
989 if (expr->type != pet_expr_access)
990 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
991 "not an access pet_expr", return pet_expr_free(expr));
993 expr->acc.access = isl_map_move_dims(expr->acc.access,
994 dst_type, dst_pos, src_type, src_pos, n);
995 expr->acc.index = isl_multi_pw_aff_move_dims(expr->acc.index,
996 dst_type, dst_pos, src_type, src_pos, n);
997 if (!expr->acc.access || !expr->acc.index)
998 return pet_expr_free(expr);
1000 return expr;
1003 /* Replace the index expression and access relation of "expr"
1004 * by their preimages under the function represented by "ma".
1006 __isl_give pet_expr *pet_expr_access_pullback_multi_aff(
1007 __isl_take pet_expr *expr, __isl_take isl_multi_aff *ma)
1009 expr = pet_expr_cow(expr);
1010 if (!expr || !ma)
1011 goto error;
1012 if (expr->type != pet_expr_access)
1013 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1014 "not an access pet_expr", goto error);
1016 expr->acc.access = isl_map_preimage_domain_multi_aff(expr->acc.access,
1017 isl_multi_aff_copy(ma));
1018 expr->acc.index = isl_multi_pw_aff_pullback_multi_aff(expr->acc.index,
1019 ma);
1020 if (!expr->acc.access || !expr->acc.index)
1021 return pet_expr_free(expr);
1023 return expr;
1024 error:
1025 isl_multi_aff_free(ma);
1026 pet_expr_free(expr);
1027 return NULL;
1030 /* Return the access relation of access expression "expr".
1032 __isl_give isl_map *pet_expr_access_get_access(__isl_keep pet_expr *expr)
1034 if (!expr)
1035 return NULL;
1036 if (expr->type != pet_expr_access)
1037 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1038 "not an access expression", return NULL);
1040 return isl_map_copy(expr->acc.access);
1043 /* Return the index expression of access expression "expr".
1045 __isl_give isl_multi_pw_aff *pet_expr_access_get_index(
1046 __isl_keep pet_expr *expr)
1048 if (!expr)
1049 return NULL;
1050 if (expr->type != pet_expr_access)
1051 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1052 "not an access expression", return NULL);
1054 return isl_multi_pw_aff_copy(expr->acc.index);
1057 /* Align the parameters of expr->acc.index and expr->acc.access.
1059 __isl_give pet_expr *pet_expr_access_align_params(__isl_take pet_expr *expr)
1061 expr = pet_expr_cow(expr);
1062 if (!expr)
1063 return NULL;
1064 if (expr->type != pet_expr_access)
1065 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1066 "not an access expression", return pet_expr_free(expr));
1068 expr->acc.access = isl_map_align_params(expr->acc.access,
1069 isl_multi_pw_aff_get_space(expr->acc.index));
1070 expr->acc.index = isl_multi_pw_aff_align_params(expr->acc.index,
1071 isl_map_get_space(expr->acc.access));
1072 if (!expr->acc.access || !expr->acc.index)
1073 return pet_expr_free(expr);
1075 return expr;
1078 /* Add extra conditions on the parameters to all access relations in "expr".
1080 * The conditions are not added to the index expression. Instead, they
1081 * are used to try and simplify the index expression.
1083 __isl_give pet_expr *pet_expr_restrict(__isl_take pet_expr *expr,
1084 __isl_take isl_set *cond)
1086 int i;
1088 expr = pet_expr_cow(expr);
1089 if (!expr)
1090 goto error;
1092 for (i = 0; i < expr->n_arg; ++i) {
1093 expr->args[i] = pet_expr_restrict(expr->args[i],
1094 isl_set_copy(cond));
1095 if (!expr->args[i])
1096 goto error;
1099 if (expr->type == pet_expr_access) {
1100 expr->acc.access = isl_map_intersect_params(expr->acc.access,
1101 isl_set_copy(cond));
1102 expr->acc.index = isl_multi_pw_aff_gist_params(
1103 expr->acc.index, isl_set_copy(cond));
1104 if (!expr->acc.access || !expr->acc.index)
1105 goto error;
1108 isl_set_free(cond);
1109 return expr;
1110 error:
1111 isl_set_free(cond);
1112 return pet_expr_free(expr);
1115 /* Modify the access relation and index expression
1116 * of the given access expression
1117 * based on the given iteration space transformation.
1118 * In particular, precompose the access relation and index expression
1119 * with the update function.
1121 * If the access has any arguments then the domain of the access relation
1122 * is a wrapped mapping from the iteration space to the space of
1123 * argument values. We only need to change the domain of this wrapped
1124 * mapping, so we extend the input transformation with an identity mapping
1125 * on the space of argument values.
1127 __isl_give pet_expr *pet_expr_access_update_domain(__isl_take pet_expr *expr,
1128 __isl_keep isl_multi_pw_aff *update)
1130 isl_space *space;
1132 expr = pet_expr_cow(expr);
1133 if (!expr)
1134 return NULL;
1135 if (expr->type != pet_expr_access)
1136 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1137 "not an access expression", return pet_expr_free(expr));
1139 update = isl_multi_pw_aff_copy(update);
1141 space = isl_map_get_space(expr->acc.access);
1142 space = isl_space_domain(space);
1143 if (!isl_space_is_wrapping(space))
1144 isl_space_free(space);
1145 else {
1146 isl_multi_pw_aff *id;
1147 space = isl_space_unwrap(space);
1148 space = isl_space_range(space);
1149 space = isl_space_map_from_set(space);
1150 id = isl_multi_pw_aff_identity(space);
1151 update = isl_multi_pw_aff_product(update, id);
1154 expr->acc.access = isl_map_preimage_domain_multi_pw_aff(
1155 expr->acc.access,
1156 isl_multi_pw_aff_copy(update));
1157 expr->acc.index = isl_multi_pw_aff_pullback_multi_pw_aff(
1158 expr->acc.index, update);
1159 if (!expr->acc.access || !expr->acc.index)
1160 return pet_expr_free(expr);
1162 return expr;
1165 static __isl_give pet_expr *update_domain(__isl_take pet_expr *expr, void *user)
1167 isl_multi_pw_aff *update = user;
1169 return pet_expr_access_update_domain(expr, update);
1172 /* Modify all access relations in "expr" by precomposing them with
1173 * the given iteration space transformation.
1175 __isl_give pet_expr *pet_expr_update_domain(__isl_take pet_expr *expr,
1176 __isl_take isl_multi_pw_aff *update)
1178 expr = pet_expr_map_access(expr, &update_domain, update);
1179 isl_multi_pw_aff_free(update);
1180 return expr;
1183 /* Add all parameters in "space" to the access relation and index expression
1184 * of "expr".
1186 static __isl_give pet_expr *align_params(__isl_take pet_expr *expr, void *user)
1188 isl_space *space = user;
1190 expr = pet_expr_cow(expr);
1191 if (!expr)
1192 return NULL;
1193 if (expr->type != pet_expr_access)
1194 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1195 "not an access expression", return pet_expr_free(expr));
1197 expr->acc.access = isl_map_align_params(expr->acc.access,
1198 isl_space_copy(space));
1199 expr->acc.index = isl_multi_pw_aff_align_params(expr->acc.index,
1200 isl_space_copy(space));
1201 if (!expr->acc.access || !expr->acc.index)
1202 return pet_expr_free(expr);
1204 return expr;
1207 /* Add all parameters in "space" to all access relations and index expressions
1208 * in "expr".
1210 __isl_give pet_expr *pet_expr_align_params(__isl_take pet_expr *expr,
1211 __isl_take isl_space *space)
1213 expr = pet_expr_map_access(expr, &align_params, space);
1214 isl_space_free(space);
1215 return expr;
1218 /* Insert an argument expression corresponding to "test" in front
1219 * of the list of arguments described by *n_arg and *args.
1221 static __isl_give pet_expr *insert_access_arg(__isl_take pet_expr *expr,
1222 __isl_keep isl_multi_pw_aff *test)
1224 int i;
1225 isl_ctx *ctx = isl_multi_pw_aff_get_ctx(test);
1227 if (!test)
1228 return pet_expr_free(expr);
1229 expr = pet_expr_cow(expr);
1230 if (!expr)
1231 return NULL;
1233 if (!expr->args) {
1234 expr->args = isl_calloc_array(ctx, pet_expr *, 1);
1235 if (!expr->args)
1236 return pet_expr_free(expr);
1237 } else {
1238 pet_expr **ext;
1239 ext = isl_calloc_array(ctx, pet_expr *, 1 + expr->n_arg);
1240 if (!ext)
1241 return pet_expr_free(expr);
1242 for (i = 0; i < expr->n_arg; ++i)
1243 ext[1 + i] = expr->args[i];
1244 free(expr->args);
1245 expr->args = ext;
1247 expr->n_arg++;
1248 expr->args[0] = pet_expr_from_index(isl_multi_pw_aff_copy(test));
1249 if (!expr->args[0])
1250 return pet_expr_free(expr);
1252 return expr;
1255 /* Make the expression "expr" depend on the value of "test"
1256 * being equal to "satisfied".
1258 * If "test" is an affine expression, we simply add the conditions
1259 * on the expression having the value "satisfied" to all access relations
1260 * and index expressions.
1262 * Otherwise, we add a filter to "expr" (which is then assumed to be
1263 * an access expression) corresponding to "test" being equal to "satisfied".
1265 __isl_give pet_expr *pet_expr_filter(__isl_take pet_expr *expr,
1266 __isl_take isl_multi_pw_aff *test, int satisfied)
1268 isl_id *id;
1269 isl_ctx *ctx;
1270 isl_space *space;
1271 isl_pw_multi_aff *pma;
1273 expr = pet_expr_cow(expr);
1274 if (!expr || !test)
1275 goto error;
1277 if (!isl_multi_pw_aff_has_tuple_id(test, isl_dim_out)) {
1278 isl_pw_aff *pa;
1279 isl_set *cond;
1281 pa = isl_multi_pw_aff_get_pw_aff(test, 0);
1282 isl_multi_pw_aff_free(test);
1283 if (satisfied)
1284 cond = isl_pw_aff_non_zero_set(pa);
1285 else
1286 cond = isl_pw_aff_zero_set(pa);
1287 return pet_expr_restrict(expr, isl_set_params(cond));
1290 ctx = isl_multi_pw_aff_get_ctx(test);
1291 if (expr->type != pet_expr_access)
1292 isl_die(ctx, isl_error_invalid,
1293 "can only filter access expressions", goto error);
1295 space = isl_space_domain(isl_map_get_space(expr->acc.access));
1296 id = isl_multi_pw_aff_get_tuple_id(test, isl_dim_out);
1297 pma = pet_filter_insert_pma(space, id, satisfied);
1299 expr->acc.access = isl_map_preimage_domain_pw_multi_aff(
1300 expr->acc.access,
1301 isl_pw_multi_aff_copy(pma));
1302 expr->acc.index = isl_multi_pw_aff_pullback_pw_multi_aff(
1303 expr->acc.index, pma);
1304 if (!expr->acc.access || !expr->acc.index)
1305 goto error;
1307 expr = insert_access_arg(expr, test);
1309 isl_multi_pw_aff_free(test);
1310 return expr;
1311 error:
1312 isl_multi_pw_aff_free(test);
1313 return pet_expr_free(expr);
1316 /* Check if the given index expression accesses a (0D) array that corresponds
1317 * to one of the parameters in "space". If so, replace the array access
1318 * by an access to the set of integers with as index (and value)
1319 * that parameter.
1321 static __isl_give isl_multi_pw_aff *index_detect_parameter(
1322 __isl_take isl_multi_pw_aff *index, __isl_take isl_space *space)
1324 isl_local_space *ls;
1325 isl_id *array_id = NULL;
1326 isl_aff *aff;
1327 int pos = -1;
1329 if (isl_multi_pw_aff_has_tuple_id(index, isl_dim_out)) {
1330 array_id = isl_multi_pw_aff_get_tuple_id(index, isl_dim_out);
1331 pos = isl_space_find_dim_by_id(space, isl_dim_param, array_id);
1333 isl_space_free(space);
1335 if (pos < 0) {
1336 isl_id_free(array_id);
1337 return index;
1340 space = isl_multi_pw_aff_get_domain_space(index);
1341 isl_multi_pw_aff_free(index);
1343 pos = isl_space_find_dim_by_id(space, isl_dim_param, array_id);
1344 if (pos < 0) {
1345 space = isl_space_insert_dims(space, isl_dim_param, 0, 1);
1346 space = isl_space_set_dim_id(space, isl_dim_param, 0, array_id);
1347 pos = 0;
1348 } else
1349 isl_id_free(array_id);
1351 ls = isl_local_space_from_space(space);
1352 aff = isl_aff_var_on_domain(ls, isl_dim_param, pos);
1353 index = isl_multi_pw_aff_from_pw_aff(isl_pw_aff_from_aff(aff));
1355 return index;
1358 /* Check if the given access relation accesses a (0D) array that corresponds
1359 * to one of the parameters in "space". If so, replace the array access
1360 * by an access to the set of integers with as index (and value)
1361 * that parameter.
1363 static __isl_give isl_map *access_detect_parameter(__isl_take isl_map *access,
1364 __isl_take isl_space *space)
1366 isl_id *array_id = NULL;
1367 int pos = -1;
1369 if (isl_map_has_tuple_id(access, isl_dim_out)) {
1370 array_id = isl_map_get_tuple_id(access, isl_dim_out);
1371 pos = isl_space_find_dim_by_id(space, isl_dim_param, array_id);
1373 isl_space_free(space);
1375 if (pos < 0) {
1376 isl_id_free(array_id);
1377 return access;
1380 pos = isl_map_find_dim_by_id(access, isl_dim_param, array_id);
1381 if (pos < 0) {
1382 access = isl_map_insert_dims(access, isl_dim_param, 0, 1);
1383 access = isl_map_set_dim_id(access, isl_dim_param, 0, array_id);
1384 pos = 0;
1385 } else
1386 isl_id_free(array_id);
1388 access = isl_map_insert_dims(access, isl_dim_out, 0, 1);
1389 access = isl_map_equate(access, isl_dim_param, pos, isl_dim_out, 0);
1391 return access;
1394 /* If "expr" accesses a (0D) array that corresponds to one of the parameters
1395 * in "space" then replace it by a value equal to the corresponding parameter.
1397 static __isl_give pet_expr *detect_parameter_accesses(__isl_take pet_expr *expr,
1398 void *user)
1400 isl_space *space = user;
1402 expr = pet_expr_cow(expr);
1403 if (!expr)
1404 return NULL;
1405 if (expr->type != pet_expr_access)
1406 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1407 "not an access expression", return pet_expr_free(expr));
1409 expr->acc.access = access_detect_parameter(expr->acc.access,
1410 isl_space_copy(space));
1411 expr->acc.index = index_detect_parameter(expr->acc.index,
1412 isl_space_copy(space));
1413 if (!expr->acc.access || !expr->acc.index)
1414 return pet_expr_free(expr);
1416 return expr;
1419 /* Replace all accesses to (0D) arrays that correspond to one of the parameters
1420 * in "space" by a value equal to the corresponding parameter.
1422 __isl_give pet_expr *pet_expr_detect_parameter_accesses(
1423 __isl_take pet_expr *expr, __isl_take isl_space *space)
1425 expr = pet_expr_map_access(expr, &detect_parameter_accesses, space);
1426 isl_space_free(space);
1427 return expr;
1430 /* Add a reference identifier to access expression "expr".
1431 * "user" points to an integer that contains the sequence number
1432 * of the next reference.
1434 static __isl_give pet_expr *access_add_ref_id(__isl_take pet_expr *expr,
1435 void *user)
1437 isl_ctx *ctx;
1438 char name[50];
1439 int *n_ref = user;
1441 expr = pet_expr_cow(expr);
1442 if (!expr)
1443 return expr;
1444 if (expr->type != pet_expr_access)
1445 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1446 "not an access expression", return pet_expr_free(expr));
1448 ctx = isl_map_get_ctx(expr->acc.access);
1449 snprintf(name, sizeof(name), "__pet_ref_%d", (*n_ref)++);
1450 expr->acc.ref_id = isl_id_alloc(ctx, name, NULL);
1451 if (!expr->acc.ref_id)
1452 return pet_expr_free(expr);
1454 return expr;
1457 __isl_give pet_expr *pet_expr_add_ref_ids(__isl_take pet_expr *expr, int *n_ref)
1459 return pet_expr_map_access(expr, &access_add_ref_id, n_ref);
1462 /* Reset the user pointer on all parameter and tuple ids in
1463 * the access relation and the index expressions
1464 * of the access expression "expr".
1466 static __isl_give pet_expr *access_anonymize(__isl_take pet_expr *expr,
1467 void *user)
1469 expr = pet_expr_cow(expr);
1470 if (!expr)
1471 return expr;
1472 if (expr->type != pet_expr_access)
1473 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1474 "not an access expression", return pet_expr_free(expr));
1476 expr->acc.access = isl_map_reset_user(expr->acc.access);
1477 expr->acc.index = isl_multi_pw_aff_reset_user(expr->acc.index);
1478 if (!expr->acc.access || !expr->acc.index)
1479 return pet_expr_free(expr);
1481 return expr;
1484 __isl_give pet_expr *pet_expr_anonymize(__isl_take pet_expr *expr)
1486 return pet_expr_map_access(expr, &access_anonymize, NULL);
1489 /* Data used in access_gist() callback.
1491 struct pet_access_gist_data {
1492 isl_set *domain;
1493 isl_union_map *value_bounds;
1496 /* Given an expression "expr" of type pet_expr_access, compute
1497 * the gist of the associated access relation and index expression
1498 * with respect to data->domain and the bounds on the values of the arguments
1499 * of the expression.
1501 static __isl_give pet_expr *access_gist(__isl_take pet_expr *expr, void *user)
1503 struct pet_access_gist_data *data = user;
1504 isl_set *domain;
1506 expr = pet_expr_cow(expr);
1507 if (!expr)
1508 return expr;
1509 if (expr->type != pet_expr_access)
1510 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1511 "not an access expression", return pet_expr_free(expr));
1513 domain = isl_set_copy(data->domain);
1514 if (expr->n_arg > 0)
1515 domain = pet_value_bounds_apply(domain, expr->n_arg, expr->args,
1516 data->value_bounds);
1518 expr->acc.access = isl_map_gist_domain(expr->acc.access,
1519 isl_set_copy(domain));
1520 expr->acc.index = isl_multi_pw_aff_gist(expr->acc.index, domain);
1521 if (!expr->acc.access || !expr->acc.index)
1522 return pet_expr_free(expr);
1524 return expr;
1527 __isl_give pet_expr *pet_expr_gist(__isl_take pet_expr *expr,
1528 __isl_keep isl_set *context, __isl_keep isl_union_map *value_bounds)
1530 struct pet_access_gist_data data = { context, value_bounds };
1532 return pet_expr_map_access(expr, &access_gist, &data);
1535 /* Mark "expr" as a read dependening on "read".
1537 __isl_give pet_expr *pet_expr_access_set_read(__isl_take pet_expr *expr,
1538 int read)
1540 if (!expr)
1541 return pet_expr_free(expr);
1542 if (expr->type != pet_expr_access)
1543 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1544 "not an access expression", return pet_expr_free(expr));
1545 if (expr->acc.read == read)
1546 return expr;
1547 expr = pet_expr_cow(expr);
1548 if (!expr)
1549 return NULL;
1550 expr->acc.read = read;
1552 return expr;
1555 /* Mark "expr" as a write dependening on "write".
1557 __isl_give pet_expr *pet_expr_access_set_write(__isl_take pet_expr *expr,
1558 int write)
1560 if (!expr)
1561 return pet_expr_free(expr);
1562 if (expr->type != pet_expr_access)
1563 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1564 "not an access expression", return pet_expr_free(expr));
1565 if (expr->acc.write == write)
1566 return expr;
1567 expr = pet_expr_cow(expr);
1568 if (!expr)
1569 return NULL;
1570 expr->acc.write = write;
1572 return expr;
1575 /* Replace the access relation of "expr" by "access".
1577 __isl_give pet_expr *pet_expr_access_set_access(__isl_take pet_expr *expr,
1578 __isl_take isl_map *access)
1580 expr = pet_expr_cow(expr);
1581 if (!expr || !access)
1582 goto error;
1583 if (expr->type != pet_expr_access)
1584 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1585 "not an access expression", goto error);
1586 isl_map_free(expr->acc.access);
1587 expr->acc.access = access;
1589 return expr;
1590 error:
1591 isl_map_free(access);
1592 pet_expr_free(expr);
1593 return NULL;
1596 /* Replace the index expression of "expr" by "index".
1598 __isl_give pet_expr *pet_expr_access_set_index(__isl_take pet_expr *expr,
1599 __isl_take isl_multi_pw_aff *index)
1601 expr = pet_expr_cow(expr);
1602 if (!expr || !index)
1603 goto error;
1604 if (expr->type != pet_expr_access)
1605 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1606 "not an access expression", goto error);
1607 isl_multi_pw_aff_free(expr->acc.index);
1608 expr->acc.index = index;
1610 return expr;
1611 error:
1612 isl_multi_pw_aff_free(index);
1613 pet_expr_free(expr);
1614 return NULL;
1617 /* Return the reference identifier of access expression "expr".
1619 __isl_give isl_id *pet_expr_access_get_ref_id(__isl_keep pet_expr *expr)
1621 if (!expr)
1622 return NULL;
1623 if (expr->type != pet_expr_access)
1624 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1625 "not an access expression", return NULL);
1627 return isl_id_copy(expr->acc.ref_id);
1630 /* Replace the reference identifier of access expression "expr" by "ref_id".
1632 __isl_give pet_expr *pet_expr_access_set_ref_id(__isl_take pet_expr *expr,
1633 __isl_take isl_id *ref_id)
1635 expr = pet_expr_cow(expr);
1636 if (!expr || !ref_id)
1637 goto error;
1638 if (expr->type != pet_expr_access)
1639 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1640 "not an access expression", goto error);
1641 isl_id_free(expr->acc.ref_id);
1642 expr->acc.ref_id = ref_id;
1644 return expr;
1645 error:
1646 isl_id_free(ref_id);
1647 pet_expr_free(expr);
1648 return NULL;
1651 /* Tag the access relation "access" with "id".
1652 * That is, insert the id as the range of a wrapped relation
1653 * in the domain of "access".
1655 * If "access" is of the form
1657 * D[i] -> A[a]
1659 * then the result is of the form
1661 * [D[i] -> id[]] -> A[a]
1663 __isl_give isl_map *pet_expr_tag_access(__isl_keep pet_expr *expr,
1664 __isl_take isl_map *access)
1666 isl_space *space;
1667 isl_map *add_tag;
1668 isl_id *id;
1670 if (expr->type != pet_expr_access)
1671 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1672 "not an access expression",
1673 return isl_map_free(access));
1675 id = isl_id_copy(expr->acc.ref_id);
1676 space = isl_space_range(isl_map_get_space(access));
1677 space = isl_space_from_range(space);
1678 space = isl_space_set_tuple_id(space, isl_dim_in, id);
1679 add_tag = isl_map_universe(space);
1680 access = isl_map_domain_product(access, add_tag);
1682 return access;
1685 /* Return the relation mapping pairs of domain iterations and argument
1686 * values to the corresponding accessed data elements.
1688 __isl_give isl_map *pet_expr_access_get_dependent_access(
1689 __isl_keep pet_expr *expr)
1691 if (!expr)
1692 return NULL;
1693 if (expr->type != pet_expr_access)
1694 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1695 "not an access expression", return NULL);
1697 return isl_map_copy(expr->acc.access);
1700 /* Return the relation mapping domain iterations to all possibly
1701 * accessed data elements.
1702 * In particular, take the access relation and project out the values
1703 * of the arguments, if any.
1705 __isl_give isl_map *pet_expr_access_get_may_access(__isl_keep pet_expr *expr)
1707 isl_map *access;
1708 isl_space *space;
1709 isl_map *map;
1711 if (!expr)
1712 return NULL;
1713 if (expr->type != pet_expr_access)
1714 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1715 "not an access expression", return NULL);
1717 access = pet_expr_access_get_dependent_access(expr);
1718 if (expr->n_arg == 0)
1719 return access;
1721 space = isl_space_domain(isl_map_get_space(access));
1722 map = isl_map_universe(isl_space_unwrap(space));
1723 map = isl_map_domain_map(map);
1724 access = isl_map_apply_domain(access, map);
1726 return access;
1729 /* Return a relation mapping domain iterations to definitely
1730 * accessed data elements, assuming the statement containing
1731 * the expression is executed.
1733 * If there are no arguments, then all elements are accessed.
1734 * Otherwise, we conservatively return an empty relation.
1736 __isl_give isl_map *pet_expr_access_get_must_access(__isl_keep pet_expr *expr)
1738 isl_space *space;
1740 if (!expr)
1741 return NULL;
1742 if (expr->type != pet_expr_access)
1743 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1744 "not an access expression", return NULL);
1746 if (expr->n_arg == 0)
1747 return pet_expr_access_get_dependent_access(expr);
1749 space = isl_map_get_space(expr->acc.access);
1750 space = isl_space_domain_factor_domain(space);
1752 return isl_map_empty(space);
1755 /* Return the relation mapping domain iterations to all possibly
1756 * accessed data elements, with its domain tagged with the reference
1757 * identifier.
1759 __isl_give isl_map *pet_expr_access_get_tagged_may_access(
1760 __isl_keep pet_expr *expr)
1762 isl_map *access;
1764 if (!expr)
1765 return NULL;
1767 access = pet_expr_access_get_may_access(expr);
1768 access = pet_expr_tag_access(expr, access);
1770 return access;
1773 /* Return the operation type of operation expression "expr".
1775 enum pet_op_type pet_expr_op_get_type(__isl_keep pet_expr *expr)
1777 if (!expr)
1778 return pet_op_last;
1779 if (expr->type != pet_expr_op)
1780 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1781 "not an operation expression", return pet_op_last);
1783 return expr->op;
1786 /* Replace the operation type of operation expression "expr" by "type".
1788 __isl_give pet_expr *pet_expr_op_set_type(__isl_take pet_expr *expr,
1789 enum pet_op_type type)
1791 if (!expr)
1792 return pet_expr_free(expr);
1793 if (expr->type != pet_expr_op)
1794 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1795 "not an operation expression",
1796 return pet_expr_free(expr));
1797 if (expr->op == type)
1798 return expr;
1799 expr = pet_expr_cow(expr);
1800 if (!expr)
1801 return NULL;
1802 expr->op = type;
1804 return expr;
1807 /* Return the name of the function called by "expr".
1809 __isl_keep const char *pet_expr_call_get_name(__isl_keep pet_expr *expr)
1811 if (!expr)
1812 return NULL;
1813 if (expr->type != pet_expr_call)
1814 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1815 "not a call expression", return NULL);
1816 return expr->name;
1819 /* Replace the name of the function called by "expr" by "name".
1821 __isl_give pet_expr *pet_expr_call_set_name(__isl_take pet_expr *expr,
1822 __isl_keep const char *name)
1824 expr = pet_expr_cow(expr);
1825 if (!expr || !name)
1826 return pet_expr_free(expr);
1827 if (expr->type != pet_expr_call)
1828 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1829 "not a call expression", return pet_expr_free(expr));
1830 free(expr->name);
1831 expr->name = strdup(name);
1832 if (!expr->name)
1833 return pet_expr_free(expr);
1834 return expr;
1837 /* Replace the type of the cast performed by "expr" by "name".
1839 __isl_give pet_expr *pet_expr_cast_set_type_name(__isl_take pet_expr *expr,
1840 __isl_keep const char *name)
1842 expr = pet_expr_cow(expr);
1843 if (!expr || !name)
1844 return pet_expr_free(expr);
1845 if (expr->type != pet_expr_cast)
1846 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1847 "not a cast expression", return pet_expr_free(expr));
1848 free(expr->type_name);
1849 expr->type_name = strdup(name);
1850 if (!expr->type_name)
1851 return pet_expr_free(expr);
1852 return expr;
1855 /* Return the value of the integer represented by "expr".
1857 __isl_give isl_val *pet_expr_int_get_val(__isl_keep pet_expr *expr)
1859 if (!expr)
1860 return NULL;
1861 if (expr->type != pet_expr_int)
1862 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1863 "not an int expression", return NULL);
1865 return isl_val_copy(expr->i);
1868 /* Replace the value of the integer represented by "expr" by "v".
1870 __isl_give pet_expr *pet_expr_int_set_val(__isl_take pet_expr *expr,
1871 __isl_take isl_val *v)
1873 expr = pet_expr_cow(expr);
1874 if (!expr || !v)
1875 goto error;
1876 if (expr->type != pet_expr_int)
1877 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1878 "not an int expression", goto error);
1879 isl_val_free(expr->i);
1880 expr->i = v;
1882 return expr;
1883 error:
1884 isl_val_free(v);
1885 pet_expr_free(expr);
1886 return NULL;
1889 /* Replace the value and string representation of the double
1890 * represented by "expr" by "d" and "s".
1892 __isl_give pet_expr *pet_expr_double_set(__isl_take pet_expr *expr,
1893 double d, __isl_keep const char *s)
1895 expr = pet_expr_cow(expr);
1896 if (!expr || !s)
1897 return pet_expr_free(expr);
1898 if (expr->type != pet_expr_double)
1899 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1900 "not a double expression", return pet_expr_free(expr));
1901 expr->d.val = d;
1902 free(expr->d.s);
1903 expr->d.s = strdup(s);
1904 if (!expr->d.s)
1905 return pet_expr_free(expr);
1906 return expr;
1909 /* Return a string representation of the double expression "expr".
1911 __isl_give char *pet_expr_double_get_str(__isl_keep pet_expr *expr)
1913 if (!expr)
1914 return NULL;
1915 if (expr->type != pet_expr_double)
1916 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1917 "not a double expression", return NULL);
1918 return strdup(expr->d.s);
1921 /* Return the number of bits needed to represent the type of "expr".
1922 * See the description of the type_size field of pet_expr.
1924 int pet_expr_get_type_size(__isl_keep pet_expr *expr)
1926 return expr ? expr->type_size : 0;
1929 /* Replace the number of bits needed to represent the type of "expr"
1930 * by "type_size".
1931 * See the description of the type_size field of pet_expr.
1933 __isl_give pet_expr *pet_expr_set_type_size(__isl_take pet_expr *expr,
1934 int type_size)
1936 expr = pet_expr_cow(expr);
1937 if (!expr)
1938 return NULL;
1940 expr->type_size = type_size;
1942 return expr;
1945 void pet_expr_dump_with_indent(__isl_keep pet_expr *expr, int indent)
1947 int i;
1949 if (!expr)
1950 return;
1952 fprintf(stderr, "%*s", indent, "");
1954 switch (expr->type) {
1955 case pet_expr_double:
1956 fprintf(stderr, "%s\n", expr->d.s);
1957 break;
1958 case pet_expr_int:
1959 isl_val_dump(expr->i);
1960 break;
1961 case pet_expr_access:
1962 if (expr->acc.ref_id) {
1963 isl_id_dump(expr->acc.ref_id);
1964 fprintf(stderr, "%*s", indent, "");
1966 isl_map_dump(expr->acc.access);
1967 fprintf(stderr, "%*s", indent, "");
1968 isl_multi_pw_aff_dump(expr->acc.index);
1969 fprintf(stderr, "%*sread: %d\n", indent + 2,
1970 "", expr->acc.read);
1971 fprintf(stderr, "%*swrite: %d\n", indent + 2,
1972 "", expr->acc.write);
1973 for (i = 0; i < expr->n_arg; ++i)
1974 pet_expr_dump_with_indent(expr->args[i], indent + 2);
1975 break;
1976 case pet_expr_op:
1977 fprintf(stderr, "%s\n", op_str[expr->op]);
1978 for (i = 0; i < expr->n_arg; ++i)
1979 pet_expr_dump_with_indent(expr->args[i], indent + 2);
1980 break;
1981 case pet_expr_call:
1982 fprintf(stderr, "%s/%d\n", expr->name, expr->n_arg);
1983 for (i = 0; i < expr->n_arg; ++i)
1984 pet_expr_dump_with_indent(expr->args[i], indent + 2);
1985 break;
1986 case pet_expr_cast:
1987 fprintf(stderr, "(%s)\n", expr->type_name);
1988 for (i = 0; i < expr->n_arg; ++i)
1989 pet_expr_dump_with_indent(expr->args[i], indent + 2);
1990 break;
1991 case pet_expr_error:
1992 fprintf(stderr, "ERROR\n");
1993 break;
1997 void pet_expr_dump(__isl_keep pet_expr *expr)
1999 pet_expr_dump_with_indent(expr, 0);