pet_expr_resolve_nested: allow specification of domain space
[pet.git] / nest.c
blob9b3b95051b9142601cbefe570f93a9ec82891e8d
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 "domain" or
551 * [domain -> [a_1,...,a_m]] at this point, is replaced by
552 * [domain -> [t_1,...,t_n]] or [domain -> [a_1,...,a_m,t_1,...,t_n]],
553 * with m the original number of arguments (n_arg) and
554 * n the number of these parameters
555 * (after identifying identical nested accesses).
557 * This transformation is performed in several steps.
558 * We first extract the arguments in pet_expr_extract_nested.
559 * param2pos maps the original parameter position to the position
560 * of the argument beyond the initial (n_arg) number of arguments.
561 * Then we move these parameters to input dimensions.
562 * t2pos maps the positions of these temporary input dimensions
563 * to the positions of the corresponding arguments inside the space
564 * [domain -> [t_1,...,t_n]].
565 * Finally, we express these temporary dimensions in terms of the domain
566 * [domain -> [a_1,...,a_m,t_1,...,t_n]] and precompose index expression and
567 * access relations with this function.
569 __isl_give pet_expr *pet_expr_resolve_nested(__isl_take pet_expr *expr,
570 __isl_keep isl_space *domain)
572 int i, n, n_arg, dim, n_in;
573 int nparam;
574 isl_ctx *ctx;
575 isl_space *space;
576 isl_local_space *ls;
577 isl_aff *aff;
578 isl_multi_aff *ma;
579 int *param2pos;
580 int *t2pos;
582 if (!expr)
583 return expr;
585 n_arg = pet_expr_get_n_arg(expr);
586 for (i = 0; i < n_arg; ++i) {
587 pet_expr *arg;
588 arg = pet_expr_get_arg(expr, i);
589 arg = pet_expr_resolve_nested(arg, domain);
590 expr = pet_expr_set_arg(expr, i, arg);
593 if (pet_expr_get_type(expr) != pet_expr_access)
594 return expr;
596 dim = isl_space_dim(domain, isl_dim_set);
597 n_in = dim + n_arg;
599 space = pet_expr_access_get_parameter_space(expr);
600 n = pet_nested_n_in_space(space);
601 isl_space_free(space);
602 if (n == 0)
603 return expr;
605 expr = pet_expr_access_align_params(expr);
606 if (!expr)
607 return NULL;
609 space = pet_expr_access_get_parameter_space(expr);
610 nparam = isl_space_dim(space, isl_dim_param);
611 isl_space_free(space);
613 ctx = pet_expr_get_ctx(expr);
615 param2pos = isl_alloc_array(ctx, int, nparam);
616 t2pos = isl_alloc_array(ctx, int, n);
617 if (!param2pos)
618 goto error;
619 expr = pet_expr_extract_nested(expr, n, param2pos);
620 expr = mark_self_dependences(expr, n_arg);
621 if (!expr)
622 goto error;
624 n = 0;
625 space = pet_expr_access_get_parameter_space(expr);
626 nparam = isl_space_dim(space, isl_dim_param);
627 for (i = nparam - 1; i >= 0; --i) {
628 isl_id *id = isl_space_get_dim_id(space, isl_dim_param, i);
629 if (!pet_nested_in_id(id)) {
630 isl_id_free(id);
631 continue;
634 expr = pet_expr_access_move_dims(expr,
635 isl_dim_in, n_in + n, isl_dim_param, i, 1);
636 t2pos[n] = n_in + param2pos[i];
637 n++;
639 isl_id_free(id);
641 isl_space_free(space);
643 space = isl_space_copy(domain);
644 space = isl_space_from_domain(space);
645 space = isl_space_add_dims(space, isl_dim_out,
646 pet_expr_get_n_arg(expr));
647 space = isl_space_wrap(space);
648 ls = isl_local_space_from_space(isl_space_copy(space));
649 space = isl_space_from_domain(space);
650 space = isl_space_add_dims(space, isl_dim_out, n_in + n);
651 ma = isl_multi_aff_zero(space);
653 for (i = 0; i < n_in; ++i) {
654 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
655 isl_dim_set, i);
656 ma = isl_multi_aff_set_aff(ma, i, aff);
658 for (i = 0; i < n; ++i) {
659 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
660 isl_dim_set, t2pos[i]);
661 ma = isl_multi_aff_set_aff(ma, n_in + i, aff);
663 isl_local_space_free(ls);
665 expr = pet_expr_access_pullback_multi_aff(expr, ma);
667 expr = remove_marked_self_dependences(expr, dim, n_arg);
669 free(t2pos);
670 free(param2pos);
671 return expr;
672 error:
673 free(t2pos);
674 free(param2pos);
675 return pet_expr_free(expr);
678 /* Precompose the access relation and the index expression associated
679 * to "expr" with the function pointed to by "user",
680 * thereby embedding the access relation in the domain of this function.
681 * The initial domain of the access relation and the index expression
682 * is the zero-dimensional domain.
684 static __isl_give pet_expr *embed_access(__isl_take pet_expr *expr, void *user)
686 isl_multi_aff *ma = (isl_multi_aff *) user;
688 return pet_expr_access_pullback_multi_aff(expr, isl_multi_aff_copy(ma));
691 /* Precompose all access relations in "expr" with "ma", thereby
692 * embedding them in the domain of "ma".
694 static __isl_give pet_expr *embed(__isl_take pet_expr *expr,
695 __isl_keep isl_multi_aff *ma)
697 return pet_expr_map_access(expr, &embed_access, ma);
700 /* For each nested access parameter in the domain of "stmt",
701 * construct a corresponding pet_expr, place it before the original
702 * elements in stmt->args and record its position in "param2pos".
703 * n is the number of nested access parameters.
705 struct pet_stmt *pet_stmt_extract_nested(struct pet_stmt *stmt, int n,
706 int *param2pos)
708 int i;
709 isl_ctx *ctx;
710 isl_space *space;
711 int n_arg;
712 pet_expr **args;
714 ctx = isl_set_get_ctx(stmt->domain);
716 n_arg = stmt->n_arg;
717 args = isl_calloc_array(ctx, pet_expr *, n + n_arg);
718 if (!args)
719 goto error;
721 space = isl_set_get_space(stmt->domain);
722 n_arg = pet_extract_nested_from_space(space, 0, args, param2pos);
723 isl_space_free(space);
725 if (n_arg < 0)
726 goto error;
728 for (i = 0; i < stmt->n_arg; ++i)
729 args[n_arg + i] = stmt->args[i];
730 free(stmt->args);
731 stmt->args = args;
732 stmt->n_arg += n_arg;
734 return stmt;
735 error:
736 if (args) {
737 for (i = 0; i < n; ++i)
738 pet_expr_free(args[i]);
739 free(args);
741 pet_stmt_free(stmt);
742 return NULL;
745 /* Check whether any of the arguments i of "stmt" starting at position "n"
746 * is equal to one of the first "n" arguments j.
747 * If so, combine the constraints on arguments i and j and remove
748 * argument i.
750 static struct pet_stmt *remove_duplicate_arguments(struct pet_stmt *stmt, int n)
752 int i, j;
753 isl_map *map;
755 if (!stmt)
756 return NULL;
757 if (n == 0)
758 return stmt;
759 if (n == stmt->n_arg)
760 return stmt;
762 map = isl_set_unwrap(stmt->domain);
764 for (i = stmt->n_arg - 1; i >= n; --i) {
765 for (j = 0; j < n; ++j)
766 if (pet_expr_is_equal(stmt->args[i], stmt->args[j]))
767 break;
768 if (j >= n)
769 continue;
771 map = isl_map_equate(map, isl_dim_out, i, isl_dim_out, j);
772 map = isl_map_project_out(map, isl_dim_out, i, 1);
774 pet_expr_free(stmt->args[i]);
775 for (j = i; j + 1 < stmt->n_arg; ++j)
776 stmt->args[j] = stmt->args[j + 1];
777 stmt->n_arg--;
780 stmt->domain = isl_map_wrap(map);
781 if (!stmt->domain)
782 goto error;
783 return stmt;
784 error:
785 pet_stmt_free(stmt);
786 return NULL;
789 /* Look for parameters in the iteration domain of "stmt" that
790 * refer to nested accesses. In particular, these are
791 * parameters with name "__pet_expr".
793 * If there are any such parameters, then as many extra variables
794 * (after identifying identical nested accesses) are inserted in the
795 * range of the map wrapped inside the domain, before the original variables.
796 * If the original domain is not a wrapped map, then a new wrapped
797 * map is created with zero output dimensions.
798 * The parameters are then equated to the corresponding output dimensions
799 * and subsequently projected out, from the iteration domain,
800 * the schedule and the access relations.
801 * For each of the output dimensions, a corresponding argument
802 * expression is inserted. Initially they are created with
803 * a zero-dimensional domain, so they have to be embedded
804 * in the current iteration domain.
805 * param2pos maps the position of the parameter to the position
806 * of the corresponding output dimension in the wrapped map.
808 struct pet_stmt *pet_stmt_resolve_nested(struct pet_stmt *stmt)
810 int i, n;
811 int pos;
812 int nparam;
813 unsigned n_arg;
814 isl_ctx *ctx;
815 isl_map *map;
816 isl_space *space;
817 isl_multi_aff *ma;
818 int *param2pos;
820 if (!stmt)
821 return NULL;
823 n = pet_nested_n_in_set(stmt->domain);
824 if (n == 0)
825 return stmt;
827 ctx = isl_set_get_ctx(stmt->domain);
829 n_arg = stmt->n_arg;
830 nparam = isl_set_dim(stmt->domain, isl_dim_param);
831 param2pos = isl_alloc_array(ctx, int, nparam);
832 stmt = pet_stmt_extract_nested(stmt, n, param2pos);
833 if (!stmt) {
834 free(param2pos);
835 return NULL;
838 n = stmt->n_arg - n_arg;
839 if (isl_set_is_wrapping(stmt->domain))
840 map = isl_set_unwrap(stmt->domain);
841 else
842 map = isl_map_from_domain(stmt->domain);
843 map = isl_map_insert_dims(map, isl_dim_out, 0, n);
845 for (i = nparam - 1; i >= 0; --i) {
846 isl_id *id;
848 if (!pet_nested_in_map(map, i))
849 continue;
851 id = pet_expr_access_get_id(stmt->args[param2pos[i]]);
852 map = isl_map_set_dim_id(map, isl_dim_out, param2pos[i], id);
853 map = isl_map_equate(map, isl_dim_param, i, isl_dim_out,
854 param2pos[i]);
855 map = isl_map_project_out(map, isl_dim_param, i, 1);
858 stmt->domain = isl_map_wrap(map);
860 space = isl_space_unwrap(isl_set_get_space(stmt->domain));
861 space = isl_space_from_domain(isl_space_domain(space));
862 ma = isl_multi_aff_zero(space);
863 for (pos = 0; pos < n; ++pos)
864 stmt->args[pos] = embed(stmt->args[pos], ma);
865 isl_multi_aff_free(ma);
867 stmt = pet_stmt_remove_nested_parameters(stmt);
868 stmt = remove_duplicate_arguments(stmt, n);
870 free(param2pos);
871 return stmt;
874 /* For each statement in "scop", move the parameters that correspond
875 * to nested access into the ranges of the domains and create
876 * corresponding argument expressions.
878 struct pet_scop *pet_scop_resolve_nested(struct pet_scop *scop)
880 int i;
882 if (!scop)
883 return NULL;
885 for (i = 0; i < scop->n_stmt; ++i) {
886 scop->stmts[i] = pet_stmt_resolve_nested(scop->stmts[i]);
887 if (!scop->stmts[i])
888 return pet_scop_free(scop);
891 return scop;