make pet_expr objects reference counted
[pet.git] / expr.c
blob296fd4da90ac70d9dae9e74fb06e627c7fb19a10
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 an index expression and
213 * the depth of the accessed array.
214 * By default, the access is considered to be a read access.
216 * If the number of indices is smaller than the depth of the array,
217 * then we assume that all elements of the remaining dimensions
218 * are accessed.
220 __isl_give pet_expr *pet_expr_from_index_and_depth(
221 __isl_take isl_multi_pw_aff *index, int depth)
223 isl_map *access;
224 int dim;
226 access = isl_map_from_multi_pw_aff(isl_multi_pw_aff_copy(index));
227 if (!access)
228 goto error;
229 dim = isl_map_dim(access, isl_dim_out);
230 if (dim > depth)
231 isl_die(isl_map_get_ctx(access), isl_error_internal,
232 "number of indices greater than depth",
233 access = isl_map_free(access));
234 if (dim == depth)
235 return pet_expr_from_access_and_index(access, index);
237 access = extend_range(access, depth - dim);
239 return pet_expr_from_access_and_index(access, index);
240 error:
241 isl_multi_pw_aff_free(index);
242 return NULL;
245 /* Construct a pet_expr that kills the elements specified by
246 * the index expression "index" and the access relation "access".
248 __isl_give pet_expr *pet_expr_kill_from_access_and_index(
249 __isl_take isl_map *access, __isl_take isl_multi_pw_aff *index)
251 pet_expr *expr;
253 if (!access || !index)
254 goto error;
256 expr = pet_expr_from_access_and_index(access, index);
257 expr = pet_expr_access_set_read(expr, 0);
258 return pet_expr_new_unary(pet_op_kill, expr);
259 error:
260 isl_map_free(access);
261 isl_multi_pw_aff_free(index);
262 return NULL;
265 /* Construct a unary pet_expr that performs "op" on "arg".
267 __isl_give pet_expr *pet_expr_new_unary(enum pet_op_type op,
268 __isl_take pet_expr *arg)
270 isl_ctx *ctx;
271 pet_expr *expr;
273 if (!arg)
274 return NULL;
275 ctx = pet_expr_get_ctx(arg);
276 expr = pet_expr_alloc(ctx, pet_expr_op);
277 expr = pet_expr_set_n_arg(expr, 1);
278 if (!expr)
279 goto error;
281 expr->op = op;
282 expr->args[pet_un_arg] = arg;
284 return expr;
285 error:
286 pet_expr_free(arg);
287 return NULL;
290 /* Construct a binary pet_expr that performs "op" on "lhs" and "rhs".
292 __isl_give pet_expr *pet_expr_new_binary(enum pet_op_type op,
293 __isl_take pet_expr *lhs, __isl_take pet_expr *rhs)
295 isl_ctx *ctx;
296 pet_expr *expr;
298 if (!lhs || !rhs)
299 goto error;
300 ctx = pet_expr_get_ctx(lhs);
301 expr = pet_expr_alloc(ctx, pet_expr_op);
302 expr = pet_expr_set_n_arg(expr, 2);
303 if (!expr)
304 goto error;
306 expr->op = op;
307 expr->args[pet_bin_lhs] = lhs;
308 expr->args[pet_bin_rhs] = rhs;
310 return expr;
311 error:
312 pet_expr_free(lhs);
313 pet_expr_free(rhs);
314 return NULL;
317 /* Construct a ternary pet_expr that performs "cond" ? "lhs" : "rhs".
319 __isl_give pet_expr *pet_expr_new_ternary(__isl_take pet_expr *cond,
320 __isl_take pet_expr *lhs, __isl_take pet_expr *rhs)
322 isl_ctx *ctx;
323 pet_expr *expr;
325 if (!cond || !lhs || !rhs)
326 goto error;
327 ctx = pet_expr_get_ctx(cond);
328 expr = pet_expr_alloc(ctx, pet_expr_op);
329 expr = pet_expr_set_n_arg(expr, 3);
330 if (!expr)
331 goto error;
333 expr->op = pet_op_cond;
334 expr->args[pet_ter_cond] = cond;
335 expr->args[pet_ter_true] = lhs;
336 expr->args[pet_ter_false] = rhs;
338 return expr;
339 error:
340 pet_expr_free(cond);
341 pet_expr_free(lhs);
342 pet_expr_free(rhs);
343 return NULL;
346 /* Construct a call pet_expr that calls function "name" with "n_arg"
347 * arguments. The caller is responsible for filling in the arguments.
349 __isl_give pet_expr *pet_expr_new_call(isl_ctx *ctx, const char *name,
350 unsigned n_arg)
352 pet_expr *expr;
354 expr = pet_expr_alloc(ctx, pet_expr_call);
355 expr = pet_expr_set_n_arg(expr, n_arg);
356 if (!expr)
357 return NULL;
359 expr->name = strdup(name);
360 if (!expr->name)
361 return pet_expr_free(expr);
363 return expr;
366 /* Construct a pet_expr that represents the cast of "arg" to "type_name".
368 __isl_give pet_expr *pet_expr_new_cast(const char *type_name,
369 __isl_take pet_expr *arg)
371 isl_ctx *ctx;
372 pet_expr *expr;
374 if (!arg)
375 return NULL;
377 ctx = pet_expr_get_ctx(arg);
378 expr = pet_expr_alloc(ctx, pet_expr_cast);
379 expr = pet_expr_set_n_arg(expr, 1);
380 if (!expr)
381 goto error;
383 expr->type_name = strdup(type_name);
384 if (!expr->type_name)
385 goto error;
387 expr->args[0] = arg;
389 return expr;
390 error:
391 pet_expr_free(arg);
392 pet_expr_free(expr);
393 return NULL;
396 /* Construct a pet_expr that represents the double "d".
398 __isl_give pet_expr *pet_expr_new_double(isl_ctx *ctx,
399 double val, const char *s)
401 pet_expr *expr;
403 expr = pet_expr_alloc(ctx, pet_expr_double);
404 if (!expr)
405 return NULL;
407 expr->d.val = val;
408 expr->d.s = strdup(s);
409 if (!expr->d.s)
410 return pet_expr_free(expr);
412 return expr;
415 /* Construct a pet_expr that represents the integer value "v".
417 __isl_give pet_expr *pet_expr_new_int(__isl_take isl_val *v)
419 isl_ctx *ctx;
420 pet_expr *expr;
422 if (!v)
423 return NULL;
425 ctx = isl_val_get_ctx(v);
426 expr = pet_expr_alloc(ctx, pet_expr_int);
427 if (!expr)
428 goto error;
430 expr->i = v;
432 return expr;
433 error:
434 isl_val_free(v);
435 return NULL;
438 static __isl_give pet_expr *pet_expr_dup(__isl_keep pet_expr *expr)
440 int i;
441 pet_expr *dup;
443 if (!expr)
444 return NULL;
446 dup = pet_expr_alloc(expr->ctx, expr->type);
447 dup = pet_expr_set_n_arg(dup, expr->n_arg);
448 for (i = 0; i < expr->n_arg; ++i)
449 dup = pet_expr_set_arg(dup, i, pet_expr_copy(expr->args[i]));
451 switch (expr->type) {
452 case pet_expr_access:
453 if (expr->acc.ref_id)
454 dup = pet_expr_access_set_ref_id(dup,
455 isl_id_copy(expr->acc.ref_id));
456 dup = pet_expr_access_set_access(dup,
457 isl_map_copy(expr->acc.access));
458 dup = pet_expr_access_set_index(dup,
459 isl_multi_pw_aff_copy(expr->acc.index));
460 dup = pet_expr_access_set_read(dup, expr->acc.read);
461 dup = pet_expr_access_set_write(dup, expr->acc.write);
462 break;
463 case pet_expr_call:
464 dup = pet_expr_call_set_name(dup, expr->name);
465 break;
466 case pet_expr_cast:
467 dup = pet_expr_cast_set_type_name(dup, expr->type_name);
468 break;
469 case pet_expr_double:
470 dup = pet_expr_double_set(dup, expr->d.val, expr->d.s);
471 break;
472 case pet_expr_int:
473 dup = pet_expr_int_set_val(dup, isl_val_copy(expr->i));
474 break;
475 case pet_expr_op:
476 dup = pet_expr_op_set_type(dup, expr->op);
477 break;
478 case pet_expr_error:
479 dup = pet_expr_free(dup);
480 break;
483 return dup;
486 __isl_give pet_expr *pet_expr_cow(__isl_take pet_expr *expr)
488 if (!expr)
489 return NULL;
491 if (expr->ref == 1)
492 return expr;
493 expr->ref--;
494 return pet_expr_dup(expr);
497 __isl_null pet_expr *pet_expr_free(__isl_take pet_expr *expr)
499 int i;
501 if (!expr)
502 return NULL;
503 if (--expr->ref > 0)
504 return NULL;
506 for (i = 0; i < expr->n_arg; ++i)
507 pet_expr_free(expr->args[i]);
508 free(expr->args);
510 switch (expr->type) {
511 case pet_expr_access:
512 isl_id_free(expr->acc.ref_id);
513 isl_map_free(expr->acc.access);
514 isl_multi_pw_aff_free(expr->acc.index);
515 break;
516 case pet_expr_call:
517 free(expr->name);
518 break;
519 case pet_expr_cast:
520 free(expr->type_name);
521 break;
522 case pet_expr_double:
523 free(expr->d.s);
524 break;
525 case pet_expr_int:
526 isl_val_free(expr->i);
527 break;
528 case pet_expr_op:
529 case pet_expr_error:
530 break;
533 isl_ctx_deref(expr->ctx);
534 free(expr);
535 return NULL;
538 /* Return an additional reference to "expr".
540 __isl_give pet_expr *pet_expr_copy(__isl_keep pet_expr *expr)
542 if (!expr)
543 return NULL;
545 expr->ref++;
546 return expr;
549 /* Return the isl_ctx in which "expr" was created.
551 isl_ctx *pet_expr_get_ctx(__isl_keep pet_expr *expr)
553 return expr ? expr->ctx : NULL;
556 /* Return the type of "expr".
558 enum pet_expr_type pet_expr_get_type(__isl_keep pet_expr *expr)
560 if (!expr)
561 return pet_expr_error;
562 return expr->type;
565 /* Return the number of arguments of "expr".
567 int pet_expr_get_n_arg(__isl_keep pet_expr *expr)
569 if (!expr)
570 return -1;
572 return expr->n_arg;
575 /* Set the number of arguments of "expr" to "n".
577 * If "expr" originally had more arguments, then remove the extra arguments.
578 * If "expr" originally had fewer arguments, then create space for
579 * the extra arguments ans initialize them to NULL.
581 __isl_give pet_expr *pet_expr_set_n_arg(__isl_take pet_expr *expr, int n)
583 int i;
584 pet_expr **args;
586 if (!expr)
587 return NULL;
588 if (expr->n_arg == n)
589 return expr;
590 expr = pet_expr_cow(expr);
591 if (!expr)
592 return NULL;
594 if (n < expr->n_arg) {
595 for (i = n; i < expr->n_arg; ++i)
596 pet_expr_free(expr->args[i]);
597 expr->n_arg = n;
598 return expr;
601 args = isl_realloc_array(expr->ctx, expr->args, pet_expr *, n);
602 if (!args)
603 return pet_expr_free(expr);
604 expr->args = args;
605 for (i = expr->n_arg; i < n; ++i)
606 expr->args[i] = NULL;
607 expr->n_arg = n;
609 return expr;
612 /* Return the argument of "expr" at position "pos".
614 __isl_give pet_expr *pet_expr_get_arg(__isl_keep pet_expr *expr, int pos)
616 if (!expr)
617 return NULL;
618 if (pos < 0 || pos >= expr->n_arg)
619 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
620 "position out of bounds", return NULL);
622 return pet_expr_copy(expr->args[pos]);
625 /* Replace the argument of "expr" at position "pos" by "arg".
627 __isl_give pet_expr *pet_expr_set_arg(__isl_take pet_expr *expr, int pos,
628 __isl_take pet_expr *arg)
630 if (!expr || !arg)
631 goto error;
632 if (pos < 0 || pos >= expr->n_arg)
633 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
634 "position out of bounds", goto error);
635 if (expr->args[pos] == arg) {
636 pet_expr_free(arg);
637 return expr;
640 expr = pet_expr_cow(expr);
641 if (!expr)
642 goto error;
644 pet_expr_free(expr->args[pos]);
645 expr->args[pos] = arg;
647 return expr;
648 error:
649 pet_expr_free(expr);
650 pet_expr_free(arg);
651 return NULL;
654 /* Does "expr" represent an access to an unnamed space, i.e.,
655 * does it represent an affine expression?
657 int pet_expr_is_affine(__isl_keep pet_expr *expr)
659 int has_id;
661 if (!expr)
662 return -1;
663 if (expr->type != pet_expr_access)
664 return 0;
666 has_id = isl_map_has_tuple_id(expr->acc.access, isl_dim_out);
667 if (has_id < 0)
668 return -1;
670 return !has_id;
673 /* Does "expr" represent an access to a scalar, i.e., zero-dimensional array?
675 int pet_expr_is_scalar_access(__isl_keep pet_expr *expr)
677 if (!expr)
678 return -1;
679 if (expr->type != pet_expr_access)
680 return 0;
682 return isl_map_dim(expr->acc.access, isl_dim_out) == 0;
685 /* Return 1 if the two pet_exprs are equivalent.
687 int pet_expr_is_equal(__isl_keep pet_expr *expr1, __isl_keep pet_expr *expr2)
689 int i;
691 if (!expr1 || !expr2)
692 return 0;
694 if (expr1->type != expr2->type)
695 return 0;
696 if (expr1->n_arg != expr2->n_arg)
697 return 0;
698 for (i = 0; i < expr1->n_arg; ++i)
699 if (!pet_expr_is_equal(expr1->args[i], expr2->args[i]))
700 return 0;
701 switch (expr1->type) {
702 case pet_expr_error:
703 return -1;
704 case pet_expr_double:
705 if (strcmp(expr1->d.s, expr2->d.s))
706 return 0;
707 if (expr1->d.val != expr2->d.val)
708 return 0;
709 break;
710 case pet_expr_int:
711 if (!isl_val_eq(expr1->i, expr2->i))
712 return 0;
713 break;
714 case pet_expr_access:
715 if (expr1->acc.read != expr2->acc.read)
716 return 0;
717 if (expr1->acc.write != expr2->acc.write)
718 return 0;
719 if (expr1->acc.ref_id != expr2->acc.ref_id)
720 return 0;
721 if (!expr1->acc.access || !expr2->acc.access)
722 return 0;
723 if (!isl_map_is_equal(expr1->acc.access, expr2->acc.access))
724 return 0;
725 if (!expr1->acc.index || !expr2->acc.index)
726 return 0;
727 if (!isl_multi_pw_aff_plain_is_equal(expr1->acc.index,
728 expr2->acc.index))
729 return 0;
730 break;
731 case pet_expr_op:
732 if (expr1->op != expr2->op)
733 return 0;
734 break;
735 case pet_expr_call:
736 if (strcmp(expr1->name, expr2->name))
737 return 0;
738 break;
739 case pet_expr_cast:
740 if (strcmp(expr1->type_name, expr2->type_name))
741 return 0;
742 break;
745 return 1;
748 /* Does the access expression "expr" read the accessed elements?
750 int pet_expr_access_is_read(__isl_keep pet_expr *expr)
752 if (!expr)
753 return -1;
754 if (expr->type != pet_expr_access)
755 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
756 "not an access expression", return -1);
758 return expr->acc.read;
761 /* Does the access expression "expr" write to the accessed elements?
763 int pet_expr_access_is_write(__isl_keep pet_expr *expr)
765 if (!expr)
766 return -1;
767 if (expr->type != pet_expr_access)
768 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
769 "not an access expression", return -1);
771 return expr->acc.write;
774 /* Return the identifier of the array accessed by "expr".
776 * If "expr" represents a member access, then return the identifier
777 * of the outer structure array.
779 __isl_give isl_id *pet_expr_access_get_id(__isl_keep pet_expr *expr)
781 if (!expr)
782 return NULL;
783 if (expr->type != pet_expr_access)
784 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
785 "not an access expression", return NULL);
787 if (isl_map_range_is_wrapping(expr->acc.access)) {
788 isl_space *space;
789 isl_id *id;
791 space = isl_map_get_space(expr->acc.access);
792 space = isl_space_range(space);
793 while (space && isl_space_is_wrapping(space))
794 space = isl_space_domain(isl_space_unwrap(space));
795 id = isl_space_get_tuple_id(space, isl_dim_set);
796 isl_space_free(space);
798 return id;
801 return isl_map_get_tuple_id(expr->acc.access, isl_dim_out);
804 /* Return the parameter space of "expr".
806 __isl_give isl_space *pet_expr_access_get_parameter_space(
807 __isl_keep pet_expr *expr)
809 isl_space *space;
811 if (!expr)
812 return NULL;
813 if (expr->type != pet_expr_access)
814 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
815 "not an access expression", return NULL);
817 space = isl_multi_pw_aff_get_space(expr->acc.index);
818 space = isl_space_params(space);
820 return space;
823 /* Return the space of the data accessed by "expr".
825 __isl_give isl_space *pet_expr_access_get_data_space(__isl_keep pet_expr *expr)
827 isl_space *space;
829 if (!expr)
830 return NULL;
831 if (expr->type != pet_expr_access)
832 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
833 "not an access expression", return NULL);
835 space = isl_multi_pw_aff_get_space(expr->acc.index);
836 space = isl_space_range(space);
838 return space;
841 /* Modify all expressions of type pet_expr_access in "expr"
842 * by calling "fn" on them.
844 __isl_give pet_expr *pet_expr_map_access(__isl_take pet_expr *expr,
845 __isl_give pet_expr *(*fn)(__isl_take pet_expr *expr, void *user),
846 void *user)
848 int i, n;
850 n = pet_expr_get_n_arg(expr);
851 for (i = 0; i < n; ++i) {
852 pet_expr *arg = pet_expr_get_arg(expr, i);
853 arg = pet_expr_map_access(arg, fn, user);
854 expr = pet_expr_set_arg(expr, i, arg);
857 if (!expr)
858 return NULL;
860 if (expr->type == pet_expr_access)
861 expr = fn(expr, user);
863 return expr;
866 /* Call "fn" on each of the subexpressions of "expr" of type "type".
868 * Return -1 on error (where fn returning a negative value is treated as
869 * an error).
870 * Otherwise return 0.
872 int pet_expr_foreach_expr_of_type(__isl_keep pet_expr *expr,
873 enum pet_expr_type type,
874 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
876 int i;
878 if (!expr)
879 return -1;
881 for (i = 0; i < expr->n_arg; ++i)
882 if (pet_expr_foreach_expr_of_type(expr->args[i],
883 type, fn, user) < 0)
884 return -1;
886 if (expr->type == type)
887 return fn(expr, user);
889 return 0;
892 /* Call "fn" on each of the subexpressions of "expr" of type pet_expr_access.
894 * Return -1 on error (where fn returning a negative value is treated as
895 * an error).
896 * Otherwise return 0.
898 int pet_expr_foreach_access_expr(__isl_keep pet_expr *expr,
899 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
901 return pet_expr_foreach_expr_of_type(expr, pet_expr_access, fn, user);
904 /* Call "fn" on each of the subexpressions of "expr" of type pet_expr_call.
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_call_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_call, fn, user);
916 /* Internal data structure for pet_expr_writes.
917 * "id" is the identifier that we are looking for.
918 * "found" is set if we have found the identifier being written to.
920 struct pet_expr_writes_data {
921 isl_id *id;
922 int found;
925 /* Given an access expression, check if it writes to data->id.
926 * If so, set data->found and abort the search.
928 static int writes(__isl_keep pet_expr *expr, void *user)
930 struct pet_expr_writes_data *data = user;
931 isl_id *write_id;
933 if (!expr->acc.write)
934 return 0;
935 if (pet_expr_is_affine(expr))
936 return 0;
938 write_id = pet_expr_access_get_id(expr);
939 isl_id_free(write_id);
941 if (!write_id)
942 return -1;
944 if (write_id != data->id)
945 return 0;
947 data->found = 1;
948 return -1;
951 /* Does expression "expr" write to "id"?
953 int pet_expr_writes(__isl_keep pet_expr *expr, __isl_keep isl_id *id)
955 struct pet_expr_writes_data data;
957 data.id = id;
958 data.found = 0;
959 if (pet_expr_foreach_access_expr(expr, &writes, &data) < 0 &&
960 !data.found)
961 return -1;
963 return data.found;
966 /* Move the "n" dimensions of "src_type" starting at "src_pos" of
967 * index expression and access relation of "expr"
968 * to dimensions of "dst_type" at "dst_pos".
970 __isl_give pet_expr *pet_expr_access_move_dims(__isl_take pet_expr *expr,
971 enum isl_dim_type dst_type, unsigned dst_pos,
972 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
974 expr = pet_expr_cow(expr);
975 if (!expr)
976 return NULL;
977 if (expr->type != pet_expr_access)
978 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
979 "not an access pet_expr", return pet_expr_free(expr));
981 expr->acc.access = isl_map_move_dims(expr->acc.access,
982 dst_type, dst_pos, src_type, src_pos, n);
983 expr->acc.index = isl_multi_pw_aff_move_dims(expr->acc.index,
984 dst_type, dst_pos, src_type, src_pos, n);
985 if (!expr->acc.access || !expr->acc.index)
986 return pet_expr_free(expr);
988 return expr;
991 /* Replace the index expression and access relation of "expr"
992 * by their preimages under the function represented by "ma".
994 __isl_give pet_expr *pet_expr_access_pullback_multi_aff(
995 __isl_take pet_expr *expr, __isl_take isl_multi_aff *ma)
997 expr = pet_expr_cow(expr);
998 if (!expr || !ma)
999 goto error;
1000 if (expr->type != pet_expr_access)
1001 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1002 "not an access pet_expr", goto error);
1004 expr->acc.access = isl_map_preimage_domain_multi_aff(expr->acc.access,
1005 isl_multi_aff_copy(ma));
1006 expr->acc.index = isl_multi_pw_aff_pullback_multi_aff(expr->acc.index,
1007 ma);
1008 if (!expr->acc.access || !expr->acc.index)
1009 return pet_expr_free(expr);
1011 return expr;
1012 error:
1013 isl_multi_aff_free(ma);
1014 pet_expr_free(expr);
1015 return NULL;
1018 /* Return the access relation of access expression "expr".
1020 __isl_give isl_map *pet_expr_access_get_access(__isl_keep pet_expr *expr)
1022 if (!expr)
1023 return NULL;
1024 if (expr->type != pet_expr_access)
1025 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1026 "not an access expression", return NULL);
1028 return isl_map_copy(expr->acc.access);
1031 /* Return the index expression of access expression "expr".
1033 __isl_give isl_multi_pw_aff *pet_expr_access_get_index(
1034 __isl_keep pet_expr *expr)
1036 if (!expr)
1037 return NULL;
1038 if (expr->type != pet_expr_access)
1039 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1040 "not an access expression", return NULL);
1042 return isl_multi_pw_aff_copy(expr->acc.index);
1045 /* Align the parameters of expr->acc.index and expr->acc.access.
1047 __isl_give pet_expr *pet_expr_access_align_params(__isl_take pet_expr *expr)
1049 expr = pet_expr_cow(expr);
1050 if (!expr)
1051 return NULL;
1052 if (expr->type != pet_expr_access)
1053 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1054 "not an access expression", return pet_expr_free(expr));
1056 expr->acc.access = isl_map_align_params(expr->acc.access,
1057 isl_multi_pw_aff_get_space(expr->acc.index));
1058 expr->acc.index = isl_multi_pw_aff_align_params(expr->acc.index,
1059 isl_map_get_space(expr->acc.access));
1060 if (!expr->acc.access || !expr->acc.index)
1061 return pet_expr_free(expr);
1063 return expr;
1066 /* Add extra conditions on the parameters to all access relations in "expr".
1068 * The conditions are not added to the index expression. Instead, they
1069 * are used to try and simplify the index expression.
1071 __isl_give pet_expr *pet_expr_restrict(__isl_take pet_expr *expr,
1072 __isl_take isl_set *cond)
1074 int i;
1076 expr = pet_expr_cow(expr);
1077 if (!expr)
1078 goto error;
1080 for (i = 0; i < expr->n_arg; ++i) {
1081 expr->args[i] = pet_expr_restrict(expr->args[i],
1082 isl_set_copy(cond));
1083 if (!expr->args[i])
1084 goto error;
1087 if (expr->type == pet_expr_access) {
1088 expr->acc.access = isl_map_intersect_params(expr->acc.access,
1089 isl_set_copy(cond));
1090 expr->acc.index = isl_multi_pw_aff_gist_params(
1091 expr->acc.index, isl_set_copy(cond));
1092 if (!expr->acc.access || !expr->acc.index)
1093 goto error;
1096 isl_set_free(cond);
1097 return expr;
1098 error:
1099 isl_set_free(cond);
1100 return pet_expr_free(expr);
1103 /* Modify the access relation and index expression
1104 * of the given access expression
1105 * based on the given iteration space transformation.
1106 * In particular, precompose the access relation and index expression
1107 * with the update function.
1109 * If the access has any arguments then the domain of the access relation
1110 * is a wrapped mapping from the iteration space to the space of
1111 * argument values. We only need to change the domain of this wrapped
1112 * mapping, so we extend the input transformation with an identity mapping
1113 * on the space of argument values.
1115 __isl_give pet_expr *pet_expr_access_update_domain(__isl_take pet_expr *expr,
1116 __isl_keep isl_multi_pw_aff *update)
1118 isl_space *space;
1120 expr = pet_expr_cow(expr);
1121 if (!expr)
1122 return NULL;
1123 if (expr->type != pet_expr_access)
1124 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1125 "not an access expression", return pet_expr_free(expr));
1127 update = isl_multi_pw_aff_copy(update);
1129 space = isl_map_get_space(expr->acc.access);
1130 space = isl_space_domain(space);
1131 if (!isl_space_is_wrapping(space))
1132 isl_space_free(space);
1133 else {
1134 isl_multi_pw_aff *id;
1135 space = isl_space_unwrap(space);
1136 space = isl_space_range(space);
1137 space = isl_space_map_from_set(space);
1138 id = isl_multi_pw_aff_identity(space);
1139 update = isl_multi_pw_aff_product(update, id);
1142 expr->acc.access = isl_map_preimage_domain_multi_pw_aff(
1143 expr->acc.access,
1144 isl_multi_pw_aff_copy(update));
1145 expr->acc.index = isl_multi_pw_aff_pullback_multi_pw_aff(
1146 expr->acc.index, update);
1147 if (!expr->acc.access || !expr->acc.index)
1148 return pet_expr_free(expr);
1150 return expr;
1153 static __isl_give pet_expr *update_domain(__isl_take pet_expr *expr, void *user)
1155 isl_multi_pw_aff *update = user;
1157 return pet_expr_access_update_domain(expr, update);
1160 /* Modify all access relations in "expr" by precomposing them with
1161 * the given iteration space transformation.
1163 __isl_give pet_expr *pet_expr_update_domain(__isl_take pet_expr *expr,
1164 __isl_take isl_multi_pw_aff *update)
1166 expr = pet_expr_map_access(expr, &update_domain, update);
1167 isl_multi_pw_aff_free(update);
1168 return expr;
1171 /* Add all parameters in "space" to the access relation and index expression
1172 * of "expr".
1174 static __isl_give pet_expr *align_params(__isl_take pet_expr *expr, void *user)
1176 isl_space *space = user;
1178 expr = pet_expr_cow(expr);
1179 if (!expr)
1180 return NULL;
1181 if (expr->type != pet_expr_access)
1182 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1183 "not an access expression", return pet_expr_free(expr));
1185 expr->acc.access = isl_map_align_params(expr->acc.access,
1186 isl_space_copy(space));
1187 expr->acc.index = isl_multi_pw_aff_align_params(expr->acc.index,
1188 isl_space_copy(space));
1189 if (!expr->acc.access || !expr->acc.index)
1190 return pet_expr_free(expr);
1192 return expr;
1195 /* Add all parameters in "space" to all access relations and index expressions
1196 * in "expr".
1198 __isl_give pet_expr *pet_expr_align_params(__isl_take pet_expr *expr,
1199 __isl_take isl_space *space)
1201 expr = pet_expr_map_access(expr, &align_params, space);
1202 isl_space_free(space);
1203 return expr;
1206 /* Insert an argument expression corresponding to "test" in front
1207 * of the list of arguments described by *n_arg and *args.
1209 static __isl_give pet_expr *insert_access_arg(__isl_take pet_expr *expr,
1210 __isl_keep isl_multi_pw_aff *test)
1212 int i;
1213 isl_ctx *ctx = isl_multi_pw_aff_get_ctx(test);
1215 if (!test)
1216 return pet_expr_free(expr);
1217 expr = pet_expr_cow(expr);
1218 if (!expr)
1219 return NULL;
1221 if (!expr->args) {
1222 expr->args = isl_calloc_array(ctx, pet_expr *, 1);
1223 if (!expr->args)
1224 return pet_expr_free(expr);
1225 } else {
1226 pet_expr **ext;
1227 ext = isl_calloc_array(ctx, pet_expr *, 1 + expr->n_arg);
1228 if (!ext)
1229 return pet_expr_free(expr);
1230 for (i = 0; i < expr->n_arg; ++i)
1231 ext[1 + i] = expr->args[i];
1232 free(expr->args);
1233 expr->args = ext;
1235 expr->n_arg++;
1236 expr->args[0] = pet_expr_from_index(isl_multi_pw_aff_copy(test));
1237 if (!expr->args[0])
1238 return pet_expr_free(expr);
1240 return expr;
1243 /* Make the expression "expr" depend on the value of "test"
1244 * being equal to "satisfied".
1246 * If "test" is an affine expression, we simply add the conditions
1247 * on the expression having the value "satisfied" to all access relations
1248 * and index expressions.
1250 * Otherwise, we add a filter to "expr" (which is then assumed to be
1251 * an access expression) corresponding to "test" being equal to "satisfied".
1253 __isl_give pet_expr *pet_expr_filter(__isl_take pet_expr *expr,
1254 __isl_take isl_multi_pw_aff *test, int satisfied)
1256 isl_id *id;
1257 isl_ctx *ctx;
1258 isl_space *space;
1259 isl_pw_multi_aff *pma;
1261 expr = pet_expr_cow(expr);
1262 if (!expr || !test)
1263 goto error;
1265 if (!isl_multi_pw_aff_has_tuple_id(test, isl_dim_out)) {
1266 isl_pw_aff *pa;
1267 isl_set *cond;
1269 pa = isl_multi_pw_aff_get_pw_aff(test, 0);
1270 isl_multi_pw_aff_free(test);
1271 if (satisfied)
1272 cond = isl_pw_aff_non_zero_set(pa);
1273 else
1274 cond = isl_pw_aff_zero_set(pa);
1275 return pet_expr_restrict(expr, isl_set_params(cond));
1278 ctx = isl_multi_pw_aff_get_ctx(test);
1279 if (expr->type != pet_expr_access)
1280 isl_die(ctx, isl_error_invalid,
1281 "can only filter access expressions", goto error);
1283 space = isl_space_domain(isl_map_get_space(expr->acc.access));
1284 id = isl_multi_pw_aff_get_tuple_id(test, isl_dim_out);
1285 pma = pet_filter_insert_pma(space, id, satisfied);
1287 expr->acc.access = isl_map_preimage_domain_pw_multi_aff(
1288 expr->acc.access,
1289 isl_pw_multi_aff_copy(pma));
1290 expr->acc.index = isl_multi_pw_aff_pullback_pw_multi_aff(
1291 expr->acc.index, pma);
1292 if (!expr->acc.access || !expr->acc.index)
1293 goto error;
1295 expr = insert_access_arg(expr, test);
1297 isl_multi_pw_aff_free(test);
1298 return expr;
1299 error:
1300 isl_multi_pw_aff_free(test);
1301 return pet_expr_free(expr);
1304 /* Check if the given index expression accesses a (0D) array that corresponds
1305 * to one of the parameters in "space". If so, replace the array access
1306 * by an access to the set of integers with as index (and value)
1307 * that parameter.
1309 static __isl_give isl_multi_pw_aff *index_detect_parameter(
1310 __isl_take isl_multi_pw_aff *index, __isl_take isl_space *space)
1312 isl_local_space *ls;
1313 isl_id *array_id = NULL;
1314 isl_aff *aff;
1315 int pos = -1;
1317 if (isl_multi_pw_aff_has_tuple_id(index, isl_dim_out)) {
1318 array_id = isl_multi_pw_aff_get_tuple_id(index, isl_dim_out);
1319 pos = isl_space_find_dim_by_id(space, isl_dim_param, array_id);
1321 isl_space_free(space);
1323 if (pos < 0) {
1324 isl_id_free(array_id);
1325 return index;
1328 space = isl_multi_pw_aff_get_domain_space(index);
1329 isl_multi_pw_aff_free(index);
1331 pos = isl_space_find_dim_by_id(space, isl_dim_param, array_id);
1332 if (pos < 0) {
1333 space = isl_space_insert_dims(space, isl_dim_param, 0, 1);
1334 space = isl_space_set_dim_id(space, isl_dim_param, 0, array_id);
1335 pos = 0;
1336 } else
1337 isl_id_free(array_id);
1339 ls = isl_local_space_from_space(space);
1340 aff = isl_aff_var_on_domain(ls, isl_dim_param, pos);
1341 index = isl_multi_pw_aff_from_pw_aff(isl_pw_aff_from_aff(aff));
1343 return index;
1346 /* Check if the given access relation accesses a (0D) array that corresponds
1347 * to one of the parameters in "space". If so, replace the array access
1348 * by an access to the set of integers with as index (and value)
1349 * that parameter.
1351 static __isl_give isl_map *access_detect_parameter(__isl_take isl_map *access,
1352 __isl_take isl_space *space)
1354 isl_id *array_id = NULL;
1355 int pos = -1;
1357 if (isl_map_has_tuple_id(access, isl_dim_out)) {
1358 array_id = isl_map_get_tuple_id(access, isl_dim_out);
1359 pos = isl_space_find_dim_by_id(space, isl_dim_param, array_id);
1361 isl_space_free(space);
1363 if (pos < 0) {
1364 isl_id_free(array_id);
1365 return access;
1368 pos = isl_map_find_dim_by_id(access, isl_dim_param, array_id);
1369 if (pos < 0) {
1370 access = isl_map_insert_dims(access, isl_dim_param, 0, 1);
1371 access = isl_map_set_dim_id(access, isl_dim_param, 0, array_id);
1372 pos = 0;
1373 } else
1374 isl_id_free(array_id);
1376 access = isl_map_insert_dims(access, isl_dim_out, 0, 1);
1377 access = isl_map_equate(access, isl_dim_param, pos, isl_dim_out, 0);
1379 return access;
1382 /* If "expr" accesses a (0D) array that corresponds to one of the parameters
1383 * in "space" then replace it by a value equal to the corresponding parameter.
1385 static __isl_give pet_expr *detect_parameter_accesses(__isl_take pet_expr *expr,
1386 void *user)
1388 isl_space *space = user;
1390 expr = pet_expr_cow(expr);
1391 if (!expr)
1392 return NULL;
1393 if (expr->type != pet_expr_access)
1394 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1395 "not an access expression", return pet_expr_free(expr));
1397 expr->acc.access = access_detect_parameter(expr->acc.access,
1398 isl_space_copy(space));
1399 expr->acc.index = index_detect_parameter(expr->acc.index,
1400 isl_space_copy(space));
1401 if (!expr->acc.access || !expr->acc.index)
1402 return pet_expr_free(expr);
1404 return expr;
1407 /* Replace all accesses to (0D) arrays that correspond to one of the parameters
1408 * in "space" by a value equal to the corresponding parameter.
1410 __isl_give pet_expr *pet_expr_detect_parameter_accesses(
1411 __isl_take pet_expr *expr, __isl_take isl_space *space)
1413 expr = pet_expr_map_access(expr, &detect_parameter_accesses, space);
1414 isl_space_free(space);
1415 return expr;
1418 /* Add a reference identifier to access expression "expr".
1419 * "user" points to an integer that contains the sequence number
1420 * of the next reference.
1422 static __isl_give pet_expr *access_add_ref_id(__isl_take pet_expr *expr,
1423 void *user)
1425 isl_ctx *ctx;
1426 char name[50];
1427 int *n_ref = user;
1429 expr = pet_expr_cow(expr);
1430 if (!expr)
1431 return expr;
1432 if (expr->type != pet_expr_access)
1433 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1434 "not an access expression", return pet_expr_free(expr));
1436 ctx = isl_map_get_ctx(expr->acc.access);
1437 snprintf(name, sizeof(name), "__pet_ref_%d", (*n_ref)++);
1438 expr->acc.ref_id = isl_id_alloc(ctx, name, NULL);
1439 if (!expr->acc.ref_id)
1440 return pet_expr_free(expr);
1442 return expr;
1445 __isl_give pet_expr *pet_expr_add_ref_ids(__isl_take pet_expr *expr, int *n_ref)
1447 return pet_expr_map_access(expr, &access_add_ref_id, n_ref);
1450 /* Reset the user pointer on all parameter and tuple ids in
1451 * the access relation and the index expressions
1452 * of the access expression "expr".
1454 static __isl_give pet_expr *access_anonymize(__isl_take pet_expr *expr,
1455 void *user)
1457 expr = pet_expr_cow(expr);
1458 if (!expr)
1459 return expr;
1460 if (expr->type != pet_expr_access)
1461 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1462 "not an access expression", return pet_expr_free(expr));
1464 expr->acc.access = isl_map_reset_user(expr->acc.access);
1465 expr->acc.index = isl_multi_pw_aff_reset_user(expr->acc.index);
1466 if (!expr->acc.access || !expr->acc.index)
1467 return pet_expr_free(expr);
1469 return expr;
1472 __isl_give pet_expr *pet_expr_anonymize(__isl_take pet_expr *expr)
1474 return pet_expr_map_access(expr, &access_anonymize, NULL);
1477 /* Data used in access_gist() callback.
1479 struct pet_access_gist_data {
1480 isl_set *domain;
1481 isl_union_map *value_bounds;
1484 /* Given an expression "expr" of type pet_expr_access, compute
1485 * the gist of the associated access relation and index expression
1486 * with respect to data->domain and the bounds on the values of the arguments
1487 * of the expression.
1489 static __isl_give pet_expr *access_gist(__isl_take pet_expr *expr, void *user)
1491 struct pet_access_gist_data *data = user;
1492 isl_set *domain;
1494 expr = pet_expr_cow(expr);
1495 if (!expr)
1496 return expr;
1497 if (expr->type != pet_expr_access)
1498 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1499 "not an access expression", return pet_expr_free(expr));
1501 domain = isl_set_copy(data->domain);
1502 if (expr->n_arg > 0)
1503 domain = pet_value_bounds_apply(domain, expr->n_arg, expr->args,
1504 data->value_bounds);
1506 expr->acc.access = isl_map_gist_domain(expr->acc.access,
1507 isl_set_copy(domain));
1508 expr->acc.index = isl_multi_pw_aff_gist(expr->acc.index, domain);
1509 if (!expr->acc.access || !expr->acc.index)
1510 return pet_expr_free(expr);
1512 return expr;
1515 __isl_give pet_expr *pet_expr_gist(__isl_take pet_expr *expr,
1516 __isl_keep isl_set *context, __isl_keep isl_union_map *value_bounds)
1518 struct pet_access_gist_data data = { context, value_bounds };
1520 return pet_expr_map_access(expr, &access_gist, &data);
1523 /* Mark "expr" as a read dependening on "read".
1525 __isl_give pet_expr *pet_expr_access_set_read(__isl_take pet_expr *expr,
1526 int read)
1528 if (!expr)
1529 return pet_expr_free(expr);
1530 if (expr->type != pet_expr_access)
1531 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1532 "not an access expression", return pet_expr_free(expr));
1533 if (expr->acc.read == read)
1534 return expr;
1535 expr = pet_expr_cow(expr);
1536 if (!expr)
1537 return NULL;
1538 expr->acc.read = read;
1540 return expr;
1543 /* Mark "expr" as a write dependening on "write".
1545 __isl_give pet_expr *pet_expr_access_set_write(__isl_take pet_expr *expr,
1546 int write)
1548 if (!expr)
1549 return pet_expr_free(expr);
1550 if (expr->type != pet_expr_access)
1551 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1552 "not an access expression", return pet_expr_free(expr));
1553 if (expr->acc.write == write)
1554 return expr;
1555 expr = pet_expr_cow(expr);
1556 if (!expr)
1557 return NULL;
1558 expr->acc.write = write;
1560 return expr;
1563 /* Replace the access relation of "expr" by "access".
1565 __isl_give pet_expr *pet_expr_access_set_access(__isl_take pet_expr *expr,
1566 __isl_take isl_map *access)
1568 expr = pet_expr_cow(expr);
1569 if (!expr || !access)
1570 goto error;
1571 if (expr->type != pet_expr_access)
1572 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1573 "not an access expression", goto error);
1574 isl_map_free(expr->acc.access);
1575 expr->acc.access = access;
1577 return expr;
1578 error:
1579 isl_map_free(access);
1580 pet_expr_free(expr);
1581 return NULL;
1584 /* Replace the index expression of "expr" by "index".
1586 __isl_give pet_expr *pet_expr_access_set_index(__isl_take pet_expr *expr,
1587 __isl_take isl_multi_pw_aff *index)
1589 expr = pet_expr_cow(expr);
1590 if (!expr || !index)
1591 goto error;
1592 if (expr->type != pet_expr_access)
1593 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1594 "not an access expression", goto error);
1595 isl_multi_pw_aff_free(expr->acc.index);
1596 expr->acc.index = index;
1598 return expr;
1599 error:
1600 isl_multi_pw_aff_free(index);
1601 pet_expr_free(expr);
1602 return NULL;
1605 /* Return the reference identifier of access expression "expr".
1607 __isl_give isl_id *pet_expr_access_get_ref_id(__isl_keep pet_expr *expr)
1609 if (!expr)
1610 return NULL;
1611 if (expr->type != pet_expr_access)
1612 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1613 "not an access expression", return NULL);
1615 return isl_id_copy(expr->acc.ref_id);
1618 /* Replace the reference identifier of access expression "expr" by "ref_id".
1620 __isl_give pet_expr *pet_expr_access_set_ref_id(__isl_take pet_expr *expr,
1621 __isl_take isl_id *ref_id)
1623 expr = pet_expr_cow(expr);
1624 if (!expr || !ref_id)
1625 goto error;
1626 if (expr->type != pet_expr_access)
1627 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1628 "not an access expression", goto error);
1629 isl_id_free(expr->acc.ref_id);
1630 expr->acc.ref_id = ref_id;
1632 return expr;
1633 error:
1634 isl_id_free(ref_id);
1635 pet_expr_free(expr);
1636 return NULL;
1639 /* Tag the access relation "access" with "id".
1640 * That is, insert the id as the range of a wrapped relation
1641 * in the domain of "access".
1643 * If "access" is of the form
1645 * D[i] -> A[a]
1647 * then the result is of the form
1649 * [D[i] -> id[]] -> A[a]
1651 __isl_give isl_map *pet_expr_tag_access(__isl_keep pet_expr *expr,
1652 __isl_take isl_map *access)
1654 isl_space *space;
1655 isl_map *add_tag;
1656 isl_id *id;
1658 if (expr->type != pet_expr_access)
1659 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1660 "not an access expression",
1661 return isl_map_free(access));
1663 id = isl_id_copy(expr->acc.ref_id);
1664 space = isl_space_range(isl_map_get_space(access));
1665 space = isl_space_from_range(space);
1666 space = isl_space_set_tuple_id(space, isl_dim_in, id);
1667 add_tag = isl_map_universe(space);
1668 access = isl_map_domain_product(access, add_tag);
1670 return access;
1673 /* Return the relation mapping pairs of domain iterations and argument
1674 * values to the corresponding accessed data elements.
1676 __isl_give isl_map *pet_expr_access_get_dependent_access(
1677 __isl_keep pet_expr *expr)
1679 if (!expr)
1680 return NULL;
1681 if (expr->type != pet_expr_access)
1682 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1683 "not an access expression", return NULL);
1685 return isl_map_copy(expr->acc.access);
1688 /* Return the relation mapping domain iterations to all possibly
1689 * accessed data elements.
1690 * In particular, take the access relation and project out the values
1691 * of the arguments, if any.
1693 __isl_give isl_map *pet_expr_access_get_may_access(__isl_keep pet_expr *expr)
1695 isl_map *access;
1696 isl_space *space;
1697 isl_map *map;
1699 if (!expr)
1700 return NULL;
1701 if (expr->type != pet_expr_access)
1702 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1703 "not an access expression", return NULL);
1705 access = pet_expr_access_get_dependent_access(expr);
1706 if (expr->n_arg == 0)
1707 return access;
1709 space = isl_space_domain(isl_map_get_space(access));
1710 map = isl_map_universe(isl_space_unwrap(space));
1711 map = isl_map_domain_map(map);
1712 access = isl_map_apply_domain(access, map);
1714 return access;
1717 /* Return a relation mapping domain iterations to definitely
1718 * accessed data elements, assuming the statement containing
1719 * the expression is executed.
1721 * If there are no arguments, then all elements are accessed.
1722 * Otherwise, we conservatively return an empty relation.
1724 __isl_give isl_map *pet_expr_access_get_must_access(__isl_keep pet_expr *expr)
1726 isl_space *space;
1728 if (!expr)
1729 return NULL;
1730 if (expr->type != pet_expr_access)
1731 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1732 "not an access expression", return NULL);
1734 if (expr->n_arg == 0)
1735 return pet_expr_access_get_dependent_access(expr);
1737 space = isl_map_get_space(expr->acc.access);
1738 space = isl_space_domain_factor_domain(space);
1740 return isl_map_empty(space);
1743 /* Return the relation mapping domain iterations to all possibly
1744 * accessed data elements, with its domain tagged with the reference
1745 * identifier.
1747 __isl_give isl_map *pet_expr_access_get_tagged_may_access(
1748 __isl_keep pet_expr *expr)
1750 isl_map *access;
1752 if (!expr)
1753 return NULL;
1755 access = pet_expr_access_get_may_access(expr);
1756 access = pet_expr_tag_access(expr, access);
1758 return access;
1761 /* Return the operation type of operation expression "expr".
1763 enum pet_op_type pet_expr_op_get_type(__isl_keep pet_expr *expr)
1765 if (!expr)
1766 return pet_op_last;
1767 if (expr->type != pet_expr_op)
1768 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1769 "not an operation expression", return pet_op_last);
1771 return expr->op;
1774 /* Replace the operation type of operation expression "expr" by "type".
1776 __isl_give pet_expr *pet_expr_op_set_type(__isl_take pet_expr *expr,
1777 enum pet_op_type type)
1779 if (!expr)
1780 return pet_expr_free(expr);
1781 if (expr->type != pet_expr_op)
1782 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1783 "not an operation expression",
1784 return pet_expr_free(expr));
1785 if (expr->op == type)
1786 return expr;
1787 expr = pet_expr_cow(expr);
1788 if (!expr)
1789 return NULL;
1790 expr->op = type;
1792 return expr;
1795 /* Return the name of the function called by "expr".
1797 __isl_keep const char *pet_expr_call_get_name(__isl_keep pet_expr *expr)
1799 if (!expr)
1800 return NULL;
1801 if (expr->type != pet_expr_call)
1802 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1803 "not a call expression", return NULL);
1804 return expr->name;
1807 /* Replace the name of the function called by "expr" by "name".
1809 __isl_give pet_expr *pet_expr_call_set_name(__isl_take pet_expr *expr,
1810 __isl_keep const char *name)
1812 expr = pet_expr_cow(expr);
1813 if (!expr || !name)
1814 return pet_expr_free(expr);
1815 if (expr->type != pet_expr_call)
1816 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1817 "not a call expression", return pet_expr_free(expr));
1818 free(expr->name);
1819 expr->name = strdup(name);
1820 if (!expr->name)
1821 return pet_expr_free(expr);
1822 return expr;
1825 /* Replace the type of the cast performed by "expr" by "name".
1827 __isl_give pet_expr *pet_expr_cast_set_type_name(__isl_take pet_expr *expr,
1828 __isl_keep const char *name)
1830 expr = pet_expr_cow(expr);
1831 if (!expr || !name)
1832 return pet_expr_free(expr);
1833 if (expr->type != pet_expr_cast)
1834 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1835 "not a cast expression", return pet_expr_free(expr));
1836 free(expr->type_name);
1837 expr->type_name = strdup(name);
1838 if (!expr->type_name)
1839 return pet_expr_free(expr);
1840 return expr;
1843 /* Return the value of the integer represented by "expr".
1845 __isl_give isl_val *pet_expr_int_get_val(__isl_keep pet_expr *expr)
1847 if (!expr)
1848 return NULL;
1849 if (expr->type != pet_expr_int)
1850 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1851 "not an int expression", return NULL);
1853 return isl_val_copy(expr->i);
1856 /* Replace the value of the integer represented by "expr" by "v".
1858 __isl_give pet_expr *pet_expr_int_set_val(__isl_take pet_expr *expr,
1859 __isl_take isl_val *v)
1861 expr = pet_expr_cow(expr);
1862 if (!expr || !v)
1863 goto error;
1864 if (expr->type != pet_expr_int)
1865 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1866 "not an int expression", goto error);
1867 isl_val_free(expr->i);
1868 expr->i = v;
1870 return expr;
1871 error:
1872 isl_val_free(v);
1873 pet_expr_free(expr);
1874 return NULL;
1877 /* Replace the value and string representation of the double
1878 * represented by "expr" by "d" and "s".
1880 __isl_give pet_expr *pet_expr_double_set(__isl_take pet_expr *expr,
1881 double d, __isl_keep const char *s)
1883 expr = pet_expr_cow(expr);
1884 if (!expr || !s)
1885 return pet_expr_free(expr);
1886 if (expr->type != pet_expr_double)
1887 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1888 "not a double expression", return pet_expr_free(expr));
1889 expr->d.val = d;
1890 free(expr->d.s);
1891 expr->d.s = strdup(s);
1892 if (!expr->d.s)
1893 return pet_expr_free(expr);
1894 return expr;
1897 /* Return a string representation of the double expression "expr".
1899 __isl_give char *pet_expr_double_get_str(__isl_keep pet_expr *expr)
1901 if (!expr)
1902 return NULL;
1903 if (expr->type != pet_expr_double)
1904 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1905 "not a double expression", return NULL);
1906 return strdup(expr->d.s);
1909 void pet_expr_dump_with_indent(__isl_keep pet_expr *expr, int indent)
1911 int i;
1913 if (!expr)
1914 return;
1916 fprintf(stderr, "%*s", indent, "");
1918 switch (expr->type) {
1919 case pet_expr_double:
1920 fprintf(stderr, "%s\n", expr->d.s);
1921 break;
1922 case pet_expr_int:
1923 isl_val_dump(expr->i);
1924 break;
1925 case pet_expr_access:
1926 if (expr->acc.ref_id) {
1927 isl_id_dump(expr->acc.ref_id);
1928 fprintf(stderr, "%*s", indent, "");
1930 isl_map_dump(expr->acc.access);
1931 fprintf(stderr, "%*s", indent, "");
1932 isl_multi_pw_aff_dump(expr->acc.index);
1933 fprintf(stderr, "%*sread: %d\n", indent + 2,
1934 "", expr->acc.read);
1935 fprintf(stderr, "%*swrite: %d\n", indent + 2,
1936 "", expr->acc.write);
1937 for (i = 0; i < expr->n_arg; ++i)
1938 pet_expr_dump_with_indent(expr->args[i], indent + 2);
1939 break;
1940 case pet_expr_op:
1941 fprintf(stderr, "%s\n", op_str[expr->op]);
1942 for (i = 0; i < expr->n_arg; ++i)
1943 pet_expr_dump_with_indent(expr->args[i], indent + 2);
1944 break;
1945 case pet_expr_call:
1946 fprintf(stderr, "%s/%d\n", expr->name, expr->n_arg);
1947 for (i = 0; i < expr->n_arg; ++i)
1948 pet_expr_dump_with_indent(expr->args[i], indent + 2);
1949 break;
1950 case pet_expr_cast:
1951 fprintf(stderr, "(%s)\n", expr->type_name);
1952 for (i = 0; i < expr->n_arg; ++i)
1953 pet_expr_dump_with_indent(expr->args[i], indent + 2);
1954 break;
1955 case pet_expr_error:
1956 fprintf(stderr, "ERROR\n");
1957 break;
1961 void pet_expr_dump(__isl_keep pet_expr *expr)
1963 pet_expr_dump_with_indent(expr, 0);