2 * Copyright 2012 Ecole Normale Superieure
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege,
7 * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
11 #include <isl_ast_build_expr.h>
12 #include <isl_ast_private.h>
13 #include <isl_ast_build_private.h>
15 /* Compute the minimum of the integer affine expression "obj" over the points
16 * in build->domain and put the result in *opt.
18 enum isl_lp_result
isl_ast_build_min(__isl_keep isl_ast_build
*build
,
19 __isl_keep isl_aff
*obj
, isl_int
*opt
)
24 return isl_set_min(build
->domain
, obj
, opt
);
27 /* Compute the maximum of the integer affine expression "obj" over the points
28 * in build->domain and put the result in *opt.
30 enum isl_lp_result
isl_ast_build_max(__isl_keep isl_ast_build
*build
,
31 __isl_keep isl_aff
*obj
, isl_int
*opt
)
36 return isl_set_max(build
->domain
, obj
, opt
);
39 /* Create an isl_ast_expr evaluating the div at position "pos" in "ls".
40 * The result is simplified in terms of build->domain.
41 * The size is computed by the caller.
43 * "ls" is known to be non-NULL.
45 * Let the div be of the form floor(e/d).
46 * If the ast_build_prefer_pdiv option is set then we check if "e"
47 * is non-negative, so that we can generate
49 * (pdiv_q, expr(e), expr(d))
53 * (fdiv_q, expr(e), expr(d))
56 static __isl_give isl_ast_expr
*var_div(__isl_keep isl_local_space
*ls
,
57 int pos
, __isl_keep isl_ast_build
*build
)
59 isl_ctx
*ctx
= isl_local_space_get_ctx(ls
);
61 isl_ast_expr
*num
, *den
;
63 enum isl_ast_op_type type
;
65 aff
= isl_local_space_get_div(ls
, pos
);
67 isl_aff_get_denominator(aff
, &d
);
68 aff
= isl_aff_scale(aff
, d
);
69 den
= isl_ast_expr_alloc_int(ctx
, d
);
72 type
= isl_ast_op_fdiv_q
;
73 if (isl_options_get_ast_build_prefer_pdiv(ctx
)) {
74 int non_neg
= isl_ast_build_aff_is_nonneg(build
, aff
);
76 aff
= isl_aff_free(aff
);
78 type
= isl_ast_op_pdiv_q
;
81 num
= isl_ast_expr_from_aff(aff
, build
);
82 return isl_ast_expr_alloc_binary(type
, num
, den
);
85 /* Create an isl_ast_expr evaluating the specified dimension of "ls".
86 * The result is simplified in terms of build->domain.
87 * The size is computed by the caller.
89 * The isl_ast_expr is constructed based on the type of the dimension.
90 * - divs are constructed by var_div
91 * - set variables are constructed from the iterator isl_ids in "build"
92 * - parameters are constructed from the isl_ids in "ls"
94 static __isl_give isl_ast_expr
*var(__isl_keep isl_local_space
*ls
,
95 enum isl_dim_type type
, int pos
, __isl_keep isl_ast_build
*build
)
97 isl_ctx
*ctx
= isl_local_space_get_ctx(ls
);
100 if (type
== isl_dim_div
)
101 return var_div(ls
, pos
, build
);
103 if (type
== isl_dim_set
) {
104 id
= isl_ast_build_get_iterator_id(build
, pos
);
105 return isl_ast_expr_from_id(id
);
108 if (!isl_local_space_has_dim_id(ls
, type
, pos
))
109 isl_die(ctx
, isl_error_internal
, "unnamed dimension",
111 id
= isl_local_space_get_dim_id(ls
, type
, pos
);
112 return isl_ast_expr_from_id(id
);
115 /* Does "expr" represent the zero integer?
117 static int ast_expr_is_zero(__isl_keep isl_ast_expr
*expr
)
121 if (expr
->type
!= isl_ast_expr_int
)
123 return isl_int_is_zero(expr
->u
.i
);
126 /* Create an expression representing the sum of "expr1" and "expr2",
127 * provided neither of the two expressions is identically zero.
129 static __isl_give isl_ast_expr
*ast_expr_add(__isl_take isl_ast_expr
*expr1
,
130 __isl_take isl_ast_expr
*expr2
)
132 if (!expr1
|| !expr2
)
135 if (ast_expr_is_zero(expr1
)) {
136 isl_ast_expr_free(expr1
);
140 if (ast_expr_is_zero(expr2
)) {
141 isl_ast_expr_free(expr2
);
145 return isl_ast_expr_add(expr1
, expr2
);
147 isl_ast_expr_free(expr1
);
148 isl_ast_expr_free(expr2
);
152 /* Subtract expr2 from expr1.
154 * If expr2 is zero, we simply return expr1.
155 * If expr1 is zero, we return
157 * (isl_ast_op_minus, expr2)
159 * Otherwise, we return
161 * (isl_ast_op_sub, expr1, expr2)
163 static __isl_give isl_ast_expr
*ast_expr_sub(__isl_take isl_ast_expr
*expr1
,
164 __isl_take isl_ast_expr
*expr2
)
166 if (!expr1
|| !expr2
)
169 if (ast_expr_is_zero(expr2
)) {
170 isl_ast_expr_free(expr2
);
174 if (ast_expr_is_zero(expr1
)) {
175 isl_ast_expr_free(expr1
);
176 return isl_ast_expr_neg(expr2
);
179 return isl_ast_expr_sub(expr1
, expr2
);
181 isl_ast_expr_free(expr1
);
182 isl_ast_expr_free(expr2
);
186 /* Return an isl_ast_expr that represents
190 * v is assumed to be non-negative.
191 * The result is simplified in terms of build->domain.
193 static __isl_give isl_ast_expr
*isl_ast_expr_mod(isl_int v
,
194 __isl_keep isl_aff
*aff
, isl_int d
, __isl_keep isl_ast_build
*build
)
203 ctx
= isl_aff_get_ctx(aff
);
204 expr
= isl_ast_expr_from_aff(isl_aff_copy(aff
), build
);
206 c
= isl_ast_expr_alloc_int(ctx
, d
);
207 expr
= isl_ast_expr_alloc_binary(isl_ast_op_pdiv_r
, expr
, c
);
209 if (!isl_int_is_one(v
)) {
210 c
= isl_ast_expr_alloc_int(ctx
, v
);
211 expr
= isl_ast_expr_mul(c
, expr
);
217 /* Create an isl_ast_expr evaluating "v" times the specified dimension of "ls".
218 * The result is simplified in terms of build->domain.
220 * Let e be the expression for the specified dimension.
221 * If v is 1, we simply return e.
222 * If v is -1, we return
224 * (isl_ast_op_minus, e)
226 * Otherwise, we return
228 * (isl_ast_op_mul, expr(v), e)
230 static __isl_give isl_ast_expr
*isl_ast_expr_term(
231 __isl_keep isl_local_space
*ls
, enum isl_dim_type type
, int pos
,
232 isl_int v
, __isl_keep isl_ast_build
*build
)
241 ctx
= isl_local_space_get_ctx(ls
);
242 expr
= var(ls
, type
, pos
, build
);
244 if (!isl_int_is_one(v
)) {
245 if (isl_int_is_negone(v
)) {
246 expr
= isl_ast_expr_neg(expr
);
248 c
= isl_ast_expr_alloc_int(ctx
, v
);
249 expr
= isl_ast_expr_mul(c
, expr
);
256 /* Add an expression for "v" times the specified dimension of "ls"
259 * Let e be the expression for the specified dimension.
260 * If "v" is negative, we create
262 * (isl_ast_op_sub, cons->expr, e)
264 * except when cons->expr is trivially zero, in which case we create
266 * (isl_ast_op_mines, e)
270 * If "v" is positive, we simply create
272 * (isl_ast_op_add, cons->expr, e)
275 static __isl_give isl_ast_expr
*isl_ast_expr_add_term(
276 __isl_take isl_ast_expr
*expr
,
277 __isl_keep isl_local_space
*ls
, enum isl_dim_type type
, int pos
,
278 isl_int v
, __isl_keep isl_ast_build
*build
)
285 if (isl_int_is_neg(v
) && !ast_expr_is_zero(expr
)) {
287 term
= isl_ast_expr_term(ls
, type
, pos
, v
, build
);
288 return ast_expr_sub(expr
, term
);
290 term
= isl_ast_expr_term(ls
, type
, pos
, v
, build
);
291 return ast_expr_add(expr
, term
);
295 /* Add an expression for "v" to expr.
297 static __isl_give isl_ast_expr
*isl_ast_expr_add_int(
298 __isl_take isl_ast_expr
*expr
, isl_int v
)
301 isl_ast_expr
*expr_int
;
306 if (isl_int_is_zero(v
))
309 ctx
= isl_ast_expr_get_ctx(expr
);
310 if (isl_int_is_neg(v
) && !ast_expr_is_zero(expr
)) {
312 expr_int
= isl_ast_expr_alloc_int(ctx
, v
);
313 return ast_expr_sub(expr
, expr_int
);
315 expr_int
= isl_ast_expr_alloc_int(ctx
, v
);
316 return ast_expr_add(expr
, expr_int
);
320 /* Check if "aff" involves any (implicit) modulo computations.
321 * If so, remove them from aff and add expressions corresponding
322 * to those modulo computations to *pos and/or *neg.
323 * We only do this if the option ast_build_prefer_pdiv is set.
325 * A modulo expression is of the form
327 * a mod m = a - m * floor(a / m)
329 * To detect them in aff, we look for terms of the form
331 * (f * m * floor(a / m)) / d
335 * (f * (a - (a mod m))) / d = (f * a) / d - (f * (a mod m)) / d
337 * and extract out -f * (a mod m).
338 * In particular, if f > 0, we add (f * (a mod m)) to *neg.
339 * If f < 0, we add ((-f) * (a mod m)) to *pos.
341 * The caller is responsible for dividing *neg and/or *pos by d.
343 static __isl_give isl_aff
*extract_modulos(__isl_take isl_aff
*aff
,
344 __isl_keep isl_ast_expr
**pos
, __isl_keep isl_ast_expr
**neg
,
345 __isl_keep isl_ast_build
*build
)
355 ctx
= isl_aff_get_ctx(aff
);
356 if (!isl_options_get_ast_build_prefer_pdiv(ctx
))
361 ls
= isl_aff_get_domain_local_space(aff
);
363 n
= isl_aff_dim(aff
, isl_dim_div
);
364 for (j
= 0; j
< n
; ++j
) {
370 isl_aff_get_coefficient(aff
, isl_dim_div
, j
, &v
);
371 if (isl_int_is_zero(v
))
373 div
= isl_local_space_get_div(ls
, j
);
374 isl_aff_get_denominator(div
, &d
);
375 mod
= isl_int_is_divisible_by(v
, d
);
377 mod
= isl_ast_build_aff_is_nonneg(build
, div
);
379 aff
= isl_aff_free(aff
);
386 div
= isl_aff_scale(div
, d
);
387 isl_int_divexact(v
, v
, d
);
390 expr
= isl_ast_expr_mod(v
, div
, d
, build
);
392 *neg
= ast_expr_add(*neg
, expr
);
394 *pos
= ast_expr_add(*pos
, expr
);
395 aff
= isl_aff_set_coefficient_si(aff
, isl_dim_div
, j
, 0);
398 div
= isl_aff_scale(div
, v
);
399 isl_aff_get_denominator(aff
, &d
);
400 div
= isl_aff_scale_down(div
, d
);
401 aff
= isl_aff_add(aff
, div
);
404 isl_local_space_free(ls
);
411 /* Construct an isl_ast_expr that evaluates the affine expression "aff",
412 * The result is simplified in terms of build->domain.
414 * We first extract hidden modulo computations from the affine expression
415 * and then add terms for each variable with a non-zero coefficient.
416 * Finally, if the affine expression has a non-trivial denominator,
417 * we divide the resulting isl_ast_expr by this denominator.
419 __isl_give isl_ast_expr
*isl_ast_expr_from_aff(__isl_take isl_aff
*aff
,
420 __isl_keep isl_ast_build
*build
)
425 isl_ctx
*ctx
= isl_aff_get_ctx(aff
);
426 isl_ast_expr
*expr
, *expr_neg
;
427 enum isl_dim_type t
[] = { isl_dim_param
, isl_dim_in
, isl_dim_div
};
428 enum isl_dim_type l
[] = { isl_dim_param
, isl_dim_set
, isl_dim_div
};
434 expr
= isl_ast_expr_alloc_int_si(ctx
, 0);
435 expr_neg
= isl_ast_expr_alloc_int_si(ctx
, 0);
437 aff
= extract_modulos(aff
, &expr
, &expr_neg
, build
);
438 expr
= ast_expr_sub(expr
, expr_neg
);
441 ls
= isl_aff_get_domain_local_space(aff
);
443 for (i
= 0; i
< 3; ++i
) {
444 n
= isl_aff_dim(aff
, t
[i
]);
445 for (j
= 0; j
< n
; ++j
) {
446 isl_aff_get_coefficient(aff
, t
[i
], j
, &v
);
447 if (isl_int_is_zero(v
))
449 expr
= isl_ast_expr_add_term(expr
,
450 ls
, l
[i
], j
, v
, build
);
454 isl_aff_get_constant(aff
, &v
);
455 expr
= isl_ast_expr_add_int(expr
, v
);
457 isl_aff_get_denominator(aff
, &v
);
458 if (!isl_int_is_one(v
)) {
460 d
= isl_ast_expr_alloc_int(ctx
, v
);
461 expr
= isl_ast_expr_div(expr
, d
);
464 isl_local_space_free(ls
);
470 /* Add terms to "expr" for each variable in "aff" with a coefficient
471 * with sign equal to "sign".
472 * The result is simplified in terms of build->domain.
474 static __isl_give isl_ast_expr
*add_signed_terms(__isl_take isl_ast_expr
*expr
,
475 __isl_keep isl_aff
*aff
, int sign
, __isl_keep isl_ast_build
*build
)
479 enum isl_dim_type t
[] = { isl_dim_param
, isl_dim_in
, isl_dim_div
};
480 enum isl_dim_type l
[] = { isl_dim_param
, isl_dim_set
, isl_dim_div
};
484 ls
= isl_aff_get_domain_local_space(aff
);
486 for (i
= 0; i
< 3; ++i
) {
487 int n
= isl_aff_dim(aff
, t
[i
]);
488 for (j
= 0; j
< n
; ++j
) {
489 isl_aff_get_coefficient(aff
, t
[i
], j
, &v
);
490 if (sign
* isl_int_sgn(v
) <= 0)
493 expr
= isl_ast_expr_add_term(expr
,
494 ls
, l
[i
], j
, v
, build
);
498 isl_aff_get_constant(aff
, &v
);
499 if (sign
* isl_int_sgn(v
) > 0) {
501 expr
= isl_ast_expr_add_int(expr
, v
);
504 isl_local_space_free(ls
);
510 /* Construct an isl_ast_expr that evaluates the condition "constraint",
511 * The result is simplified in terms of build->domain.
513 * Let the constraint by either "a >= 0" or "a == 0".
514 * We first extract hidden modulo computations from "a"
515 * and then collect all the terms with a positive coefficient in cons_pos
516 * and the terms with a negative coefficient in cons_neg.
518 * The result is then of the form
520 * (isl_ast_op_ge, expr(pos), expr(-neg)))
524 * (isl_ast_op_eq, expr(pos), expr(-neg)))
526 * However, if the first expression is an integer constant (and the second
527 * is not), then we swap the two expressions. This ensures that we construct,
528 * e.g., "i <= 5" rather than "5 >= i".
530 static __isl_give isl_ast_expr
*isl_ast_expr_from_constraint(
531 __isl_take isl_constraint
*constraint
, __isl_keep isl_ast_build
*build
)
534 isl_ast_expr
*expr_pos
;
535 isl_ast_expr
*expr_neg
;
539 enum isl_ast_op_type type
;
544 aff
= isl_constraint_get_aff(constraint
);
546 ctx
= isl_constraint_get_ctx(constraint
);
547 expr_pos
= isl_ast_expr_alloc_int_si(ctx
, 0);
548 expr_neg
= isl_ast_expr_alloc_int_si(ctx
, 0);
550 aff
= extract_modulos(aff
, &expr_pos
, &expr_neg
, build
);
552 expr_pos
= add_signed_terms(expr_pos
, aff
, 1, build
);
553 expr_neg
= add_signed_terms(expr_neg
, aff
, -1, build
);
555 eq
= isl_constraint_is_equality(constraint
);
557 if (isl_ast_expr_get_type(expr_pos
) == isl_ast_expr_int
&&
558 isl_ast_expr_get_type(expr_neg
) != isl_ast_expr_int
) {
559 type
= eq
? isl_ast_op_eq
: isl_ast_op_le
;
560 expr
= isl_ast_expr_alloc_binary(type
, expr_neg
, expr_pos
);
562 type
= eq
? isl_ast_op_eq
: isl_ast_op_ge
;
563 expr
= isl_ast_expr_alloc_binary(type
, expr_pos
, expr_neg
);
566 isl_constraint_free(constraint
);
571 struct isl_expr_from_basic_data
{
572 isl_ast_build
*build
;
577 /* Construct an isl_ast_expr that evaluates the condition "c",
578 * except if it is a div constraint, and add it to the data->res.
579 * The result is simplified in terms of data->build->domain.
581 static int expr_from_basic_set(__isl_take isl_constraint
*c
, void *user
)
583 struct isl_expr_from_basic_data
*data
= user
;
586 if (isl_constraint_is_div_constraint(c
)) {
587 isl_constraint_free(c
);
591 expr
= isl_ast_expr_from_constraint(c
, data
->build
);
595 data
->res
= isl_ast_expr_and(data
->res
, expr
);
604 /* Construct an isl_ast_expr that evaluates the conditions defining "bset".
605 * The result is simplified in terms of build->domain.
607 * We filter out the div constraints during printing, so we do not know
608 * in advance how many constraints are going to be printed.
610 * If it turns out that there was no constraint, then we contruct
611 * the expression "1", i.e., "true".
613 __isl_give isl_ast_expr
*isl_ast_build_expr_from_basic_set(
614 __isl_keep isl_ast_build
*build
, __isl_take isl_basic_set
*bset
)
616 struct isl_expr_from_basic_data data
= { build
, 1, NULL
};
618 if (isl_basic_set_foreach_constraint(bset
,
619 &expr_from_basic_set
, &data
) < 0) {
620 data
.res
= isl_ast_expr_free(data
.res
);
621 } else if (data
.res
== NULL
) {
622 isl_ctx
*ctx
= isl_basic_set_get_ctx(bset
);
623 data
.res
= isl_ast_expr_alloc_int_si(ctx
, 1);
626 isl_basic_set_free(bset
);
630 struct isl_expr_from_set_data
{
631 isl_ast_build
*build
;
636 /* Construct an isl_ast_expr that evaluates the conditions defining "bset"
637 * and add it to data->res.
638 * The result is simplified in terms of data->build->domain.
640 static int expr_from_set(__isl_take isl_basic_set
*bset
, void *user
)
642 struct isl_expr_from_set_data
*data
= user
;
645 expr
= isl_ast_build_expr_from_basic_set(data
->build
, bset
);
649 data
->res
= isl_ast_expr_or(data
->res
, expr
);
658 /* Construct an isl_ast_expr that evaluates the conditions defining "set".
659 * The result is simplified in terms of build->domain.
661 __isl_give isl_ast_expr
*isl_ast_build_expr_from_set(
662 __isl_keep isl_ast_build
*build
, __isl_take isl_set
*set
)
664 struct isl_expr_from_set_data data
= { build
, 1, NULL
};
666 if (isl_set_foreach_basic_set(set
, &expr_from_set
, &data
) < 0)
667 data
.res
= isl_ast_expr_free(data
.res
);
673 struct isl_from_pw_aff_data
{
674 isl_ast_build
*build
;
680 /* This function is called during the construction of an isl_ast_expr
681 * that evaluates an isl_pw_aff.
682 * Adjust data->next to take into account this piece.
684 * data->n is the number of pairs of set and aff to go.
685 * data->dom is the domain of the entire isl_pw_aff.
687 * If this is the last pair, then data->next is set to evaluate aff
688 * and the domain is ignored.
689 * Otherwise, data->next is set to a select operation that selects
690 * an isl_ast_expr correponding to "aff" on "set" and to an expression
691 * that will be filled in by later calls otherwise.
693 static int ast_expr_from_pw_aff(__isl_take isl_set
*set
,
694 __isl_take isl_aff
*aff
, void *user
)
696 struct isl_from_pw_aff_data
*data
= user
;
699 ctx
= isl_set_get_ctx(set
);
702 *data
->next
= isl_ast_expr_from_aff(aff
, data
->build
);
707 isl_ast_expr
*ternary
, *arg
;
709 ternary
= isl_ast_expr_alloc_op(ctx
, isl_ast_op_select
, 3);
710 set
= isl_set_gist(set
, isl_set_copy(data
->dom
));
711 arg
= isl_ast_build_expr_from_set(data
->build
, set
);
712 ternary
= isl_ast_expr_set_op_arg(ternary
, 0, arg
);
713 arg
= isl_ast_expr_from_aff(aff
, data
->build
);
714 ternary
= isl_ast_expr_set_op_arg(ternary
, 1, arg
);
718 *data
->next
= ternary
;
719 data
->next
= &ternary
->u
.op
.args
[2];
725 /* Construct an isl_ast_expr that evaluates "pa".
726 * The result is simplified in terms of build->domain.
728 * The domain of "pa" lives in the internal schedule space.
730 __isl_give isl_ast_expr
*isl_ast_build_expr_from_pw_aff_internal(
731 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_aff
*pa
)
733 struct isl_from_pw_aff_data data
;
734 isl_ast_expr
*res
= NULL
;
740 data
.n
= isl_pw_aff_n_piece(pa
);
742 data
.dom
= isl_pw_aff_domain(isl_pw_aff_copy(pa
));
744 if (isl_pw_aff_foreach_piece(pa
, &ast_expr_from_pw_aff
, &data
) < 0)
745 res
= isl_ast_expr_free(res
);
747 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
748 "cannot handle void expression", res
= NULL
);
751 isl_set_free(data
.dom
);
755 /* Construct an isl_ast_expr that evaluates "pa".
756 * The result is simplified in terms of build->domain.
758 * The domain of "pa" lives in the external schedule space.
760 __isl_give isl_ast_expr
*isl_ast_build_expr_from_pw_aff(
761 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_aff
*pa
)
765 if (isl_ast_build_need_schedule_map(build
)) {
767 ma
= isl_ast_build_get_schedule_map_multi_aff(build
);
768 pa
= isl_pw_aff_pullback_multi_aff(pa
, ma
);
770 expr
= isl_ast_build_expr_from_pw_aff_internal(build
, pa
);
774 /* Set the ids of the input dimensions of "pma" to the iterator ids
777 * The domain of "pma" is assumed to live in the internal schedule domain.
779 static __isl_give isl_pw_multi_aff
*set_iterator_names(
780 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_multi_aff
*pma
)
784 n
= isl_pw_multi_aff_dim(pma
, isl_dim_in
);
785 for (i
= 0; i
< n
; ++i
) {
788 id
= isl_ast_build_get_iterator_id(build
, i
);
789 pma
= isl_pw_multi_aff_set_dim_id(pma
, isl_dim_in
, i
, id
);
795 /* Construct an isl_ast_expr that calls the domain element specified by "pma".
796 * The name of the function is obtained from the output tuple name.
797 * The arguments are given by the piecewise affine expressions.
799 * The domain of "pma" is assumed to live in the internal schedule domain.
801 static __isl_give isl_ast_expr
*isl_ast_build_call_from_pw_multi_aff_internal(
802 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_multi_aff
*pma
)
809 pma
= set_iterator_names(build
, pma
);
811 return isl_pw_multi_aff_free(pma
);
813 ctx
= isl_ast_build_get_ctx(build
);
814 n
= isl_pw_multi_aff_dim(pma
, isl_dim_out
);
815 expr
= isl_ast_expr_alloc_op(ctx
, isl_ast_op_call
, 1 + n
);
817 if (isl_pw_multi_aff_has_tuple_id(pma
, isl_dim_out
))
818 id
= isl_pw_multi_aff_get_tuple_id(pma
, isl_dim_out
);
820 id
= isl_id_alloc(ctx
, "", NULL
);
822 expr
= isl_ast_expr_set_op_arg(expr
, 0, isl_ast_expr_from_id(id
));
823 for (i
= 0; i
< n
; ++i
) {
827 pa
= isl_pw_multi_aff_get_pw_aff(pma
, i
);
828 arg
= isl_ast_build_expr_from_pw_aff_internal(build
, pa
);
829 expr
= isl_ast_expr_set_op_arg(expr
, 1 + i
, arg
);
832 isl_pw_multi_aff_free(pma
);
836 /* Construct an isl_ast_expr that calls the domain element specified by "pma".
837 * The name of the function is obtained from the output tuple name.
838 * The arguments are given by the piecewise affine expressions.
840 * The domain of "pma" is assumed to live in the external schedule domain.
842 __isl_give isl_ast_expr
*isl_ast_build_call_from_pw_multi_aff(
843 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_multi_aff
*pma
)
847 isl_space
*space_build
, *space_pma
;
849 space_build
= isl_ast_build_get_space(build
, 0);
850 space_pma
= isl_pw_multi_aff_get_space(pma
);
851 is_domain
= isl_space_tuple_match(space_build
, isl_dim_set
,
852 space_pma
, isl_dim_in
);
853 isl_space_free(space_build
);
854 isl_space_free(space_pma
);
856 return isl_pw_multi_aff_free(pma
);
858 isl_die(isl_ast_build_get_ctx(build
), isl_error_invalid
,
859 "spaces don't match",
860 return isl_pw_multi_aff_free(pma
));
862 if (isl_ast_build_need_schedule_map(build
)) {
864 ma
= isl_ast_build_get_schedule_map_multi_aff(build
);
865 pma
= isl_pw_multi_aff_pullback_multi_aff(pma
, ma
);
868 expr
= isl_ast_build_call_from_pw_multi_aff_internal(build
, pma
);
872 /* Construct an isl_ast_expr that calls the domain element
873 * specified by "executed".
875 * "executed" is assumed to be single-valued, with a domain that lives
876 * in the internal schedule space.
878 __isl_give isl_ast_node
*isl_ast_build_call_from_executed(
879 __isl_keep isl_ast_build
*build
, __isl_take isl_map
*executed
)
881 isl_pw_multi_aff
*iteration
;
884 iteration
= isl_pw_multi_aff_from_map(executed
);
885 iteration
= isl_ast_build_compute_gist_pw_multi_aff(build
, iteration
);
886 iteration
= isl_pw_multi_aff_intersect_domain(iteration
,
887 isl_ast_build_get_domain(build
));
888 expr
= isl_ast_build_call_from_pw_multi_aff_internal(build
, iteration
);
889 return isl_ast_node_alloc_user(expr
);