2 * Copyright 2011 Leiden University. All rights reserved.
3 * Copyright 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
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
46 /* A pet_context represents the context in which a pet_expr
47 * in converted to an affine expression.
49 * "domain" prescribes the domain of the affine expressions.
51 * "assignments" maps variable names to their currently known values.
52 * Internally, the domains of the values may be equal to some prefix
53 * of the space of "domain", but the domains are updated to be
54 * equal to the space of "domain" before passing them to the user.
56 * If "allow_nested" is set, then the affine expression created
57 * in this context may involve new parameters that encode a pet_expr.
63 isl_id_to_pw_aff
*assignments
;
67 /* Create a pet_context with the given domain, assignments,
68 * and value for allow_nested.
70 static __isl_give pet_context
*context_alloc(__isl_take isl_set
*domain
,
71 __isl_take isl_id_to_pw_aff
*assignments
, int allow_nested
)
75 if (!domain
|| !assignments
)
78 pc
= isl_calloc_type(isl_set_get_ctx(domain
), struct pet_context
);
84 pc
->assignments
= assignments
;
85 pc
->allow_nested
= allow_nested
;
90 isl_id_to_pw_aff_free(assignments
);
94 /* Create a pet_context with the given domain.
96 * Initially, there are no assigned values and parameters that
97 * encode a pet_expr are not allowed.
99 __isl_give pet_context
*pet_context_alloc(__isl_take isl_set
*domain
)
101 isl_id_to_pw_aff
*assignments
;
106 assignments
= isl_id_to_pw_aff_alloc(isl_set_get_ctx(domain
), 0);
107 return context_alloc(domain
, assignments
, 0);
110 /* Return an independent duplicate of "pc".
112 static __isl_give pet_context
*pet_context_dup(__isl_keep pet_context
*pc
)
119 dup
= context_alloc(isl_set_copy(pc
->domain
),
120 isl_id_to_pw_aff_copy(pc
->assignments
),
126 /* Return a pet_context that is equal to "pc" and that has only one reference.
128 static __isl_give pet_context
*pet_context_cow(__isl_take pet_context
*pc
)
136 return pet_context_dup(pc
);
139 /* Return an extra reference to "pc".
141 __isl_give pet_context
*pet_context_copy(__isl_keep pet_context
*pc
)
150 /* Free a reference to "pc" and return NULL.
152 __isl_null pet_context
*pet_context_free(__isl_take pet_context
*pc
)
159 isl_set_free(pc
->domain
);
160 isl_id_to_pw_aff_free(pc
->assignments
);
165 /* Return the isl_ctx in which "pc" was created.
167 isl_ctx
*pet_context_get_ctx(__isl_keep pet_context
*pc
)
169 return pc
? isl_set_get_ctx(pc
->domain
) : NULL
;
172 /* Return the domain of "pc".
174 __isl_give isl_set
*pet_context_get_domain(__isl_keep pet_context
*pc
)
178 return isl_set_copy(pc
->domain
);
181 /* Return the domain of "pc" in a form that is suitable
182 * for use as a gist context.
183 * In particular, remove all references to nested expression parameters
184 * so that they do not get introduced in the gisted expression.
186 __isl_give isl_set
*pet_context_get_gist_domain(__isl_keep pet_context
*pc
)
190 domain
= pet_context_get_domain(pc
);
191 domain
= pet_nested_remove_from_set(domain
);
195 /* Return the domain space of "pc".
197 * The domain of "pc" may have constraints involving parameters
198 * that encode a pet_expr. These parameters are not relevant
199 * outside this domain. Furthermore, they need to be resolved
200 * from the final result, so we do not want to propagate them needlessly.
202 __isl_give isl_space
*pet_context_get_space(__isl_keep pet_context
*pc
)
209 space
= isl_set_get_space(pc
->domain
);
210 space
= pet_nested_remove_from_space(space
);
214 /* Return the dimension of the domain space of "pc".
216 unsigned pet_context_dim(__isl_keep pet_context
*pc
)
220 return isl_set_dim(pc
->domain
, isl_dim_set
);
223 /* Return the assignments of "pc".
225 __isl_give isl_id_to_pw_aff
*pet_context_get_assignments(
226 __isl_keep pet_context
*pc
)
230 return isl_id_to_pw_aff_copy(pc
->assignments
);
233 /* Is "id" assigned any value in "pc"?
235 int pet_context_is_assigned(__isl_keep pet_context
*pc
, __isl_keep isl_id
*id
)
239 return isl_id_to_pw_aff_has(pc
->assignments
, id
);
242 /* Return the value assigned to "id" in "pc".
244 * Some dimensions may have been added to pc->domain after the value
245 * associated to "id" was added. We therefore need to adjust the domain
246 * of the stored value to match pc->domain by adding the missing
249 __isl_give isl_pw_aff
*pet_context_get_value(__isl_keep pet_context
*pc
,
250 __isl_take isl_id
*id
)
259 pa
= isl_id_to_pw_aff_get(pc
->assignments
, id
);
260 dim
= isl_pw_aff_dim(pa
, isl_dim_in
);
261 if (dim
== isl_set_dim(pc
->domain
, isl_dim_set
))
264 ma
= pet_prefix_projection(pet_context_get_space(pc
), dim
);
265 pa
= isl_pw_aff_pullback_multi_aff(pa
, ma
);
273 /* Assign the value "value" to "id" in "pc", replacing the previously
274 * assigned value, if any.
276 __isl_give pet_context
*pet_context_set_value(__isl_take pet_context
*pc
,
277 __isl_take isl_id
*id
, isl_pw_aff
*value
)
279 pc
= pet_context_cow(pc
);
282 pc
->assignments
= isl_id_to_pw_aff_set(pc
->assignments
, id
, value
);
283 if (!pc
->assignments
)
284 return pet_context_free(pc
);
288 isl_pw_aff_free(value
);
292 /* Remove any assignment to "id" in "pc".
294 __isl_give pet_context
*pet_context_clear_value(__isl_keep pet_context
*pc
,
295 __isl_take isl_id
*id
)
297 pc
= pet_context_cow(pc
);
300 pc
->assignments
= isl_id_to_pw_aff_drop(pc
->assignments
, id
);
301 if (!pc
->assignments
)
302 return pet_context_free(pc
);
309 /* Are affine expressions created in this context allowed to involve
310 * parameters that encode a pet_expr?
312 int pet_context_allow_nesting(__isl_keep pet_context
*pc
)
316 return pc
->allow_nested
;
319 /* Allow affine expressions created in this context to involve
320 * parameters that encode a pet_expr based on the value of "allow_nested".
322 __isl_give pet_context
*pet_context_set_allow_nested(__isl_take pet_context
*pc
,
327 if (pc
->allow_nested
== allow_nested
)
329 pc
= pet_context_cow(pc
);
332 pc
->allow_nested
= allow_nested
;
336 /* If the access expression "expr" writes to a (non-virtual) scalar,
337 * then remove any assignment to the scalar in "pc".
339 static int clear_write(__isl_keep pet_expr
*expr
, void *user
)
342 pet_context
**pc
= (pet_context
**) user
;
344 if (!pet_expr_access_is_write(expr
))
346 if (!pet_expr_is_scalar_access(expr
))
349 id
= pet_expr_access_get_id(expr
);
350 if (isl_id_get_user(id
))
351 *pc
= pet_context_clear_value(*pc
, id
);
358 /* Look for any writes to scalar variables in "expr" and
359 * remove any assignment to them in "pc".
361 __isl_give pet_context
*pet_context_clear_writes_in_expr(
362 __isl_take pet_context
*pc
, __isl_keep pet_expr
*expr
)
364 if (pet_expr_foreach_access_expr(expr
, &clear_write
, &pc
) < 0)
365 pc
= pet_context_free(pc
);
370 /* Look for any writes to scalar variables in "tree" and
371 * remove any assignment to them in "pc".
373 __isl_give pet_context
*pet_context_clear_writes_in_tree(
374 __isl_take pet_context
*pc
, __isl_keep pet_tree
*tree
)
376 if (pet_tree_foreach_access_expr(tree
, &clear_write
, &pc
) < 0)
377 pc
= pet_context_free(pc
);
382 /* Internal data structure for pet_context_add_parameters.
384 * "pc" is the context that is being updated.
385 * "get_array_size" is a callback function that can be used to determine
386 * the size of the array that is accessed by a given access expression.
387 * "user" is the user data for this callback.
389 struct pet_context_add_parameter_data
{
391 __isl_give pet_expr
*(*get_array_size
)(__isl_keep pet_expr
*access
,
396 /* Given an access expression "expr", add a parameter assignment to data->pc
397 * to the variable being accessed, provided it is a read from an integer
399 * If an array is being accesed, then recursively call the function
400 * on each of the access expressions in the size expression of the array.
402 static int add_parameter(__isl_keep pet_expr
*expr
, void *user
)
404 struct pet_context_add_parameter_data
*data
= user
;
412 if (!pet_expr_is_scalar_access(expr
)) {
413 pet_expr
*size
= data
->get_array_size(expr
, data
->user
);
414 if (pet_expr_foreach_access_expr(size
,
415 &add_parameter
, data
) < 0)
416 data
->pc
= pet_context_free(data
->pc
);
420 if (!pet_expr_access_is_read(expr
))
422 if (pet_expr_get_type_size(expr
) == 0)
425 id
= pet_expr_access_get_id(expr
);
426 if (pet_context_is_assigned(data
->pc
, id
)) {
431 space
= pet_context_get_space(data
->pc
);
432 pos
= isl_space_find_dim_by_id(space
, isl_dim_param
, id
);
434 pos
= isl_space_dim(space
, isl_dim_param
);
435 space
= isl_space_add_dims(space
, isl_dim_param
, 1);
436 space
= isl_space_set_dim_id(space
, isl_dim_param
, pos
,
440 ls
= isl_local_space_from_space(space
);
441 aff
= isl_aff_var_on_domain(ls
, isl_dim_param
, pos
);
442 pa
= isl_pw_aff_from_aff(aff
);
443 data
->pc
= pet_context_set_value(data
->pc
, id
, pa
);
448 /* Add an assignment to "pc" for each parameter in "tree".
449 * "get_array_size" is a callback function that can be used to determine
450 * the size of the array that is accessed by a given access expression.
452 * We initially treat as parameters any integer variable that is read
453 * anywhere in "tree" or in any of the size expressions for any of
454 * the arrays accessed in "tree".
455 * Then we remove from those variables that are written anywhere
458 __isl_give pet_context
*pet_context_add_parameters(__isl_take pet_context
*pc
,
459 __isl_keep pet_tree
*tree
,
460 __isl_give pet_expr
*(*get_array_size
)(__isl_keep pet_expr
*access
,
461 void *user
), void *user
)
463 struct pet_context_add_parameter_data data
;
466 data
.get_array_size
= get_array_size
;
468 if (pet_tree_foreach_access_expr(tree
, &add_parameter
, &data
) < 0)
469 data
.pc
= pet_context_free(data
.pc
);
471 data
.pc
= pet_context_clear_writes_in_tree(data
.pc
, tree
);
476 /* Given an access expression, check if it reads a scalar variable
477 * that has a known value in "pc".
478 * If so, then replace the access by an access to that value.
480 static __isl_give pet_expr
*access_plug_in_affine_read(
481 __isl_take pet_expr
*expr
, void *user
)
483 pet_context
*pc
= user
;
486 if (pet_expr_access_is_write(expr
))
488 if (!pet_expr_is_scalar_access(expr
))
491 pa
= pet_expr_extract_affine(expr
, pc
);
493 return pet_expr_free(expr
);
494 if (isl_pw_aff_involves_nan(pa
)) {
500 expr
= pet_expr_from_index(isl_multi_pw_aff_from_pw_aff(pa
));
505 /* Replace every read access in "expr" to a scalar variable
506 * that has a known value in "pc" by that known value.
508 static __isl_give pet_expr
*plug_in_affine_read(__isl_take pet_expr
*expr
,
509 __isl_keep pet_context
*pc
)
511 return pet_expr_map_access(expr
, &access_plug_in_affine_read
, pc
);
514 /* Add an extra affine expression to "mpa" that is equal to
515 * an extra dimension in the range of the wrapped relation in the domain
516 * of "mpa". "n_arg" is the original number of dimensions in this range.
518 * That is, if "n_arg" is 0, then the input has the form
522 * and the output has the form
524 * [D(i) -> [y]] -> [f(i), y]
526 * If "n_arg" is different from 0, then the input has the form
528 * [D(i) -> [x]] -> [f(i,x)]
530 * with x consisting of "n_arg" dimensions, and the output has the form
532 * [D(i) -> [x,y]] -> [f(i,x), y]
535 * We first adjust the domain of "mpa" and then add the extra
536 * affine expression (y).
538 static __isl_give isl_multi_pw_aff
*add_arg(__isl_take isl_multi_pw_aff
*mpa
,
544 isl_multi_pw_aff
*mpa2
;
547 space
= isl_space_domain(isl_multi_pw_aff_get_space(mpa
));
548 dim
= isl_space_dim(space
, isl_dim_set
);
549 space
= isl_space_from_domain(space
);
550 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
551 ma
= isl_multi_aff_domain_map(space
);
554 isl_space
*dom
, *ran
;
556 space
= isl_space_domain(isl_multi_pw_aff_get_space(mpa
));
557 space
= isl_space_unwrap(space
);
558 dom
= isl_space_domain(isl_space_copy(space
));
559 dim
= isl_space_dim(dom
, isl_dim_set
);
560 ran
= isl_space_range(space
);
561 ran
= isl_space_add_dims(ran
, isl_dim_set
, 1);
562 space
= isl_space_map_from_set(dom
);
563 ma
= isl_multi_aff_identity(space
);
564 ma2
= isl_multi_aff_project_out_map(ran
, isl_dim_set
, n_arg
, 1);
565 ma
= isl_multi_aff_product(ma
, ma2
);
568 mpa
= isl_multi_pw_aff_pullback_multi_aff(mpa
, ma
);
569 space
= isl_space_domain(isl_multi_pw_aff_get_space(mpa
));
570 ma
= isl_multi_aff_project_out_map(space
, isl_dim_set
, 0, dim
+ n_arg
);
571 mpa2
= isl_multi_pw_aff_from_multi_aff(ma
);
572 mpa
= isl_multi_pw_aff_flat_range_product(mpa
, mpa2
);
577 /* Add the integer value from "arg" to "mpa".
579 static __isl_give isl_multi_pw_aff
*add_int(__isl_take isl_multi_pw_aff
*mpa
,
580 __isl_take pet_expr
*arg
)
585 isl_multi_pw_aff
*mpa_arg
;
587 v
= pet_expr_int_get_val(arg
);
590 space
= isl_space_domain(isl_multi_pw_aff_get_space(mpa
));
591 aff
= isl_aff_val_on_domain(isl_local_space_from_space(space
), v
);
592 mpa_arg
= isl_multi_pw_aff_from_pw_aff(isl_pw_aff_from_aff(aff
));
594 mpa
= isl_multi_pw_aff_flat_range_product(mpa
, mpa_arg
);
599 /* Add the affine expression from "arg" to "mpa".
600 * "n_arg" is the number of dimensions in the range of the wrapped
601 * relation in the domain of "mpa".
603 static __isl_give isl_multi_pw_aff
*add_aff(__isl_take isl_multi_pw_aff
*mpa
,
604 int n_arg
, __isl_take pet_expr
*arg
)
606 isl_multi_pw_aff
*mpa_arg
;
608 mpa_arg
= pet_expr_access_get_index(arg
);
615 space
= isl_space_domain(isl_multi_pw_aff_get_space(mpa
));
616 space
= isl_space_unwrap(space
);
617 ma
= isl_multi_aff_domain_map(space
);
618 mpa_arg
= isl_multi_pw_aff_pullback_multi_aff(mpa_arg
, ma
);
621 mpa
= isl_multi_pw_aff_flat_range_product(mpa
, mpa_arg
);
626 /* Combine the index expression of "expr" with the subaccess relation "access".
627 * If "add" is set, then it is not the index expression of "expr" itself
628 * that is passed to the function, but its address.
630 * We call patch_map on each map in "access" and return the combined results.
632 static __isl_give isl_union_map
*patch(__isl_take isl_union_map
*access
,
633 __isl_keep pet_expr
*expr
, int add
)
635 isl_multi_pw_aff
*prefix
;
637 prefix
= pet_expr_access_get_index(expr
);
638 return pet_patch_union_map(prefix
, access
, add
, 1);
641 /* Set the access relations of "expr", which appears in the argument
642 * at position "pos" in a call expression by composing the access
643 * relations in "summary" with the expression "int_arg" of the integer
644 * arguments in terms of the domain and expression arguments of "expr" and
645 * combining the result with the index expression passed to the function.
646 * If "add" is set, then it is not "expr" itself that is passed
647 * to the function, but the address of "expr".
649 * We reset the read an write flag of "expr" and rely on
650 * pet_expr_access_set_access setting the flags based on
651 * the access relations.
653 * After relating each access relation of the called function
654 * to the domain and expression arguments at the call site,
655 * the result is combined with the index expression by the function patch
656 * and then stored in the access expression.
658 static __isl_give pet_expr
*set_access_relations(__isl_take pet_expr
*expr
,
659 __isl_keep pet_function_summary
*summary
, int pos
,
660 __isl_take isl_multi_pw_aff
*int_arg
, int add
)
662 enum pet_expr_access_type type
;
664 expr
= pet_expr_access_set_read(expr
, 0);
665 expr
= pet_expr_access_set_write(expr
, 0);
666 for (type
= pet_expr_access_begin
; type
< pet_expr_access_end
; ++type
) {
667 isl_union_map
*access
;
669 access
= pet_function_summary_arg_get_access(summary
,
671 access
= isl_union_map_preimage_domain_multi_pw_aff(access
,
672 isl_multi_pw_aff_copy(int_arg
));
673 access
= patch(access
, expr
, add
);
674 expr
= pet_expr_access_set_access(expr
, type
, access
);
676 isl_multi_pw_aff_free(int_arg
);
681 /* Set the access relations of "arg", which appears in the argument
682 * at position "pos" in the call expression "call" based on the
683 * information in "summary".
684 * If "add" is set, then it is not "arg" itself that is passed
685 * to the function, but the address of "arg".
687 * We create an affine function "int_arg" that expresses
688 * the integer function call arguments in terms of the domain of "arg"
689 * (i.e., the outer loop iterators) and the expression arguments.
690 * If the actual argument is not an affine expression or if it itself
691 * has expression arguments, then it is added as an argument to "arg" and
692 * "int_arg" is made to reference this additional expression argument.
694 * Finally, we call set_access_relations to plug in the actual arguments
695 * (expressed in "int_arg") into the access relations in "summary" and
696 * to add the resulting access relations to "arg".
698 static __isl_give pet_expr
*access_plug_in_summary(__isl_take pet_expr
*arg
,
699 __isl_keep pet_expr
*call
, __isl_keep pet_function_summary
*summary
,
704 isl_multi_pw_aff
*int_arg
;
707 space
= pet_expr_access_get_augmented_domain_space(arg
);
708 space
= isl_space_from_domain(space
);
709 arg_n_arg
= pet_expr_get_n_arg(arg
);
710 int_arg
= isl_multi_pw_aff_zero(space
);
711 n
= pet_function_summary_get_n_arg(summary
);
712 for (j
= 0; j
< n
; ++j
) {
716 if (!pet_function_summary_arg_is_int(summary
, j
))
719 arg_j
= pet_expr_get_arg(call
, j
);
720 arg_j_n_arg
= pet_expr_get_n_arg(arg_j
);
721 if (pet_expr_get_type(arg_j
) == pet_expr_int
) {
722 int_arg
= add_int(int_arg
, arg_j
);
723 } else if (arg_j_n_arg
!= 0 || !pet_expr_is_affine(arg_j
)) {
724 arg
= pet_expr_insert_arg(arg
, arg_n_arg
,
726 int_arg
= add_arg(int_arg
, arg_n_arg
);
729 int_arg
= add_aff(int_arg
, arg_n_arg
, arg_j
);
732 arg
= set_access_relations(arg
, summary
, pos
, int_arg
, add
);
737 /* Given the argument "arg" at position "pos" of "call",
738 * check if it is either an access expression or the address
739 * of an access expression. If so, use the information in "summary"
740 * to set the access relations of the access expression.
742 static __isl_give pet_expr
*arg_plug_in_summary(__isl_take pet_expr
*arg
,
743 __isl_keep pet_expr
*call
, __isl_keep pet_function_summary
*summary
,
746 enum pet_expr_type type
;
749 type
= pet_expr_get_type(arg
);
750 if (type
== pet_expr_access
)
751 return access_plug_in_summary(arg
, call
, summary
, pos
, 0);
752 if (!pet_expr_is_address_of(arg
))
755 arg2
= pet_expr_get_arg(arg
, 0);
756 if (pet_expr_get_type(arg2
) == pet_expr_access
)
757 arg2
= access_plug_in_summary(arg2
, call
, summary
, pos
, 1);
758 arg
= pet_expr_set_arg(arg
, 0, arg2
);
763 /* Given a call expression, check if the integer arguments can
764 * be represented by affine expressions in the context "pc"
765 * (assuming they are not already affine expressions).
766 * If so, replace these arguments by the corresponding affine expressions.
768 static __isl_give pet_expr
*call_plug_in_affine_args(__isl_take pet_expr
*call
,
769 __isl_keep pet_context
*pc
)
773 n
= pet_expr_get_n_arg(call
);
774 for (i
= 0; i
< n
; ++i
) {
778 arg
= pet_expr_get_arg(call
, i
);
780 return pet_expr_free(call
);
781 if (pet_expr_get_type_size(arg
) == 0 ||
782 pet_expr_is_affine(arg
)) {
787 pa
= pet_expr_extract_affine(arg
, pc
);
790 return pet_expr_free(call
);
791 if (isl_pw_aff_involves_nan(pa
)) {
796 arg
= pet_expr_from_index(isl_multi_pw_aff_from_pw_aff(pa
));
797 call
= pet_expr_set_arg(call
, i
, arg
);
803 /* If "call" has an associated function summary, then use it
804 * to set the access relations of the array arguments of the function call.
806 * We first plug in affine expressions for the integer arguments
807 * whenever possible as these arguments will be plugged in
808 * in the access relations of the array arguments.
810 static __isl_give pet_expr
*call_plug_in_summary(__isl_take pet_expr
*call
,
813 pet_context
*pc
= user
;
814 pet_function_summary
*summary
;
817 if (!pet_expr_call_has_summary(call
))
820 call
= call_plug_in_affine_args(call
, pc
);
822 summary
= pet_expr_call_get_summary(call
);
824 return pet_expr_free(call
);
826 n
= pet_expr_get_n_arg(call
);
827 for (i
= 0; i
< n
; ++i
) {
830 if (!pet_function_summary_arg_is_array(summary
, i
))
833 arg_i
= pet_expr_get_arg(call
, i
);
834 arg_i
= arg_plug_in_summary(arg_i
, call
, summary
, i
);
835 call
= pet_expr_set_arg(call
, i
, arg_i
);
838 pet_function_summary_free(summary
);
842 /* For each call subexpression of "expr", plug in the access relations
843 * from the associated function summary (if any).
845 static __isl_give pet_expr
*plug_in_summaries(__isl_take pet_expr
*expr
,
846 __isl_keep pet_context
*pc
)
848 return pet_expr_map_call(expr
, &call_plug_in_summary
, pc
);
851 /* Evaluate "expr" in the context of "pc".
853 * In particular, we first make sure that all the access expressions
854 * inside "expr" have the same domain as "pc".
855 * Then, we plug in affine expressions for scalar reads,
856 * plug in the arguments of all access expressions in "expr" and
857 * plug in the access relations from the summary functions associated
858 * to call expressions.
860 __isl_give pet_expr
*pet_context_evaluate_expr(__isl_keep pet_context
*pc
,
861 __isl_take pet_expr
*expr
)
863 expr
= pet_expr_insert_domain(expr
, pet_context_get_space(pc
));
864 expr
= plug_in_affine_read(expr
, pc
);
865 expr
= pet_expr_plug_in_args(expr
, pc
);
866 expr
= plug_in_summaries(expr
, pc
);
870 /* Wrapper around pet_context_evaluate_expr
871 * for use as a callback to pet_tree_map_expr.
873 static __isl_give pet_expr
*evaluate_expr(__isl_take pet_expr
*expr
,
876 pet_context
*pc
= user
;
878 return pet_context_evaluate_expr(pc
, expr
);
881 /* Evaluate "tree" in the context of "pc".
882 * That is, evaluate all the expressions of "tree" in the context of "pc".
884 __isl_give pet_tree
*pet_context_evaluate_tree(__isl_keep pet_context
*pc
,
885 __isl_take pet_tree
*tree
)
887 return pet_tree_map_expr(tree
, &evaluate_expr
, pc
);
890 /* Add an unbounded inner dimension "id" to pc->domain.
892 * The assignments are not adjusted here and therefore keep
893 * their original domain. These domains need to be adjusted before
894 * these assigned values can be used. This is taken care of by
895 * pet_context_get_value.
897 static __isl_give pet_context
*extend_domain(__isl_take pet_context
*pc
,
898 __isl_take isl_id
*id
)
902 pc
= pet_context_cow(pc
);
906 pos
= pet_context_dim(pc
);
907 pc
->domain
= isl_set_add_dims(pc
->domain
, isl_dim_set
, 1);
908 pc
->domain
= isl_set_set_dim_id(pc
->domain
, isl_dim_set
, pos
, id
);
910 return pet_context_free(pc
);
914 pet_context_free(pc
);
919 /* Add an unbounded inner iterator "id" to pc->domain.
920 * Additionally, mark the variable "id" as having the value of this
921 * new inner iterator.
923 __isl_give pet_context
*pet_context_add_inner_iterator(
924 __isl_take pet_context
*pc
, __isl_take isl_id
*id
)
935 pos
= pet_context_dim(pc
);
936 pc
= extend_domain(pc
, isl_id_copy(id
));
940 space
= pet_context_get_space(pc
);
941 ls
= isl_local_space_from_space(space
);
942 aff
= isl_aff_var_on_domain(ls
, isl_dim_set
, pos
);
943 pa
= isl_pw_aff_from_aff(aff
);
945 pc
= pet_context_set_value(pc
, id
, pa
);
949 pet_context_free(pc
);
954 /* Add an inner iterator to pc->domain.
955 * In particular, extend the domain with an inner loop { [t] : t >= 0 }.
957 __isl_give pet_context
*pet_context_add_infinite_loop(
958 __isl_take pet_context
*pc
)
967 dim
= pet_context_dim(pc
);
968 ctx
= pet_context_get_ctx(pc
);
969 id
= isl_id_alloc(ctx
, "t", NULL
);
970 pc
= extend_domain(pc
, id
);
971 pc
= pet_context_cow(pc
);
974 pc
->domain
= isl_set_lower_bound_si(pc
->domain
, isl_dim_set
, dim
, 0);
976 return pet_context_free(pc
);
981 /* Internal data structure for preimage_domain.
983 * "ma" is the function under which the preimage should be computed.
984 * "assignments" collects the results.
986 struct pet_preimage_domain_data
{
988 isl_id_to_pw_aff
*assignments
;
991 /* Add the assignment to "key" of the preimage of "val" under data->ma
992 * to data->assignments.
994 * Some dimensions may have been added to the domain of the enclosing
995 * pet_context after the value "val" was added. We therefore need to
996 * adjust the domain of "val" to match the range of data->ma (which
997 * in turn matches the domain of the pet_context), by adding the missing
1000 static isl_stat
preimage_domain_pair(__isl_take isl_id
*key
,
1001 __isl_take isl_pw_aff
*val
, void *user
)
1003 struct pet_preimage_domain_data
*data
= user
;
1007 ma
= isl_multi_aff_copy(data
->ma
);
1009 dim
= isl_pw_aff_dim(val
, isl_dim_in
);
1010 if (dim
!= isl_multi_aff_dim(data
->ma
, isl_dim_out
)) {
1012 isl_multi_aff
*proj
;
1013 space
= isl_multi_aff_get_space(data
->ma
);
1014 space
= isl_space_range(space
);
1015 proj
= pet_prefix_projection(space
, dim
);
1016 ma
= isl_multi_aff_pullback_multi_aff(proj
, ma
);
1019 val
= isl_pw_aff_pullback_multi_aff(val
, ma
);
1020 data
->assignments
= isl_id_to_pw_aff_set(data
->assignments
, key
, val
);
1025 /* Compute the preimage of "assignments" under the function represented by "ma".
1026 * In other words, plug in "ma" in the domains of the assigned values.
1028 static __isl_give isl_id_to_pw_aff
*preimage_domain(
1029 __isl_take isl_id_to_pw_aff
*assignments
, __isl_keep isl_multi_aff
*ma
)
1031 struct pet_preimage_domain_data data
= { ma
};
1034 ctx
= isl_id_to_pw_aff_get_ctx(assignments
);
1035 data
.assignments
= isl_id_to_pw_aff_alloc(ctx
, 0);
1036 if (isl_id_to_pw_aff_foreach(assignments
, &preimage_domain_pair
,
1038 data
.assignments
= isl_id_to_pw_aff_free(data
.assignments
);
1039 isl_id_to_pw_aff_free(assignments
);
1041 return data
.assignments
;
1044 /* Compute the preimage of "pc" under the function represented by "ma".
1045 * In other words, plug in "ma" in the domain of "pc".
1047 __isl_give pet_context
*pet_context_preimage_domain(__isl_take pet_context
*pc
,
1048 __isl_keep isl_multi_aff
*ma
)
1050 pc
= pet_context_cow(pc
);
1053 pc
->domain
= isl_set_preimage_multi_aff(pc
->domain
,
1054 isl_multi_aff_copy(ma
));
1055 pc
->assignments
= preimage_domain(pc
->assignments
, ma
);
1056 if (!pc
->domain
|| !pc
->assignments
)
1057 return pet_context_free(pc
);
1061 /* Add the constraints of "set" to the domain of "pc".
1063 __isl_give pet_context
*pet_context_intersect_domain(__isl_take pet_context
*pc
,
1064 __isl_take isl_set
*set
)
1066 pc
= pet_context_cow(pc
);
1069 pc
->domain
= isl_set_intersect(pc
->domain
, set
);
1071 return pet_context_free(pc
);
1074 pet_context_free(pc
);
1079 void pet_context_dump(__isl_keep pet_context
*pc
)
1083 fprintf(stderr
, "domain: ");
1084 isl_set_dump(pc
->domain
);
1085 fprintf(stderr
, "assignments: ");
1086 isl_id_to_pw_aff_dump(pc
->assignments
);
1087 fprintf(stderr
, "nesting allowed: %d\n", pc
->allow_nested
);