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 "opposite" of the (numerator of the) argument of a div
16 * with denonimator "d".
18 * In particular, compute
22 static __isl_give isl_aff
*oppose_div_arg(__isl_take isl_aff
*aff
, isl_int d
)
24 aff
= isl_aff_neg(aff
);
25 aff
= isl_aff_add_constant(aff
, d
);
26 aff
= isl_aff_add_constant_si(aff
, -1);
31 /* Create an isl_ast_expr evaluating the div at position "pos" in "ls".
32 * The result is simplified in terms of build->domain.
34 * "v" points to the coefficient of the div in the expression where it
35 * appears and may be updated by this function.
36 * "ls" is known to be non-NULL.
38 * Let the div be of the form floor(e/d).
39 * If the ast_build_prefer_pdiv option is set then we check if "e"
40 * is non-negative, so that we can generate
42 * (pdiv_q, expr(e), expr(d))
46 * (fdiv_q, expr(e), expr(d))
48 * If the ast_build_prefer_pdiv option is set and
49 * if "e" is not non-negative, then we check if "-e + d - 1" is non-negative.
50 * If so, we can rewrite
52 * floor(e/d) = -ceil(-e/d) = -floor((-e + d - 1)/d)
54 * and still use pdiv_q.
56 static __isl_give isl_ast_expr
*var_div(isl_int
*v
,
57 __isl_keep isl_local_space
*ls
,
58 int pos
, __isl_keep isl_ast_build
*build
)
60 isl_ctx
*ctx
= isl_local_space_get_ctx(ls
);
62 isl_ast_expr
*num
, *den
;
64 enum isl_ast_op_type type
;
66 aff
= isl_local_space_get_div(ls
, pos
);
68 isl_aff_get_denominator(aff
, &d
);
69 aff
= isl_aff_scale(aff
, d
);
70 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
);
75 if (non_neg
>= 0 && !non_neg
) {
76 isl_aff
*opp
= oppose_div_arg(isl_aff_copy(aff
), d
);
77 non_neg
= isl_ast_build_aff_is_nonneg(build
, opp
);
78 if (non_neg
>= 0 && non_neg
) {
86 aff
= isl_aff_free(aff
);
88 type
= isl_ast_op_pdiv_q
;
92 num
= isl_ast_expr_from_aff(aff
, build
);
93 return isl_ast_expr_alloc_binary(type
, num
, den
);
96 /* Create an isl_ast_expr evaluating the specified dimension of "ls".
97 * The result is simplified in terms of build->domain.
99 * "v" points to the coefficient of the specified dimension
100 * in the expression where it appears and may be updated by this function.
102 * The isl_ast_expr is constructed based on the type of the dimension.
103 * - divs are constructed by var_div
104 * - set variables are constructed from the iterator isl_ids in "build"
105 * - parameters are constructed from the isl_ids in "ls"
107 static __isl_give isl_ast_expr
*var(isl_int
*v
, __isl_keep isl_local_space
*ls
,
108 enum isl_dim_type type
, int pos
, __isl_keep isl_ast_build
*build
)
110 isl_ctx
*ctx
= isl_local_space_get_ctx(ls
);
113 if (type
== isl_dim_div
)
114 return var_div(v
, ls
, pos
, build
);
116 if (type
== isl_dim_set
) {
117 id
= isl_ast_build_get_iterator_id(build
, pos
);
118 return isl_ast_expr_from_id(id
);
121 if (!isl_local_space_has_dim_id(ls
, type
, pos
))
122 isl_die(ctx
, isl_error_internal
, "unnamed dimension",
124 id
= isl_local_space_get_dim_id(ls
, type
, pos
);
125 return isl_ast_expr_from_id(id
);
128 /* Does "expr" represent the zero integer?
130 static int ast_expr_is_zero(__isl_keep isl_ast_expr
*expr
)
134 if (expr
->type
!= isl_ast_expr_int
)
136 return isl_int_is_zero(expr
->u
.i
);
139 /* Create an expression representing the sum of "expr1" and "expr2",
140 * provided neither of the two expressions is identically zero.
142 static __isl_give isl_ast_expr
*ast_expr_add(__isl_take isl_ast_expr
*expr1
,
143 __isl_take isl_ast_expr
*expr2
)
145 if (!expr1
|| !expr2
)
148 if (ast_expr_is_zero(expr1
)) {
149 isl_ast_expr_free(expr1
);
153 if (ast_expr_is_zero(expr2
)) {
154 isl_ast_expr_free(expr2
);
158 return isl_ast_expr_add(expr1
, expr2
);
160 isl_ast_expr_free(expr1
);
161 isl_ast_expr_free(expr2
);
165 /* Subtract expr2 from expr1.
167 * If expr2 is zero, we simply return expr1.
168 * If expr1 is zero, we return
170 * (isl_ast_op_minus, expr2)
172 * Otherwise, we return
174 * (isl_ast_op_sub, expr1, expr2)
176 static __isl_give isl_ast_expr
*ast_expr_sub(__isl_take isl_ast_expr
*expr1
,
177 __isl_take isl_ast_expr
*expr2
)
179 if (!expr1
|| !expr2
)
182 if (ast_expr_is_zero(expr2
)) {
183 isl_ast_expr_free(expr2
);
187 if (ast_expr_is_zero(expr1
)) {
188 isl_ast_expr_free(expr1
);
189 return isl_ast_expr_neg(expr2
);
192 return isl_ast_expr_sub(expr1
, expr2
);
194 isl_ast_expr_free(expr1
);
195 isl_ast_expr_free(expr2
);
199 /* Return an isl_ast_expr that represents
203 * v is assumed to be non-negative.
204 * The result is simplified in terms of build->domain.
206 static __isl_give isl_ast_expr
*isl_ast_expr_mod(isl_int v
,
207 __isl_keep isl_aff
*aff
, isl_int d
, __isl_keep isl_ast_build
*build
)
216 ctx
= isl_aff_get_ctx(aff
);
217 expr
= isl_ast_expr_from_aff(isl_aff_copy(aff
), build
);
219 c
= isl_ast_expr_alloc_int(ctx
, d
);
220 expr
= isl_ast_expr_alloc_binary(isl_ast_op_pdiv_r
, expr
, c
);
222 if (!isl_int_is_one(v
)) {
223 c
= isl_ast_expr_alloc_int(ctx
, v
);
224 expr
= isl_ast_expr_mul(c
, expr
);
230 /* Create an isl_ast_expr that scales "expr" by "v".
232 * If v is 1, we simply return expr.
233 * If v is -1, we return
235 * (isl_ast_op_minus, expr)
237 * Otherwise, we return
239 * (isl_ast_op_mul, expr(v), expr)
241 static __isl_give isl_ast_expr
*scale(__isl_take isl_ast_expr
*expr
, isl_int v
)
248 if (isl_int_is_one(v
))
251 if (isl_int_is_negone(v
)) {
252 expr
= isl_ast_expr_neg(expr
);
254 ctx
= isl_ast_expr_get_ctx(expr
);
255 c
= isl_ast_expr_alloc_int(ctx
, v
);
256 expr
= isl_ast_expr_mul(c
, expr
);
262 /* Add an expression for "*v" times the specified dimension of "ls"
265 * Let e be the expression for the specified dimension,
266 * multiplied by the absolute value of "*v".
267 * If "*v" is negative, we create
269 * (isl_ast_op_sub, expr, e)
271 * except when expr is trivially zero, in which case we create
273 * (isl_ast_op_minus, e)
277 * If "*v" is positive, we simply create
279 * (isl_ast_op_add, expr, e)
282 static __isl_give isl_ast_expr
*isl_ast_expr_add_term(
283 __isl_take isl_ast_expr
*expr
,
284 __isl_keep isl_local_space
*ls
, enum isl_dim_type type
, int pos
,
285 isl_int
*v
, __isl_keep isl_ast_build
*build
)
292 term
= var(v
, ls
, type
, pos
, build
);
294 if (isl_int_is_neg(*v
) && !ast_expr_is_zero(expr
)) {
296 term
= scale(term
, *v
);
297 return ast_expr_sub(expr
, term
);
299 term
= scale(term
, *v
);
300 return ast_expr_add(expr
, term
);
304 /* Add an expression for "v" to expr.
306 static __isl_give isl_ast_expr
*isl_ast_expr_add_int(
307 __isl_take isl_ast_expr
*expr
, isl_int v
)
310 isl_ast_expr
*expr_int
;
315 if (isl_int_is_zero(v
))
318 ctx
= isl_ast_expr_get_ctx(expr
);
319 if (isl_int_is_neg(v
) && !ast_expr_is_zero(expr
)) {
321 expr_int
= isl_ast_expr_alloc_int(ctx
, v
);
322 return ast_expr_sub(expr
, expr_int
);
324 expr_int
= isl_ast_expr_alloc_int(ctx
, v
);
325 return ast_expr_add(expr
, expr_int
);
329 /* Check if "aff" involves any (implicit) modulo computations based
331 * If so, remove them from aff and add expressions corresponding
332 * to those modulo computations to *pos and/or *neg.
333 * "v" is the coefficient of div "j".
335 * In particular, check if (v * div_j) / d is of the form
337 * (f * m * floor(a / m)) / d
339 * and, if so, rewrite it as
341 * (f * (a - (a mod m))) / d = (f * a) / d - (f * (a mod m)) / d
343 * and extract out -f * (a mod m).
344 * In particular, if f > 0, we add (f * (a mod m)) to *neg.
345 * If f < 0, we add ((-f) * (a mod m)) to *pos.
347 * Note that in order to represent "a mod m" as
349 * (isl_ast_op_pdiv_r, a, m)
351 * we need to make sure that a is non-negative.
352 * If not, we check if "-a + m - 1" is non-negative.
353 * If so, we can rewrite
355 * floor(a/m) = -ceil(-a/m) = -floor((-a + m - 1)/m)
357 * and still extract a modulo.
359 * The caller is responsible for dividing *neg and/or *pos by d.
361 static __isl_give isl_aff
*extract_modulo(__isl_take isl_aff
*aff
,
362 __isl_keep isl_ast_expr
**pos
, __isl_keep isl_ast_expr
**neg
,
363 __isl_keep isl_ast_build
*build
, int j
, isl_int v
)
372 div
= isl_aff_get_div(aff
, j
);
373 isl_aff_get_denominator(div
, &d
);
374 mod
= isl_int_is_divisible_by(v
, d
);
376 div
= isl_aff_scale(div
, d
);
377 mod
= isl_ast_build_aff_is_nonneg(build
, div
);
378 if (mod
>= 0 && !mod
) {
379 isl_aff
*opp
= oppose_div_arg(isl_aff_copy(div
), d
);
380 mod
= isl_ast_build_aff_is_nonneg(build
, opp
);
381 if (mod
>= 0 && mod
) {
392 return isl_aff_free(aff
);
398 isl_int_divexact(v
, v
, d
);
401 expr
= isl_ast_expr_mod(v
, div
, d
, build
);
403 *neg
= ast_expr_add(*neg
, expr
);
405 *pos
= ast_expr_add(*pos
, expr
);
406 aff
= isl_aff_set_coefficient_si(aff
, isl_dim_div
, j
, 0);
409 div
= isl_aff_scale(div
, v
);
410 isl_aff_get_denominator(aff
, &d
);
411 div
= isl_aff_scale_down(div
, d
);
412 aff
= isl_aff_add(aff
, div
);
418 /* Check if "aff" involves any (implicit) modulo computations.
419 * If so, remove them from aff and add expressions corresponding
420 * to those modulo computations to *pos and/or *neg.
421 * We only do this if the option ast_build_prefer_pdiv is set.
423 * A modulo expression is of the form
425 * a mod m = a - m * floor(a / m)
427 * To detect them in aff, we look for terms of the form
429 * (f * m * floor(a / m)) / d
433 * (f * (a - (a mod m))) / d = (f * a) / d - (f * (a mod m)) / d
435 * and extract out -f * (a mod m).
436 * In particular, if f > 0, we add (f * (a mod m)) to *neg.
437 * If f < 0, we add ((-f) * (a mod m)) to *pos.
439 * The caller is responsible for dividing *neg and/or *pos by d.
441 static __isl_give isl_aff
*extract_modulos(__isl_take isl_aff
*aff
,
442 __isl_keep isl_ast_expr
**pos
, __isl_keep isl_ast_expr
**neg
,
443 __isl_keep isl_ast_build
*build
)
452 ctx
= isl_aff_get_ctx(aff
);
453 if (!isl_options_get_ast_build_prefer_pdiv(ctx
))
458 n
= isl_aff_dim(aff
, isl_dim_div
);
459 for (j
= 0; j
< n
; ++j
) {
460 isl_aff_get_coefficient(aff
, isl_dim_div
, j
, &v
);
461 if (isl_int_is_zero(v
) ||
462 isl_int_is_one(v
) || isl_int_is_negone(v
))
464 aff
= extract_modulo(aff
, pos
, neg
, build
, j
, v
);
474 /* Construct an isl_ast_expr that evaluates the affine expression "aff",
475 * The result is simplified in terms of build->domain.
477 * We first extract hidden modulo computations from the affine expression
478 * and then add terms for each variable with a non-zero coefficient.
479 * Finally, if the affine expression has a non-trivial denominator,
480 * we divide the resulting isl_ast_expr by this denominator.
482 __isl_give isl_ast_expr
*isl_ast_expr_from_aff(__isl_take isl_aff
*aff
,
483 __isl_keep isl_ast_build
*build
)
488 isl_ctx
*ctx
= isl_aff_get_ctx(aff
);
489 isl_ast_expr
*expr
, *expr_neg
;
490 enum isl_dim_type t
[] = { isl_dim_param
, isl_dim_in
, isl_dim_div
};
491 enum isl_dim_type l
[] = { isl_dim_param
, isl_dim_set
, isl_dim_div
};
497 expr
= isl_ast_expr_alloc_int_si(ctx
, 0);
498 expr_neg
= isl_ast_expr_alloc_int_si(ctx
, 0);
500 aff
= extract_modulos(aff
, &expr
, &expr_neg
, build
);
501 expr
= ast_expr_sub(expr
, expr_neg
);
504 ls
= isl_aff_get_domain_local_space(aff
);
506 for (i
= 0; i
< 3; ++i
) {
507 n
= isl_aff_dim(aff
, t
[i
]);
508 for (j
= 0; j
< n
; ++j
) {
509 isl_aff_get_coefficient(aff
, t
[i
], j
, &v
);
510 if (isl_int_is_zero(v
))
512 expr
= isl_ast_expr_add_term(expr
,
513 ls
, l
[i
], j
, &v
, build
);
517 isl_aff_get_constant(aff
, &v
);
518 expr
= isl_ast_expr_add_int(expr
, v
);
520 isl_aff_get_denominator(aff
, &v
);
521 if (!isl_int_is_one(v
)) {
523 d
= isl_ast_expr_alloc_int(ctx
, v
);
524 expr
= isl_ast_expr_div(expr
, d
);
527 isl_local_space_free(ls
);
533 /* Add terms to "expr" for each variable in "aff" with a coefficient
534 * with sign equal to "sign".
535 * The result is simplified in terms of build->domain.
537 static __isl_give isl_ast_expr
*add_signed_terms(__isl_take isl_ast_expr
*expr
,
538 __isl_keep isl_aff
*aff
, int sign
, __isl_keep isl_ast_build
*build
)
542 enum isl_dim_type t
[] = { isl_dim_param
, isl_dim_in
, isl_dim_div
};
543 enum isl_dim_type l
[] = { isl_dim_param
, isl_dim_set
, isl_dim_div
};
547 ls
= isl_aff_get_domain_local_space(aff
);
549 for (i
= 0; i
< 3; ++i
) {
550 int n
= isl_aff_dim(aff
, t
[i
]);
551 for (j
= 0; j
< n
; ++j
) {
552 isl_aff_get_coefficient(aff
, t
[i
], j
, &v
);
553 if (sign
* isl_int_sgn(v
) <= 0)
556 expr
= isl_ast_expr_add_term(expr
,
557 ls
, l
[i
], j
, &v
, build
);
561 isl_aff_get_constant(aff
, &v
);
562 if (sign
* isl_int_sgn(v
) > 0) {
564 expr
= isl_ast_expr_add_int(expr
, v
);
567 isl_local_space_free(ls
);
573 /* Construct an isl_ast_expr that evaluates the condition "constraint",
574 * The result is simplified in terms of build->domain.
576 * Let the constraint by either "a >= 0" or "a == 0".
577 * We first extract hidden modulo computations from "a"
578 * and then collect all the terms with a positive coefficient in cons_pos
579 * and the terms with a negative coefficient in cons_neg.
581 * The result is then of the form
583 * (isl_ast_op_ge, expr(pos), expr(-neg)))
587 * (isl_ast_op_eq, expr(pos), expr(-neg)))
589 * However, if the first expression is an integer constant (and the second
590 * is not), then we swap the two expressions. This ensures that we construct,
591 * e.g., "i <= 5" rather than "5 >= i".
593 static __isl_give isl_ast_expr
*isl_ast_expr_from_constraint(
594 __isl_take isl_constraint
*constraint
, __isl_keep isl_ast_build
*build
)
597 isl_ast_expr
*expr_pos
;
598 isl_ast_expr
*expr_neg
;
602 enum isl_ast_op_type type
;
607 aff
= isl_constraint_get_aff(constraint
);
609 ctx
= isl_constraint_get_ctx(constraint
);
610 expr_pos
= isl_ast_expr_alloc_int_si(ctx
, 0);
611 expr_neg
= isl_ast_expr_alloc_int_si(ctx
, 0);
613 aff
= extract_modulos(aff
, &expr_pos
, &expr_neg
, build
);
615 expr_pos
= add_signed_terms(expr_pos
, aff
, 1, build
);
616 expr_neg
= add_signed_terms(expr_neg
, aff
, -1, build
);
618 eq
= isl_constraint_is_equality(constraint
);
620 if (isl_ast_expr_get_type(expr_pos
) == isl_ast_expr_int
&&
621 isl_ast_expr_get_type(expr_neg
) != isl_ast_expr_int
) {
622 type
= eq
? isl_ast_op_eq
: isl_ast_op_le
;
623 expr
= isl_ast_expr_alloc_binary(type
, expr_neg
, expr_pos
);
625 type
= eq
? isl_ast_op_eq
: isl_ast_op_ge
;
626 expr
= isl_ast_expr_alloc_binary(type
, expr_pos
, expr_neg
);
629 isl_constraint_free(constraint
);
634 struct isl_expr_from_basic_data
{
635 isl_ast_build
*build
;
640 /* Construct an isl_ast_expr that evaluates the condition "c",
641 * except if it is a div constraint, and add it to the data->res.
642 * The result is simplified in terms of data->build->domain.
644 static int expr_from_basic_set(__isl_take isl_constraint
*c
, void *user
)
646 struct isl_expr_from_basic_data
*data
= user
;
649 if (isl_constraint_is_div_constraint(c
)) {
650 isl_constraint_free(c
);
654 expr
= isl_ast_expr_from_constraint(c
, data
->build
);
658 data
->res
= isl_ast_expr_and(data
->res
, expr
);
667 /* Construct an isl_ast_expr that evaluates the conditions defining "bset".
668 * The result is simplified in terms of build->domain.
670 * We filter out the div constraints during printing, so we do not know
671 * in advance how many constraints are going to be printed.
673 * If it turns out that there was no constraint, then we contruct
674 * the expression "1", i.e., "true".
676 __isl_give isl_ast_expr
*isl_ast_build_expr_from_basic_set(
677 __isl_keep isl_ast_build
*build
, __isl_take isl_basic_set
*bset
)
679 struct isl_expr_from_basic_data data
= { build
, 1, NULL
};
681 if (isl_basic_set_foreach_constraint(bset
,
682 &expr_from_basic_set
, &data
) < 0) {
683 data
.res
= isl_ast_expr_free(data
.res
);
684 } else if (data
.res
== NULL
) {
685 isl_ctx
*ctx
= isl_basic_set_get_ctx(bset
);
686 data
.res
= isl_ast_expr_alloc_int_si(ctx
, 1);
689 isl_basic_set_free(bset
);
693 struct isl_expr_from_set_data
{
694 isl_ast_build
*build
;
699 /* Construct an isl_ast_expr that evaluates the conditions defining "bset"
700 * and add it to data->res.
701 * The result is simplified in terms of data->build->domain.
703 static int expr_from_set(__isl_take isl_basic_set
*bset
, void *user
)
705 struct isl_expr_from_set_data
*data
= user
;
708 expr
= isl_ast_build_expr_from_basic_set(data
->build
, bset
);
712 data
->res
= isl_ast_expr_or(data
->res
, expr
);
721 /* Construct an isl_ast_expr that evaluates the conditions defining "set".
722 * The result is simplified in terms of build->domain.
724 __isl_give isl_ast_expr
*isl_ast_build_expr_from_set(
725 __isl_keep isl_ast_build
*build
, __isl_take isl_set
*set
)
727 struct isl_expr_from_set_data data
= { build
, 1, NULL
};
729 if (isl_set_foreach_basic_set(set
, &expr_from_set
, &data
) < 0)
730 data
.res
= isl_ast_expr_free(data
.res
);
736 struct isl_from_pw_aff_data
{
737 isl_ast_build
*build
;
743 /* This function is called during the construction of an isl_ast_expr
744 * that evaluates an isl_pw_aff.
745 * Adjust data->next to take into account this piece.
747 * data->n is the number of pairs of set and aff to go.
748 * data->dom is the domain of the entire isl_pw_aff.
750 * If this is the last pair, then data->next is set to evaluate aff
751 * and the domain is ignored.
752 * Otherwise, data->next is set to a select operation that selects
753 * an isl_ast_expr correponding to "aff" on "set" and to an expression
754 * that will be filled in by later calls otherwise.
756 static int ast_expr_from_pw_aff(__isl_take isl_set
*set
,
757 __isl_take isl_aff
*aff
, void *user
)
759 struct isl_from_pw_aff_data
*data
= user
;
762 ctx
= isl_set_get_ctx(set
);
765 *data
->next
= isl_ast_expr_from_aff(aff
, data
->build
);
770 isl_ast_expr
*ternary
, *arg
;
772 ternary
= isl_ast_expr_alloc_op(ctx
, isl_ast_op_select
, 3);
773 set
= isl_set_gist(set
, isl_set_copy(data
->dom
));
774 arg
= isl_ast_build_expr_from_set(data
->build
, set
);
775 ternary
= isl_ast_expr_set_op_arg(ternary
, 0, arg
);
776 arg
= isl_ast_expr_from_aff(aff
, data
->build
);
777 ternary
= isl_ast_expr_set_op_arg(ternary
, 1, arg
);
781 *data
->next
= ternary
;
782 data
->next
= &ternary
->u
.op
.args
[2];
788 /* Construct an isl_ast_expr that evaluates "pa".
789 * The result is simplified in terms of build->domain.
791 * The domain of "pa" lives in the internal schedule space.
793 __isl_give isl_ast_expr
*isl_ast_build_expr_from_pw_aff_internal(
794 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_aff
*pa
)
796 struct isl_from_pw_aff_data data
;
797 isl_ast_expr
*res
= NULL
;
803 data
.n
= isl_pw_aff_n_piece(pa
);
805 data
.dom
= isl_pw_aff_domain(isl_pw_aff_copy(pa
));
807 if (isl_pw_aff_foreach_piece(pa
, &ast_expr_from_pw_aff
, &data
) < 0)
808 res
= isl_ast_expr_free(res
);
810 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
811 "cannot handle void expression", res
= NULL
);
814 isl_set_free(data
.dom
);
818 /* Construct an isl_ast_expr that evaluates "pa".
819 * The result is simplified in terms of build->domain.
821 * The domain of "pa" lives in the external schedule space.
823 __isl_give isl_ast_expr
*isl_ast_build_expr_from_pw_aff(
824 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_aff
*pa
)
828 if (isl_ast_build_need_schedule_map(build
)) {
830 ma
= isl_ast_build_get_schedule_map_multi_aff(build
);
831 pa
= isl_pw_aff_pullback_multi_aff(pa
, ma
);
833 expr
= isl_ast_build_expr_from_pw_aff_internal(build
, pa
);
837 /* Set the ids of the input dimensions of "pma" to the iterator ids
840 * The domain of "pma" is assumed to live in the internal schedule domain.
842 static __isl_give isl_pw_multi_aff
*set_iterator_names(
843 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_multi_aff
*pma
)
847 n
= isl_pw_multi_aff_dim(pma
, isl_dim_in
);
848 for (i
= 0; i
< n
; ++i
) {
851 id
= isl_ast_build_get_iterator_id(build
, i
);
852 pma
= isl_pw_multi_aff_set_dim_id(pma
, isl_dim_in
, i
, id
);
858 /* Construct an isl_ast_expr that calls the domain element specified by "pma".
859 * The name of the function is obtained from the output tuple name.
860 * The arguments are given by the piecewise affine expressions.
862 * The domain of "pma" is assumed to live in the internal schedule domain.
864 static __isl_give isl_ast_expr
*isl_ast_build_call_from_pw_multi_aff_internal(
865 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_multi_aff
*pma
)
872 pma
= set_iterator_names(build
, pma
);
874 return isl_pw_multi_aff_free(pma
);
876 ctx
= isl_ast_build_get_ctx(build
);
877 n
= isl_pw_multi_aff_dim(pma
, isl_dim_out
);
878 expr
= isl_ast_expr_alloc_op(ctx
, isl_ast_op_call
, 1 + n
);
880 if (isl_pw_multi_aff_has_tuple_id(pma
, isl_dim_out
))
881 id
= isl_pw_multi_aff_get_tuple_id(pma
, isl_dim_out
);
883 id
= isl_id_alloc(ctx
, "", NULL
);
885 expr
= isl_ast_expr_set_op_arg(expr
, 0, isl_ast_expr_from_id(id
));
886 for (i
= 0; i
< n
; ++i
) {
890 pa
= isl_pw_multi_aff_get_pw_aff(pma
, i
);
891 arg
= isl_ast_build_expr_from_pw_aff_internal(build
, pa
);
892 expr
= isl_ast_expr_set_op_arg(expr
, 1 + i
, arg
);
895 isl_pw_multi_aff_free(pma
);
899 /* Construct an isl_ast_expr that calls the domain element specified by "pma".
900 * The name of the function is obtained from the output tuple name.
901 * The arguments are given by the piecewise affine expressions.
903 * The domain of "pma" is assumed to live in the external schedule domain.
905 __isl_give isl_ast_expr
*isl_ast_build_call_from_pw_multi_aff(
906 __isl_keep isl_ast_build
*build
, __isl_take isl_pw_multi_aff
*pma
)
910 isl_space
*space_build
, *space_pma
;
912 space_build
= isl_ast_build_get_space(build
, 0);
913 space_pma
= isl_pw_multi_aff_get_space(pma
);
914 is_domain
= isl_space_tuple_match(space_build
, isl_dim_set
,
915 space_pma
, isl_dim_in
);
916 isl_space_free(space_build
);
917 isl_space_free(space_pma
);
919 return isl_pw_multi_aff_free(pma
);
921 isl_die(isl_ast_build_get_ctx(build
), isl_error_invalid
,
922 "spaces don't match",
923 return isl_pw_multi_aff_free(pma
));
925 if (isl_ast_build_need_schedule_map(build
)) {
927 ma
= isl_ast_build_get_schedule_map_multi_aff(build
);
928 pma
= isl_pw_multi_aff_pullback_multi_aff(pma
, ma
);
931 expr
= isl_ast_build_call_from_pw_multi_aff_internal(build
, pma
);
935 /* Construct an isl_ast_expr that calls the domain element
936 * specified by "executed".
938 * "executed" is assumed to be single-valued, with a domain that lives
939 * in the internal schedule space.
941 __isl_give isl_ast_node
*isl_ast_build_call_from_executed(
942 __isl_keep isl_ast_build
*build
, __isl_take isl_map
*executed
)
944 isl_pw_multi_aff
*iteration
;
947 iteration
= isl_pw_multi_aff_from_map(executed
);
948 iteration
= isl_ast_build_compute_gist_pw_multi_aff(build
, iteration
);
949 iteration
= isl_pw_multi_aff_intersect_domain(iteration
,
950 isl_ast_build_get_domain(build
));
951 expr
= isl_ast_build_call_from_pw_multi_aff_internal(build
, iteration
);
952 return isl_ast_node_alloc_user(expr
);