pet_codegen.c: add missing include
[pet.git] / nest.c
blobb4747e6972528c99845b01983f5911d601a5cb49
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 <isl/id.h>
38 #include <isl/space.h>
39 #include <isl/set.h>
40 #include <isl/map.h>
41 #include <isl/union_map.h>
42 #include <isl/aff.h>
43 #include <isl/val.h>
45 #include "aff.h"
46 #include "expr.h"
47 #include "expr_arg.h"
48 #include "nest.h"
49 #include "scop.h"
50 #include "tree.h"
52 /* A wrapper around pet_expr_free to be used as an isl_id free user function.
54 static void pet_expr_free_wrap(void *user)
56 pet_expr_free((pet_expr *) user);
59 /* Create an isl_id that refers to the nested access "expr".
61 __isl_give isl_id *pet_nested_pet_expr(__isl_take pet_expr *expr)
63 isl_id *id;
65 id = isl_id_alloc(pet_expr_get_ctx(expr), "__pet_expr", expr);
66 id = isl_id_set_free_user(id, &pet_expr_free_wrap);
68 return id;
71 /* Extract a pet_expr from an isl_id created by pet_nested_pet_expr.
72 * Such an isl_id has name "__pet_expr" and
73 * the user pointer points to a pet_expr object.
75 __isl_give pet_expr *pet_nested_extract_expr(__isl_keep isl_id *id)
77 return pet_expr_copy((pet_expr *) isl_id_get_user(id));
80 /* Does "id" refer to a nested access created by pet_nested_pet_expr?
82 int pet_nested_in_id(__isl_keep isl_id *id)
84 const char *name;
86 if (!id)
87 return 0;
88 if (!isl_id_get_user(id))
89 return 0;
91 name = isl_id_get_name(id);
92 return !strcmp(name, "__pet_expr");
95 /* Does parameter "pos" of "space" refer to a nested access?
97 static int pet_nested_in_space(__isl_keep isl_space *space, int pos)
99 int nested;
100 isl_id *id;
102 id = isl_space_get_dim_id(space, isl_dim_param, pos);
103 nested = pet_nested_in_id(id);
104 isl_id_free(id);
106 return nested;
109 /* Does parameter "pos" of "set" refer to a nested access?
111 int pet_nested_in_set(__isl_keep isl_set *set, int pos)
113 int nested;
114 isl_id *id;
116 id = isl_set_get_dim_id(set, isl_dim_param, pos);
117 nested = pet_nested_in_id(id);
118 isl_id_free(id);
120 return nested;
123 /* Does parameter "pos" of "map" refer to a nested access?
125 int pet_nested_in_map(__isl_keep isl_map *map, int pos)
127 int nested;
128 isl_id *id;
130 id = isl_map_get_dim_id(map, isl_dim_param, pos);
131 nested = pet_nested_in_id(id);
132 isl_id_free(id);
134 return nested;
137 /* Does parameter "pos" of "umap" refer to a nested access?
139 static int pet_nested_in_union_map(__isl_keep isl_union_map *umap, int pos)
141 int nested;
142 isl_id *id;
144 id = isl_union_map_get_dim_id(umap, isl_dim_param, pos);
145 nested = pet_nested_in_id(id);
146 isl_id_free(id);
148 return nested;
151 /* Does "space" involve any parameters that refer to nested accesses?
153 int pet_nested_any_in_space(__isl_keep isl_space *space)
155 int i;
156 int nparam;
158 nparam = isl_space_dim(space, isl_dim_param);
159 for (i = 0; i < nparam; ++i)
160 if (pet_nested_in_space(space, i))
161 return 1;
163 return 0;
166 /* Does "pa" involve any parameters that refer to nested accesses?
168 int pet_nested_any_in_pw_aff(__isl_keep isl_pw_aff *pa)
170 isl_space *space;
171 int nested;
173 space = isl_pw_aff_get_space(pa);
174 nested = pet_nested_any_in_space(space);
175 isl_space_free(space);
177 return nested;
180 /* How many parameters of "space" refer to nested accesses?
182 int pet_nested_n_in_space(__isl_keep isl_space *space)
184 int i, n = 0;
185 int nparam;
187 nparam = isl_space_dim(space, isl_dim_param);
188 for (i = 0; i < nparam; ++i)
189 if (pet_nested_in_space(space, i))
190 ++n;
192 return n;
195 /* How many parameters of "map" refer to nested accesses?
197 int pet_nested_n_in_map(__isl_keep isl_map *map)
199 isl_space *space;
200 int n;
202 space = isl_map_get_space(map);
203 n = pet_nested_n_in_space(space);
204 isl_space_free(space);
206 return n;
209 /* How many parameters of "set" refer to nested accesses?
211 int pet_nested_n_in_set(__isl_keep isl_set *set)
213 isl_space *space;
214 int n;
216 space = isl_set_get_space(set);
217 n = pet_nested_n_in_space(space);
218 isl_space_free(space);
220 return n;
223 /* Remove all parameters from "space" that refer to nested accesses.
225 __isl_give isl_space *pet_nested_remove_from_space(__isl_take isl_space *space)
227 int i;
228 int nparam;
230 nparam = isl_space_dim(space, isl_dim_param);
231 for (i = nparam - 1; i >= 0; --i)
232 if (pet_nested_in_space(space, i))
233 space = isl_space_drop_dims(space, isl_dim_param, i, 1);
235 return space;
238 /* Remove all parameters from "set" that refer to nested accesses.
240 __isl_give isl_set *pet_nested_remove_from_set(__isl_take isl_set *set)
242 int i;
243 int nparam;
245 nparam = isl_set_dim(set, isl_dim_param);
246 for (i = nparam - 1; i >= 0; --i)
247 if (pet_nested_in_set(set, i))
248 set = isl_set_project_out(set, isl_dim_param, i, 1);
250 return set;
253 /* Remove all parameters from "umap" that refer to nested accesses.
255 static __isl_give isl_union_map *pet_nested_remove_from_union_map(
256 __isl_take isl_union_map *umap)
258 int i;
259 int nparam;
261 nparam = isl_union_map_dim(umap, isl_dim_param);
262 for (i = nparam - 1; i >= 0; --i)
263 if (pet_nested_in_union_map(umap, i))
264 umap = isl_union_map_project_out(umap,
265 isl_dim_param, i, 1);
267 return umap;
270 /* Remove all parameters from "mpa" that refer to nested accesses.
272 static __isl_give isl_multi_pw_aff *pet_nested_remove_from_multi_pw_aff(
273 __isl_take isl_multi_pw_aff *mpa)
275 int i;
276 int nparam;
277 isl_space *space;
279 space = isl_multi_pw_aff_get_space(mpa);
280 nparam = isl_space_dim(space, isl_dim_param);
281 for (i = nparam - 1; i >= 0; --i) {
282 if (!pet_nested_in_space(space, i))
283 continue;
284 mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_param, i, 1);
286 isl_space_free(space);
288 return mpa;
291 /* Remove all parameters from the index expression and
292 * access relations of "expr" that refer to nested accesses.
294 static __isl_give pet_expr *expr_remove_nested_parameters(
295 __isl_take pet_expr *expr, void *user)
297 enum pet_expr_access_type type;
299 expr = pet_expr_cow(expr);
300 if (!expr)
301 return NULL;
303 for (type = pet_expr_access_begin; type < pet_expr_access_end; ++type) {
304 if (!expr->acc.access[type])
305 continue;
306 expr->acc.access[type] =
307 pet_nested_remove_from_union_map(expr->acc.access[type]);
308 if (!expr->acc.access[type])
309 break;
311 expr->acc.index = pet_nested_remove_from_multi_pw_aff(expr->acc.index);
312 if (type < pet_expr_access_end || !expr->acc.index)
313 return pet_expr_free(expr);
315 return expr;
318 /* Remove all nested access parameters from the schedule and all
319 * accesses of "stmt".
320 * There is no need to remove them from the domain as these parameters
321 * have already been removed from the domain when this function is called.
323 struct pet_stmt *pet_stmt_remove_nested_parameters(struct pet_stmt *stmt)
325 int i;
327 if (!stmt)
328 return NULL;
329 stmt->body = pet_tree_map_access_expr(stmt->body,
330 &expr_remove_nested_parameters, NULL);
331 if (!stmt->body)
332 goto error;
333 for (i = 0; i < stmt->n_arg; ++i) {
334 stmt->args[i] = pet_expr_map_access(stmt->args[i],
335 &expr_remove_nested_parameters, NULL);
336 if (!stmt->args[i])
337 goto error;
340 return stmt;
341 error:
342 pet_stmt_free(stmt);
343 return NULL;
346 /* Set *dim to the dimension of the domain of the access expression "expr" and
347 * abort the search.
349 static int set_dim(__isl_keep pet_expr *expr, void *user)
351 int *dim = user;
352 isl_space *space;
354 space = pet_expr_access_get_domain_space(expr);
355 *dim = isl_space_dim(space, isl_dim_set);
356 isl_space_free(space);
358 return -1;
361 /* Determine the dimension of the domain of the access expressions in "expr".
363 * In particular, return the dimension of the domain of the first access
364 * expression in "expr" as all access expressions should have the same
365 * domain.
367 * If "expr" does not contain any access expressions, then we return 0.
369 static int pet_expr_domain_dim(__isl_keep pet_expr *expr)
371 int dim = -1;
373 if (pet_expr_foreach_access_expr(expr, &set_dim, &dim) >= 0)
374 return 0;
376 return dim;
379 /* Embed all access expressions in "expr" in the domain "space".
380 * The initial domain of the access expressions
381 * is an anonymous domain of a dimension that may be lower
382 * than the dimension of "space".
383 * We may therefore need to introduce extra dimensions as well as
384 * (potentially) the name of "space".
386 static __isl_give pet_expr *embed(__isl_take pet_expr *expr,
387 __isl_keep isl_space *space)
389 int n;
390 isl_multi_pw_aff *mpa;
392 n = pet_expr_domain_dim(expr);
393 if (n < 0)
394 return pet_expr_free(expr);
396 space = isl_space_copy(space);
397 mpa = isl_multi_pw_aff_from_multi_aff(pet_prefix_projection(space, n));
398 expr = pet_expr_update_domain(expr, mpa);
400 return expr;
403 /* For each nested access parameter in "space",
404 * construct a corresponding pet_expr, place it in args and
405 * record its position in "param2pos".
406 * The constructed pet_expr objects are embedded in "space"
407 * (with the nested access parameters removed).
408 * "n_arg" is the number of elements that are already in args.
409 * The position recorded in "param2pos" takes this number into account.
410 * If the pet_expr corresponding to a parameter is identical to
411 * the pet_expr corresponding to an earlier parameter, then these two
412 * parameters are made to refer to the same element in args.
414 * Return the final number of elements in args or -1 if an error has occurred.
416 int pet_extract_nested_from_space(__isl_keep isl_space *space,
417 int n_arg, __isl_give pet_expr **args, int *param2pos)
419 int i, nparam;
420 isl_space *domain;
422 domain = isl_space_copy(space);
423 domain = pet_nested_remove_from_space(domain);
424 nparam = isl_space_dim(space, isl_dim_param);
425 for (i = 0; i < nparam; ++i) {
426 int j;
427 isl_id *id = isl_space_get_dim_id(space, isl_dim_param, i);
429 if (!pet_nested_in_id(id)) {
430 isl_id_free(id);
431 continue;
434 args[n_arg] = embed(pet_nested_extract_expr(id), domain);
435 isl_id_free(id);
436 if (!args[n_arg])
437 return -1;
439 for (j = 0; j < n_arg; ++j)
440 if (pet_expr_is_equal(args[j], args[n_arg]))
441 break;
443 if (j < n_arg) {
444 pet_expr_free(args[n_arg]);
445 args[n_arg] = NULL;
446 param2pos[i] = j;
447 } else
448 param2pos[i] = n_arg++;
450 isl_space_free(domain);
452 return n_arg;
455 /* For each nested access parameter in the access relations in "expr",
456 * construct a corresponding pet_expr, append it to the arguments of "expr"
457 * and record its position in "param2pos" (relative to the initial
458 * number of arguments).
459 * n is the number of nested access parameters.
461 __isl_give pet_expr *pet_expr_extract_nested(__isl_take pet_expr *expr, int n,
462 int *param2pos)
464 isl_ctx *ctx;
465 isl_space *space;
466 int i, n_arg;
467 pet_expr **args;
469 ctx = pet_expr_get_ctx(expr);
470 args = isl_calloc_array(ctx, pet_expr *, n);
471 if (!args)
472 return pet_expr_free(expr);
474 n_arg = pet_expr_get_n_arg(expr);
475 space = pet_expr_access_get_domain_space(expr);
476 n = pet_extract_nested_from_space(space, 0, args, param2pos);
477 isl_space_free(space);
479 if (n < 0)
480 expr = pet_expr_free(expr);
481 else
482 expr = pet_expr_set_n_arg(expr, n_arg + n);
484 for (i = 0; i < n; ++i)
485 expr = pet_expr_set_arg(expr, n_arg + i, args[i]);
486 free(args);
488 return expr;
491 /* Mark self dependences among the arguments of "expr" starting at "first".
492 * These arguments have already been added to the list of arguments
493 * but are not yet referenced directly from the index expression.
494 * Instead, they are still referenced through parameters encoding
495 * nested accesses.
497 * In particular, if "expr" is a read access, then check the arguments
498 * starting at "first" to see if "expr" accesses a subset of
499 * the elements accessed by the argument, or under more restrictive conditions.
500 * If so, then this nested access can be removed from the constraints
501 * governing the outer access. There is no point in restricting
502 * accesses to an array if in order to evaluate the restriction,
503 * we have to access the same elements (or more).
505 * Rather than removing the argument at this point (which would
506 * complicate the resolution of the other nested accesses), we simply
507 * mark it here by replacing it by a NaN pet_expr.
508 * These NaNs are then later removed in remove_marked_self_dependences.
510 static __isl_give pet_expr *mark_self_dependences(__isl_take pet_expr *expr,
511 int first)
513 int i, n;
515 if (pet_expr_access_is_write(expr))
516 return expr;
518 n = pet_expr_get_n_arg(expr);
519 for (i = first; i < n; ++i) {
520 int mark;
521 pet_expr *arg;
523 arg = pet_expr_get_arg(expr, i);
524 mark = pet_expr_is_sub_access(expr, arg, first);
525 pet_expr_free(arg);
526 if (mark < 0)
527 return pet_expr_free(expr);
528 if (!mark)
529 continue;
531 arg = pet_expr_new_int(isl_val_nan(pet_expr_get_ctx(expr)));
532 expr = pet_expr_set_arg(expr, i, arg);
535 return expr;
538 /* Is "expr" a NaN integer expression?
540 static int expr_is_nan(__isl_keep pet_expr *expr)
542 isl_val *v;
543 int is_nan;
545 if (pet_expr_get_type(expr) != pet_expr_int)
546 return 0;
548 v = pet_expr_int_get_val(expr);
549 is_nan = isl_val_is_nan(v);
550 isl_val_free(v);
552 return is_nan;
555 /* Check if we have marked any self dependences (as NaNs)
556 * in mark_self_dependences and remove them here.
557 * It is safe to project them out since these arguments
558 * can at most be referenced from the condition of the access relation,
559 * but do not appear in the index expression.
560 * "dim" is the dimension of the iteration domain.
562 static __isl_give pet_expr *remove_marked_self_dependences(
563 __isl_take pet_expr *expr, int dim, int first)
565 int i, n;
567 n = pet_expr_get_n_arg(expr);
568 for (i = n - 1; i >= first; --i) {
569 int is_nan;
570 pet_expr *arg;
572 arg = pet_expr_get_arg(expr, i);
573 is_nan = expr_is_nan(arg);
574 pet_expr_free(arg);
575 if (!is_nan)
576 continue;
577 expr = pet_expr_access_project_out_arg(expr, dim, i);
580 return expr;
583 /* Look for parameters in any access relation in "expr" that
584 * refer to nested accesses. In particular, these are
585 * parameters with name "__pet_expr".
587 * If there are any such parameters, then the domain of the index
588 * expression and the access relation, which is either "domain" or
589 * [domain -> [a_1,...,a_m]] at this point, is replaced by
590 * [domain -> [t_1,...,t_n]] or [domain -> [a_1,...,a_m,t_1,...,t_n]],
591 * with m the original number of arguments (n_arg) and
592 * n the number of these parameters
593 * (after identifying identical nested accesses).
595 * This transformation is performed in several steps.
596 * We first extract the arguments in pet_expr_extract_nested.
597 * param2pos maps the original parameter position to the position
598 * of the argument beyond the initial (n_arg) number of arguments.
599 * Then we move these parameters to input dimensions.
600 * t2pos maps the positions of these temporary input dimensions
601 * to the positions of the corresponding arguments inside the space
602 * [domain -> [t_1,...,t_n]].
603 * Finally, we express these temporary dimensions in terms of the domain
604 * [domain -> [a_1,...,a_m,t_1,...,t_n]] and precompose index expression and
605 * access relations with this function.
607 __isl_give pet_expr *pet_expr_resolve_nested(__isl_take pet_expr *expr,
608 __isl_keep isl_space *domain)
610 int i, n, n_arg, dim, n_in;
611 int nparam;
612 isl_ctx *ctx;
613 isl_space *space;
614 isl_local_space *ls;
615 isl_aff *aff;
616 isl_multi_aff *ma;
617 int *param2pos;
618 int *t2pos;
620 if (!expr)
621 return expr;
623 n_arg = pet_expr_get_n_arg(expr);
624 for (i = 0; i < n_arg; ++i) {
625 pet_expr *arg;
626 arg = pet_expr_get_arg(expr, i);
627 arg = pet_expr_resolve_nested(arg, domain);
628 expr = pet_expr_set_arg(expr, i, arg);
631 if (pet_expr_get_type(expr) != pet_expr_access)
632 return expr;
634 dim = isl_space_dim(domain, isl_dim_set);
635 n_in = dim + n_arg;
637 space = pet_expr_access_get_parameter_space(expr);
638 n = pet_nested_n_in_space(space);
639 isl_space_free(space);
640 if (n == 0)
641 return expr;
643 expr = pet_expr_access_align_params(expr);
644 if (!expr)
645 return NULL;
647 space = pet_expr_access_get_parameter_space(expr);
648 nparam = isl_space_dim(space, isl_dim_param);
649 isl_space_free(space);
651 ctx = pet_expr_get_ctx(expr);
653 param2pos = isl_alloc_array(ctx, int, nparam);
654 t2pos = isl_alloc_array(ctx, int, n);
655 if (!param2pos)
656 goto error;
657 expr = pet_expr_extract_nested(expr, n, param2pos);
658 expr = mark_self_dependences(expr, n_arg);
659 if (!expr)
660 goto error;
662 n = 0;
663 space = pet_expr_access_get_parameter_space(expr);
664 nparam = isl_space_dim(space, isl_dim_param);
665 for (i = nparam - 1; i >= 0; --i) {
666 isl_id *id = isl_space_get_dim_id(space, isl_dim_param, i);
667 if (!pet_nested_in_id(id)) {
668 isl_id_free(id);
669 continue;
672 expr = pet_expr_access_move_dims(expr,
673 isl_dim_in, n_in + n, isl_dim_param, i, 1);
674 t2pos[n] = n_in + param2pos[i];
675 n++;
677 isl_id_free(id);
679 isl_space_free(space);
681 space = isl_space_copy(domain);
682 space = isl_space_from_domain(space);
683 space = isl_space_add_dims(space, isl_dim_out,
684 pet_expr_get_n_arg(expr));
685 space = isl_space_wrap(space);
686 ls = isl_local_space_from_space(isl_space_copy(space));
687 space = isl_space_from_domain(space);
688 space = isl_space_add_dims(space, isl_dim_out, n_in + n);
689 ma = isl_multi_aff_zero(space);
691 for (i = 0; i < n_in; ++i) {
692 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
693 isl_dim_set, i);
694 ma = isl_multi_aff_set_aff(ma, i, aff);
696 for (i = 0; i < n; ++i) {
697 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
698 isl_dim_set, t2pos[i]);
699 ma = isl_multi_aff_set_aff(ma, n_in + i, aff);
701 isl_local_space_free(ls);
703 expr = pet_expr_access_pullback_multi_aff(expr, ma);
705 expr = remove_marked_self_dependences(expr, dim, n_arg);
707 free(t2pos);
708 free(param2pos);
709 return expr;
710 error:
711 free(t2pos);
712 free(param2pos);
713 return pet_expr_free(expr);
716 /* Wrapper around pet_expr_resolve_nested
717 * for use as a callback to pet_tree_map_expr.
719 static __isl_give pet_expr *resolve_nested(__isl_take pet_expr *expr,
720 void *user)
722 isl_space *space = user;
724 return pet_expr_resolve_nested(expr, space);
727 /* Call pet_expr_resolve_nested on each of the expressions in "tree".
729 __isl_give pet_tree *pet_tree_resolve_nested(__isl_take pet_tree *tree,
730 __isl_keep isl_space *space)
732 return pet_tree_map_expr(tree, &resolve_nested, space);
735 /* For each nested access parameter in the domain of "stmt",
736 * construct a corresponding pet_expr, place it before the original
737 * elements in stmt->args and record its position in "param2pos".
738 * n is the number of nested access parameters.
740 struct pet_stmt *pet_stmt_extract_nested(struct pet_stmt *stmt, int n,
741 int *param2pos)
743 int i;
744 isl_ctx *ctx;
745 isl_space *space;
746 int n_arg;
747 pet_expr **args;
749 ctx = isl_set_get_ctx(stmt->domain);
751 n_arg = stmt->n_arg;
752 args = isl_calloc_array(ctx, pet_expr *, n + n_arg);
753 if (!args)
754 goto error;
756 space = isl_set_get_space(stmt->domain);
757 if (isl_space_is_wrapping(space))
758 space = isl_space_domain(isl_space_unwrap(space));
759 n_arg = pet_extract_nested_from_space(space, 0, args, param2pos);
760 isl_space_free(space);
762 if (n_arg < 0)
763 goto error;
765 for (i = 0; i < stmt->n_arg; ++i)
766 args[n_arg + i] = stmt->args[i];
767 free(stmt->args);
768 stmt->args = args;
769 stmt->n_arg += n_arg;
771 return stmt;
772 error:
773 if (args) {
774 for (i = 0; i < n; ++i)
775 pet_expr_free(args[i]);
776 free(args);
778 pet_stmt_free(stmt);
779 return NULL;
782 /* Check whether any of the arguments i of "stmt" starting at position "n"
783 * is equal to one of the first "n" arguments j.
784 * If so, combine the constraints on arguments i and j and remove
785 * argument i.
787 static struct pet_stmt *remove_duplicate_arguments(struct pet_stmt *stmt, int n)
789 int i, j;
790 isl_map *map;
792 if (!stmt)
793 return NULL;
794 if (n == 0)
795 return stmt;
796 if (n == stmt->n_arg)
797 return stmt;
799 map = isl_set_unwrap(stmt->domain);
801 for (i = stmt->n_arg - 1; i >= n; --i) {
802 for (j = 0; j < n; ++j)
803 if (pet_expr_is_equal(stmt->args[i], stmt->args[j]))
804 break;
805 if (j >= n)
806 continue;
808 map = isl_map_equate(map, isl_dim_out, i, isl_dim_out, j);
809 map = isl_map_project_out(map, isl_dim_out, i, 1);
811 pet_expr_free(stmt->args[i]);
812 for (j = i; j + 1 < stmt->n_arg; ++j)
813 stmt->args[j] = stmt->args[j + 1];
814 stmt->n_arg--;
817 stmt->domain = isl_map_wrap(map);
818 if (!stmt->domain)
819 goto error;
820 return stmt;
821 error:
822 pet_stmt_free(stmt);
823 return NULL;
826 /* Look for parameters in the iteration domain of "stmt" that
827 * refer to nested accesses. In particular, these are
828 * parameters with name "__pet_expr".
830 * If there are any such parameters, then as many extra variables
831 * (after identifying identical nested accesses) are inserted in the
832 * range of the map wrapped inside the domain, before the original variables.
833 * If the original domain is not a wrapped map, then a new wrapped
834 * map is created with zero output dimensions.
835 * The parameters are then equated to the corresponding output dimensions
836 * and subsequently projected out, from the iteration domain,
837 * the schedule and the access relations.
838 * For each of the output dimensions, a corresponding argument
839 * expression is inserted, embedded in the current iteration domain.
840 * param2pos maps the position of the parameter to the position
841 * of the corresponding output dimension in the wrapped map.
843 struct pet_stmt *pet_stmt_resolve_nested(struct pet_stmt *stmt)
845 int i, n;
846 int nparam;
847 unsigned n_arg;
848 isl_ctx *ctx;
849 isl_map *map;
850 int *param2pos;
852 if (!stmt)
853 return NULL;
855 n = pet_nested_n_in_set(stmt->domain);
856 if (n == 0)
857 return stmt;
859 ctx = isl_set_get_ctx(stmt->domain);
861 n_arg = stmt->n_arg;
862 nparam = isl_set_dim(stmt->domain, isl_dim_param);
863 param2pos = isl_alloc_array(ctx, int, nparam);
864 stmt = pet_stmt_extract_nested(stmt, n, param2pos);
865 if (!stmt) {
866 free(param2pos);
867 return NULL;
870 n = stmt->n_arg - n_arg;
871 if (isl_set_is_wrapping(stmt->domain))
872 map = isl_set_unwrap(stmt->domain);
873 else
874 map = isl_map_from_domain(stmt->domain);
875 map = isl_map_insert_dims(map, isl_dim_out, 0, n);
877 for (i = nparam - 1; i >= 0; --i) {
878 isl_id *id;
880 if (!pet_nested_in_map(map, i))
881 continue;
883 id = pet_expr_access_get_id(stmt->args[param2pos[i]]);
884 map = isl_map_set_dim_id(map, isl_dim_out, param2pos[i], id);
885 map = isl_map_equate(map, isl_dim_param, i, isl_dim_out,
886 param2pos[i]);
887 map = isl_map_project_out(map, isl_dim_param, i, 1);
890 stmt->domain = isl_map_wrap(map);
892 stmt = pet_stmt_remove_nested_parameters(stmt);
893 stmt = remove_duplicate_arguments(stmt, n);
895 free(param2pos);
896 return stmt;
899 /* For each statement in "scop", move the parameters that correspond
900 * to nested access into the ranges of the domains and create
901 * corresponding argument expressions.
903 struct pet_scop *pet_scop_resolve_nested(struct pet_scop *scop)
905 int i;
907 if (!scop)
908 return NULL;
910 for (i = 0; i < scop->n_stmt; ++i) {
911 scop->stmts[i] = pet_stmt_resolve_nested(scop->stmts[i]);
912 if (!scop->stmts[i])
913 return pet_scop_free(scop);
916 return scop;