add extra AST generation test case from CLooG
[isl.git] / isl_ast_build_expr.c
blob4f945f891881d7d40a960cec51495d2756ffb9df
1 /*
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
8 */
10 #include <isl/ilp.h>
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)
21 if (!build)
22 return isl_lp_error;
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)
33 if (!build)
34 return isl_lp_error;
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))
51 * instead of
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);
60 isl_aff *aff;
61 isl_ast_expr *num, *den;
62 isl_int d;
63 enum isl_ast_op_type type;
65 aff = isl_local_space_get_div(ls, pos);
66 isl_int_init(d);
67 isl_aff_get_denominator(aff, &d);
68 aff = isl_aff_scale(aff, d);
69 den = isl_ast_expr_alloc_int(ctx, d);
70 isl_int_clear(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)
76 aff = isl_aff_free(aff);
77 else if (non_neg)
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);
98 isl_id *id;
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",
110 return NULL);
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)
119 if (!expr)
120 return -1;
121 if (expr->type != isl_ast_expr_int)
122 return 0;
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)
133 goto error;
135 if (ast_expr_is_zero(expr1)) {
136 isl_ast_expr_free(expr1);
137 return expr2;
140 if (ast_expr_is_zero(expr2)) {
141 isl_ast_expr_free(expr2);
142 return expr1;
145 return isl_ast_expr_add(expr1, expr2);
146 error:
147 isl_ast_expr_free(expr1);
148 isl_ast_expr_free(expr2);
149 return NULL;
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)
167 goto error;
169 if (ast_expr_is_zero(expr2)) {
170 isl_ast_expr_free(expr2);
171 return expr1;
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);
180 error:
181 isl_ast_expr_free(expr1);
182 isl_ast_expr_free(expr2);
183 return NULL;
186 /* Return an isl_ast_expr that represents
188 * v * (aff mod d)
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)
196 isl_ctx *ctx;
197 isl_ast_expr *expr;
198 isl_ast_expr *c;
200 if (!aff)
201 return NULL;
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);
214 return 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)
234 isl_ctx *ctx;
235 isl_ast_expr *expr;
236 isl_ast_expr *c;
238 if (!ls)
239 return NULL;
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);
247 } else {
248 c = isl_ast_expr_alloc_int(ctx, v);
249 expr = isl_ast_expr_mul(c, expr);
253 return expr;
256 /* Add an expression for "v" times the specified dimension of "ls"
257 * to expr.
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)
268 * instead.
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)
280 isl_ast_expr *term;
282 if (!expr)
283 return NULL;
285 if (isl_int_is_neg(v) && !ast_expr_is_zero(expr)) {
286 isl_int_neg(v, v);
287 term = isl_ast_expr_term(ls, type, pos, v, build);
288 return ast_expr_sub(expr, term);
289 } else {
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)
300 isl_ctx *ctx;
301 isl_ast_expr *expr_int;
303 if (!expr)
304 return NULL;
306 if (isl_int_is_zero(v))
307 return expr;
309 ctx = isl_ast_expr_get_ctx(expr);
310 if (isl_int_is_neg(v) && !ast_expr_is_zero(expr)) {
311 isl_int_neg(v, v);
312 expr_int = isl_ast_expr_alloc_int(ctx, v);
313 return ast_expr_sub(expr, expr_int);
314 } else {
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
333 * rewrite them as
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)
347 isl_ctx *ctx;
348 int j, n;
349 isl_int v, d;
350 isl_local_space *ls;
352 if (!aff)
353 return NULL;
355 ctx = isl_aff_get_ctx(aff);
356 if (!isl_options_get_ast_build_prefer_pdiv(ctx))
357 return aff;
359 isl_int_init(v);
360 isl_int_init(d);
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) {
365 isl_ast_expr *expr;
366 isl_aff *div;
367 int s;
368 int mod;
370 isl_aff_get_coefficient(aff, isl_dim_div, j, &v);
371 if (isl_int_is_zero(v))
372 continue;
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);
376 if (mod)
377 mod = isl_ast_build_aff_is_nonneg(build, div);
378 if (mod < 0) {
379 aff = isl_aff_free(aff);
380 isl_aff_free(div);
381 break;
382 } else if (!mod) {
383 isl_aff_free(div);
384 continue;
386 div = isl_aff_scale(div, d);
387 isl_int_divexact(v, v, d);
388 s = isl_int_sgn(v);
389 isl_int_abs(v, v);
390 expr = isl_ast_expr_mod(v, div, d, build);
391 if (s > 0)
392 *neg = ast_expr_add(*neg, expr);
393 else
394 *pos = ast_expr_add(*pos, expr);
395 aff = isl_aff_set_coefficient_si(aff, isl_dim_div, j, 0);
396 if (s < 0)
397 isl_int_neg(v, v);
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);
405 isl_int_clear(d);
406 isl_int_clear(v);
408 return aff;
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)
422 int i, j;
423 isl_int v;
424 int n;
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 };
429 isl_local_space *ls;
431 if (!aff)
432 return NULL;
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);
440 isl_int_init(v);
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))
448 continue;
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)) {
459 isl_ast_expr *d;
460 d = isl_ast_expr_alloc_int(ctx, v);
461 expr = isl_ast_expr_div(expr, d);
464 isl_local_space_free(ls);
465 isl_int_clear(v);
466 isl_aff_free(aff);
467 return expr;
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)
477 int i, j;
478 isl_int v;
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 };
481 isl_local_space *ls;
483 isl_int_init(v);
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)
491 continue;
492 isl_int_abs(v, v);
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) {
500 isl_int_abs(v, v);
501 expr = isl_ast_expr_add_int(expr, v);
504 isl_local_space_free(ls);
505 isl_int_clear(v);
507 return expr;
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)))
522 * or
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)
533 isl_ctx *ctx;
534 isl_ast_expr *expr_pos;
535 isl_ast_expr *expr_neg;
536 isl_ast_expr *expr;
537 isl_aff *aff;
538 int eq;
539 enum isl_ast_op_type type;
541 if (!constraint)
542 return NULL;
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);
561 } else {
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);
567 isl_aff_free(aff);
568 return expr;
571 struct isl_expr_from_basic_data {
572 isl_ast_build *build;
573 int first;
574 isl_ast_expr *res;
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;
584 isl_ast_expr *expr;
586 if (isl_constraint_is_div_constraint(c)) {
587 isl_constraint_free(c);
588 return 0;
591 expr = isl_ast_expr_from_constraint(c, data->build);
592 if (data->first)
593 data->res = expr;
594 else
595 data->res = isl_ast_expr_and(data->res, expr);
597 data->first = 0;
599 if (!data->res)
600 return -1;
601 return 0;
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);
627 return data.res;
630 struct isl_expr_from_set_data {
631 isl_ast_build *build;
632 int first;
633 isl_ast_expr *res;
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;
643 isl_ast_expr *expr;
645 expr = isl_ast_build_expr_from_basic_set(data->build, bset);
646 if (data->first)
647 data->res = expr;
648 else
649 data->res = isl_ast_expr_or(data->res, expr);
651 data->first = 0;
653 if (!data->res)
654 return -1;
655 return 0;
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);
669 isl_set_free(set);
670 return data.res;
673 struct isl_from_pw_aff_data {
674 isl_ast_build *build;
675 int n;
676 isl_ast_expr **next;
677 isl_set *dom;
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;
697 isl_ctx *ctx;
699 ctx = isl_set_get_ctx(set);
700 data->n--;
701 if (data->n == 0) {
702 *data->next = isl_ast_expr_from_aff(aff, data->build);
703 isl_set_free(set);
704 if (!*data->next)
705 return -1;
706 } else {
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);
715 if (!ternary)
716 return -1;
718 *data->next = ternary;
719 data->next = &ternary->u.op.args[2];
722 return 0;
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;
736 if (!pa)
737 return NULL;
739 data.build = build;
740 data.n = isl_pw_aff_n_piece(pa);
741 data.next = &res;
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);
746 else if (!res)
747 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
748 "cannot handle void expression", res = NULL);
750 isl_pw_aff_free(pa);
751 isl_set_free(data.dom);
752 return res;
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)
763 isl_ast_expr *expr;
765 if (isl_ast_build_need_schedule_map(build)) {
766 isl_multi_aff *ma;
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);
771 return expr;
774 /* Set the ids of the input dimensions of "pma" to the iterator ids
775 * of "build".
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)
782 int i, n;
784 n = isl_pw_multi_aff_dim(pma, isl_dim_in);
785 for (i = 0; i < n; ++i) {
786 isl_id *id;
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);
792 return pma;
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)
804 int i, n;
805 isl_ctx *ctx;
806 isl_id *id;
807 isl_ast_expr *expr;
809 pma = set_iterator_names(build, pma);
810 if (!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);
819 else
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) {
824 isl_pw_aff *pa;
825 isl_ast_expr *arg;
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);
833 return expr;
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)
845 int is_domain;
846 isl_ast_expr *expr;
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);
855 if (is_domain < 0)
856 return isl_pw_multi_aff_free(pma);
857 if (!is_domain)
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)) {
863 isl_multi_aff *ma;
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);
869 return expr;
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;
882 isl_ast_expr *expr;
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);