isl_printer_print_pw_aff: use isl_ast_expr when printing in C format
[isl.git] / isl_ast_build_expr.c
blobadab2a2407dde787b67308f7ed5f6a5a8e556c93
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 return isl_ast_expr_alloc_binary(isl_ast_op_pdiv_r, expr, c);
210 /* Create an isl_ast_expr evaluating "v" times the specified dimension of "ls".
211 * The result is simplified in terms of build->domain.
213 * Let e be the expression for the specified dimension.
214 * If v is 1, we simply return e.
215 * If v is -1, we return
217 * (isl_ast_op_minus, e)
219 * Otherwise, we return
221 * (isl_ast_op_mul, expr(v), e)
223 static __isl_give isl_ast_expr *isl_ast_expr_term(
224 __isl_keep isl_local_space *ls, enum isl_dim_type type, int pos,
225 isl_int v, __isl_keep isl_ast_build *build)
227 isl_ctx *ctx;
228 isl_ast_expr *expr;
229 isl_ast_expr *c;
231 if (!ls)
232 return NULL;
234 ctx = isl_local_space_get_ctx(ls);
235 expr = var(ls, type, pos, build);
237 if (!isl_int_is_one(v)) {
238 if (isl_int_is_negone(v)) {
239 expr = isl_ast_expr_neg(expr);
240 } else {
241 c = isl_ast_expr_alloc_int(ctx, v);
242 expr = isl_ast_expr_mul(c, expr);
246 return expr;
249 /* Add an expression for "v" times the specified dimension of "ls"
250 * to expr.
252 * Let e be the expression for the specified dimension.
253 * If "v" is negative, we create
255 * (isl_ast_op_sub, cons->expr, e)
257 * except when cons->expr is trivially zero, in which case we create
259 * (isl_ast_op_mines, e)
261 * instead.
263 * If "v" is positive, we simply create
265 * (isl_ast_op_add, cons->expr, e)
268 static __isl_give isl_ast_expr *isl_ast_expr_add_term(
269 __isl_take isl_ast_expr *expr,
270 __isl_keep isl_local_space *ls, enum isl_dim_type type, int pos,
271 isl_int v, __isl_keep isl_ast_build *build)
273 isl_ast_expr *term;
275 if (!expr)
276 return NULL;
278 if (isl_int_is_neg(v) && !ast_expr_is_zero(expr)) {
279 isl_int_neg(v, v);
280 term = isl_ast_expr_term(ls, type, pos, v, build);
281 return ast_expr_sub(expr, term);
282 } else {
283 term = isl_ast_expr_term(ls, type, pos, v, build);
284 return ast_expr_add(expr, term);
288 /* Add an expression for "v" to expr.
290 static __isl_give isl_ast_expr *isl_ast_expr_add_int(
291 __isl_take isl_ast_expr *expr, isl_int v)
293 isl_ctx *ctx;
294 isl_ast_expr *expr_int;
296 if (!expr)
297 return NULL;
299 if (isl_int_is_zero(v))
300 return expr;
302 ctx = isl_ast_expr_get_ctx(expr);
303 if (isl_int_is_neg(v) && !ast_expr_is_zero(expr)) {
304 isl_int_neg(v, v);
305 expr_int = isl_ast_expr_alloc_int(ctx, v);
306 return ast_expr_sub(expr, expr_int);
307 } else {
308 expr_int = isl_ast_expr_alloc_int(ctx, v);
309 return ast_expr_add(expr, expr_int);
313 /* Check if "aff" involves any (implicit) modulo computations.
314 * If so, remove them from aff and add expressions corresponding
315 * to those modulo computations to *pos and/or *neg.
316 * We only do this if the option ast_build_prefer_pdiv is set.
318 * A modulo expression is of the form
320 * a mod m = a - m * floor(a / m)
322 * To detect them in aff, we look for terms of the form
324 * (f * m * floor(a / m)) / d
326 * rewrite them as
328 * (f * (a - (a mod m))) / d = (f * a) / d - (f * (a mod m)) / d
330 * and extract out -f * (a mod m).
331 * In particular, if f > 0, we add (f * (a mod m)) to *neg.
332 * If f < 0, we add ((-f) * (a mod m)) to *pos.
334 * The caller is responsible for dividing *neg and/or *pos by d.
336 static __isl_give isl_aff *extract_modulos(__isl_take isl_aff *aff,
337 __isl_keep isl_ast_expr **pos, __isl_keep isl_ast_expr **neg,
338 __isl_keep isl_ast_build *build)
340 isl_ctx *ctx;
341 int j, n;
342 isl_int v, d;
343 isl_local_space *ls;
345 if (!aff)
346 return NULL;
348 ctx = isl_aff_get_ctx(aff);
349 if (!isl_options_get_ast_build_prefer_pdiv(ctx))
350 return aff;
352 isl_int_init(v);
353 isl_int_init(d);
354 ls = isl_aff_get_domain_local_space(aff);
356 n = isl_aff_dim(aff, isl_dim_div);
357 for (j = 0; j < n; ++j) {
358 isl_ast_expr *expr;
359 isl_aff *div;
360 int s;
361 int mod;
363 isl_aff_get_coefficient(aff, isl_dim_div, j, &v);
364 if (isl_int_is_zero(v))
365 continue;
366 div = isl_local_space_get_div(ls, j);
367 isl_aff_get_denominator(div, &d);
368 mod = isl_int_is_divisible_by(v, d);
369 if (mod)
370 mod = isl_ast_build_aff_is_nonneg(build, div);
371 if (mod < 0) {
372 aff = isl_aff_free(aff);
373 isl_aff_free(div);
374 break;
375 } else if (!mod) {
376 isl_aff_free(div);
377 continue;
379 div = isl_aff_scale(div, d);
380 isl_int_divexact(v, v, d);
381 s = isl_int_sgn(v);
382 isl_int_abs(v, v);
383 expr = isl_ast_expr_mod(v, div, d, build);
384 if (s > 0)
385 *neg = ast_expr_add(*neg, expr);
386 else
387 *pos = ast_expr_add(*pos, expr);
388 aff = isl_aff_set_coefficient_si(aff, isl_dim_div, j, 0);
389 if (s < 0)
390 isl_int_neg(v, v);
391 div = isl_aff_scale(div, v);
392 isl_aff_get_denominator(aff, &d);
393 div = isl_aff_scale_down(div, d);
394 aff = isl_aff_add(aff, div);
397 isl_local_space_free(ls);
398 isl_int_clear(d);
399 isl_int_clear(v);
401 return aff;
404 /* Construct an isl_ast_expr that evaluates the affine expression "aff",
405 * The result is simplified in terms of build->domain.
407 * We first extract hidden modulo computations from the affine expression
408 * and then add terms for each variable with a non-zero coefficient.
409 * Finally, if the affine expression has a non-trivial denominator,
410 * we divide the resulting isl_ast_expr by this denominator.
412 __isl_give isl_ast_expr *isl_ast_expr_from_aff(__isl_take isl_aff *aff,
413 __isl_keep isl_ast_build *build)
415 int i, j;
416 isl_int v;
417 int n;
418 isl_ctx *ctx = isl_aff_get_ctx(aff);
419 isl_ast_expr *expr, *expr_neg;
420 enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
421 enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
422 isl_local_space *ls;
424 if (!aff)
425 return NULL;
427 expr = isl_ast_expr_alloc_int_si(ctx, 0);
428 expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
430 aff = extract_modulos(aff, &expr, &expr_neg, build);
431 expr = ast_expr_sub(expr, expr_neg);
433 isl_int_init(v);
434 ls = isl_aff_get_domain_local_space(aff);
436 for (i = 0; i < 3; ++i) {
437 n = isl_aff_dim(aff, t[i]);
438 for (j = 0; j < n; ++j) {
439 isl_aff_get_coefficient(aff, t[i], j, &v);
440 if (isl_int_is_zero(v))
441 continue;
442 expr = isl_ast_expr_add_term(expr,
443 ls, l[i], j, v, build);
447 isl_aff_get_constant(aff, &v);
448 expr = isl_ast_expr_add_int(expr, v);
450 isl_aff_get_denominator(aff, &v);
451 if (!isl_int_is_one(v)) {
452 isl_ast_expr *d;
453 d = isl_ast_expr_alloc_int(ctx, v);
454 expr = isl_ast_expr_div(expr, d);
457 isl_local_space_free(ls);
458 isl_int_clear(v);
459 isl_aff_free(aff);
460 return expr;
463 /* Add terms to "expr" for each variable in "aff" with a coefficient
464 * with sign equal to "sign".
465 * The result is simplified in terms of build->domain.
467 static __isl_give isl_ast_expr *add_signed_terms(__isl_take isl_ast_expr *expr,
468 __isl_keep isl_aff *aff, int sign, __isl_keep isl_ast_build *build)
470 int i, j;
471 isl_int v;
472 enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
473 enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
474 isl_local_space *ls;
476 isl_int_init(v);
477 ls = isl_aff_get_domain_local_space(aff);
479 for (i = 0; i < 3; ++i) {
480 int n = isl_aff_dim(aff, t[i]);
481 for (j = 0; j < n; ++j) {
482 isl_aff_get_coefficient(aff, t[i], j, &v);
483 if (sign * isl_int_sgn(v) <= 0)
484 continue;
485 isl_int_abs(v, v);
486 expr = isl_ast_expr_add_term(expr,
487 ls, l[i], j, v, build);
491 isl_aff_get_constant(aff, &v);
492 if (sign * isl_int_sgn(v) > 0) {
493 isl_int_abs(v, v);
494 expr = isl_ast_expr_add_int(expr, v);
497 isl_local_space_free(ls);
498 isl_int_clear(v);
500 return expr;
503 /* Construct an isl_ast_expr that evaluates the condition "constraint",
504 * The result is simplified in terms of build->domain.
506 * Let the constraint by either "a >= 0" or "a == 0".
507 * We first extract hidden modulo computations from "a"
508 * and then collect all the terms with a positive coefficient in cons_pos
509 * and the terms with a negative coefficient in cons_neg.
511 * The result is then of the form
513 * (isl_ast_op_ge, expr(pos), expr(-neg)))
515 * or
517 * (isl_ast_op_eq, expr(pos), expr(-neg)))
519 * However, if the first expression is an integer constant (and the second
520 * is not), then we swap the two expressions. This ensures that we construct,
521 * e.g., "i <= 5" rather than "5 >= i".
523 static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
524 __isl_take isl_constraint *constraint, __isl_keep isl_ast_build *build)
526 isl_ctx *ctx;
527 isl_ast_expr *expr_pos;
528 isl_ast_expr *expr_neg;
529 isl_ast_expr *expr;
530 isl_aff *aff;
531 int eq;
532 enum isl_ast_op_type type;
534 if (!constraint)
535 return NULL;
537 aff = isl_constraint_get_aff(constraint);
539 ctx = isl_constraint_get_ctx(constraint);
540 expr_pos = isl_ast_expr_alloc_int_si(ctx, 0);
541 expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
543 aff = extract_modulos(aff, &expr_pos, &expr_neg, build);
545 expr_pos = add_signed_terms(expr_pos, aff, 1, build);
546 expr_neg = add_signed_terms(expr_neg, aff, -1, build);
548 eq = isl_constraint_is_equality(constraint);
550 if (isl_ast_expr_get_type(expr_pos) == isl_ast_expr_int &&
551 isl_ast_expr_get_type(expr_neg) != isl_ast_expr_int) {
552 type = eq ? isl_ast_op_eq : isl_ast_op_le;
553 expr = isl_ast_expr_alloc_binary(type, expr_neg, expr_pos);
554 } else {
555 type = eq ? isl_ast_op_eq : isl_ast_op_ge;
556 expr = isl_ast_expr_alloc_binary(type, expr_pos, expr_neg);
559 isl_constraint_free(constraint);
560 isl_aff_free(aff);
561 return expr;
564 struct isl_expr_from_basic_data {
565 isl_ast_build *build;
566 int first;
567 isl_ast_expr *res;
570 /* Construct an isl_ast_expr that evaluates the condition "c",
571 * except if it is a div constraint, and add it to the data->res.
572 * The result is simplified in terms of data->build->domain.
574 static int expr_from_basic_set(__isl_take isl_constraint *c, void *user)
576 struct isl_expr_from_basic_data *data = user;
577 isl_ast_expr *expr;
579 if (isl_constraint_is_div_constraint(c)) {
580 isl_constraint_free(c);
581 return 0;
584 expr = isl_ast_expr_from_constraint(c, data->build);
585 if (data->first)
586 data->res = expr;
587 else
588 data->res = isl_ast_expr_and(data->res, expr);
590 data->first = 0;
592 if (!data->res)
593 return -1;
594 return 0;
597 /* Construct an isl_ast_expr that evaluates the conditions defining "bset".
598 * The result is simplified in terms of build->domain.
600 * We filter out the div constraints during printing, so we do not know
601 * in advance how many constraints are going to be printed.
603 * If it turns out that there was no constraint, then we contruct
604 * the expression "1", i.e., "true".
606 __isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
607 __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
609 struct isl_expr_from_basic_data data = { build, 1, NULL };
611 if (isl_basic_set_foreach_constraint(bset,
612 &expr_from_basic_set, &data) < 0) {
613 data.res = isl_ast_expr_free(data.res);
614 } else if (data.res == NULL) {
615 isl_ctx *ctx = isl_basic_set_get_ctx(bset);
616 data.res = isl_ast_expr_alloc_int_si(ctx, 1);
619 isl_basic_set_free(bset);
620 return data.res;
623 struct isl_expr_from_set_data {
624 isl_ast_build *build;
625 int first;
626 isl_ast_expr *res;
629 /* Construct an isl_ast_expr that evaluates the conditions defining "bset"
630 * and add it to data->res.
631 * The result is simplified in terms of data->build->domain.
633 static int expr_from_set(__isl_take isl_basic_set *bset, void *user)
635 struct isl_expr_from_set_data *data = user;
636 isl_ast_expr *expr;
638 expr = isl_ast_build_expr_from_basic_set(data->build, bset);
639 if (data->first)
640 data->res = expr;
641 else
642 data->res = isl_ast_expr_or(data->res, expr);
644 data->first = 0;
646 if (!data->res)
647 return -1;
648 return 0;
651 /* Construct an isl_ast_expr that evaluates the conditions defining "set".
652 * The result is simplified in terms of build->domain.
654 __isl_give isl_ast_expr *isl_ast_build_expr_from_set(
655 __isl_keep isl_ast_build *build, __isl_take isl_set *set)
657 struct isl_expr_from_set_data data = { build, 1, NULL };
659 if (isl_set_foreach_basic_set(set, &expr_from_set, &data) < 0)
660 data.res = isl_ast_expr_free(data.res);
662 isl_set_free(set);
663 return data.res;
666 struct isl_from_pw_aff_data {
667 isl_ast_build *build;
668 int n;
669 isl_ast_expr **next;
670 isl_set *dom;
673 /* This function is called during the construction of an isl_ast_expr
674 * that evaluates an isl_pw_aff.
675 * Adjust data->next to take into account this piece.
677 * data->n is the number of pairs of set and aff to go.
678 * data->dom is the domain of the entire isl_pw_aff.
680 * If this is the last pair, then data->next is set to evaluate aff
681 * and the domain is ignored.
682 * Otherwise, data->next is set to a select operation that selects
683 * an isl_ast_expr correponding to "aff" on "set" and to an expression
684 * that will be filled in by later calls otherwise.
686 static int ast_expr_from_pw_aff(__isl_take isl_set *set,
687 __isl_take isl_aff *aff, void *user)
689 struct isl_from_pw_aff_data *data = user;
690 isl_ctx *ctx;
692 ctx = isl_set_get_ctx(set);
693 data->n--;
694 if (data->n == 0) {
695 *data->next = isl_ast_expr_from_aff(aff, data->build);
696 isl_set_free(set);
697 if (!*data->next)
698 return -1;
699 } else {
700 isl_ast_expr *ternary, *arg;
702 ternary = isl_ast_expr_alloc_op(ctx, isl_ast_op_select, 3);
703 set = isl_set_gist(set, isl_set_copy(data->dom));
704 arg = isl_ast_build_expr_from_set(data->build, set);
705 ternary = isl_ast_expr_set_op_arg(ternary, 0, arg);
706 arg = isl_ast_expr_from_aff(aff, data->build);
707 ternary = isl_ast_expr_set_op_arg(ternary, 1, arg);
708 if (!ternary)
709 return -1;
711 *data->next = ternary;
712 data->next = &ternary->u.op.args[2];
715 return 0;
718 /* Construct an isl_ast_expr that evaluates "pa".
719 * The result is simplified in terms of build->domain.
721 * The domain of "pa" lives in the internal schedule space.
723 __isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff_internal(
724 __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
726 struct isl_from_pw_aff_data data;
727 isl_ast_expr *res = NULL;
729 if (!pa)
730 return NULL;
732 data.build = build;
733 data.n = isl_pw_aff_n_piece(pa);
734 data.next = &res;
735 data.dom = isl_pw_aff_domain(isl_pw_aff_copy(pa));
737 if (isl_pw_aff_foreach_piece(pa, &ast_expr_from_pw_aff, &data) < 0)
738 res = isl_ast_expr_free(res);
739 else if (!res)
740 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
741 "cannot handle void expression", res = NULL);
743 isl_pw_aff_free(pa);
744 isl_set_free(data.dom);
745 return res;
748 /* Construct an isl_ast_expr that evaluates "pa".
749 * The result is simplified in terms of build->domain.
751 * The domain of "pa" lives in the external schedule space.
753 __isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
754 __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
756 isl_ast_expr *expr;
758 if (isl_ast_build_need_schedule_map(build)) {
759 isl_multi_aff *ma;
760 ma = isl_ast_build_get_schedule_map_multi_aff(build);
761 pa = isl_pw_aff_pullback_multi_aff(pa, ma);
763 expr = isl_ast_build_expr_from_pw_aff_internal(build, pa);
764 return expr;
767 /* Set the ids of the input dimensions of "pma" to the iterator ids
768 * of "build".
770 * The domain of "pma" is assumed to live in the internal schedule domain.
772 static __isl_give isl_pw_multi_aff *set_iterator_names(
773 __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
775 int i, n;
777 n = isl_pw_multi_aff_dim(pma, isl_dim_in);
778 for (i = 0; i < n; ++i) {
779 isl_id *id;
781 id = isl_ast_build_get_iterator_id(build, i);
782 pma = isl_pw_multi_aff_set_dim_id(pma, isl_dim_in, i, id);
785 return pma;
788 /* Construct an isl_ast_expr that calls the domain element specified by "pma".
789 * The name of the function is obtained from the output tuple name.
790 * The arguments are given by the piecewise affine expressions.
792 * The domain of "pma" is assumed to live in the internal schedule domain.
794 static __isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff_internal(
795 __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
797 int i, n;
798 isl_ctx *ctx;
799 isl_id *id;
800 isl_ast_expr *expr;
802 pma = set_iterator_names(build, pma);
803 if (!build || !pma)
804 return isl_pw_multi_aff_free(pma);
806 ctx = isl_ast_build_get_ctx(build);
807 n = isl_pw_multi_aff_dim(pma, isl_dim_out);
808 expr = isl_ast_expr_alloc_op(ctx, isl_ast_op_call, 1 + n);
810 if (isl_pw_multi_aff_has_tuple_id(pma, isl_dim_out))
811 id = isl_pw_multi_aff_get_tuple_id(pma, isl_dim_out);
812 else
813 id = isl_id_alloc(ctx, "", NULL);
815 expr = isl_ast_expr_set_op_arg(expr, 0, isl_ast_expr_from_id(id));
816 for (i = 0; i < n; ++i) {
817 isl_pw_aff *pa;
818 isl_ast_expr *arg;
820 pa = isl_pw_multi_aff_get_pw_aff(pma, i);
821 arg = isl_ast_build_expr_from_pw_aff_internal(build, pa);
822 expr = isl_ast_expr_set_op_arg(expr, 1 + i, arg);
825 isl_pw_multi_aff_free(pma);
826 return expr;
829 /* Construct an isl_ast_expr that calls the domain element specified by "pma".
830 * The name of the function is obtained from the output tuple name.
831 * The arguments are given by the piecewise affine expressions.
833 * The domain of "pma" is assumed to live in the external schedule domain.
835 __isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
836 __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
838 int is_domain;
839 isl_ast_expr *expr;
840 isl_space *space_build, *space_pma;
842 space_build = isl_ast_build_get_space(build, 0);
843 space_pma = isl_pw_multi_aff_get_space(pma);
844 is_domain = isl_space_tuple_match(space_build, isl_dim_set,
845 space_pma, isl_dim_in);
846 isl_space_free(space_build);
847 isl_space_free(space_pma);
848 if (is_domain < 0)
849 return isl_pw_multi_aff_free(pma);
850 if (!is_domain)
851 isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
852 "spaces don't match",
853 return isl_pw_multi_aff_free(pma));
855 if (isl_ast_build_need_schedule_map(build)) {
856 isl_multi_aff *ma;
857 ma = isl_ast_build_get_schedule_map_multi_aff(build);
858 pma = isl_pw_multi_aff_pullback_multi_aff(pma, ma);
861 expr = isl_ast_build_call_from_pw_multi_aff_internal(build, pma);
862 return expr;
865 /* Construct an isl_ast_expr that calls the domain element
866 * specified by "executed".
868 * "executed" is assumed to be single-valued, with a domain that lives
869 * in the internal schedule space.
871 __isl_give isl_ast_node *isl_ast_build_call_from_executed(
872 __isl_keep isl_ast_build *build, __isl_take isl_map *executed)
874 isl_pw_multi_aff *iteration;
875 isl_ast_expr *expr;
877 iteration = isl_pw_multi_aff_from_map(executed);
878 iteration = isl_ast_build_compute_gist_pw_multi_aff(build, iteration);
879 iteration = isl_pw_multi_aff_intersect_domain(iteration,
880 isl_ast_build_get_domain(build));
881 expr = isl_ast_build_call_from_pw_multi_aff_internal(build, iteration);
882 return isl_ast_node_alloc_user(expr);