pet_comparison: handle NaN input
[pet.git] / expr.c
blob0fa0d7c78c9524758dff8677d67643affbf33b3b
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" perform a comparison operation?
668 int pet_expr_is_comparison(__isl_keep pet_expr *expr)
670 if (!expr)
671 return -1;
672 if (expr->type != pet_expr_op)
673 return 0;
674 switch (expr->op) {
675 case pet_op_eq:
676 case pet_op_ne:
677 case pet_op_le:
678 case pet_op_ge:
679 case pet_op_lt:
680 case pet_op_gt:
681 return 1;
682 default:
683 return 0;
687 /* Does "expr" perform a boolean operation?
689 int pet_expr_is_boolean(__isl_keep pet_expr *expr)
691 if (!expr)
692 return -1;
693 if (expr->type != pet_expr_op)
694 return 0;
695 switch (expr->op) {
696 case pet_op_land:
697 case pet_op_lor:
698 case pet_op_lnot:
699 return 1;
700 default:
701 return 0;
705 /* Does "expr" perform a min operation?
707 int pet_expr_is_min(__isl_keep pet_expr *expr)
709 if (!expr)
710 return -1;
711 if (expr->type != pet_expr_call)
712 return 0;
713 if (expr->n_arg != 2)
714 return 0;
715 if (strcmp(expr->name, "min") != 0)
716 return 0;
717 return 1;
720 /* Does "expr" perform a max operation?
722 int pet_expr_is_max(__isl_keep pet_expr *expr)
724 if (!expr)
725 return -1;
726 if (expr->type != pet_expr_call)
727 return 0;
728 if (expr->n_arg != 2)
729 return 0;
730 if (strcmp(expr->name, "max") != 0)
731 return 0;
732 return 1;
735 /* Does "expr" represent an access to an unnamed space, i.e.,
736 * does it represent an affine expression?
738 int pet_expr_is_affine(__isl_keep pet_expr *expr)
740 int has_id;
742 if (!expr)
743 return -1;
744 if (expr->type != pet_expr_access)
745 return 0;
747 has_id = isl_map_has_tuple_id(expr->acc.access, isl_dim_out);
748 if (has_id < 0)
749 return -1;
751 return !has_id;
754 /* Does "expr" represent an access to a scalar, i.e., a zero-dimensional array,
755 * not part of any struct?
757 int pet_expr_is_scalar_access(__isl_keep pet_expr *expr)
759 if (!expr)
760 return -1;
761 if (expr->type != pet_expr_access)
762 return 0;
763 if (isl_map_range_is_wrapping(expr->acc.access))
764 return 0;
766 return isl_map_dim(expr->acc.access, isl_dim_out) == 0;
769 /* Return 1 if the two pet_exprs are equivalent.
771 int pet_expr_is_equal(__isl_keep pet_expr *expr1, __isl_keep pet_expr *expr2)
773 int i;
775 if (!expr1 || !expr2)
776 return 0;
778 if (expr1->type != expr2->type)
779 return 0;
780 if (expr1->n_arg != expr2->n_arg)
781 return 0;
782 for (i = 0; i < expr1->n_arg; ++i)
783 if (!pet_expr_is_equal(expr1->args[i], expr2->args[i]))
784 return 0;
785 switch (expr1->type) {
786 case pet_expr_error:
787 return -1;
788 case pet_expr_double:
789 if (strcmp(expr1->d.s, expr2->d.s))
790 return 0;
791 if (expr1->d.val != expr2->d.val)
792 return 0;
793 break;
794 case pet_expr_int:
795 if (!isl_val_eq(expr1->i, expr2->i))
796 return 0;
797 break;
798 case pet_expr_access:
799 if (expr1->acc.read != expr2->acc.read)
800 return 0;
801 if (expr1->acc.write != expr2->acc.write)
802 return 0;
803 if (expr1->acc.ref_id != expr2->acc.ref_id)
804 return 0;
805 if (!expr1->acc.access || !expr2->acc.access)
806 return 0;
807 if (!isl_map_is_equal(expr1->acc.access, expr2->acc.access))
808 return 0;
809 if (!expr1->acc.index || !expr2->acc.index)
810 return 0;
811 if (!isl_multi_pw_aff_plain_is_equal(expr1->acc.index,
812 expr2->acc.index))
813 return 0;
814 break;
815 case pet_expr_op:
816 if (expr1->op != expr2->op)
817 return 0;
818 break;
819 case pet_expr_call:
820 if (strcmp(expr1->name, expr2->name))
821 return 0;
822 break;
823 case pet_expr_cast:
824 if (strcmp(expr1->type_name, expr2->type_name))
825 return 0;
826 break;
829 return 1;
832 /* Does the access expression "expr" read the accessed elements?
834 int pet_expr_access_is_read(__isl_keep pet_expr *expr)
836 if (!expr)
837 return -1;
838 if (expr->type != pet_expr_access)
839 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
840 "not an access expression", return -1);
842 return expr->acc.read;
845 /* Does the access expression "expr" write to the accessed elements?
847 int pet_expr_access_is_write(__isl_keep pet_expr *expr)
849 if (!expr)
850 return -1;
851 if (expr->type != pet_expr_access)
852 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
853 "not an access expression", return -1);
855 return expr->acc.write;
858 /* Return the identifier of the array accessed by "expr".
860 * If "expr" represents a member access, then return the identifier
861 * of the outer structure array.
863 __isl_give isl_id *pet_expr_access_get_id(__isl_keep pet_expr *expr)
865 if (!expr)
866 return NULL;
867 if (expr->type != pet_expr_access)
868 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
869 "not an access expression", return NULL);
871 if (isl_map_range_is_wrapping(expr->acc.access)) {
872 isl_space *space;
873 isl_id *id;
875 space = isl_map_get_space(expr->acc.access);
876 space = isl_space_range(space);
877 while (space && isl_space_is_wrapping(space))
878 space = isl_space_domain(isl_space_unwrap(space));
879 id = isl_space_get_tuple_id(space, isl_dim_set);
880 isl_space_free(space);
882 return id;
885 return isl_map_get_tuple_id(expr->acc.access, isl_dim_out);
888 /* Return the parameter space of "expr".
890 __isl_give isl_space *pet_expr_access_get_parameter_space(
891 __isl_keep pet_expr *expr)
893 isl_space *space;
895 if (!expr)
896 return NULL;
897 if (expr->type != pet_expr_access)
898 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
899 "not an access expression", return NULL);
901 space = isl_multi_pw_aff_get_space(expr->acc.index);
902 space = isl_space_params(space);
904 return space;
907 /* Return the space of the data accessed by "expr".
909 __isl_give isl_space *pet_expr_access_get_data_space(__isl_keep pet_expr *expr)
911 isl_space *space;
913 if (!expr)
914 return NULL;
915 if (expr->type != pet_expr_access)
916 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
917 "not an access expression", return NULL);
919 space = isl_multi_pw_aff_get_space(expr->acc.index);
920 space = isl_space_range(space);
922 return space;
925 /* Modify all expressions of type pet_expr_access in "expr"
926 * by calling "fn" on them.
928 __isl_give pet_expr *pet_expr_map_access(__isl_take pet_expr *expr,
929 __isl_give pet_expr *(*fn)(__isl_take pet_expr *expr, void *user),
930 void *user)
932 int i, n;
934 n = pet_expr_get_n_arg(expr);
935 for (i = 0; i < n; ++i) {
936 pet_expr *arg = pet_expr_get_arg(expr, i);
937 arg = pet_expr_map_access(arg, fn, user);
938 expr = pet_expr_set_arg(expr, i, arg);
941 if (!expr)
942 return NULL;
944 if (expr->type == pet_expr_access)
945 expr = fn(expr, user);
947 return expr;
950 /* Call "fn" on each of the subexpressions of "expr" of type "type".
952 * Return -1 on error (where fn returning a negative value is treated as
953 * an error).
954 * Otherwise return 0.
956 int pet_expr_foreach_expr_of_type(__isl_keep pet_expr *expr,
957 enum pet_expr_type type,
958 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
960 int i;
962 if (!expr)
963 return -1;
965 for (i = 0; i < expr->n_arg; ++i)
966 if (pet_expr_foreach_expr_of_type(expr->args[i],
967 type, fn, user) < 0)
968 return -1;
970 if (expr->type == type)
971 return fn(expr, user);
973 return 0;
976 /* Call "fn" on each of the subexpressions of "expr" of type pet_expr_access.
978 * Return -1 on error (where fn returning a negative value is treated as
979 * an error).
980 * Otherwise return 0.
982 int pet_expr_foreach_access_expr(__isl_keep pet_expr *expr,
983 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
985 return pet_expr_foreach_expr_of_type(expr, pet_expr_access, fn, user);
988 /* Call "fn" on each of the subexpressions of "expr" of type pet_expr_call.
990 * Return -1 on error (where fn returning a negative value is treated as
991 * an error).
992 * Otherwise return 0.
994 int pet_expr_foreach_call_expr(__isl_keep pet_expr *expr,
995 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
997 return pet_expr_foreach_expr_of_type(expr, pet_expr_call, fn, user);
1000 /* Internal data structure for pet_expr_writes.
1001 * "id" is the identifier that we are looking for.
1002 * "found" is set if we have found the identifier being written to.
1004 struct pet_expr_writes_data {
1005 isl_id *id;
1006 int found;
1009 /* Given an access expression, check if it writes to data->id.
1010 * If so, set data->found and abort the search.
1012 static int writes(__isl_keep pet_expr *expr, void *user)
1014 struct pet_expr_writes_data *data = user;
1015 isl_id *write_id;
1017 if (!expr->acc.write)
1018 return 0;
1019 if (pet_expr_is_affine(expr))
1020 return 0;
1022 write_id = pet_expr_access_get_id(expr);
1023 isl_id_free(write_id);
1025 if (!write_id)
1026 return -1;
1028 if (write_id != data->id)
1029 return 0;
1031 data->found = 1;
1032 return -1;
1035 /* Does expression "expr" write to "id"?
1037 int pet_expr_writes(__isl_keep pet_expr *expr, __isl_keep isl_id *id)
1039 struct pet_expr_writes_data data;
1041 data.id = id;
1042 data.found = 0;
1043 if (pet_expr_foreach_access_expr(expr, &writes, &data) < 0 &&
1044 !data.found)
1045 return -1;
1047 return data.found;
1050 /* Move the "n" dimensions of "src_type" starting at "src_pos" of
1051 * index expression and access relation of "expr"
1052 * to dimensions of "dst_type" at "dst_pos".
1054 __isl_give pet_expr *pet_expr_access_move_dims(__isl_take pet_expr *expr,
1055 enum isl_dim_type dst_type, unsigned dst_pos,
1056 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1058 expr = pet_expr_cow(expr);
1059 if (!expr)
1060 return NULL;
1061 if (expr->type != pet_expr_access)
1062 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1063 "not an access pet_expr", return pet_expr_free(expr));
1065 expr->acc.access = isl_map_move_dims(expr->acc.access,
1066 dst_type, dst_pos, src_type, src_pos, n);
1067 expr->acc.index = isl_multi_pw_aff_move_dims(expr->acc.index,
1068 dst_type, dst_pos, src_type, src_pos, n);
1069 if (!expr->acc.access || !expr->acc.index)
1070 return pet_expr_free(expr);
1072 return expr;
1075 /* Replace the index expression and access relation of "expr"
1076 * by their preimages under the function represented by "ma".
1078 __isl_give pet_expr *pet_expr_access_pullback_multi_aff(
1079 __isl_take pet_expr *expr, __isl_take isl_multi_aff *ma)
1081 expr = pet_expr_cow(expr);
1082 if (!expr || !ma)
1083 goto error;
1084 if (expr->type != pet_expr_access)
1085 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1086 "not an access pet_expr", goto error);
1088 expr->acc.access = isl_map_preimage_domain_multi_aff(expr->acc.access,
1089 isl_multi_aff_copy(ma));
1090 expr->acc.index = isl_multi_pw_aff_pullback_multi_aff(expr->acc.index,
1091 ma);
1092 if (!expr->acc.access || !expr->acc.index)
1093 return pet_expr_free(expr);
1095 return expr;
1096 error:
1097 isl_multi_aff_free(ma);
1098 pet_expr_free(expr);
1099 return NULL;
1102 /* Return the access relation of access expression "expr".
1104 __isl_give isl_map *pet_expr_access_get_access(__isl_keep pet_expr *expr)
1106 if (!expr)
1107 return NULL;
1108 if (expr->type != pet_expr_access)
1109 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1110 "not an access expression", return NULL);
1112 return isl_map_copy(expr->acc.access);
1115 /* Return the index expression of access expression "expr".
1117 __isl_give isl_multi_pw_aff *pet_expr_access_get_index(
1118 __isl_keep pet_expr *expr)
1120 if (!expr)
1121 return NULL;
1122 if (expr->type != pet_expr_access)
1123 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1124 "not an access expression", return NULL);
1126 return isl_multi_pw_aff_copy(expr->acc.index);
1129 /* Align the parameters of expr->acc.index and expr->acc.access.
1131 __isl_give pet_expr *pet_expr_access_align_params(__isl_take pet_expr *expr)
1133 expr = pet_expr_cow(expr);
1134 if (!expr)
1135 return NULL;
1136 if (expr->type != pet_expr_access)
1137 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1138 "not an access expression", return pet_expr_free(expr));
1140 expr->acc.access = isl_map_align_params(expr->acc.access,
1141 isl_multi_pw_aff_get_space(expr->acc.index));
1142 expr->acc.index = isl_multi_pw_aff_align_params(expr->acc.index,
1143 isl_map_get_space(expr->acc.access));
1144 if (!expr->acc.access || !expr->acc.index)
1145 return pet_expr_free(expr);
1147 return expr;
1150 /* Add extra conditions on the parameters to all access relations in "expr".
1152 * The conditions are not added to the index expression. Instead, they
1153 * are used to try and simplify the index expression.
1155 __isl_give pet_expr *pet_expr_restrict(__isl_take pet_expr *expr,
1156 __isl_take isl_set *cond)
1158 int i;
1160 expr = pet_expr_cow(expr);
1161 if (!expr)
1162 goto error;
1164 for (i = 0; i < expr->n_arg; ++i) {
1165 expr->args[i] = pet_expr_restrict(expr->args[i],
1166 isl_set_copy(cond));
1167 if (!expr->args[i])
1168 goto error;
1171 if (expr->type == pet_expr_access) {
1172 expr->acc.access = isl_map_intersect_params(expr->acc.access,
1173 isl_set_copy(cond));
1174 expr->acc.index = isl_multi_pw_aff_gist_params(
1175 expr->acc.index, isl_set_copy(cond));
1176 if (!expr->acc.access || !expr->acc.index)
1177 goto error;
1180 isl_set_free(cond);
1181 return expr;
1182 error:
1183 isl_set_free(cond);
1184 return pet_expr_free(expr);
1187 /* Modify the access relation and index expression
1188 * of the given access expression
1189 * based on the given iteration space transformation.
1190 * In particular, precompose the access relation and index expression
1191 * with the update function.
1193 * If the access has any arguments then the domain of the access relation
1194 * is a wrapped mapping from the iteration space to the space of
1195 * argument values. We only need to change the domain of this wrapped
1196 * mapping, so we extend the input transformation with an identity mapping
1197 * on the space of argument values.
1199 __isl_give pet_expr *pet_expr_access_update_domain(__isl_take pet_expr *expr,
1200 __isl_keep isl_multi_pw_aff *update)
1202 isl_space *space;
1204 expr = pet_expr_cow(expr);
1205 if (!expr)
1206 return NULL;
1207 if (expr->type != pet_expr_access)
1208 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1209 "not an access expression", return pet_expr_free(expr));
1211 update = isl_multi_pw_aff_copy(update);
1213 space = isl_map_get_space(expr->acc.access);
1214 space = isl_space_domain(space);
1215 if (!isl_space_is_wrapping(space))
1216 isl_space_free(space);
1217 else {
1218 isl_multi_pw_aff *id;
1219 space = isl_space_unwrap(space);
1220 space = isl_space_range(space);
1221 space = isl_space_map_from_set(space);
1222 id = isl_multi_pw_aff_identity(space);
1223 update = isl_multi_pw_aff_product(update, id);
1226 expr->acc.access = isl_map_preimage_domain_multi_pw_aff(
1227 expr->acc.access,
1228 isl_multi_pw_aff_copy(update));
1229 expr->acc.index = isl_multi_pw_aff_pullback_multi_pw_aff(
1230 expr->acc.index, update);
1231 if (!expr->acc.access || !expr->acc.index)
1232 return pet_expr_free(expr);
1234 return expr;
1237 static __isl_give pet_expr *update_domain(__isl_take pet_expr *expr, void *user)
1239 isl_multi_pw_aff *update = user;
1241 return pet_expr_access_update_domain(expr, update);
1244 /* Modify all access relations in "expr" by precomposing them with
1245 * the given iteration space transformation.
1247 __isl_give pet_expr *pet_expr_update_domain(__isl_take pet_expr *expr,
1248 __isl_take isl_multi_pw_aff *update)
1250 expr = pet_expr_map_access(expr, &update_domain, update);
1251 isl_multi_pw_aff_free(update);
1252 return expr;
1255 /* Add all parameters in "space" to the access relation and index expression
1256 * of "expr".
1258 static __isl_give pet_expr *align_params(__isl_take pet_expr *expr, void *user)
1260 isl_space *space = user;
1262 expr = pet_expr_cow(expr);
1263 if (!expr)
1264 return NULL;
1265 if (expr->type != pet_expr_access)
1266 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1267 "not an access expression", return pet_expr_free(expr));
1269 expr->acc.access = isl_map_align_params(expr->acc.access,
1270 isl_space_copy(space));
1271 expr->acc.index = isl_multi_pw_aff_align_params(expr->acc.index,
1272 isl_space_copy(space));
1273 if (!expr->acc.access || !expr->acc.index)
1274 return pet_expr_free(expr);
1276 return expr;
1279 /* Add all parameters in "space" to all access relations and index expressions
1280 * in "expr".
1282 __isl_give pet_expr *pet_expr_align_params(__isl_take pet_expr *expr,
1283 __isl_take isl_space *space)
1285 expr = pet_expr_map_access(expr, &align_params, space);
1286 isl_space_free(space);
1287 return expr;
1290 /* Insert an argument expression corresponding to "test" in front
1291 * of the list of arguments described by *n_arg and *args.
1293 static __isl_give pet_expr *insert_access_arg(__isl_take pet_expr *expr,
1294 __isl_keep isl_multi_pw_aff *test)
1296 int i;
1297 isl_ctx *ctx = isl_multi_pw_aff_get_ctx(test);
1299 if (!test)
1300 return pet_expr_free(expr);
1301 expr = pet_expr_cow(expr);
1302 if (!expr)
1303 return NULL;
1305 if (!expr->args) {
1306 expr->args = isl_calloc_array(ctx, pet_expr *, 1);
1307 if (!expr->args)
1308 return pet_expr_free(expr);
1309 } else {
1310 pet_expr **ext;
1311 ext = isl_calloc_array(ctx, pet_expr *, 1 + expr->n_arg);
1312 if (!ext)
1313 return pet_expr_free(expr);
1314 for (i = 0; i < expr->n_arg; ++i)
1315 ext[1 + i] = expr->args[i];
1316 free(expr->args);
1317 expr->args = ext;
1319 expr->n_arg++;
1320 expr->args[0] = pet_expr_from_index(isl_multi_pw_aff_copy(test));
1321 if (!expr->args[0])
1322 return pet_expr_free(expr);
1324 return expr;
1327 /* Make the expression "expr" depend on the value of "test"
1328 * being equal to "satisfied".
1330 * If "test" is an affine expression, we simply add the conditions
1331 * on the expression having the value "satisfied" to all access relations
1332 * and index expressions.
1334 * Otherwise, we add a filter to "expr" (which is then assumed to be
1335 * an access expression) corresponding to "test" being equal to "satisfied".
1337 __isl_give pet_expr *pet_expr_filter(__isl_take pet_expr *expr,
1338 __isl_take isl_multi_pw_aff *test, int satisfied)
1340 isl_id *id;
1341 isl_ctx *ctx;
1342 isl_space *space;
1343 isl_pw_multi_aff *pma;
1345 expr = pet_expr_cow(expr);
1346 if (!expr || !test)
1347 goto error;
1349 if (!isl_multi_pw_aff_has_tuple_id(test, isl_dim_out)) {
1350 isl_pw_aff *pa;
1351 isl_set *cond;
1353 pa = isl_multi_pw_aff_get_pw_aff(test, 0);
1354 isl_multi_pw_aff_free(test);
1355 if (satisfied)
1356 cond = isl_pw_aff_non_zero_set(pa);
1357 else
1358 cond = isl_pw_aff_zero_set(pa);
1359 return pet_expr_restrict(expr, isl_set_params(cond));
1362 ctx = isl_multi_pw_aff_get_ctx(test);
1363 if (expr->type != pet_expr_access)
1364 isl_die(ctx, isl_error_invalid,
1365 "can only filter access expressions", goto error);
1367 space = isl_space_domain(isl_map_get_space(expr->acc.access));
1368 id = isl_multi_pw_aff_get_tuple_id(test, isl_dim_out);
1369 pma = pet_filter_insert_pma(space, id, satisfied);
1371 expr->acc.access = isl_map_preimage_domain_pw_multi_aff(
1372 expr->acc.access,
1373 isl_pw_multi_aff_copy(pma));
1374 expr->acc.index = isl_multi_pw_aff_pullback_pw_multi_aff(
1375 expr->acc.index, pma);
1376 if (!expr->acc.access || !expr->acc.index)
1377 goto error;
1379 expr = insert_access_arg(expr, test);
1381 isl_multi_pw_aff_free(test);
1382 return expr;
1383 error:
1384 isl_multi_pw_aff_free(test);
1385 return pet_expr_free(expr);
1388 /* Check if the given index expression accesses a (0D) array that corresponds
1389 * to one of the parameters in "space". If so, replace the array access
1390 * by an access to the set of integers with as index (and value)
1391 * that parameter.
1393 static __isl_give isl_multi_pw_aff *index_detect_parameter(
1394 __isl_take isl_multi_pw_aff *index, __isl_take isl_space *space)
1396 isl_local_space *ls;
1397 isl_id *array_id = NULL;
1398 isl_aff *aff;
1399 int pos = -1;
1401 if (isl_multi_pw_aff_has_tuple_id(index, isl_dim_out)) {
1402 array_id = isl_multi_pw_aff_get_tuple_id(index, isl_dim_out);
1403 pos = isl_space_find_dim_by_id(space, isl_dim_param, array_id);
1405 isl_space_free(space);
1407 if (pos < 0) {
1408 isl_id_free(array_id);
1409 return index;
1412 space = isl_multi_pw_aff_get_domain_space(index);
1413 isl_multi_pw_aff_free(index);
1415 pos = isl_space_find_dim_by_id(space, isl_dim_param, array_id);
1416 if (pos < 0) {
1417 space = isl_space_insert_dims(space, isl_dim_param, 0, 1);
1418 space = isl_space_set_dim_id(space, isl_dim_param, 0, array_id);
1419 pos = 0;
1420 } else
1421 isl_id_free(array_id);
1423 ls = isl_local_space_from_space(space);
1424 aff = isl_aff_var_on_domain(ls, isl_dim_param, pos);
1425 index = isl_multi_pw_aff_from_pw_aff(isl_pw_aff_from_aff(aff));
1427 return index;
1430 /* Check if the given access relation accesses a (0D) array that corresponds
1431 * to one of the parameters in "space". If so, replace the array access
1432 * by an access to the set of integers with as index (and value)
1433 * that parameter.
1435 static __isl_give isl_map *access_detect_parameter(__isl_take isl_map *access,
1436 __isl_take isl_space *space)
1438 isl_id *array_id = NULL;
1439 int pos = -1;
1441 if (isl_map_has_tuple_id(access, isl_dim_out)) {
1442 array_id = isl_map_get_tuple_id(access, isl_dim_out);
1443 pos = isl_space_find_dim_by_id(space, isl_dim_param, array_id);
1445 isl_space_free(space);
1447 if (pos < 0) {
1448 isl_id_free(array_id);
1449 return access;
1452 pos = isl_map_find_dim_by_id(access, isl_dim_param, array_id);
1453 if (pos < 0) {
1454 access = isl_map_insert_dims(access, isl_dim_param, 0, 1);
1455 access = isl_map_set_dim_id(access, isl_dim_param, 0, array_id);
1456 pos = 0;
1457 } else
1458 isl_id_free(array_id);
1460 access = isl_map_insert_dims(access, isl_dim_out, 0, 1);
1461 access = isl_map_equate(access, isl_dim_param, pos, isl_dim_out, 0);
1463 return access;
1466 /* If "expr" accesses a (0D) array that corresponds to one of the parameters
1467 * in "space" then replace it by a value equal to the corresponding parameter.
1469 static __isl_give pet_expr *detect_parameter_accesses(__isl_take pet_expr *expr,
1470 void *user)
1472 isl_space *space = user;
1474 expr = pet_expr_cow(expr);
1475 if (!expr)
1476 return NULL;
1477 if (expr->type != pet_expr_access)
1478 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1479 "not an access expression", return pet_expr_free(expr));
1481 expr->acc.access = access_detect_parameter(expr->acc.access,
1482 isl_space_copy(space));
1483 expr->acc.index = index_detect_parameter(expr->acc.index,
1484 isl_space_copy(space));
1485 if (!expr->acc.access || !expr->acc.index)
1486 return pet_expr_free(expr);
1488 return expr;
1491 /* Replace all accesses to (0D) arrays that correspond to one of the parameters
1492 * in "space" by a value equal to the corresponding parameter.
1494 __isl_give pet_expr *pet_expr_detect_parameter_accesses(
1495 __isl_take pet_expr *expr, __isl_take isl_space *space)
1497 expr = pet_expr_map_access(expr, &detect_parameter_accesses, space);
1498 isl_space_free(space);
1499 return expr;
1502 /* Add a reference identifier to access expression "expr".
1503 * "user" points to an integer that contains the sequence number
1504 * of the next reference.
1506 static __isl_give pet_expr *access_add_ref_id(__isl_take pet_expr *expr,
1507 void *user)
1509 isl_ctx *ctx;
1510 char name[50];
1511 int *n_ref = user;
1513 expr = pet_expr_cow(expr);
1514 if (!expr)
1515 return expr;
1516 if (expr->type != pet_expr_access)
1517 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1518 "not an access expression", return pet_expr_free(expr));
1520 ctx = isl_map_get_ctx(expr->acc.access);
1521 snprintf(name, sizeof(name), "__pet_ref_%d", (*n_ref)++);
1522 expr->acc.ref_id = isl_id_alloc(ctx, name, NULL);
1523 if (!expr->acc.ref_id)
1524 return pet_expr_free(expr);
1526 return expr;
1529 __isl_give pet_expr *pet_expr_add_ref_ids(__isl_take pet_expr *expr, int *n_ref)
1531 return pet_expr_map_access(expr, &access_add_ref_id, n_ref);
1534 /* Reset the user pointer on all parameter and tuple ids in
1535 * the access relation and the index expressions
1536 * of the access expression "expr".
1538 static __isl_give pet_expr *access_anonymize(__isl_take pet_expr *expr,
1539 void *user)
1541 expr = pet_expr_cow(expr);
1542 if (!expr)
1543 return expr;
1544 if (expr->type != pet_expr_access)
1545 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1546 "not an access expression", return pet_expr_free(expr));
1548 expr->acc.access = isl_map_reset_user(expr->acc.access);
1549 expr->acc.index = isl_multi_pw_aff_reset_user(expr->acc.index);
1550 if (!expr->acc.access || !expr->acc.index)
1551 return pet_expr_free(expr);
1553 return expr;
1556 __isl_give pet_expr *pet_expr_anonymize(__isl_take pet_expr *expr)
1558 return pet_expr_map_access(expr, &access_anonymize, NULL);
1561 /* Data used in access_gist() callback.
1563 struct pet_access_gist_data {
1564 isl_set *domain;
1565 isl_union_map *value_bounds;
1568 /* Given an expression "expr" of type pet_expr_access, compute
1569 * the gist of the associated access relation and index expression
1570 * with respect to data->domain and the bounds on the values of the arguments
1571 * of the expression.
1573 static __isl_give pet_expr *access_gist(__isl_take pet_expr *expr, void *user)
1575 struct pet_access_gist_data *data = user;
1576 isl_set *domain;
1578 expr = pet_expr_cow(expr);
1579 if (!expr)
1580 return expr;
1581 if (expr->type != pet_expr_access)
1582 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1583 "not an access expression", return pet_expr_free(expr));
1585 domain = isl_set_copy(data->domain);
1586 if (expr->n_arg > 0)
1587 domain = pet_value_bounds_apply(domain, expr->n_arg, expr->args,
1588 data->value_bounds);
1590 expr->acc.access = isl_map_gist_domain(expr->acc.access,
1591 isl_set_copy(domain));
1592 expr->acc.index = isl_multi_pw_aff_gist(expr->acc.index, domain);
1593 if (!expr->acc.access || !expr->acc.index)
1594 return pet_expr_free(expr);
1596 return expr;
1599 __isl_give pet_expr *pet_expr_gist(__isl_take pet_expr *expr,
1600 __isl_keep isl_set *context, __isl_keep isl_union_map *value_bounds)
1602 struct pet_access_gist_data data = { context, value_bounds };
1604 return pet_expr_map_access(expr, &access_gist, &data);
1607 /* Mark "expr" as a read dependening on "read".
1609 __isl_give pet_expr *pet_expr_access_set_read(__isl_take pet_expr *expr,
1610 int read)
1612 if (!expr)
1613 return pet_expr_free(expr);
1614 if (expr->type != pet_expr_access)
1615 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1616 "not an access expression", return pet_expr_free(expr));
1617 if (expr->acc.read == read)
1618 return expr;
1619 expr = pet_expr_cow(expr);
1620 if (!expr)
1621 return NULL;
1622 expr->acc.read = read;
1624 return expr;
1627 /* Mark "expr" as a write dependening on "write".
1629 __isl_give pet_expr *pet_expr_access_set_write(__isl_take pet_expr *expr,
1630 int write)
1632 if (!expr)
1633 return pet_expr_free(expr);
1634 if (expr->type != pet_expr_access)
1635 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1636 "not an access expression", return pet_expr_free(expr));
1637 if (expr->acc.write == write)
1638 return expr;
1639 expr = pet_expr_cow(expr);
1640 if (!expr)
1641 return NULL;
1642 expr->acc.write = write;
1644 return expr;
1647 /* Replace the access relation of "expr" by "access".
1649 __isl_give pet_expr *pet_expr_access_set_access(__isl_take pet_expr *expr,
1650 __isl_take isl_map *access)
1652 expr = pet_expr_cow(expr);
1653 if (!expr || !access)
1654 goto error;
1655 if (expr->type != pet_expr_access)
1656 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1657 "not an access expression", goto error);
1658 isl_map_free(expr->acc.access);
1659 expr->acc.access = access;
1661 return expr;
1662 error:
1663 isl_map_free(access);
1664 pet_expr_free(expr);
1665 return NULL;
1668 /* Replace the index expression of "expr" by "index".
1670 __isl_give pet_expr *pet_expr_access_set_index(__isl_take pet_expr *expr,
1671 __isl_take isl_multi_pw_aff *index)
1673 expr = pet_expr_cow(expr);
1674 if (!expr || !index)
1675 goto error;
1676 if (expr->type != pet_expr_access)
1677 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1678 "not an access expression", goto error);
1679 isl_multi_pw_aff_free(expr->acc.index);
1680 expr->acc.index = index;
1682 return expr;
1683 error:
1684 isl_multi_pw_aff_free(index);
1685 pet_expr_free(expr);
1686 return NULL;
1689 /* Return the reference identifier of access expression "expr".
1691 __isl_give isl_id *pet_expr_access_get_ref_id(__isl_keep pet_expr *expr)
1693 if (!expr)
1694 return NULL;
1695 if (expr->type != pet_expr_access)
1696 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1697 "not an access expression", return NULL);
1699 return isl_id_copy(expr->acc.ref_id);
1702 /* Replace the reference identifier of access expression "expr" by "ref_id".
1704 __isl_give pet_expr *pet_expr_access_set_ref_id(__isl_take pet_expr *expr,
1705 __isl_take isl_id *ref_id)
1707 expr = pet_expr_cow(expr);
1708 if (!expr || !ref_id)
1709 goto error;
1710 if (expr->type != pet_expr_access)
1711 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1712 "not an access expression", goto error);
1713 isl_id_free(expr->acc.ref_id);
1714 expr->acc.ref_id = ref_id;
1716 return expr;
1717 error:
1718 isl_id_free(ref_id);
1719 pet_expr_free(expr);
1720 return NULL;
1723 /* Tag the access relation "access" with "id".
1724 * That is, insert the id as the range of a wrapped relation
1725 * in the domain of "access".
1727 * If "access" is of the form
1729 * D[i] -> A[a]
1731 * then the result is of the form
1733 * [D[i] -> id[]] -> A[a]
1735 __isl_give isl_map *pet_expr_tag_access(__isl_keep pet_expr *expr,
1736 __isl_take isl_map *access)
1738 isl_space *space;
1739 isl_map *add_tag;
1740 isl_id *id;
1742 if (expr->type != pet_expr_access)
1743 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1744 "not an access expression",
1745 return isl_map_free(access));
1747 id = isl_id_copy(expr->acc.ref_id);
1748 space = isl_space_range(isl_map_get_space(access));
1749 space = isl_space_from_range(space);
1750 space = isl_space_set_tuple_id(space, isl_dim_in, id);
1751 add_tag = isl_map_universe(space);
1752 access = isl_map_domain_product(access, add_tag);
1754 return access;
1757 /* Return the relation mapping pairs of domain iterations and argument
1758 * values to the corresponding accessed data elements.
1760 __isl_give isl_map *pet_expr_access_get_dependent_access(
1761 __isl_keep pet_expr *expr)
1763 if (!expr)
1764 return NULL;
1765 if (expr->type != pet_expr_access)
1766 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1767 "not an access expression", return NULL);
1769 return isl_map_copy(expr->acc.access);
1772 /* Return the relation mapping domain iterations to all possibly
1773 * accessed data elements.
1774 * In particular, take the access relation and project out the values
1775 * of the arguments, if any.
1777 __isl_give isl_map *pet_expr_access_get_may_access(__isl_keep pet_expr *expr)
1779 isl_map *access;
1780 isl_space *space;
1781 isl_map *map;
1783 if (!expr)
1784 return NULL;
1785 if (expr->type != pet_expr_access)
1786 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1787 "not an access expression", return NULL);
1789 access = pet_expr_access_get_dependent_access(expr);
1790 if (expr->n_arg == 0)
1791 return access;
1793 space = isl_space_domain(isl_map_get_space(access));
1794 map = isl_map_universe(isl_space_unwrap(space));
1795 map = isl_map_domain_map(map);
1796 access = isl_map_apply_domain(access, map);
1798 return access;
1801 /* Return a relation mapping domain iterations to definitely
1802 * accessed data elements, assuming the statement containing
1803 * the expression is executed.
1805 * If there are no arguments, then all elements are accessed.
1806 * Otherwise, we conservatively return an empty relation.
1808 __isl_give isl_map *pet_expr_access_get_must_access(__isl_keep pet_expr *expr)
1810 isl_space *space;
1812 if (!expr)
1813 return NULL;
1814 if (expr->type != pet_expr_access)
1815 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1816 "not an access expression", return NULL);
1818 if (expr->n_arg == 0)
1819 return pet_expr_access_get_dependent_access(expr);
1821 space = isl_map_get_space(expr->acc.access);
1822 space = isl_space_domain_factor_domain(space);
1824 return isl_map_empty(space);
1827 /* Return the relation mapping domain iterations to all possibly
1828 * accessed data elements, with its domain tagged with the reference
1829 * identifier.
1831 __isl_give isl_map *pet_expr_access_get_tagged_may_access(
1832 __isl_keep pet_expr *expr)
1834 isl_map *access;
1836 if (!expr)
1837 return NULL;
1839 access = pet_expr_access_get_may_access(expr);
1840 access = pet_expr_tag_access(expr, access);
1842 return access;
1845 /* Return the operation type of operation expression "expr".
1847 enum pet_op_type pet_expr_op_get_type(__isl_keep pet_expr *expr)
1849 if (!expr)
1850 return pet_op_last;
1851 if (expr->type != pet_expr_op)
1852 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1853 "not an operation expression", return pet_op_last);
1855 return expr->op;
1858 /* Replace the operation type of operation expression "expr" by "type".
1860 __isl_give pet_expr *pet_expr_op_set_type(__isl_take pet_expr *expr,
1861 enum pet_op_type type)
1863 if (!expr)
1864 return pet_expr_free(expr);
1865 if (expr->type != pet_expr_op)
1866 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1867 "not an operation expression",
1868 return pet_expr_free(expr));
1869 if (expr->op == type)
1870 return expr;
1871 expr = pet_expr_cow(expr);
1872 if (!expr)
1873 return NULL;
1874 expr->op = type;
1876 return expr;
1879 /* Return the name of the function called by "expr".
1881 __isl_keep const char *pet_expr_call_get_name(__isl_keep pet_expr *expr)
1883 if (!expr)
1884 return NULL;
1885 if (expr->type != pet_expr_call)
1886 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1887 "not a call expression", return NULL);
1888 return expr->name;
1891 /* Replace the name of the function called by "expr" by "name".
1893 __isl_give pet_expr *pet_expr_call_set_name(__isl_take pet_expr *expr,
1894 __isl_keep const char *name)
1896 expr = pet_expr_cow(expr);
1897 if (!expr || !name)
1898 return pet_expr_free(expr);
1899 if (expr->type != pet_expr_call)
1900 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1901 "not a call expression", return pet_expr_free(expr));
1902 free(expr->name);
1903 expr->name = strdup(name);
1904 if (!expr->name)
1905 return pet_expr_free(expr);
1906 return expr;
1909 /* Replace the type of the cast performed by "expr" by "name".
1911 __isl_give pet_expr *pet_expr_cast_set_type_name(__isl_take pet_expr *expr,
1912 __isl_keep const char *name)
1914 expr = pet_expr_cow(expr);
1915 if (!expr || !name)
1916 return pet_expr_free(expr);
1917 if (expr->type != pet_expr_cast)
1918 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1919 "not a cast expression", return pet_expr_free(expr));
1920 free(expr->type_name);
1921 expr->type_name = strdup(name);
1922 if (!expr->type_name)
1923 return pet_expr_free(expr);
1924 return expr;
1927 /* Return the value of the integer represented by "expr".
1929 __isl_give isl_val *pet_expr_int_get_val(__isl_keep pet_expr *expr)
1931 if (!expr)
1932 return NULL;
1933 if (expr->type != pet_expr_int)
1934 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1935 "not an int expression", return NULL);
1937 return isl_val_copy(expr->i);
1940 /* Replace the value of the integer represented by "expr" by "v".
1942 __isl_give pet_expr *pet_expr_int_set_val(__isl_take pet_expr *expr,
1943 __isl_take isl_val *v)
1945 expr = pet_expr_cow(expr);
1946 if (!expr || !v)
1947 goto error;
1948 if (expr->type != pet_expr_int)
1949 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1950 "not an int expression", goto error);
1951 isl_val_free(expr->i);
1952 expr->i = v;
1954 return expr;
1955 error:
1956 isl_val_free(v);
1957 pet_expr_free(expr);
1958 return NULL;
1961 /* Replace the value and string representation of the double
1962 * represented by "expr" by "d" and "s".
1964 __isl_give pet_expr *pet_expr_double_set(__isl_take pet_expr *expr,
1965 double d, __isl_keep const char *s)
1967 expr = pet_expr_cow(expr);
1968 if (!expr || !s)
1969 return pet_expr_free(expr);
1970 if (expr->type != pet_expr_double)
1971 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1972 "not a double expression", return pet_expr_free(expr));
1973 expr->d.val = d;
1974 free(expr->d.s);
1975 expr->d.s = strdup(s);
1976 if (!expr->d.s)
1977 return pet_expr_free(expr);
1978 return expr;
1981 /* Return a string representation of the double expression "expr".
1983 __isl_give char *pet_expr_double_get_str(__isl_keep pet_expr *expr)
1985 if (!expr)
1986 return NULL;
1987 if (expr->type != pet_expr_double)
1988 isl_die(pet_expr_get_ctx(expr), isl_error_invalid,
1989 "not a double expression", return NULL);
1990 return strdup(expr->d.s);
1993 /* Return the number of bits needed to represent the type of "expr".
1994 * See the description of the type_size field of pet_expr.
1996 int pet_expr_get_type_size(__isl_keep pet_expr *expr)
1998 return expr ? expr->type_size : 0;
2001 /* Replace the number of bits needed to represent the type of "expr"
2002 * by "type_size".
2003 * See the description of the type_size field of pet_expr.
2005 __isl_give pet_expr *pet_expr_set_type_size(__isl_take pet_expr *expr,
2006 int type_size)
2008 expr = pet_expr_cow(expr);
2009 if (!expr)
2010 return NULL;
2012 expr->type_size = type_size;
2014 return expr;
2017 void pet_expr_dump_with_indent(__isl_keep pet_expr *expr, int indent)
2019 int i;
2021 if (!expr)
2022 return;
2024 fprintf(stderr, "%*s", indent, "");
2026 switch (expr->type) {
2027 case pet_expr_double:
2028 fprintf(stderr, "%s\n", expr->d.s);
2029 break;
2030 case pet_expr_int:
2031 isl_val_dump(expr->i);
2032 break;
2033 case pet_expr_access:
2034 if (expr->acc.ref_id) {
2035 isl_id_dump(expr->acc.ref_id);
2036 fprintf(stderr, "%*s", indent, "");
2038 isl_map_dump(expr->acc.access);
2039 fprintf(stderr, "%*s", indent, "");
2040 isl_multi_pw_aff_dump(expr->acc.index);
2041 fprintf(stderr, "%*sread: %d\n", indent + 2,
2042 "", expr->acc.read);
2043 fprintf(stderr, "%*swrite: %d\n", indent + 2,
2044 "", expr->acc.write);
2045 for (i = 0; i < expr->n_arg; ++i)
2046 pet_expr_dump_with_indent(expr->args[i], indent + 2);
2047 break;
2048 case pet_expr_op:
2049 fprintf(stderr, "%s\n", op_str[expr->op]);
2050 for (i = 0; i < expr->n_arg; ++i)
2051 pet_expr_dump_with_indent(expr->args[i], indent + 2);
2052 break;
2053 case pet_expr_call:
2054 fprintf(stderr, "%s/%d\n", expr->name, expr->n_arg);
2055 for (i = 0; i < expr->n_arg; ++i)
2056 pet_expr_dump_with_indent(expr->args[i], indent + 2);
2057 break;
2058 case pet_expr_cast:
2059 fprintf(stderr, "(%s)\n", expr->type_name);
2060 for (i = 0; i < expr->n_arg; ++i)
2061 pet_expr_dump_with_indent(expr->args[i], indent + 2);
2062 break;
2063 case pet_expr_error:
2064 fprintf(stderr, "ERROR\n");
2065 break;
2069 void pet_expr_dump(__isl_keep pet_expr *expr)
2071 pet_expr_dump_with_indent(expr, 0);