pet_scop_add_boolean_array: allow specification of domain constraints
[pet.git] / nest.c
blobefe0227e5f8a2f5f032a77215a0b93d0c11409c5
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 "expr_arg.h"
39 #include "nest.h"
40 #include "scop.h"
42 /* A wrapper around pet_expr_free to be used as an isl_id free user function.
44 static void pet_expr_free_wrap(void *user)
46 pet_expr_free((pet_expr *) user);
49 /* Create an isl_id that refers to the nested access "expr".
51 __isl_give isl_id *pet_nested_pet_expr(__isl_take pet_expr *expr)
53 isl_id *id;
55 id = isl_id_alloc(pet_expr_get_ctx(expr), "__pet_expr", expr);
56 id = isl_id_set_free_user(id, &pet_expr_free_wrap);
58 return id;
61 /* Extract a pet_expr from an isl_id created by pet_nested_pet_expr.
62 * Such an isl_id has name "__pet_expr" and
63 * the user pointer points to a pet_expr object.
65 __isl_give pet_expr *pet_nested_extract_expr(__isl_keep isl_id *id)
67 return pet_expr_copy((pet_expr *) isl_id_get_user(id));
70 /* Does "id" refer to a nested access created by pet_nested_pet_expr?
72 int pet_nested_in_id(__isl_keep isl_id *id)
74 const char *name;
76 if (!id)
77 return 0;
78 if (!isl_id_get_user(id))
79 return 0;
81 name = isl_id_get_name(id);
82 return !strcmp(name, "__pet_expr");
85 /* Does parameter "pos" of "space" refer to a nested access?
87 static int pet_nested_in_space(__isl_keep isl_space *space, int pos)
89 int nested;
90 isl_id *id;
92 id = isl_space_get_dim_id(space, isl_dim_param, pos);
93 nested = pet_nested_in_id(id);
94 isl_id_free(id);
96 return nested;
99 /* Does parameter "pos" of "set" refer to a nested access?
101 int pet_nested_in_set(__isl_keep isl_set *set, int pos)
103 int nested;
104 isl_id *id;
106 id = isl_set_get_dim_id(set, isl_dim_param, pos);
107 nested = pet_nested_in_id(id);
108 isl_id_free(id);
110 return nested;
113 /* Does parameter "pos" of "map" refer to a nested access?
115 int pet_nested_in_map(__isl_keep isl_map *map, int pos)
117 int nested;
118 isl_id *id;
120 id = isl_map_get_dim_id(map, isl_dim_param, pos);
121 nested = pet_nested_in_id(id);
122 isl_id_free(id);
124 return nested;
127 /* Does "space" involve any parameters that refer to nested accesses?
129 int pet_nested_any_in_space(__isl_keep isl_space *space)
131 int i;
132 int nparam;
134 nparam = isl_space_dim(space, isl_dim_param);
135 for (i = 0; i < nparam; ++i)
136 if (pet_nested_in_space(space, i))
137 return 1;
139 return 0;
142 /* Does "pa" involve any parameters that refer to nested accesses?
144 int pet_nested_any_in_pw_aff(__isl_keep isl_pw_aff *pa)
146 isl_space *space;
147 int nested;
149 space = isl_pw_aff_get_space(pa);
150 nested = pet_nested_any_in_space(space);
151 isl_space_free(space);
153 return nested;
156 /* How many parameters of "space" refer to nested accesses?
158 int pet_nested_n_in_space(__isl_keep isl_space *space)
160 int i, n = 0;
161 int nparam;
163 nparam = isl_space_dim(space, isl_dim_param);
164 for (i = 0; i < nparam; ++i)
165 if (pet_nested_in_space(space, i))
166 ++n;
168 return n;
171 /* How many parameters of "map" refer to nested accesses?
173 int pet_nested_n_in_map(__isl_keep isl_map *map)
175 isl_space *space;
176 int n;
178 space = isl_map_get_space(map);
179 n = pet_nested_n_in_space(space);
180 isl_space_free(space);
182 return n;
185 /* How many parameters of "set" refer to nested accesses?
187 int pet_nested_n_in_set(__isl_keep isl_set *set)
189 isl_space *space;
190 int n;
192 space = isl_set_get_space(set);
193 n = pet_nested_n_in_space(space);
194 isl_space_free(space);
196 return n;
199 /* Remove all parameters from "space" that refer to nested accesses.
201 __isl_give isl_space *pet_nested_remove_from_space(__isl_take isl_space *space)
203 int i;
204 int nparam;
206 nparam = isl_space_dim(space, isl_dim_param);
207 for (i = nparam - 1; i >= 0; --i)
208 if (pet_nested_in_space(space, i))
209 space = isl_space_drop_dims(space, isl_dim_param, i, 1);
211 return space;
214 /* Remove all parameters from "set" that refer to nested accesses.
216 __isl_give isl_set *pet_nested_remove_from_set(__isl_take isl_set *set)
218 int i;
219 int nparam;
221 nparam = isl_set_dim(set, isl_dim_param);
222 for (i = nparam - 1; i >= 0; --i)
223 if (pet_nested_in_set(set, i))
224 set = isl_set_project_out(set, isl_dim_param, i, 1);
226 return set;
229 /* Remove all parameters from "map" that refer to nested accesses.
231 static __isl_give isl_map *pet_nested_remove_from_map(__isl_take isl_map *map)
233 int i;
234 int nparam;
236 nparam = isl_map_dim(map, isl_dim_param);
237 for (i = nparam - 1; i >= 0; --i)
238 if (pet_nested_in_map(map, i))
239 map = isl_map_project_out(map, isl_dim_param, i, 1);
241 return map;
244 /* Remove all parameters from "mpa" that refer to nested accesses.
246 static __isl_give isl_multi_pw_aff *pet_nested_remove_from_multi_pw_aff(
247 __isl_take isl_multi_pw_aff *mpa)
249 int i;
250 int nparam;
251 isl_space *space;
253 space = isl_multi_pw_aff_get_space(mpa);
254 nparam = isl_space_dim(space, isl_dim_param);
255 for (i = nparam - 1; i >= 0; --i) {
256 if (!pet_nested_in_space(space, i))
257 continue;
258 mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_param, i, 1);
260 isl_space_free(space);
262 return mpa;
265 /* Remove all parameters from the index expression and access relation of "expr"
266 * that refer to nested accesses.
268 static __isl_give pet_expr *expr_remove_nested_parameters(
269 __isl_take pet_expr *expr, void *user)
271 expr = pet_expr_cow(expr);
272 if (!expr)
273 return NULL;
275 expr->acc.access = pet_nested_remove_from_map(expr->acc.access);
276 expr->acc.index = pet_nested_remove_from_multi_pw_aff(expr->acc.index);
277 if (!expr->acc.access || !expr->acc.index)
278 return pet_expr_free(expr);
280 return expr;
283 /* Remove all nested access parameters from the schedule and all
284 * accesses of "stmt".
285 * There is no need to remove them from the domain as these parameters
286 * have already been removed from the domain when this function is called.
288 struct pet_stmt *pet_stmt_remove_nested_parameters(struct pet_stmt *stmt)
290 int i;
292 if (!stmt)
293 return NULL;
294 stmt->schedule = pet_nested_remove_from_map(stmt->schedule);
295 stmt->body = pet_expr_map_access(stmt->body,
296 &expr_remove_nested_parameters, NULL);
297 if (!stmt->schedule || !stmt->body)
298 goto error;
299 for (i = 0; i < stmt->n_arg; ++i) {
300 stmt->args[i] = pet_expr_map_access(stmt->args[i],
301 &expr_remove_nested_parameters, NULL);
302 if (!stmt->args[i])
303 goto error;
306 return stmt;
307 error:
308 pet_stmt_free(stmt);
309 return NULL;
312 /* For each nested access parameter in "space",
313 * construct a corresponding pet_expr, place it in args and
314 * record its position in "param2pos".
315 * "n_arg" is the number of elements that are already in args.
316 * The position recorded in "param2pos" takes this number into account.
317 * If the pet_expr corresponding to a parameter is identical to
318 * the pet_expr corresponding to an earlier parameter, then these two
319 * parameters are made to refer to the same element in args.
321 * Return the final number of elements in args or -1 if an error has occurred.
323 int pet_extract_nested_from_space(__isl_keep isl_space *space,
324 int n_arg, __isl_give pet_expr **args, int *param2pos)
326 int i, nparam;
328 nparam = isl_space_dim(space, isl_dim_param);
329 for (i = 0; i < nparam; ++i) {
330 int j;
331 isl_id *id = isl_space_get_dim_id(space, isl_dim_param, i);
333 if (!pet_nested_in_id(id)) {
334 isl_id_free(id);
335 continue;
338 args[n_arg] = pet_nested_extract_expr(id);
339 isl_id_free(id);
340 if (!args[n_arg])
341 return -1;
343 for (j = 0; j < n_arg; ++j)
344 if (pet_expr_is_equal(args[j], args[n_arg]))
345 break;
347 if (j < n_arg) {
348 pet_expr_free(args[n_arg]);
349 args[n_arg] = NULL;
350 param2pos[i] = j;
351 } else
352 param2pos[i] = n_arg++;
355 return n_arg;
358 /* For each nested access parameter in the access relations in "expr",
359 * construct a corresponding pet_expr, append it to the arguments of "expr"
360 * and record its position in "param2pos" (relative to the initial
361 * number of arguments).
362 * n is the number of nested access parameters.
364 __isl_give pet_expr *pet_expr_extract_nested(__isl_take pet_expr *expr, int n,
365 int *param2pos)
367 isl_ctx *ctx;
368 isl_space *space;
369 int i, n_arg;
370 pet_expr **args;
372 ctx = pet_expr_get_ctx(expr);
373 args = isl_calloc_array(ctx, pet_expr *, n);
374 if (!args)
375 return pet_expr_free(expr);
377 n_arg = pet_expr_get_n_arg(expr);
378 space = pet_expr_access_get_parameter_space(expr);
379 n = pet_extract_nested_from_space(space, 0, args, param2pos);
380 isl_space_free(space);
382 if (n < 0)
383 expr = pet_expr_free(expr);
384 else
385 expr = pet_expr_set_n_arg(expr, n_arg + n);
387 for (i = 0; i < n; ++i)
388 expr = pet_expr_set_arg(expr, n_arg + i, args[i]);
389 free(args);
391 return expr;
394 /* Are "expr1" and "expr2" both array accesses such that
395 * the access relation of "expr1" is a subset of that of "expr2"?
396 * Only take into account the first "n_arg" arguments.
398 static int is_sub_access(__isl_keep pet_expr *expr1, __isl_keep pet_expr *expr2,
399 int n_arg)
401 isl_id *id1, *id2;
402 isl_map *access1, *access2;
403 int is_subset;
404 int i, n1, n2;
406 if (!expr1 || !expr2)
407 return 0;
408 if (pet_expr_get_type(expr1) != pet_expr_access)
409 return 0;
410 if (pet_expr_get_type(expr2) != pet_expr_access)
411 return 0;
412 if (pet_expr_is_affine(expr1))
413 return 0;
414 if (pet_expr_is_affine(expr2))
415 return 0;
416 n1 = pet_expr_get_n_arg(expr1);
417 if (n1 > n_arg)
418 n1 = n_arg;
419 n2 = pet_expr_get_n_arg(expr2);
420 if (n2 > n_arg)
421 n2 = n_arg;
422 if (n1 != n2)
423 return 0;
424 for (i = 0; i < n1; ++i) {
425 pet_expr *arg1, *arg2;
426 int equal;
427 arg1 = pet_expr_get_arg(expr1, i);
428 arg2 = pet_expr_get_arg(expr2, i);
429 equal = pet_expr_is_equal(arg1, arg2);
430 pet_expr_free(arg1);
431 pet_expr_free(arg2);
432 if (equal < 0 || !equal)
433 return equal;
435 id1 = pet_expr_access_get_id(expr1);
436 id2 = pet_expr_access_get_id(expr2);
437 isl_id_free(id1);
438 isl_id_free(id2);
439 if (!id1 || !id2)
440 return 0;
441 if (id1 != id2)
442 return 0;
444 access1 = pet_expr_access_get_access(expr1);
445 access2 = pet_expr_access_get_access(expr2);
446 is_subset = isl_map_is_subset(access1, access2);
447 isl_map_free(access1);
448 isl_map_free(access2);
450 return is_subset;
453 /* Mark self dependences among the arguments of "expr" starting at "first".
454 * These arguments have already been added to the list of arguments
455 * but are not yet referenced directly from the index expression.
456 * Instead, they are still referenced through parameters encoding
457 * nested accesses.
459 * In particular, if "expr" is a read access, then check the arguments
460 * starting at "first" to see if "expr" accesses a subset of
461 * the elements accessed by the argument, or under more restrictive conditions.
462 * If so, then this nested access can be removed from the constraints
463 * governing the outer access. There is no point in restricting
464 * accesses to an array if in order to evaluate the restriction,
465 * we have to access the same elements (or more).
467 * Rather than removing the argument at this point (which would
468 * complicate the resolution of the other nested accesses), we simply
469 * mark it here by replacing it by a NaN pet_expr.
470 * These NaNs are then later removed in remove_marked_self_dependences.
472 static __isl_give pet_expr *mark_self_dependences(__isl_take pet_expr *expr,
473 int first)
475 int i, n;
477 if (pet_expr_access_is_write(expr))
478 return expr;
480 n = pet_expr_get_n_arg(expr);
481 for (i = first; i < n; ++i) {
482 int mark;
483 pet_expr *arg;
485 arg = pet_expr_get_arg(expr, i);
486 mark = is_sub_access(expr, arg, first);
487 pet_expr_free(arg);
488 if (mark < 0)
489 return pet_expr_free(expr);
490 if (!mark)
491 continue;
493 arg = pet_expr_new_int(isl_val_nan(pet_expr_get_ctx(expr)));
494 expr = pet_expr_set_arg(expr, i, arg);
497 return expr;
500 /* Is "expr" a NaN integer expression?
502 static int expr_is_nan(__isl_keep pet_expr *expr)
504 isl_val *v;
505 int is_nan;
507 if (pet_expr_get_type(expr) != pet_expr_int)
508 return 0;
510 v = pet_expr_int_get_val(expr);
511 is_nan = isl_val_is_nan(v);
512 isl_val_free(v);
514 return is_nan;
517 /* Check if we have marked any self dependences (as NaNs)
518 * in mark_self_dependences and remove them here.
519 * It is safe to project them out since these arguments
520 * can at most be referenced from the condition of the access relation,
521 * but do not appear in the index expression.
522 * "dim" is the dimension of the iteration domain.
524 static __isl_give pet_expr *remove_marked_self_dependences(
525 __isl_take pet_expr *expr, int dim, int first)
527 int i, n;
529 n = pet_expr_get_n_arg(expr);
530 for (i = n - 1; i >= first; --i) {
531 int is_nan;
532 pet_expr *arg;
534 arg = pet_expr_get_arg(expr, i);
535 is_nan = expr_is_nan(arg);
536 pet_expr_free(arg);
537 if (!is_nan)
538 continue;
539 expr = pet_expr_access_project_out_arg(expr, dim, i);
542 return expr;
545 /* Look for parameters in any access relation in "expr" that
546 * refer to nested accesses. In particular, these are
547 * parameters with name "__pet_expr".
549 * If there are any such parameters, then the domain of the index
550 * expression and the access relation, which is either [] or
551 * [[] -> [a_1,...,a_m]] at this point, is replaced by [[] -> [t_1,...,t_n]] or
552 * [[] -> [a_1,...,a_m,t_1,...,t_n]], with m the original number of arguments
553 * (n_arg) and n the number of these parameters
554 * (after identifying identical nested accesses).
556 * This transformation is performed in several steps.
557 * We first extract the arguments in pet_expr_extract_nested.
558 * param2pos maps the original parameter position to the position
559 * of the argument beyond the initial (n_arg) number of arguments.
560 * Then we move these parameters to input dimensions.
561 * t2pos maps the positions of these temporary input dimensions
562 * to the positions of the corresponding arguments.
563 * Finally, we express these temporary dimensions in terms of the domain
564 * [[] -> [a_1,...,a_m,t_1,...,t_n]] and precompose index expression and access
565 * relations with this function.
567 __isl_give pet_expr *pet_expr_resolve_nested(__isl_take pet_expr *expr)
569 int i, n, n_arg;
570 int nparam;
571 isl_ctx *ctx;
572 isl_space *space;
573 isl_local_space *ls;
574 isl_aff *aff;
575 isl_multi_aff *ma;
576 int *param2pos;
577 int *t2pos;
579 if (!expr)
580 return expr;
582 n_arg = pet_expr_get_n_arg(expr);
583 for (i = 0; i < n_arg; ++i) {
584 pet_expr *arg;
585 arg = pet_expr_get_arg(expr, i);
586 arg = pet_expr_resolve_nested(arg);
587 expr = pet_expr_set_arg(expr, i, arg);
590 if (pet_expr_get_type(expr) != pet_expr_access)
591 return expr;
593 space = pet_expr_access_get_parameter_space(expr);
594 n = pet_nested_n_in_space(space);
595 isl_space_free(space);
596 if (n == 0)
597 return expr;
599 expr = pet_expr_access_align_params(expr);
600 if (!expr)
601 return NULL;
603 space = pet_expr_access_get_parameter_space(expr);
604 nparam = isl_space_dim(space, isl_dim_param);
605 isl_space_free(space);
607 ctx = pet_expr_get_ctx(expr);
609 param2pos = isl_alloc_array(ctx, int, nparam);
610 t2pos = isl_alloc_array(ctx, int, n);
611 if (!param2pos)
612 goto error;
613 expr = pet_expr_extract_nested(expr, n, param2pos);
614 expr = mark_self_dependences(expr, n_arg);
615 if (!expr)
616 goto error;
618 n = 0;
619 space = pet_expr_access_get_parameter_space(expr);
620 nparam = isl_space_dim(space, isl_dim_param);
621 for (i = nparam - 1; i >= 0; --i) {
622 isl_id *id = isl_space_get_dim_id(space, isl_dim_param, i);
623 if (!pet_nested_in_id(id)) {
624 isl_id_free(id);
625 continue;
628 expr = pet_expr_access_move_dims(expr,
629 isl_dim_in, n_arg + n, isl_dim_param, i, 1);
630 t2pos[n] = n_arg + param2pos[i];
631 n++;
633 isl_id_free(id);
635 isl_space_free(space);
637 space = pet_expr_access_get_parameter_space(expr);
638 space = isl_space_set_from_params(space);
639 space = isl_space_add_dims(space, isl_dim_set,
640 pet_expr_get_n_arg(expr));
641 space = isl_space_wrap(isl_space_from_range(space));
642 ls = isl_local_space_from_space(isl_space_copy(space));
643 space = isl_space_from_domain(space);
644 space = isl_space_add_dims(space, isl_dim_out, n_arg + n);
645 ma = isl_multi_aff_zero(space);
647 for (i = 0; i < n_arg; ++i) {
648 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
649 isl_dim_set, i);
650 ma = isl_multi_aff_set_aff(ma, i, aff);
652 for (i = 0; i < n; ++i) {
653 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
654 isl_dim_set, t2pos[i]);
655 ma = isl_multi_aff_set_aff(ma, n_arg + i, aff);
657 isl_local_space_free(ls);
659 expr = pet_expr_access_pullback_multi_aff(expr, ma);
661 expr = remove_marked_self_dependences(expr, 0, n_arg);
663 free(t2pos);
664 free(param2pos);
665 return expr;
666 error:
667 free(t2pos);
668 free(param2pos);
669 return pet_expr_free(expr);
672 /* Precompose the access relation and the index expression associated
673 * to "expr" with the function pointed to by "user",
674 * thereby embedding the access relation in the domain of this function.
675 * The initial domain of the access relation and the index expression
676 * is the zero-dimensional domain.
678 static __isl_give pet_expr *embed_access(__isl_take pet_expr *expr, void *user)
680 isl_multi_aff *ma = (isl_multi_aff *) user;
682 return pet_expr_access_pullback_multi_aff(expr, isl_multi_aff_copy(ma));
685 /* Precompose all access relations in "expr" with "ma", thereby
686 * embedding them in the domain of "ma".
688 static __isl_give pet_expr *embed(__isl_take pet_expr *expr,
689 __isl_keep isl_multi_aff *ma)
691 return pet_expr_map_access(expr, &embed_access, ma);
694 /* For each nested access parameter in the domain of "stmt",
695 * construct a corresponding pet_expr, place it before the original
696 * elements in stmt->args and record its position in "param2pos".
697 * n is the number of nested access parameters.
699 struct pet_stmt *pet_stmt_extract_nested(struct pet_stmt *stmt, int n,
700 int *param2pos)
702 int i;
703 isl_ctx *ctx;
704 isl_space *space;
705 int n_arg;
706 pet_expr **args;
708 ctx = isl_set_get_ctx(stmt->domain);
710 n_arg = stmt->n_arg;
711 args = isl_calloc_array(ctx, pet_expr *, n + n_arg);
712 if (!args)
713 goto error;
715 space = isl_set_get_space(stmt->domain);
716 n_arg = pet_extract_nested_from_space(space, 0, args, param2pos);
717 isl_space_free(space);
719 if (n_arg < 0)
720 goto error;
722 for (i = 0; i < stmt->n_arg; ++i)
723 args[n_arg + i] = stmt->args[i];
724 free(stmt->args);
725 stmt->args = args;
726 stmt->n_arg += n_arg;
728 return stmt;
729 error:
730 if (args) {
731 for (i = 0; i < n; ++i)
732 pet_expr_free(args[i]);
733 free(args);
735 pet_stmt_free(stmt);
736 return NULL;
739 /* Check whether any of the arguments i of "stmt" starting at position "n"
740 * is equal to one of the first "n" arguments j.
741 * If so, combine the constraints on arguments i and j and remove
742 * argument i.
744 static struct pet_stmt *remove_duplicate_arguments(struct pet_stmt *stmt, int n)
746 int i, j;
747 isl_map *map;
749 if (!stmt)
750 return NULL;
751 if (n == 0)
752 return stmt;
753 if (n == stmt->n_arg)
754 return stmt;
756 map = isl_set_unwrap(stmt->domain);
758 for (i = stmt->n_arg - 1; i >= n; --i) {
759 for (j = 0; j < n; ++j)
760 if (pet_expr_is_equal(stmt->args[i], stmt->args[j]))
761 break;
762 if (j >= n)
763 continue;
765 map = isl_map_equate(map, isl_dim_out, i, isl_dim_out, j);
766 map = isl_map_project_out(map, isl_dim_out, i, 1);
768 pet_expr_free(stmt->args[i]);
769 for (j = i; j + 1 < stmt->n_arg; ++j)
770 stmt->args[j] = stmt->args[j + 1];
771 stmt->n_arg--;
774 stmt->domain = isl_map_wrap(map);
775 if (!stmt->domain)
776 goto error;
777 return stmt;
778 error:
779 pet_stmt_free(stmt);
780 return NULL;
783 /* Look for parameters in the iteration domain of "stmt" that
784 * refer to nested accesses. In particular, these are
785 * parameters with name "__pet_expr".
787 * If there are any such parameters, then as many extra variables
788 * (after identifying identical nested accesses) are inserted in the
789 * range of the map wrapped inside the domain, before the original variables.
790 * If the original domain is not a wrapped map, then a new wrapped
791 * map is created with zero output dimensions.
792 * The parameters are then equated to the corresponding output dimensions
793 * and subsequently projected out, from the iteration domain,
794 * the schedule and the access relations.
795 * For each of the output dimensions, a corresponding argument
796 * expression is inserted. Initially they are created with
797 * a zero-dimensional domain, so they have to be embedded
798 * in the current iteration domain.
799 * param2pos maps the position of the parameter to the position
800 * of the corresponding output dimension in the wrapped map.
802 struct pet_stmt *pet_stmt_resolve_nested(struct pet_stmt *stmt)
804 int i, n;
805 int pos;
806 int nparam;
807 unsigned n_arg;
808 isl_ctx *ctx;
809 isl_map *map;
810 isl_space *space;
811 isl_multi_aff *ma;
812 int *param2pos;
814 if (!stmt)
815 return NULL;
817 n = pet_nested_n_in_set(stmt->domain);
818 if (n == 0)
819 return stmt;
821 ctx = isl_set_get_ctx(stmt->domain);
823 n_arg = stmt->n_arg;
824 nparam = isl_set_dim(stmt->domain, isl_dim_param);
825 param2pos = isl_alloc_array(ctx, int, nparam);
826 stmt = pet_stmt_extract_nested(stmt, n, param2pos);
827 if (!stmt) {
828 free(param2pos);
829 return NULL;
832 n = stmt->n_arg - n_arg;
833 if (isl_set_is_wrapping(stmt->domain))
834 map = isl_set_unwrap(stmt->domain);
835 else
836 map = isl_map_from_domain(stmt->domain);
837 map = isl_map_insert_dims(map, isl_dim_out, 0, n);
839 for (i = nparam - 1; i >= 0; --i) {
840 isl_id *id;
842 if (!pet_nested_in_map(map, i))
843 continue;
845 id = pet_expr_access_get_id(stmt->args[param2pos[i]]);
846 map = isl_map_set_dim_id(map, isl_dim_out, param2pos[i], id);
847 map = isl_map_equate(map, isl_dim_param, i, isl_dim_out,
848 param2pos[i]);
849 map = isl_map_project_out(map, isl_dim_param, i, 1);
852 stmt->domain = isl_map_wrap(map);
854 space = isl_space_unwrap(isl_set_get_space(stmt->domain));
855 space = isl_space_from_domain(isl_space_domain(space));
856 ma = isl_multi_aff_zero(space);
857 for (pos = 0; pos < n; ++pos)
858 stmt->args[pos] = embed(stmt->args[pos], ma);
859 isl_multi_aff_free(ma);
861 stmt = pet_stmt_remove_nested_parameters(stmt);
862 stmt = remove_duplicate_arguments(stmt, n);
864 free(param2pos);
865 return stmt;
868 /* For each statement in "scop", move the parameters that correspond
869 * to nested access into the ranges of the domains and create
870 * corresponding argument expressions.
872 struct pet_scop *pet_scop_resolve_nested(struct pet_scop *scop)
874 int i;
876 if (!scop)
877 return NULL;
879 for (i = 0; i < scop->n_stmt; ++i) {
880 scop->stmts[i] = pet_stmt_resolve_nested(scop->stmts[i]);
881 if (!scop->stmts[i])
882 return pet_scop_free(scop);
885 return scop;