• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012-2014 Ecole Normale Superieure
3  * Copyright 2014      INRIA Rocquencourt
4  *
5  * Use of this software is governed by the MIT license
6  *
7  * Written by Sven Verdoolaege,
8  * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
9  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
10  * B.P. 105 - 78153 Le Chesnay, France
11  */
12 
13 #include <isl/id.h>
14 #include <isl/space.h>
15 #include <isl/constraint.h>
16 #include <isl/ilp.h>
17 #include <isl/val.h>
18 #include <isl_ast_build_expr.h>
19 #include <isl_ast_private.h>
20 #include <isl_ast_build_private.h>
21 #include <isl_sort.h>
22 
23 /* Compute the "opposite" of the (numerator of the) argument of a div
24  * with denominator "d".
25  *
26  * In particular, compute
27  *
28  *	-aff + (d - 1)
29  */
oppose_div_arg(__isl_take isl_aff * aff,__isl_take isl_val * d)30 static __isl_give isl_aff *oppose_div_arg(__isl_take isl_aff *aff,
31 	__isl_take isl_val *d)
32 {
33 	aff = isl_aff_neg(aff);
34 	aff = isl_aff_add_constant_val(aff, d);
35 	aff = isl_aff_add_constant_si(aff, -1);
36 
37 	return aff;
38 }
39 
40 /* Internal data structure used inside isl_ast_expr_add_term.
41  * The domain of "build" is used to simplify the expressions.
42  * "build" needs to be set by the caller of isl_ast_expr_add_term.
43  * "cst" is the constant term of the expression in which the added term
44  * appears.  It may be modified by isl_ast_expr_add_term.
45  *
46  * "v" is the coefficient of the term that is being constructed and
47  * is set internally by isl_ast_expr_add_term.
48  */
49 struct isl_ast_add_term_data {
50 	isl_ast_build *build;
51 	isl_val *cst;
52 	isl_val *v;
53 };
54 
55 /* Given the numerator "aff" of the argument of an integer division
56  * with denominator "d", check if it can be made non-negative over
57  * data->build->domain by stealing part of the constant term of
58  * the expression in which the integer division appears.
59  *
60  * In particular, the outer expression is of the form
61  *
62  *	v * floor(aff/d) + cst
63  *
64  * We already know that "aff" itself may attain negative values.
65  * Here we check if aff + d*floor(cst/v) is non-negative, such
66  * that we could rewrite the expression to
67  *
68  *	v * floor((aff + d*floor(cst/v))/d) + cst - v*floor(cst/v)
69  *
70  * Note that aff + d*floor(cst/v) can only possibly be non-negative
71  * if data->cst and data->v have the same sign.
72  * Similarly, if floor(cst/v) is zero, then there is no point in
73  * checking again.
74  */
is_non_neg_after_stealing(__isl_keep isl_aff * aff,__isl_keep isl_val * d,struct isl_ast_add_term_data * data)75 static int is_non_neg_after_stealing(__isl_keep isl_aff *aff,
76 	__isl_keep isl_val *d, struct isl_ast_add_term_data *data)
77 {
78 	isl_aff *shifted;
79 	isl_val *shift;
80 	int is_zero;
81 	int non_neg;
82 
83 	if (isl_val_sgn(data->cst) != isl_val_sgn(data->v))
84 		return 0;
85 
86 	shift = isl_val_div(isl_val_copy(data->cst), isl_val_copy(data->v));
87 	shift = isl_val_floor(shift);
88 	is_zero = isl_val_is_zero(shift);
89 	if (is_zero < 0 || is_zero) {
90 		isl_val_free(shift);
91 		return is_zero < 0 ? -1 : 0;
92 	}
93 	shift = isl_val_mul(shift, isl_val_copy(d));
94 	shifted = isl_aff_copy(aff);
95 	shifted = isl_aff_add_constant_val(shifted, shift);
96 	non_neg = isl_ast_build_aff_is_nonneg(data->build, shifted);
97 	isl_aff_free(shifted);
98 
99 	return non_neg;
100 }
101 
102 /* Given the numerator "aff' of the argument of an integer division
103  * with denominator "d", steal part of the constant term of
104  * the expression in which the integer division appears to make it
105  * non-negative over data->build->domain.
106  *
107  * In particular, the outer expression is of the form
108  *
109  *	v * floor(aff/d) + cst
110  *
111  * We know that "aff" itself may attain negative values,
112  * but that aff + d*floor(cst/v) is non-negative.
113  * Find the minimal positive value that we need to add to "aff"
114  * to make it positive and adjust data->cst accordingly.
115  * That is, compute the minimal value "m" of "aff" over
116  * data->build->domain and take
117  *
118  *	s = ceil(m/d)
119  *
120  * such that
121  *
122  *	aff + d * s >= 0
123  *
124  * and rewrite the expression to
125  *
126  *	v * floor((aff + s*d)/d) + (cst - v*s)
127  */
steal_from_cst(__isl_take isl_aff * aff,__isl_keep isl_val * d,struct isl_ast_add_term_data * data)128 static __isl_give isl_aff *steal_from_cst(__isl_take isl_aff *aff,
129 	__isl_keep isl_val *d, struct isl_ast_add_term_data *data)
130 {
131 	isl_set *domain;
132 	isl_val *shift, *t;
133 
134 	domain = isl_ast_build_get_domain(data->build);
135 	shift = isl_set_min_val(domain, aff);
136 	isl_set_free(domain);
137 
138 	shift = isl_val_neg(shift);
139 	shift = isl_val_div(shift, isl_val_copy(d));
140 	shift = isl_val_ceil(shift);
141 
142 	t = isl_val_copy(shift);
143 	t = isl_val_mul(t, isl_val_copy(data->v));
144 	data->cst = isl_val_sub(data->cst, t);
145 
146 	shift = isl_val_mul(shift, isl_val_copy(d));
147 	return isl_aff_add_constant_val(aff, shift);
148 }
149 
150 /* Create an isl_ast_expr evaluating the div at position "pos" in "ls".
151  * The result is simplified in terms of data->build->domain.
152  * This function may change (the sign of) data->v.
153  *
154  * "ls" is known to be non-NULL.
155  *
156  * Let the div be of the form floor(e/d).
157  * If the ast_build_prefer_pdiv option is set then we check if "e"
158  * is non-negative, so that we can generate
159  *
160  *	(pdiv_q, expr(e), expr(d))
161  *
162  * instead of
163  *
164  *	(fdiv_q, expr(e), expr(d))
165  *
166  * If the ast_build_prefer_pdiv option is set and
167  * if "e" is not non-negative, then we check if "-e + d - 1" is non-negative.
168  * If so, we can rewrite
169  *
170  *	floor(e/d) = -ceil(-e/d) = -floor((-e + d - 1)/d)
171  *
172  * and still use pdiv_q, while changing the sign of data->v.
173  *
174  * Otherwise, we check if
175  *
176  *	e + d*floor(cst/v)
177  *
178  * is non-negative and if so, replace floor(e/d) by
179  *
180  *	floor((e + s*d)/d) - s
181  *
182  * with s the minimal shift that makes the argument non-negative.
183  */
var_div(struct isl_ast_add_term_data * data,__isl_keep isl_local_space * ls,int pos)184 static __isl_give isl_ast_expr *var_div(struct isl_ast_add_term_data *data,
185 	__isl_keep isl_local_space *ls, int pos)
186 {
187 	isl_ctx *ctx = isl_local_space_get_ctx(ls);
188 	isl_aff *aff;
189 	isl_ast_expr *num, *den;
190 	isl_val *d;
191 	enum isl_ast_expr_op_type type;
192 
193 	aff = isl_local_space_get_div(ls, pos);
194 	d = isl_aff_get_denominator_val(aff);
195 	aff = isl_aff_scale_val(aff, isl_val_copy(d));
196 	den = isl_ast_expr_from_val(isl_val_copy(d));
197 
198 	type = isl_ast_expr_op_fdiv_q;
199 	if (isl_options_get_ast_build_prefer_pdiv(ctx)) {
200 		int non_neg = isl_ast_build_aff_is_nonneg(data->build, aff);
201 		if (non_neg >= 0 && !non_neg) {
202 			isl_aff *opp = oppose_div_arg(isl_aff_copy(aff),
203 							isl_val_copy(d));
204 			non_neg = isl_ast_build_aff_is_nonneg(data->build, opp);
205 			if (non_neg >= 0 && non_neg) {
206 				data->v = isl_val_neg(data->v);
207 				isl_aff_free(aff);
208 				aff = opp;
209 			} else
210 				isl_aff_free(opp);
211 		}
212 		if (non_neg >= 0 && !non_neg) {
213 			non_neg = is_non_neg_after_stealing(aff, d, data);
214 			if (non_neg >= 0 && non_neg)
215 				aff = steal_from_cst(aff, d, data);
216 		}
217 		if (non_neg < 0)
218 			aff = isl_aff_free(aff);
219 		else if (non_neg)
220 			type = isl_ast_expr_op_pdiv_q;
221 	}
222 
223 	isl_val_free(d);
224 	num = isl_ast_expr_from_aff(aff, data->build);
225 	return isl_ast_expr_alloc_binary(type, num, den);
226 }
227 
228 /* Create an isl_ast_expr evaluating the specified dimension of "ls".
229  * The result is simplified in terms of data->build->domain.
230  * This function may change (the sign of) data->v.
231  *
232  * The isl_ast_expr is constructed based on the type of the dimension.
233  * - divs are constructed by var_div
234  * - set variables are constructed from the iterator isl_ids in data->build
235  * - parameters are constructed from the isl_ids in "ls"
236  */
var(struct isl_ast_add_term_data * data,__isl_keep isl_local_space * ls,enum isl_dim_type type,int pos)237 static __isl_give isl_ast_expr *var(struct isl_ast_add_term_data *data,
238 	__isl_keep isl_local_space *ls, enum isl_dim_type type, int pos)
239 {
240 	isl_ctx *ctx = isl_local_space_get_ctx(ls);
241 	isl_id *id;
242 
243 	if (type == isl_dim_div)
244 		return var_div(data, ls, pos);
245 
246 	if (type == isl_dim_set) {
247 		id = isl_ast_build_get_iterator_id(data->build, pos);
248 		return isl_ast_expr_from_id(id);
249 	}
250 
251 	if (!isl_local_space_has_dim_id(ls, type, pos))
252 		isl_die(ctx, isl_error_internal, "unnamed dimension",
253 			return NULL);
254 	id = isl_local_space_get_dim_id(ls, type, pos);
255 	return isl_ast_expr_from_id(id);
256 }
257 
258 /* Does "expr" represent the zero integer?
259  */
ast_expr_is_zero(__isl_keep isl_ast_expr * expr)260 static int ast_expr_is_zero(__isl_keep isl_ast_expr *expr)
261 {
262 	if (!expr)
263 		return -1;
264 	if (expr->type != isl_ast_expr_int)
265 		return 0;
266 	return isl_val_is_zero(expr->u.v);
267 }
268 
269 /* Create an expression representing the sum of "expr1" and "expr2",
270  * provided neither of the two expressions is identically zero.
271  */
ast_expr_add(__isl_take isl_ast_expr * expr1,__isl_take isl_ast_expr * expr2)272 static __isl_give isl_ast_expr *ast_expr_add(__isl_take isl_ast_expr *expr1,
273 	__isl_take isl_ast_expr *expr2)
274 {
275 	if (!expr1 || !expr2)
276 		goto error;
277 
278 	if (ast_expr_is_zero(expr1)) {
279 		isl_ast_expr_free(expr1);
280 		return expr2;
281 	}
282 
283 	if (ast_expr_is_zero(expr2)) {
284 		isl_ast_expr_free(expr2);
285 		return expr1;
286 	}
287 
288 	return isl_ast_expr_add(expr1, expr2);
289 error:
290 	isl_ast_expr_free(expr1);
291 	isl_ast_expr_free(expr2);
292 	return NULL;
293 }
294 
295 /* Subtract expr2 from expr1.
296  *
297  * If expr2 is zero, we simply return expr1.
298  * If expr1 is zero, we return
299  *
300  *	(isl_ast_expr_op_minus, expr2)
301  *
302  * Otherwise, we return
303  *
304  *	(isl_ast_expr_op_sub, expr1, expr2)
305  */
ast_expr_sub(__isl_take isl_ast_expr * expr1,__isl_take isl_ast_expr * expr2)306 static __isl_give isl_ast_expr *ast_expr_sub(__isl_take isl_ast_expr *expr1,
307 	__isl_take isl_ast_expr *expr2)
308 {
309 	if (!expr1 || !expr2)
310 		goto error;
311 
312 	if (ast_expr_is_zero(expr2)) {
313 		isl_ast_expr_free(expr2);
314 		return expr1;
315 	}
316 
317 	if (ast_expr_is_zero(expr1)) {
318 		isl_ast_expr_free(expr1);
319 		return isl_ast_expr_neg(expr2);
320 	}
321 
322 	return isl_ast_expr_sub(expr1, expr2);
323 error:
324 	isl_ast_expr_free(expr1);
325 	isl_ast_expr_free(expr2);
326 	return NULL;
327 }
328 
329 /* Return an isl_ast_expr that represents
330  *
331  *	v * (aff mod d)
332  *
333  * v is assumed to be non-negative.
334  * The result is simplified in terms of build->domain.
335  */
isl_ast_expr_mod(__isl_keep isl_val * v,__isl_keep isl_aff * aff,__isl_keep isl_val * d,__isl_keep isl_ast_build * build)336 static __isl_give isl_ast_expr *isl_ast_expr_mod(__isl_keep isl_val *v,
337 	__isl_keep isl_aff *aff, __isl_keep isl_val *d,
338 	__isl_keep isl_ast_build *build)
339 {
340 	isl_ast_expr *expr;
341 	isl_ast_expr *c;
342 
343 	if (!aff)
344 		return NULL;
345 
346 	expr = isl_ast_expr_from_aff(isl_aff_copy(aff), build);
347 
348 	c = isl_ast_expr_from_val(isl_val_copy(d));
349 	expr = isl_ast_expr_alloc_binary(isl_ast_expr_op_pdiv_r, expr, c);
350 
351 	if (!isl_val_is_one(v)) {
352 		c = isl_ast_expr_from_val(isl_val_copy(v));
353 		expr = isl_ast_expr_mul(c, expr);
354 	}
355 
356 	return expr;
357 }
358 
359 /* Create an isl_ast_expr that scales "expr" by "v".
360  *
361  * If v is 1, we simply return expr.
362  * If v is -1, we return
363  *
364  *	(isl_ast_expr_op_minus, expr)
365  *
366  * Otherwise, we return
367  *
368  *	(isl_ast_expr_op_mul, expr(v), expr)
369  */
scale(__isl_take isl_ast_expr * expr,__isl_take isl_val * v)370 static __isl_give isl_ast_expr *scale(__isl_take isl_ast_expr *expr,
371 	__isl_take isl_val *v)
372 {
373 	isl_ast_expr *c;
374 
375 	if (!expr || !v)
376 		goto error;
377 	if (isl_val_is_one(v)) {
378 		isl_val_free(v);
379 		return expr;
380 	}
381 
382 	if (isl_val_is_negone(v)) {
383 		isl_val_free(v);
384 		expr = isl_ast_expr_neg(expr);
385 	} else {
386 		c = isl_ast_expr_from_val(v);
387 		expr = isl_ast_expr_mul(c, expr);
388 	}
389 
390 	return expr;
391 error:
392 	isl_val_free(v);
393 	isl_ast_expr_free(expr);
394 	return NULL;
395 }
396 
397 /* Add an expression for "*v" times the specified dimension of "ls"
398  * to expr.
399  * If the dimension is an integer division, then this function
400  * may modify data->cst in order to make the numerator non-negative.
401  * The result is simplified in terms of data->build->domain.
402  *
403  * Let e be the expression for the specified dimension,
404  * multiplied by the absolute value of "*v".
405  * If "*v" is negative, we create
406  *
407  *	(isl_ast_expr_op_sub, expr, e)
408  *
409  * except when expr is trivially zero, in which case we create
410  *
411  *	(isl_ast_expr_op_minus, e)
412  *
413  * instead.
414  *
415  * If "*v" is positive, we simply create
416  *
417  *	(isl_ast_expr_op_add, expr, e)
418  *
419  */
isl_ast_expr_add_term(__isl_take isl_ast_expr * expr,__isl_keep isl_local_space * ls,enum isl_dim_type type,int pos,__isl_take isl_val * v,struct isl_ast_add_term_data * data)420 static __isl_give isl_ast_expr *isl_ast_expr_add_term(
421 	__isl_take isl_ast_expr *expr,
422 	__isl_keep isl_local_space *ls, enum isl_dim_type type, int pos,
423 	__isl_take isl_val *v, struct isl_ast_add_term_data *data)
424 {
425 	isl_ast_expr *term;
426 
427 	if (!expr)
428 		return NULL;
429 
430 	data->v = v;
431 	term = var(data, ls, type, pos);
432 	v = data->v;
433 
434 	if (isl_val_is_neg(v) && !ast_expr_is_zero(expr)) {
435 		v = isl_val_neg(v);
436 		term = scale(term, v);
437 		return ast_expr_sub(expr, term);
438 	} else {
439 		term = scale(term, v);
440 		return ast_expr_add(expr, term);
441 	}
442 }
443 
444 /* Add an expression for "v" to expr.
445  */
isl_ast_expr_add_int(__isl_take isl_ast_expr * expr,__isl_take isl_val * v)446 static __isl_give isl_ast_expr *isl_ast_expr_add_int(
447 	__isl_take isl_ast_expr *expr, __isl_take isl_val *v)
448 {
449 	isl_ast_expr *expr_int;
450 
451 	if (!expr || !v)
452 		goto error;
453 
454 	if (isl_val_is_zero(v)) {
455 		isl_val_free(v);
456 		return expr;
457 	}
458 
459 	if (isl_val_is_neg(v) && !ast_expr_is_zero(expr)) {
460 		v = isl_val_neg(v);
461 		expr_int = isl_ast_expr_from_val(v);
462 		return ast_expr_sub(expr, expr_int);
463 	} else {
464 		expr_int = isl_ast_expr_from_val(v);
465 		return ast_expr_add(expr, expr_int);
466 	}
467 error:
468 	isl_ast_expr_free(expr);
469 	isl_val_free(v);
470 	return NULL;
471 }
472 
473 /* Internal data structure used inside extract_modulos.
474  *
475  * If any modulo expressions are detected in "aff", then the
476  * expression is removed from "aff" and added to either "pos" or "neg"
477  * depending on the sign of the coefficient of the modulo expression
478  * inside "aff".
479  *
480  * "add" is an expression that needs to be added to "aff" at the end of
481  * the computation.  It is NULL as long as no modulos have been extracted.
482  *
483  * "i" is the position in "aff" of the div under investigation
484  * "v" is the coefficient in "aff" of the div
485  * "div" is the argument of the div, with the denominator removed
486  * "d" is the original denominator of the argument of the div
487  *
488  * "nonneg" is an affine expression that is non-negative over "build"
489  * and that can be used to extract a modulo expression from "div".
490  * In particular, if "sign" is 1, then the coefficients of "nonneg"
491  * are equal to those of "div" modulo "d".  If "sign" is -1, then
492  * the coefficients of "nonneg" are opposite to those of "div" modulo "d".
493  * If "sign" is 0, then no such affine expression has been found (yet).
494  */
495 struct isl_extract_mod_data {
496 	isl_ast_build *build;
497 	isl_aff *aff;
498 
499 	isl_ast_expr *pos;
500 	isl_ast_expr *neg;
501 
502 	isl_aff *add;
503 
504 	int i;
505 	isl_val *v;
506 	isl_val *d;
507 	isl_aff *div;
508 
509 	isl_aff *nonneg;
510 	int sign;
511 };
512 
513 /* Does
514  *
515  *	arg mod data->d
516  *
517  * represent (a special case of) a test for some linear expression
518  * being even?
519  *
520  * In particular, is it of the form
521  *
522  *	(lin - 1) mod 2
523  *
524  * ?
525  */
is_even_test(struct isl_extract_mod_data * data,__isl_keep isl_aff * arg)526 static isl_bool is_even_test(struct isl_extract_mod_data *data,
527 	__isl_keep isl_aff *arg)
528 {
529 	isl_bool res;
530 	isl_val *cst;
531 
532 	res = isl_val_eq_si(data->d, 2);
533 	if (res < 0 || !res)
534 		return res;
535 
536 	cst = isl_aff_get_constant_val(arg);
537 	res = isl_val_eq_si(cst, -1);
538 	isl_val_free(cst);
539 
540 	return res;
541 }
542 
543 /* Given that data->v * div_i in data->aff is equal to
544  *
545  *	f * (term - (arg mod d))
546  *
547  * with data->d * f = data->v and "arg" non-negative on data->build, add
548  *
549  *	f * term
550  *
551  * to data->add and
552  *
553  *	abs(f) * (arg mod d)
554  *
555  * to data->neg or data->pos depending on the sign of -f.
556  *
557  * In the special case that "arg mod d" is of the form "(lin - 1) mod 2",
558  * with "lin" some linear expression, first replace
559  *
560  *	f * (term - ((lin - 1) mod 2))
561  *
562  * by
563  *
564  *	-f * (1 - term - (lin mod 2))
565  *
566  * These two are equal because
567  *
568  *	((lin - 1) mod 2) + (lin mod 2) = 1
569  *
570  * Also, if "lin - 1" is non-negative, then "lin" is non-negative too.
571  */
extract_term_and_mod(struct isl_extract_mod_data * data,__isl_take isl_aff * term,__isl_take isl_aff * arg)572 static int extract_term_and_mod(struct isl_extract_mod_data *data,
573 	__isl_take isl_aff *term, __isl_take isl_aff *arg)
574 {
575 	isl_bool even;
576 	isl_ast_expr *expr;
577 	int s;
578 
579 	even = is_even_test(data, arg);
580 	if (even < 0) {
581 		arg = isl_aff_free(arg);
582 	} else if (even) {
583 		term = oppose_div_arg(term, isl_val_copy(data->d));
584 		data->v = isl_val_neg(data->v);
585 		arg = isl_aff_set_constant_si(arg, 0);
586 	}
587 
588 	data->v = isl_val_div(data->v, isl_val_copy(data->d));
589 	s = isl_val_sgn(data->v);
590 	data->v = isl_val_abs(data->v);
591 	expr = isl_ast_expr_mod(data->v, arg, data->d, data->build);
592 	isl_aff_free(arg);
593 	if (s > 0)
594 		data->neg = ast_expr_add(data->neg, expr);
595 	else
596 		data->pos = ast_expr_add(data->pos, expr);
597 	data->aff = isl_aff_set_coefficient_si(data->aff,
598 						isl_dim_div, data->i, 0);
599 	if (s < 0)
600 		data->v = isl_val_neg(data->v);
601 	term = isl_aff_scale_val(term, isl_val_copy(data->v));
602 
603 	if (!data->add)
604 		data->add = term;
605 	else
606 		data->add = isl_aff_add(data->add, term);
607 	if (!data->add)
608 		return -1;
609 
610 	return 0;
611 }
612 
613 /* Given that data->v * div_i in data->aff is of the form
614  *
615  *	f * d * floor(div/d)
616  *
617  * with div nonnegative on data->build, rewrite it as
618  *
619  *	f * (div - (div mod d)) = f * div - f * (div mod d)
620  *
621  * and add
622  *
623  *	f * div
624  *
625  * to data->add and
626  *
627  *	abs(f) * (div mod d)
628  *
629  * to data->neg or data->pos depending on the sign of -f.
630  */
extract_mod(struct isl_extract_mod_data * data)631 static int extract_mod(struct isl_extract_mod_data *data)
632 {
633 	return extract_term_and_mod(data, isl_aff_copy(data->div),
634 			isl_aff_copy(data->div));
635 }
636 
637 /* Given that data->v * div_i in data->aff is of the form
638  *
639  *	f * d * floor(div/d)					(1)
640  *
641  * check if div is non-negative on data->build and, if so,
642  * extract the corresponding modulo from data->aff.
643  * If not, then check if
644  *
645  *	-div + d - 1
646  *
647  * is non-negative on data->build.  If so, replace (1) by
648  *
649  *	-f * d * floor((-div + d - 1)/d)
650  *
651  * and extract the corresponding modulo from data->aff.
652  *
653  * This function may modify data->div.
654  */
extract_nonneg_mod(struct isl_extract_mod_data * data)655 static int extract_nonneg_mod(struct isl_extract_mod_data *data)
656 {
657 	int mod;
658 
659 	mod = isl_ast_build_aff_is_nonneg(data->build, data->div);
660 	if (mod < 0)
661 		goto error;
662 	if (mod)
663 		return extract_mod(data);
664 
665 	data->div = oppose_div_arg(data->div, isl_val_copy(data->d));
666 	mod = isl_ast_build_aff_is_nonneg(data->build, data->div);
667 	if (mod < 0)
668 		goto error;
669 	if (mod) {
670 		data->v = isl_val_neg(data->v);
671 		return extract_mod(data);
672 	}
673 
674 	return 0;
675 error:
676 	data->aff = isl_aff_free(data->aff);
677 	return -1;
678 }
679 
680 /* Is the affine expression of constraint "c" "simpler" than data->nonneg
681  * for use in extracting a modulo expression?
682  *
683  * We currently only consider the constant term of the affine expression.
684  * In particular, we prefer the affine expression with the smallest constant
685  * term.
686  * This means that if there are two constraints, say x >= 0 and -x + 10 >= 0,
687  * then we would pick x >= 0
688  *
689  * More detailed heuristics could be used if it turns out that there is a need.
690  */
mod_constraint_is_simpler(struct isl_extract_mod_data * data,__isl_keep isl_constraint * c)691 static int mod_constraint_is_simpler(struct isl_extract_mod_data *data,
692 	__isl_keep isl_constraint *c)
693 {
694 	isl_val *v1, *v2;
695 	int simpler;
696 
697 	if (!data->nonneg)
698 		return 1;
699 
700 	v1 = isl_val_abs(isl_constraint_get_constant_val(c));
701 	v2 = isl_val_abs(isl_aff_get_constant_val(data->nonneg));
702 	simpler = isl_val_lt(v1, v2);
703 	isl_val_free(v1);
704 	isl_val_free(v2);
705 
706 	return simpler;
707 }
708 
709 /* Check if the coefficients of "c" are either equal or opposite to those
710  * of data->div modulo data->d.  If so, and if "c" is "simpler" than
711  * data->nonneg, then replace data->nonneg by the affine expression of "c"
712  * and set data->sign accordingly.
713  *
714  * Both "c" and data->div are assumed not to involve any integer divisions.
715  *
716  * Before we start the actual comparison, we first quickly check if
717  * "c" and data->div have the same non-zero coefficients.
718  * If not, then we assume that "c" is not of the desired form.
719  * Note that while the coefficients of data->div can be reasonably expected
720  * not to involve any coefficients that are multiples of d, "c" may
721  * very well involve such coefficients.  This means that we may actually
722  * miss some cases.
723  *
724  * If the constant term is "too large", then the constraint is rejected,
725  * where "too large" is fairly arbitrarily set to 1 << 15.
726  * We do this to avoid picking up constraints that bound a variable
727  * by a very large number, say the largest or smallest possible
728  * variable in the representation of some integer type.
729  */
check_parallel_or_opposite(__isl_take isl_constraint * c,void * user)730 static isl_stat check_parallel_or_opposite(__isl_take isl_constraint *c,
731 	void *user)
732 {
733 	struct isl_extract_mod_data *data = user;
734 	enum isl_dim_type c_type[2] = { isl_dim_param, isl_dim_set };
735 	enum isl_dim_type a_type[2] = { isl_dim_param, isl_dim_in };
736 	int i, t;
737 	isl_size n[2];
738 	int parallel = 1, opposite = 1;
739 
740 	for (t = 0; t < 2; ++t) {
741 		n[t] = isl_constraint_dim(c, c_type[t]);
742 		if (n[t] < 0)
743 			return isl_stat_error;
744 		for (i = 0; i < n[t]; ++i) {
745 			int a, b;
746 
747 			a = isl_constraint_involves_dims(c, c_type[t], i, 1);
748 			b = isl_aff_involves_dims(data->div, a_type[t], i, 1);
749 			if (a != b)
750 				parallel = opposite = 0;
751 		}
752 	}
753 
754 	if (parallel || opposite) {
755 		isl_val *v;
756 
757 		v = isl_val_abs(isl_constraint_get_constant_val(c));
758 		if (isl_val_cmp_si(v, 1 << 15) > 0)
759 			parallel = opposite = 0;
760 		isl_val_free(v);
761 	}
762 
763 	for (t = 0; t < 2; ++t) {
764 		for (i = 0; i < n[t]; ++i) {
765 			isl_val *v1, *v2;
766 
767 			if (!parallel && !opposite)
768 				break;
769 			v1 = isl_constraint_get_coefficient_val(c,
770 								c_type[t], i);
771 			v2 = isl_aff_get_coefficient_val(data->div,
772 								a_type[t], i);
773 			if (parallel) {
774 				v1 = isl_val_sub(v1, isl_val_copy(v2));
775 				parallel = isl_val_is_divisible_by(v1, data->d);
776 				v1 = isl_val_add(v1, isl_val_copy(v2));
777 			}
778 			if (opposite) {
779 				v1 = isl_val_add(v1, isl_val_copy(v2));
780 				opposite = isl_val_is_divisible_by(v1, data->d);
781 			}
782 			isl_val_free(v1);
783 			isl_val_free(v2);
784 		}
785 	}
786 
787 	if ((parallel || opposite) && mod_constraint_is_simpler(data, c)) {
788 		isl_aff_free(data->nonneg);
789 		data->nonneg = isl_constraint_get_aff(c);
790 		data->sign = parallel ? 1 : -1;
791 	}
792 
793 	isl_constraint_free(c);
794 
795 	if (data->sign != 0 && data->nonneg == NULL)
796 		return isl_stat_error;
797 
798 	return isl_stat_ok;
799 }
800 
801 /* Given that data->v * div_i in data->aff is of the form
802  *
803  *	f * d * floor(div/d)					(1)
804  *
805  * see if we can find an expression div' that is non-negative over data->build
806  * and that is related to div through
807  *
808  *	div' = div + d * e
809  *
810  * or
811  *
812  *	div' = -div + d - 1 + d * e
813  *
814  * with e some affine expression.
815  * If so, we write (1) as
816  *
817  *	f * div + f * (div' mod d)
818  *
819  * or
820  *
821  *	-f * (-div + d - 1) - f * (div' mod d)
822  *
823  * exploiting (in the second case) the fact that
824  *
825  *	f * d * floor(div/d) =	-f * d * floor((-div + d - 1)/d)
826  *
827  *
828  * We first try to find an appropriate expression for div'
829  * from the constraints of data->build->domain (which is therefore
830  * guaranteed to be non-negative on data->build), where we remove
831  * any integer divisions from the constraints and skip this step
832  * if "div" itself involves any integer divisions.
833  * If we cannot find an appropriate expression this way, then
834  * we pass control to extract_nonneg_mod where check
835  * if div or "-div + d -1" themselves happen to be
836  * non-negative on data->build.
837  *
838  * While looking for an appropriate constraint in data->build->domain,
839  * we ignore the constant term, so after finding such a constraint,
840  * we still need to fix up the constant term.
841  * In particular, if a is the constant term of "div"
842  * (or d - 1 - the constant term of "div" if data->sign < 0)
843  * and b is the constant term of the constraint, then we need to find
844  * a non-negative constant c such that
845  *
846  *	b + c \equiv a	mod d
847  *
848  * We therefore take
849  *
850  *	c = (a - b) mod d
851  *
852  * and add it to b to obtain the constant term of div'.
853  * If this constant term is "too negative", then we add an appropriate
854  * multiple of d to make it positive.
855  *
856  *
857  * Note that the above is a only a very simple heuristic for finding an
858  * appropriate expression.  We could try a bit harder by also considering
859  * sums of constraints that involve disjoint sets of variables or
860  * we could consider arbitrary linear combinations of constraints,
861  * although that could potentially be much more expensive as it involves
862  * the solution of an LP problem.
863  *
864  * In particular, if v_i is a column vector representing constraint i,
865  * w represents div and e_i is the i-th unit vector, then we are looking
866  * for a solution of the constraints
867  *
868  *	\sum_i lambda_i v_i = w + \sum_i alpha_i d e_i
869  *
870  * with \lambda_i >= 0 and alpha_i of unrestricted sign.
871  * If we are not just interested in a non-negative expression, but
872  * also in one with a minimal range, then we don't just want
873  * c = \sum_i lambda_i v_i to be non-negative over the domain,
874  * but also beta - c = \sum_i mu_i v_i, where beta is a scalar
875  * that we want to minimize and we now also have to take into account
876  * the constant terms of the constraints.
877  * Alternatively, we could first compute the dual of the domain
878  * and plug in the constraints on the coefficients.
879  */
try_extract_mod(struct isl_extract_mod_data * data)880 static int try_extract_mod(struct isl_extract_mod_data *data)
881 {
882 	isl_basic_set *hull;
883 	isl_val *v1, *v2;
884 	isl_stat r;
885 	isl_size n;
886 
887 	if (!data->build)
888 		goto error;
889 
890 	n = isl_aff_dim(data->div, isl_dim_div);
891 	if (n < 0)
892 		goto error;
893 
894 	if (isl_aff_involves_dims(data->div, isl_dim_div, 0, n))
895 		return extract_nonneg_mod(data);
896 
897 	hull = isl_set_simple_hull(isl_set_copy(data->build->domain));
898 	hull = isl_basic_set_remove_divs(hull);
899 	data->sign = 0;
900 	data->nonneg = NULL;
901 	r = isl_basic_set_foreach_constraint(hull, &check_parallel_or_opposite,
902 					data);
903 	isl_basic_set_free(hull);
904 
905 	if (!data->sign || r < 0) {
906 		isl_aff_free(data->nonneg);
907 		if (r < 0)
908 			goto error;
909 		return extract_nonneg_mod(data);
910 	}
911 
912 	v1 = isl_aff_get_constant_val(data->div);
913 	v2 = isl_aff_get_constant_val(data->nonneg);
914 	if (data->sign < 0) {
915 		v1 = isl_val_neg(v1);
916 		v1 = isl_val_add(v1, isl_val_copy(data->d));
917 		v1 = isl_val_sub_ui(v1, 1);
918 	}
919 	v1 = isl_val_sub(v1, isl_val_copy(v2));
920 	v1 = isl_val_mod(v1, isl_val_copy(data->d));
921 	v1 = isl_val_add(v1, v2);
922 	v2 = isl_val_div(isl_val_copy(v1), isl_val_copy(data->d));
923 	v2 = isl_val_ceil(v2);
924 	if (isl_val_is_neg(v2)) {
925 		v2 = isl_val_mul(v2, isl_val_copy(data->d));
926 		v1 = isl_val_sub(v1, isl_val_copy(v2));
927 	}
928 	data->nonneg = isl_aff_set_constant_val(data->nonneg, v1);
929 	isl_val_free(v2);
930 
931 	if (data->sign < 0) {
932 		data->div = oppose_div_arg(data->div, isl_val_copy(data->d));
933 		data->v = isl_val_neg(data->v);
934 	}
935 
936 	return extract_term_and_mod(data,
937 				    isl_aff_copy(data->div), data->nonneg);
938 error:
939 	data->aff = isl_aff_free(data->aff);
940 	return -1;
941 }
942 
943 /* Check if "data->aff" involves any (implicit) modulo computations based
944  * on div "data->i".
945  * If so, remove them from aff and add expressions corresponding
946  * to those modulo computations to data->pos and/or data->neg.
947  *
948  * "aff" is assumed to be an integer affine expression.
949  *
950  * In particular, check if (v * div_j) is of the form
951  *
952  *	f * m * floor(a / m)
953  *
954  * and, if so, rewrite it as
955  *
956  *	f * (a - (a mod m)) = f * a - f * (a mod m)
957  *
958  * and extract out -f * (a mod m).
959  * In particular, if f > 0, we add (f * (a mod m)) to *neg.
960  * If f < 0, we add ((-f) * (a mod m)) to *pos.
961  *
962  * Note that in order to represent "a mod m" as
963  *
964  *	(isl_ast_expr_op_pdiv_r, a, m)
965  *
966  * we need to make sure that a is non-negative.
967  * If not, we check if "-a + m - 1" is non-negative.
968  * If so, we can rewrite
969  *
970  *	floor(a/m) = -ceil(-a/m) = -floor((-a + m - 1)/m)
971  *
972  * and still extract a modulo.
973  */
extract_modulo(struct isl_extract_mod_data * data)974 static int extract_modulo(struct isl_extract_mod_data *data)
975 {
976 	data->div = isl_aff_get_div(data->aff, data->i);
977 	data->d = isl_aff_get_denominator_val(data->div);
978 	if (isl_val_is_divisible_by(data->v, data->d)) {
979 		data->div = isl_aff_scale_val(data->div, isl_val_copy(data->d));
980 		if (try_extract_mod(data) < 0)
981 			data->aff = isl_aff_free(data->aff);
982 	}
983 	isl_aff_free(data->div);
984 	isl_val_free(data->d);
985 	return 0;
986 }
987 
988 /* Check if "aff" involves any (implicit) modulo computations.
989  * If so, remove them from aff and add expressions corresponding
990  * to those modulo computations to *pos and/or *neg.
991  * We only do this if the option ast_build_prefer_pdiv is set.
992  *
993  * "aff" is assumed to be an integer affine expression.
994  *
995  * A modulo expression is of the form
996  *
997  *	a mod m = a - m * floor(a / m)
998  *
999  * To detect them in aff, we look for terms of the form
1000  *
1001  *	f * m * floor(a / m)
1002  *
1003  * rewrite them as
1004  *
1005  *	f * (a - (a mod m)) = f * a - f * (a mod m)
1006  *
1007  * and extract out -f * (a mod m).
1008  * In particular, if f > 0, we add (f * (a mod m)) to *neg.
1009  * If f < 0, we add ((-f) * (a mod m)) to *pos.
1010  */
extract_modulos(__isl_take isl_aff * aff,__isl_keep isl_ast_expr ** pos,__isl_keep isl_ast_expr ** neg,__isl_keep isl_ast_build * build)1011 static __isl_give isl_aff *extract_modulos(__isl_take isl_aff *aff,
1012 	__isl_keep isl_ast_expr **pos, __isl_keep isl_ast_expr **neg,
1013 	__isl_keep isl_ast_build *build)
1014 {
1015 	struct isl_extract_mod_data data = { build, aff, *pos, *neg };
1016 	isl_ctx *ctx;
1017 	isl_size n;
1018 
1019 	if (!aff)
1020 		return NULL;
1021 
1022 	ctx = isl_aff_get_ctx(aff);
1023 	if (!isl_options_get_ast_build_prefer_pdiv(ctx))
1024 		return aff;
1025 
1026 	n = isl_aff_dim(data.aff, isl_dim_div);
1027 	if (n < 0)
1028 		return isl_aff_free(aff);
1029 	for (data.i = 0; data.i < n; ++data.i) {
1030 		data.v = isl_aff_get_coefficient_val(data.aff,
1031 							isl_dim_div, data.i);
1032 		if (!data.v)
1033 			return isl_aff_free(aff);
1034 		if (isl_val_is_zero(data.v) ||
1035 		    isl_val_is_one(data.v) || isl_val_is_negone(data.v)) {
1036 			isl_val_free(data.v);
1037 			continue;
1038 		}
1039 		if (extract_modulo(&data) < 0)
1040 			data.aff = isl_aff_free(data.aff);
1041 		isl_val_free(data.v);
1042 		if (!data.aff)
1043 			break;
1044 	}
1045 
1046 	if (data.add)
1047 		data.aff = isl_aff_add(data.aff, data.add);
1048 
1049 	*pos = data.pos;
1050 	*neg = data.neg;
1051 	return data.aff;
1052 }
1053 
1054 /* Check if aff involves any non-integer coefficients.
1055  * If so, split aff into
1056  *
1057  *	aff = aff1 + (aff2 / d)
1058  *
1059  * with both aff1 and aff2 having only integer coefficients.
1060  * Return aff1 and add (aff2 / d) to *expr.
1061  */
extract_rational(__isl_take isl_aff * aff,__isl_keep isl_ast_expr ** expr,__isl_keep isl_ast_build * build)1062 static __isl_give isl_aff *extract_rational(__isl_take isl_aff *aff,
1063 	__isl_keep isl_ast_expr **expr, __isl_keep isl_ast_build *build)
1064 {
1065 	int i, j;
1066 	isl_size n;
1067 	isl_aff *rat = NULL;
1068 	isl_local_space *ls = NULL;
1069 	isl_ast_expr *rat_expr;
1070 	isl_val *v, *d;
1071 	enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
1072 	enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
1073 
1074 	if (!aff)
1075 		return NULL;
1076 	d = isl_aff_get_denominator_val(aff);
1077 	if (!d)
1078 		goto error;
1079 	if (isl_val_is_one(d)) {
1080 		isl_val_free(d);
1081 		return aff;
1082 	}
1083 
1084 	aff = isl_aff_scale_val(aff, isl_val_copy(d));
1085 
1086 	ls = isl_aff_get_domain_local_space(aff);
1087 	rat = isl_aff_zero_on_domain(isl_local_space_copy(ls));
1088 
1089 	for (i = 0; i < 3; ++i) {
1090 		n = isl_aff_dim(aff, t[i]);
1091 		if (n < 0)
1092 			goto error;
1093 		for (j = 0; j < n; ++j) {
1094 			isl_aff *rat_j;
1095 
1096 			v = isl_aff_get_coefficient_val(aff, t[i], j);
1097 			if (!v)
1098 				goto error;
1099 			if (isl_val_is_divisible_by(v, d)) {
1100 				isl_val_free(v);
1101 				continue;
1102 			}
1103 			rat_j = isl_aff_var_on_domain(isl_local_space_copy(ls),
1104 							l[i], j);
1105 			rat_j = isl_aff_scale_val(rat_j, v);
1106 			rat = isl_aff_add(rat, rat_j);
1107 		}
1108 	}
1109 
1110 	v = isl_aff_get_constant_val(aff);
1111 	if (isl_val_is_divisible_by(v, d)) {
1112 		isl_val_free(v);
1113 	} else {
1114 		isl_aff *rat_0;
1115 
1116 		rat_0 = isl_aff_val_on_domain(isl_local_space_copy(ls), v);
1117 		rat = isl_aff_add(rat, rat_0);
1118 	}
1119 
1120 	isl_local_space_free(ls);
1121 
1122 	aff = isl_aff_sub(aff, isl_aff_copy(rat));
1123 	aff = isl_aff_scale_down_val(aff, isl_val_copy(d));
1124 
1125 	rat_expr = isl_ast_expr_from_aff(rat, build);
1126 	rat_expr = isl_ast_expr_div(rat_expr, isl_ast_expr_from_val(d));
1127 	*expr = ast_expr_add(*expr, rat_expr);
1128 
1129 	return aff;
1130 error:
1131 	isl_aff_free(rat);
1132 	isl_local_space_free(ls);
1133 	isl_aff_free(aff);
1134 	isl_val_free(d);
1135 	return NULL;
1136 }
1137 
1138 /* Construct an isl_ast_expr that evaluates the affine expression "aff",
1139  * The result is simplified in terms of build->domain.
1140  *
1141  * We first extract hidden modulo computations from the affine expression
1142  * and then add terms for each variable with a non-zero coefficient.
1143  * Finally, if the affine expression has a non-trivial denominator,
1144  * we divide the resulting isl_ast_expr by this denominator.
1145  */
isl_ast_expr_from_aff(__isl_take isl_aff * aff,__isl_keep isl_ast_build * build)1146 __isl_give isl_ast_expr *isl_ast_expr_from_aff(__isl_take isl_aff *aff,
1147 	__isl_keep isl_ast_build *build)
1148 {
1149 	int i, j;
1150 	isl_size n;
1151 	isl_val *v;
1152 	isl_ctx *ctx = isl_aff_get_ctx(aff);
1153 	isl_ast_expr *expr, *expr_neg;
1154 	enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
1155 	enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
1156 	isl_local_space *ls;
1157 	struct isl_ast_add_term_data data;
1158 
1159 	if (!aff)
1160 		return NULL;
1161 
1162 	expr = isl_ast_expr_alloc_int_si(ctx, 0);
1163 	expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
1164 
1165 	aff = extract_rational(aff, &expr, build);
1166 
1167 	aff = extract_modulos(aff, &expr, &expr_neg, build);
1168 	expr = ast_expr_sub(expr, expr_neg);
1169 
1170 	ls = isl_aff_get_domain_local_space(aff);
1171 
1172 	data.build = build;
1173 	data.cst = isl_aff_get_constant_val(aff);
1174 	for (i = 0; i < 3; ++i) {
1175 		n = isl_aff_dim(aff, t[i]);
1176 		if (n < 0)
1177 			expr = isl_ast_expr_free(expr);
1178 		for (j = 0; j < n; ++j) {
1179 			v = isl_aff_get_coefficient_val(aff, t[i], j);
1180 			if (!v)
1181 				expr = isl_ast_expr_free(expr);
1182 			if (isl_val_is_zero(v)) {
1183 				isl_val_free(v);
1184 				continue;
1185 			}
1186 			expr = isl_ast_expr_add_term(expr,
1187 							ls, l[i], j, v, &data);
1188 		}
1189 	}
1190 
1191 	expr = isl_ast_expr_add_int(expr, data.cst);
1192 
1193 	isl_local_space_free(ls);
1194 	isl_aff_free(aff);
1195 	return expr;
1196 }
1197 
1198 /* Add terms to "expr" for each variable in "aff" with a coefficient
1199  * with sign equal to "sign".
1200  * The result is simplified in terms of data->build->domain.
1201  */
add_signed_terms(__isl_take isl_ast_expr * expr,__isl_keep isl_aff * aff,int sign,struct isl_ast_add_term_data * data)1202 static __isl_give isl_ast_expr *add_signed_terms(__isl_take isl_ast_expr *expr,
1203 	__isl_keep isl_aff *aff, int sign, struct isl_ast_add_term_data *data)
1204 {
1205 	int i, j;
1206 	isl_val *v;
1207 	enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
1208 	enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
1209 	isl_local_space *ls;
1210 
1211 	ls = isl_aff_get_domain_local_space(aff);
1212 
1213 	for (i = 0; i < 3; ++i) {
1214 		isl_size n = isl_aff_dim(aff, t[i]);
1215 		if (n < 0)
1216 			expr = isl_ast_expr_free(expr);
1217 		for (j = 0; j < n; ++j) {
1218 			v = isl_aff_get_coefficient_val(aff, t[i], j);
1219 			if (sign * isl_val_sgn(v) <= 0) {
1220 				isl_val_free(v);
1221 				continue;
1222 			}
1223 			v = isl_val_abs(v);
1224 			expr = isl_ast_expr_add_term(expr,
1225 						ls, l[i], j, v, data);
1226 		}
1227 	}
1228 
1229 	isl_local_space_free(ls);
1230 
1231 	return expr;
1232 }
1233 
1234 /* Should the constant term "v" be considered positive?
1235  *
1236  * A positive constant will be added to "pos" by the caller,
1237  * while a negative constant will be added to "neg".
1238  * If either "pos" or "neg" is exactly zero, then we prefer
1239  * to add the constant "v" to that side, irrespective of the sign of "v".
1240  * This results in slightly shorter expressions and may reduce the risk
1241  * of overflows.
1242  */
constant_is_considered_positive(__isl_keep isl_val * v,__isl_keep isl_ast_expr * pos,__isl_keep isl_ast_expr * neg)1243 static int constant_is_considered_positive(__isl_keep isl_val *v,
1244 	__isl_keep isl_ast_expr *pos, __isl_keep isl_ast_expr *neg)
1245 {
1246 	if (ast_expr_is_zero(pos))
1247 		return 1;
1248 	if (ast_expr_is_zero(neg))
1249 		return 0;
1250 	return isl_val_is_pos(v);
1251 }
1252 
1253 /* Check if the equality
1254  *
1255  *	aff = 0
1256  *
1257  * represents a stride constraint on the integer division "pos".
1258  *
1259  * In particular, if the integer division "pos" is equal to
1260  *
1261  *	floor(e/d)
1262  *
1263  * then check if aff is equal to
1264  *
1265  *	e - d floor(e/d)
1266  *
1267  * or its opposite.
1268  *
1269  * If so, the equality is exactly
1270  *
1271  *	e mod d = 0
1272  *
1273  * Note that in principle we could also accept
1274  *
1275  *	e - d floor(e'/d)
1276  *
1277  * where e and e' differ by a constant.
1278  */
is_stride_constraint(__isl_keep isl_aff * aff,int pos)1279 static int is_stride_constraint(__isl_keep isl_aff *aff, int pos)
1280 {
1281 	isl_aff *div;
1282 	isl_val *c, *d;
1283 	int eq;
1284 
1285 	div = isl_aff_get_div(aff, pos);
1286 	c = isl_aff_get_coefficient_val(aff, isl_dim_div, pos);
1287 	d = isl_aff_get_denominator_val(div);
1288 	eq = isl_val_abs_eq(c, d);
1289 	if (eq >= 0 && eq) {
1290 		aff = isl_aff_copy(aff);
1291 		aff = isl_aff_set_coefficient_si(aff, isl_dim_div, pos, 0);
1292 		div = isl_aff_scale_val(div, d);
1293 		if (isl_val_is_pos(c))
1294 			div = isl_aff_neg(div);
1295 		eq = isl_aff_plain_is_equal(div, aff);
1296 		isl_aff_free(aff);
1297 	} else
1298 		isl_val_free(d);
1299 	isl_val_free(c);
1300 	isl_aff_free(div);
1301 
1302 	return eq;
1303 }
1304 
1305 /* Are all coefficients of "aff" (zero or) negative?
1306  */
all_negative_coefficients(__isl_keep isl_aff * aff)1307 static isl_bool all_negative_coefficients(__isl_keep isl_aff *aff)
1308 {
1309 	int i;
1310 	isl_size n;
1311 
1312 	n = isl_aff_dim(aff, isl_dim_param);
1313 	if (n < 0)
1314 		return isl_bool_error;
1315 	for (i = 0; i < n; ++i)
1316 		if (isl_aff_coefficient_sgn(aff, isl_dim_param, i) > 0)
1317 			return isl_bool_false;
1318 
1319 	n = isl_aff_dim(aff, isl_dim_in);
1320 	if (n < 0)
1321 		return isl_bool_error;
1322 	for (i = 0; i < n; ++i)
1323 		if (isl_aff_coefficient_sgn(aff, isl_dim_in, i) > 0)
1324 			return isl_bool_false;
1325 
1326 	return isl_bool_true;
1327 }
1328 
1329 /* Give an equality of the form
1330  *
1331  *	aff = e - d floor(e/d) = 0
1332  *
1333  * or
1334  *
1335  *	aff = -e + d floor(e/d) = 0
1336  *
1337  * with the integer division "pos" equal to floor(e/d),
1338  * construct the AST expression
1339  *
1340  *	(isl_ast_expr_op_eq,
1341  *		(isl_ast_expr_op_zdiv_r, expr(e), expr(d)), expr(0))
1342  *
1343  * If e only has negative coefficients, then construct
1344  *
1345  *	(isl_ast_expr_op_eq,
1346  *		(isl_ast_expr_op_zdiv_r, expr(-e), expr(d)), expr(0))
1347  *
1348  * instead.
1349  */
extract_stride_constraint(__isl_take isl_aff * aff,int pos,__isl_keep isl_ast_build * build)1350 static __isl_give isl_ast_expr *extract_stride_constraint(
1351 	__isl_take isl_aff *aff, int pos, __isl_keep isl_ast_build *build)
1352 {
1353 	isl_bool all_neg;
1354 	isl_ctx *ctx;
1355 	isl_val *c;
1356 	isl_ast_expr *expr, *cst;
1357 
1358 	if (!aff)
1359 		return NULL;
1360 
1361 	ctx = isl_aff_get_ctx(aff);
1362 
1363 	c = isl_aff_get_coefficient_val(aff, isl_dim_div, pos);
1364 	aff = isl_aff_set_coefficient_si(aff, isl_dim_div, pos, 0);
1365 
1366 	all_neg = all_negative_coefficients(aff);
1367 	if (all_neg < 0)
1368 		aff = isl_aff_free(aff);
1369 	else if (all_neg)
1370 		aff = isl_aff_neg(aff);
1371 
1372 	cst = isl_ast_expr_from_val(isl_val_abs(c));
1373 	expr = isl_ast_expr_from_aff(aff, build);
1374 
1375 	expr = isl_ast_expr_alloc_binary(isl_ast_expr_op_zdiv_r, expr, cst);
1376 	cst = isl_ast_expr_alloc_int_si(ctx, 0);
1377 	expr = isl_ast_expr_alloc_binary(isl_ast_expr_op_eq, expr, cst);
1378 
1379 	return expr;
1380 }
1381 
1382 /* Construct an isl_ast_expr that evaluates the condition "constraint",
1383  * The result is simplified in terms of build->domain.
1384  *
1385  * We first check if the constraint is an equality of the form
1386  *
1387  *	e - d floor(e/d) = 0
1388  *
1389  * i.e.,
1390  *
1391  *	e mod d = 0
1392  *
1393  * If so, we convert it to
1394  *
1395  *	(isl_ast_expr_op_eq,
1396  *		(isl_ast_expr_op_zdiv_r, expr(e), expr(d)), expr(0))
1397  *
1398  * Otherwise, let the constraint by either "a >= 0" or "a == 0".
1399  * We first extract hidden modulo computations from "a"
1400  * and then collect all the terms with a positive coefficient in cons_pos
1401  * and the terms with a negative coefficient in cons_neg.
1402  *
1403  * The result is then of the form
1404  *
1405  *	(isl_ast_expr_op_ge, expr(pos), expr(-neg)))
1406  *
1407  * or
1408  *
1409  *	(isl_ast_expr_op_eq, expr(pos), expr(-neg)))
1410  *
1411  * However, if the first expression is an integer constant (and the second
1412  * is not), then we swap the two expressions.  This ensures that we construct,
1413  * e.g., "i <= 5" rather than "5 >= i".
1414  *
1415  * Furthermore, is there are no terms with positive coefficients (or no terms
1416  * with negative coefficients), then the constant term is added to "pos"
1417  * (or "neg"), ignoring the sign of the constant term.
1418  */
isl_ast_expr_from_constraint(__isl_take isl_constraint * constraint,__isl_keep isl_ast_build * build)1419 static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
1420 	__isl_take isl_constraint *constraint, __isl_keep isl_ast_build *build)
1421 {
1422 	int i;
1423 	isl_size n;
1424 	isl_ctx *ctx;
1425 	isl_ast_expr *expr_pos;
1426 	isl_ast_expr *expr_neg;
1427 	isl_ast_expr *expr;
1428 	isl_aff *aff;
1429 	int eq;
1430 	enum isl_ast_expr_op_type type;
1431 	struct isl_ast_add_term_data data;
1432 
1433 	if (!constraint)
1434 		return NULL;
1435 
1436 	aff = isl_constraint_get_aff(constraint);
1437 	eq = isl_constraint_is_equality(constraint);
1438 	isl_constraint_free(constraint);
1439 
1440 	n = isl_aff_dim(aff, isl_dim_div);
1441 	if (n < 0)
1442 		aff = isl_aff_free(aff);
1443 	if (eq && n > 0)
1444 		for (i = 0; i < n; ++i) {
1445 			int is_stride;
1446 			is_stride = is_stride_constraint(aff, i);
1447 			if (is_stride < 0)
1448 				goto error;
1449 			if (is_stride)
1450 				return extract_stride_constraint(aff, i, build);
1451 		}
1452 
1453 	ctx = isl_aff_get_ctx(aff);
1454 	expr_pos = isl_ast_expr_alloc_int_si(ctx, 0);
1455 	expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
1456 
1457 	aff = extract_modulos(aff, &expr_pos, &expr_neg, build);
1458 
1459 	data.build = build;
1460 	data.cst = isl_aff_get_constant_val(aff);
1461 	expr_pos = add_signed_terms(expr_pos, aff, 1, &data);
1462 	data.cst = isl_val_neg(data.cst);
1463 	expr_neg = add_signed_terms(expr_neg, aff, -1, &data);
1464 	data.cst = isl_val_neg(data.cst);
1465 
1466 	if (constant_is_considered_positive(data.cst, expr_pos, expr_neg)) {
1467 		expr_pos = isl_ast_expr_add_int(expr_pos, data.cst);
1468 	} else {
1469 		data.cst = isl_val_neg(data.cst);
1470 		expr_neg = isl_ast_expr_add_int(expr_neg, data.cst);
1471 	}
1472 
1473 	if (isl_ast_expr_get_type(expr_pos) == isl_ast_expr_int &&
1474 	    isl_ast_expr_get_type(expr_neg) != isl_ast_expr_int) {
1475 		type = eq ? isl_ast_expr_op_eq : isl_ast_expr_op_le;
1476 		expr = isl_ast_expr_alloc_binary(type, expr_neg, expr_pos);
1477 	} else {
1478 		type = eq ? isl_ast_expr_op_eq : isl_ast_expr_op_ge;
1479 		expr = isl_ast_expr_alloc_binary(type, expr_pos, expr_neg);
1480 	}
1481 
1482 	isl_aff_free(aff);
1483 	return expr;
1484 error:
1485 	isl_aff_free(aff);
1486 	return NULL;
1487 }
1488 
1489 /* Wrapper around isl_constraint_cmp_last_non_zero for use
1490  * as a callback to isl_constraint_list_sort.
1491  * If isl_constraint_cmp_last_non_zero cannot tell the constraints
1492  * apart, then use isl_constraint_plain_cmp instead.
1493  */
cmp_constraint(__isl_keep isl_constraint * a,__isl_keep isl_constraint * b,void * user)1494 static int cmp_constraint(__isl_keep isl_constraint *a,
1495 	__isl_keep isl_constraint *b, void *user)
1496 {
1497 	int cmp;
1498 
1499 	cmp = isl_constraint_cmp_last_non_zero(a, b);
1500 	if (cmp != 0)
1501 		return cmp;
1502 	return isl_constraint_plain_cmp(a, b);
1503 }
1504 
1505 /* Construct an isl_ast_expr that evaluates the conditions defining "bset".
1506  * The result is simplified in terms of build->domain.
1507  *
1508  * If "bset" is not bounded by any constraint, then we construct
1509  * the expression "1", i.e., "true".
1510  *
1511  * Otherwise, we sort the constraints, putting constraints that involve
1512  * integer divisions after those that do not, and construct an "and"
1513  * of the ast expressions of the individual constraints.
1514  *
1515  * Each constraint is added to the generated constraints of the build
1516  * after it has been converted to an AST expression so that it can be used
1517  * to simplify the following constraints.  This may change the truth value
1518  * of subsequent constraints that do not satisfy the earlier constraints,
1519  * but this does not affect the outcome of the conjunction as it is
1520  * only true if all the conjuncts are true (no matter in what order
1521  * they are evaluated).  In particular, the constraints that do not
1522  * involve integer divisions may serve to simplify some constraints
1523  * that do involve integer divisions.
1524  */
isl_ast_build_expr_from_basic_set(__isl_keep isl_ast_build * build,__isl_take isl_basic_set * bset)1525 __isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
1526 	 __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
1527 {
1528 	int i;
1529 	isl_size n;
1530 	isl_constraint *c;
1531 	isl_constraint_list *list;
1532 	isl_ast_expr *res;
1533 	isl_set *set;
1534 
1535 	list = isl_basic_set_get_constraint_list(bset);
1536 	isl_basic_set_free(bset);
1537 	list = isl_constraint_list_sort(list, &cmp_constraint, NULL);
1538 	n = isl_constraint_list_n_constraint(list);
1539 	if (n < 0)
1540 		build = NULL;
1541 	if (n == 0) {
1542 		isl_ctx *ctx = isl_constraint_list_get_ctx(list);
1543 		isl_constraint_list_free(list);
1544 		return isl_ast_expr_alloc_int_si(ctx, 1);
1545 	}
1546 
1547 	build = isl_ast_build_copy(build);
1548 
1549 	c = isl_constraint_list_get_constraint(list, 0);
1550 	bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
1551 	set = isl_set_from_basic_set(bset);
1552 	res = isl_ast_expr_from_constraint(c, build);
1553 	build = isl_ast_build_restrict_generated(build, set);
1554 
1555 	for (i = 1; i < n; ++i) {
1556 		isl_ast_expr *expr;
1557 
1558 		c = isl_constraint_list_get_constraint(list, i);
1559 		bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
1560 		set = isl_set_from_basic_set(bset);
1561 		expr = isl_ast_expr_from_constraint(c, build);
1562 		build = isl_ast_build_restrict_generated(build, set);
1563 		res = isl_ast_expr_and(res, expr);
1564 	}
1565 
1566 	isl_constraint_list_free(list);
1567 	isl_ast_build_free(build);
1568 	return res;
1569 }
1570 
1571 /* Construct an isl_ast_expr that evaluates the conditions defining "set".
1572  * The result is simplified in terms of build->domain.
1573  *
1574  * If "set" is an (obviously) empty set, then return the expression "0".
1575  *
1576  * If there are multiple disjuncts in the description of the set,
1577  * then subsequent disjuncts are simplified in a context where
1578  * the previous disjuncts have been removed from build->domain.
1579  * In particular, constraints that ensure that there is no overlap
1580  * with these previous disjuncts, can be removed.
1581  * This is mostly useful for disjuncts that are only defined by
1582  * a single constraint (relative to the build domain) as the opposite
1583  * of that single constraint can then be removed from the other disjuncts.
1584  * In order not to increase the number of disjuncts in the build domain
1585  * after subtracting the previous disjuncts of "set", the simple hull
1586  * is computed after taking the difference with each of these disjuncts.
1587  * This means that constraints that prevent overlap with a union
1588  * of multiple previous disjuncts are not removed.
1589  *
1590  * "set" lives in the internal schedule space.
1591  */
isl_ast_build_expr_from_set_internal(__isl_keep isl_ast_build * build,__isl_take isl_set * set)1592 __isl_give isl_ast_expr *isl_ast_build_expr_from_set_internal(
1593 	__isl_keep isl_ast_build *build, __isl_take isl_set *set)
1594 {
1595 	int i;
1596 	isl_size n;
1597 	isl_basic_set *bset;
1598 	isl_basic_set_list *list;
1599 	isl_set *domain;
1600 	isl_ast_expr *res;
1601 
1602 	list = isl_set_get_basic_set_list(set);
1603 	isl_set_free(set);
1604 
1605 	n = isl_basic_set_list_n_basic_set(list);
1606 	if (n < 0)
1607 		build = NULL;
1608 	if (n == 0) {
1609 		isl_ctx *ctx = isl_ast_build_get_ctx(build);
1610 		isl_basic_set_list_free(list);
1611 		return isl_ast_expr_from_val(isl_val_zero(ctx));
1612 	}
1613 
1614 	domain = isl_ast_build_get_domain(build);
1615 
1616 	bset = isl_basic_set_list_get_basic_set(list, 0);
1617 	set = isl_set_from_basic_set(isl_basic_set_copy(bset));
1618 	res = isl_ast_build_expr_from_basic_set(build, bset);
1619 
1620 	for (i = 1; i < n; ++i) {
1621 		isl_ast_expr *expr;
1622 		isl_set *rest;
1623 
1624 		rest = isl_set_subtract(isl_set_copy(domain), set);
1625 		rest = isl_set_from_basic_set(isl_set_simple_hull(rest));
1626 		domain = isl_set_intersect(domain, rest);
1627 		bset = isl_basic_set_list_get_basic_set(list, i);
1628 		set = isl_set_from_basic_set(isl_basic_set_copy(bset));
1629 		bset = isl_basic_set_gist(bset,
1630 				isl_set_simple_hull(isl_set_copy(domain)));
1631 		expr = isl_ast_build_expr_from_basic_set(build, bset);
1632 		res = isl_ast_expr_or(res, expr);
1633 	}
1634 
1635 	isl_set_free(domain);
1636 	isl_set_free(set);
1637 	isl_basic_set_list_free(list);
1638 	return res;
1639 }
1640 
1641 /* Construct an isl_ast_expr that evaluates the conditions defining "set".
1642  * The result is simplified in terms of build->domain.
1643  *
1644  * If "set" is an (obviously) empty set, then return the expression "0".
1645  *
1646  * "set" lives in the external schedule space.
1647  *
1648  * The internal AST expression generation assumes that there are
1649  * no unknown divs, so make sure an explicit representation is available.
1650  * Since the set comes from the outside, it may have constraints that
1651  * are redundant with respect to the build domain.  Remove them first.
1652  */
isl_ast_build_expr_from_set(__isl_keep isl_ast_build * build,__isl_take isl_set * set)1653 __isl_give isl_ast_expr *isl_ast_build_expr_from_set(
1654 	__isl_keep isl_ast_build *build, __isl_take isl_set *set)
1655 {
1656 	isl_bool needs_map;
1657 
1658 	needs_map = isl_ast_build_need_schedule_map(build);
1659 	if (needs_map < 0) {
1660 		set = isl_set_free(set);
1661 	} else if (needs_map) {
1662 		isl_multi_aff *ma;
1663 		ma = isl_ast_build_get_schedule_map_multi_aff(build);
1664 		set = isl_set_preimage_multi_aff(set, ma);
1665 	}
1666 
1667 	set = isl_set_compute_divs(set);
1668 	set = isl_ast_build_compute_gist(build, set);
1669 	return isl_ast_build_expr_from_set_internal(build, set);
1670 }
1671 
1672 /* State of data about previous pieces in
1673  * isl_ast_build_expr_from_pw_aff_internal.
1674  *
1675  * isl_state_none: no data about previous pieces
1676  * isl_state_single: data about a single previous piece
1677  * isl_state_min: data represents minimum of several pieces
1678  * isl_state_max: data represents maximum of several pieces
1679  */
1680 enum isl_from_pw_aff_state {
1681 	isl_state_none,
1682 	isl_state_single,
1683 	isl_state_min,
1684 	isl_state_max
1685 };
1686 
1687 /* Internal date structure representing a single piece in the input of
1688  * isl_ast_build_expr_from_pw_aff_internal.
1689  *
1690  * If "state" is isl_state_none, then "set_list" and "aff_list" are not used.
1691  * If "state" is isl_state_single, then "set_list" and "aff_list" contain the
1692  * single previous subpiece.
1693  * If "state" is isl_state_min, then "set_list" and "aff_list" contain
1694  * a sequence of several previous subpieces that are equal to the minimum
1695  * of the entries in "aff_list" over the union of "set_list"
1696  * If "state" is isl_state_max, then "set_list" and "aff_list" contain
1697  * a sequence of several previous subpieces that are equal to the maximum
1698  * of the entries in "aff_list" over the union of "set_list"
1699  *
1700  * During the construction of the pieces, "set" is NULL.
1701  * After the construction, "set" is set to the union of the elements
1702  * in "set_list", at which point "set_list" is set to NULL.
1703  */
1704 struct isl_from_pw_aff_piece {
1705 	enum isl_from_pw_aff_state state;
1706 	isl_set *set;
1707 	isl_set_list *set_list;
1708 	isl_aff_list *aff_list;
1709 };
1710 
1711 /* Internal data structure for isl_ast_build_expr_from_pw_aff_internal.
1712  *
1713  * "build" specifies the domain against which the result is simplified.
1714  * "dom" is the domain of the entire isl_pw_aff.
1715  *
1716  * "n" is the number of pieces constructed already.
1717  * In particular, during the construction of the pieces, "n" points to
1718  * the piece that is being constructed.  After the construction of the
1719  * pieces, "n" is set to the total number of pieces.
1720  * "max" is the total number of allocated entries.
1721  * "p" contains the individual pieces.
1722  */
1723 struct isl_from_pw_aff_data {
1724 	isl_ast_build *build;
1725 	isl_set *dom;
1726 
1727 	int n;
1728 	int max;
1729 	struct isl_from_pw_aff_piece *p;
1730 };
1731 
1732 /* Initialize "data" based on "build" and "pa".
1733  */
isl_from_pw_aff_data_init(struct isl_from_pw_aff_data * data,__isl_keep isl_ast_build * build,__isl_keep isl_pw_aff * pa)1734 static isl_stat isl_from_pw_aff_data_init(struct isl_from_pw_aff_data *data,
1735 	__isl_keep isl_ast_build *build, __isl_keep isl_pw_aff *pa)
1736 {
1737 	isl_size n;
1738 	isl_ctx *ctx;
1739 
1740 	ctx = isl_pw_aff_get_ctx(pa);
1741 	n = isl_pw_aff_n_piece(pa);
1742 	if (n < 0)
1743 		return isl_stat_error;
1744 	if (n == 0)
1745 		isl_die(ctx, isl_error_invalid,
1746 			"cannot handle void expression", return isl_stat_error);
1747 	data->max = n;
1748 	data->p = isl_calloc_array(ctx, struct isl_from_pw_aff_piece, n);
1749 	if (!data->p)
1750 		return isl_stat_error;
1751 	data->build = build;
1752 	data->dom = isl_pw_aff_domain(isl_pw_aff_copy(pa));
1753 	data->n = 0;
1754 
1755 	return isl_stat_ok;
1756 }
1757 
1758 /* Free all memory allocated for "data".
1759  */
isl_from_pw_aff_data_clear(struct isl_from_pw_aff_data * data)1760 static void isl_from_pw_aff_data_clear(struct isl_from_pw_aff_data *data)
1761 {
1762 	int i;
1763 
1764 	isl_set_free(data->dom);
1765 	if (!data->p)
1766 		return;
1767 
1768 	for (i = 0; i < data->max; ++i) {
1769 		isl_set_free(data->p[i].set);
1770 		isl_set_list_free(data->p[i].set_list);
1771 		isl_aff_list_free(data->p[i].aff_list);
1772 	}
1773 	free(data->p);
1774 }
1775 
1776 /* Initialize the current entry of "data" to an unused piece.
1777  */
set_none(struct isl_from_pw_aff_data * data)1778 static void set_none(struct isl_from_pw_aff_data *data)
1779 {
1780 	data->p[data->n].state = isl_state_none;
1781 	data->p[data->n].set_list = NULL;
1782 	data->p[data->n].aff_list = NULL;
1783 }
1784 
1785 /* Store "set" and "aff" in the current entry of "data" as a single subpiece.
1786  */
set_single(struct isl_from_pw_aff_data * data,__isl_take isl_set * set,__isl_take isl_aff * aff)1787 static void set_single(struct isl_from_pw_aff_data *data,
1788 	__isl_take isl_set *set, __isl_take isl_aff *aff)
1789 {
1790 	data->p[data->n].state = isl_state_single;
1791 	data->p[data->n].set_list = isl_set_list_from_set(set);
1792 	data->p[data->n].aff_list = isl_aff_list_from_aff(aff);
1793 }
1794 
1795 /* Extend the current entry of "data" with "set" and "aff"
1796  * as a minimum expression.
1797  */
extend_min(struct isl_from_pw_aff_data * data,__isl_take isl_set * set,__isl_take isl_aff * aff)1798 static isl_stat extend_min(struct isl_from_pw_aff_data *data,
1799 	__isl_take isl_set *set, __isl_take isl_aff *aff)
1800 {
1801 	int n = data->n;
1802 	data->p[n].state = isl_state_min;
1803 	data->p[n].set_list = isl_set_list_add(data->p[n].set_list, set);
1804 	data->p[n].aff_list = isl_aff_list_add(data->p[n].aff_list, aff);
1805 
1806 	if (!data->p[n].set_list || !data->p[n].aff_list)
1807 		return isl_stat_error;
1808 	return isl_stat_ok;
1809 }
1810 
1811 /* Extend the current entry of "data" with "set" and "aff"
1812  * as a maximum expression.
1813  */
extend_max(struct isl_from_pw_aff_data * data,__isl_take isl_set * set,__isl_take isl_aff * aff)1814 static isl_stat extend_max(struct isl_from_pw_aff_data *data,
1815 	__isl_take isl_set *set, __isl_take isl_aff *aff)
1816 {
1817 	int n = data->n;
1818 	data->p[n].state = isl_state_max;
1819 	data->p[n].set_list = isl_set_list_add(data->p[n].set_list, set);
1820 	data->p[n].aff_list = isl_aff_list_add(data->p[n].aff_list, aff);
1821 
1822 	if (!data->p[n].set_list || !data->p[n].aff_list)
1823 		return isl_stat_error;
1824 	return isl_stat_ok;
1825 }
1826 
1827 /* Extend the domain of the current entry of "data", which is assumed
1828  * to contain a single subpiece, with "set".  If "replace" is set,
1829  * then also replace the affine function by "aff".  Otherwise,
1830  * simply free "aff".
1831  */
extend_domain(struct isl_from_pw_aff_data * data,__isl_take isl_set * set,__isl_take isl_aff * aff,int replace)1832 static isl_stat extend_domain(struct isl_from_pw_aff_data *data,
1833 	__isl_take isl_set *set, __isl_take isl_aff *aff, int replace)
1834 {
1835 	int n = data->n;
1836 	isl_set *set_n;
1837 
1838 	set_n = isl_set_list_get_set(data->p[n].set_list, 0);
1839 	set_n = isl_set_union(set_n, set);
1840 	data->p[n].set_list =
1841 		isl_set_list_set_set(data->p[n].set_list, 0, set_n);
1842 
1843 	if (replace)
1844 		data->p[n].aff_list =
1845 			isl_aff_list_set_aff(data->p[n].aff_list, 0, aff);
1846 	else
1847 		isl_aff_free(aff);
1848 
1849 	if (!data->p[n].set_list || !data->p[n].aff_list)
1850 		return isl_stat_error;
1851 	return isl_stat_ok;
1852 }
1853 
1854 /* Construct an isl_ast_expr from "list" within "build".
1855  * If "state" is isl_state_single, then "list" contains a single entry and
1856  * an isl_ast_expr is constructed for that entry.
1857  * Otherwise a min or max expression is constructed from "list"
1858  * depending on "state".
1859  */
ast_expr_from_aff_list(__isl_take isl_aff_list * list,enum isl_from_pw_aff_state state,__isl_keep isl_ast_build * build)1860 static __isl_give isl_ast_expr *ast_expr_from_aff_list(
1861 	__isl_take isl_aff_list *list, enum isl_from_pw_aff_state state,
1862 	__isl_keep isl_ast_build *build)
1863 {
1864 	int i;
1865 	isl_size n;
1866 	isl_aff *aff;
1867 	isl_ast_expr *expr = NULL;
1868 	enum isl_ast_expr_op_type op_type;
1869 
1870 	if (state == isl_state_single) {
1871 		aff = isl_aff_list_get_aff(list, 0);
1872 		isl_aff_list_free(list);
1873 		return isl_ast_expr_from_aff(aff, build);
1874 	}
1875 	n = isl_aff_list_n_aff(list);
1876 	if (n < 0)
1877 		goto error;
1878 	op_type = state == isl_state_min ? isl_ast_expr_op_min
1879 					 : isl_ast_expr_op_max;
1880 	expr = isl_ast_expr_alloc_op(isl_ast_build_get_ctx(build), op_type, n);
1881 	if (!expr)
1882 		goto error;
1883 
1884 	for (i = 0; i < n; ++i) {
1885 		isl_ast_expr *expr_i;
1886 
1887 		aff = isl_aff_list_get_aff(list, i);
1888 		expr_i = isl_ast_expr_from_aff(aff, build);
1889 		if (!expr_i)
1890 			goto error;
1891 		expr->u.op.args[i] = expr_i;
1892 	}
1893 
1894 	isl_aff_list_free(list);
1895 	return expr;
1896 error:
1897 	isl_aff_list_free(list);
1898 	isl_ast_expr_free(expr);
1899 	return NULL;
1900 }
1901 
1902 /* Extend the expression in "next" to take into account
1903  * the piece at position "pos" in "data", allowing for a further extension
1904  * for the next piece(s).
1905  * In particular, "next" is set to a select operation that selects
1906  * an isl_ast_expr corresponding to data->aff_list on data->set and
1907  * to an expression that will be filled in by later calls.
1908  * Return a pointer to this location.
1909  * Afterwards, the state of "data" is set to isl_state_none.
1910  *
1911  * The constraints of data->set are added to the generated
1912  * constraints of the build such that they can be exploited to simplify
1913  * the AST expression constructed from data->aff_list.
1914  */
add_intermediate_piece(struct isl_from_pw_aff_data * data,int pos,isl_ast_expr ** next)1915 static isl_ast_expr **add_intermediate_piece(struct isl_from_pw_aff_data *data,
1916 	int pos, isl_ast_expr **next)
1917 {
1918 	isl_ctx *ctx;
1919 	isl_ast_build *build;
1920 	isl_ast_expr *ternary, *arg;
1921 	isl_set *set, *gist;
1922 
1923 	set = data->p[pos].set;
1924 	data->p[pos].set = NULL;
1925 	ctx = isl_ast_build_get_ctx(data->build);
1926 	ternary = isl_ast_expr_alloc_op(ctx, isl_ast_expr_op_select, 3);
1927 	gist = isl_set_gist(isl_set_copy(set), isl_set_copy(data->dom));
1928 	arg = isl_ast_build_expr_from_set_internal(data->build, gist);
1929 	ternary = isl_ast_expr_set_op_arg(ternary, 0, arg);
1930 	build = isl_ast_build_copy(data->build);
1931 	build = isl_ast_build_restrict_generated(build, set);
1932 	arg = ast_expr_from_aff_list(data->p[pos].aff_list,
1933 					data->p[pos].state, build);
1934 	data->p[pos].aff_list = NULL;
1935 	isl_ast_build_free(build);
1936 	ternary = isl_ast_expr_set_op_arg(ternary, 1, arg);
1937 	data->p[pos].state = isl_state_none;
1938 	if (!ternary)
1939 		return NULL;
1940 
1941 	*next = ternary;
1942 	return &ternary->u.op.args[2];
1943 }
1944 
1945 /* Extend the expression in "next" to take into account
1946  * the final piece, located at position "pos" in "data".
1947  * In particular, "next" is set to evaluate data->aff_list
1948  * and the domain is ignored.
1949  * Return isl_stat_ok on success and isl_stat_error on failure.
1950  *
1951  * The constraints of data->set are however added to the generated
1952  * constraints of the build such that they can be exploited to simplify
1953  * the AST expression constructed from data->aff_list.
1954  */
add_last_piece(struct isl_from_pw_aff_data * data,int pos,isl_ast_expr ** next)1955 static isl_stat add_last_piece(struct isl_from_pw_aff_data *data,
1956 	int pos, isl_ast_expr **next)
1957 {
1958 	isl_ast_build *build;
1959 
1960 	if (data->p[pos].state == isl_state_none)
1961 		isl_die(isl_ast_build_get_ctx(data->build), isl_error_invalid,
1962 			"cannot handle void expression", return isl_stat_error);
1963 
1964 	build = isl_ast_build_copy(data->build);
1965 	build = isl_ast_build_restrict_generated(build, data->p[pos].set);
1966 	data->p[pos].set = NULL;
1967 	*next = ast_expr_from_aff_list(data->p[pos].aff_list,
1968 						data->p[pos].state, build);
1969 	data->p[pos].aff_list = NULL;
1970 	isl_ast_build_free(build);
1971 	data->p[pos].state = isl_state_none;
1972 	if (!*next)
1973 		return isl_stat_error;
1974 
1975 	return isl_stat_ok;
1976 }
1977 
1978 /* Return -1 if the piece "p1" should be sorted before "p2"
1979  * and 1 if it should be sorted after "p2".
1980  * Return 0 if they do not need to be sorted in a specific order.
1981  *
1982  * Pieces are sorted according to the number of disjuncts
1983  * in their domains.
1984  */
sort_pieces_cmp(const void * p1,const void * p2,void * arg)1985 static int sort_pieces_cmp(const void *p1, const void *p2, void *arg)
1986 {
1987 	const struct isl_from_pw_aff_piece *piece1 = p1;
1988 	const struct isl_from_pw_aff_piece *piece2 = p2;
1989 	isl_size n1, n2;
1990 
1991 	n1 = isl_set_n_basic_set(piece1->set);
1992 	n2 = isl_set_n_basic_set(piece2->set);
1993 
1994 	return n1 - n2;
1995 }
1996 
1997 /* Construct an isl_ast_expr from the pieces in "data".
1998  * Return the result or NULL on failure.
1999  *
2000  * When this function is called, data->n points to the current piece.
2001  * If this is an effective piece, then first increment data->n such
2002  * that data->n contains the number of pieces.
2003  * The "set_list" fields are subsequently replaced by the corresponding
2004  * "set" fields, after which the pieces are sorted according to
2005  * the number of disjuncts in these "set" fields.
2006  *
2007  * Construct intermediate AST expressions for the initial pieces and
2008  * finish off with the final pieces.
2009  */
build_pieces(struct isl_from_pw_aff_data * data)2010 static isl_ast_expr *build_pieces(struct isl_from_pw_aff_data *data)
2011 {
2012 	int i;
2013 	isl_ast_expr *res = NULL;
2014 	isl_ast_expr **next = &res;
2015 
2016 	if (data->p[data->n].state != isl_state_none)
2017 		data->n++;
2018 	if (data->n == 0)
2019 		isl_die(isl_ast_build_get_ctx(data->build), isl_error_invalid,
2020 			"cannot handle void expression", return NULL);
2021 
2022 	for (i = 0; i < data->n; ++i) {
2023 		data->p[i].set = isl_set_list_union(data->p[i].set_list);
2024 		if (data->p[i].state != isl_state_single)
2025 			data->p[i].set = isl_set_coalesce(data->p[i].set);
2026 		data->p[i].set_list = NULL;
2027 	}
2028 
2029 	if (isl_sort(data->p, data->n, sizeof(data->p[0]),
2030 			&sort_pieces_cmp, NULL) < 0)
2031 		return isl_ast_expr_free(res);
2032 
2033 	for (i = 0; i + 1 < data->n; ++i) {
2034 		next = add_intermediate_piece(data, i, next);
2035 		if (!next)
2036 			return isl_ast_expr_free(res);
2037 	}
2038 
2039 	if (add_last_piece(data, data->n - 1, next) < 0)
2040 		return isl_ast_expr_free(res);
2041 
2042 	return res;
2043 }
2044 
2045 /* Is the domain of the current entry of "data", which is assumed
2046  * to contain a single subpiece, a subset of "set"?
2047  */
single_is_subset(struct isl_from_pw_aff_data * data,__isl_keep isl_set * set)2048 static isl_bool single_is_subset(struct isl_from_pw_aff_data *data,
2049 	__isl_keep isl_set *set)
2050 {
2051 	isl_bool subset;
2052 	isl_set *set_n;
2053 
2054 	set_n = isl_set_list_get_set(data->p[data->n].set_list, 0);
2055 	subset = isl_set_is_subset(set_n, set);
2056 	isl_set_free(set_n);
2057 
2058 	return subset;
2059 }
2060 
2061 /* Is "aff" a rational expression, i.e., does it have a denominator
2062  * different from one?
2063  */
aff_is_rational(__isl_keep isl_aff * aff)2064 static isl_bool aff_is_rational(__isl_keep isl_aff *aff)
2065 {
2066 	isl_bool rational;
2067 	isl_val *den;
2068 
2069 	den = isl_aff_get_denominator_val(aff);
2070 	rational = isl_bool_not(isl_val_is_one(den));
2071 	isl_val_free(den);
2072 
2073 	return rational;
2074 }
2075 
2076 /* Does "list" consist of a single rational affine expression?
2077  */
is_single_rational_aff(__isl_keep isl_aff_list * list)2078 static isl_bool is_single_rational_aff(__isl_keep isl_aff_list *list)
2079 {
2080 	isl_size n;
2081 	isl_bool rational;
2082 	isl_aff *aff;
2083 
2084 	n = isl_aff_list_n_aff(list);
2085 	if (n < 0)
2086 		return isl_bool_error;
2087 	if (n != 1)
2088 		return isl_bool_false;
2089 	aff = isl_aff_list_get_aff(list, 0);
2090 	rational = aff_is_rational(aff);
2091 	isl_aff_free(aff);
2092 
2093 	return rational;
2094 }
2095 
2096 /* Can the list of subpieces in the last piece of "data" be extended with
2097  * "set" and "aff" based on "test"?
2098  * In particular, is it the case for each entry (set_i, aff_i) that
2099  *
2100  *	test(aff, aff_i) holds on set_i, and
2101  *	test(aff_i, aff) holds on set?
2102  *
2103  * "test" returns the set of elements where the tests holds, meaning
2104  * that test(aff_i, aff) holds on set if set is a subset of test(aff_i, aff).
2105  *
2106  * This function is used to detect min/max expressions.
2107  * If the ast_build_detect_min_max option is turned off, then
2108  * do not even try and perform any detection and return false instead.
2109  *
2110  * Rational affine expressions are not considered for min/max expressions
2111  * since the combined expression will be defined on the union of the domains,
2112  * while a rational expression may only yield integer values
2113  * on its own definition domain.
2114  */
extends(struct isl_from_pw_aff_data * data,__isl_keep isl_set * set,__isl_keep isl_aff * aff,__isl_give isl_basic_set * (* test)(__isl_take isl_aff * aff1,__isl_take isl_aff * aff2))2115 static isl_bool extends(struct isl_from_pw_aff_data *data,
2116 	__isl_keep isl_set *set, __isl_keep isl_aff *aff,
2117 	__isl_give isl_basic_set *(*test)(__isl_take isl_aff *aff1,
2118 		__isl_take isl_aff *aff2))
2119 {
2120 	int i;
2121 	isl_size n;
2122 	isl_bool is_rational;
2123 	isl_ctx *ctx;
2124 	isl_set *dom;
2125 
2126 	is_rational = aff_is_rational(aff);
2127 	if (is_rational >= 0 && !is_rational)
2128 		is_rational = is_single_rational_aff(data->p[data->n].aff_list);
2129 	if (is_rational < 0 || is_rational)
2130 		return isl_bool_not(is_rational);
2131 
2132 	ctx = isl_ast_build_get_ctx(data->build);
2133 	if (!isl_options_get_ast_build_detect_min_max(ctx))
2134 		return isl_bool_false;
2135 
2136 	n = isl_set_list_n_set(data->p[data->n].set_list);
2137 	if (n < 0)
2138 		return isl_bool_error;
2139 
2140 	dom = isl_ast_build_get_domain(data->build);
2141 	set = isl_set_intersect(dom, isl_set_copy(set));
2142 
2143 	for (i = 0; i < n ; ++i) {
2144 		isl_aff *aff_i;
2145 		isl_set *valid;
2146 		isl_set *dom, *required;
2147 		isl_bool is_valid;
2148 
2149 		aff_i = isl_aff_list_get_aff(data->p[data->n].aff_list, i);
2150 		valid = isl_set_from_basic_set(test(isl_aff_copy(aff), aff_i));
2151 		required = isl_set_list_get_set(data->p[data->n].set_list, i);
2152 		dom = isl_ast_build_get_domain(data->build);
2153 		required = isl_set_intersect(dom, required);
2154 		is_valid = isl_set_is_subset(required, valid);
2155 		isl_set_free(required);
2156 		isl_set_free(valid);
2157 		if (is_valid < 0 || !is_valid) {
2158 			isl_set_free(set);
2159 			return is_valid;
2160 		}
2161 
2162 		aff_i = isl_aff_list_get_aff(data->p[data->n].aff_list, i);
2163 		valid = isl_set_from_basic_set(test(aff_i, isl_aff_copy(aff)));
2164 		is_valid = isl_set_is_subset(set, valid);
2165 		isl_set_free(valid);
2166 		if (is_valid < 0 || !is_valid) {
2167 			isl_set_free(set);
2168 			return is_valid;
2169 		}
2170 	}
2171 
2172 	isl_set_free(set);
2173 	return isl_bool_true;
2174 }
2175 
2176 /* Can the list of pieces in "data" be extended with "set" and "aff"
2177  * to form/preserve a minimum expression?
2178  * In particular, is it the case for each entry (set_i, aff_i) that
2179  *
2180  *	aff >= aff_i on set_i, and
2181  *	aff_i >= aff on set?
2182  */
extends_min(struct isl_from_pw_aff_data * data,__isl_keep isl_set * set,__isl_keep isl_aff * aff)2183 static isl_bool extends_min(struct isl_from_pw_aff_data *data,
2184 	__isl_keep isl_set *set,  __isl_keep isl_aff *aff)
2185 {
2186 	return extends(data, set, aff, &isl_aff_ge_basic_set);
2187 }
2188 
2189 /* Can the list of pieces in "data" be extended with "set" and "aff"
2190  * to form/preserve a maximum expression?
2191  * In particular, is it the case for each entry (set_i, aff_i) that
2192  *
2193  *	aff <= aff_i on set_i, and
2194  *	aff_i <= aff on set?
2195  */
extends_max(struct isl_from_pw_aff_data * data,__isl_keep isl_set * set,__isl_keep isl_aff * aff)2196 static isl_bool extends_max(struct isl_from_pw_aff_data *data,
2197 	__isl_keep isl_set *set,  __isl_keep isl_aff *aff)
2198 {
2199 	return extends(data, set, aff, &isl_aff_le_basic_set);
2200 }
2201 
2202 /* This function is called during the construction of an isl_ast_expr
2203  * that evaluates an isl_pw_aff.
2204  * If the last piece of "data" contains a single subpiece and
2205  * if its affine function is equal to "aff" on a part of the domain
2206  * that includes either "set" or the domain of that single subpiece,
2207  * then extend the domain of that single subpiece with "set".
2208  * If it was the original domain of the single subpiece where
2209  * the two affine functions are equal, then also replace
2210  * the affine function of the single subpiece by "aff".
2211  * If the last piece of "data" contains either a single subpiece
2212  * or a minimum, then check if this minimum expression can be extended
2213  * with (set, aff).
2214  * If so, extend the sequence and return.
2215  * Perform the same operation for maximum expressions.
2216  * If no such extension can be performed, then move to the next piece
2217  * in "data" (if the current piece contains any data), and then store
2218  * the current subpiece in the current piece of "data" for later handling.
2219  */
ast_expr_from_pw_aff(__isl_take isl_set * set,__isl_take isl_aff * aff,void * user)2220 static isl_stat ast_expr_from_pw_aff(__isl_take isl_set *set,
2221 	__isl_take isl_aff *aff, void *user)
2222 {
2223 	struct isl_from_pw_aff_data *data = user;
2224 	isl_bool test;
2225 	enum isl_from_pw_aff_state state;
2226 
2227 	state = data->p[data->n].state;
2228 	if (state == isl_state_single) {
2229 		isl_aff *aff0;
2230 		isl_set *eq;
2231 		isl_bool subset1, subset2 = isl_bool_false;
2232 		aff0 = isl_aff_list_get_aff(data->p[data->n].aff_list, 0);
2233 		eq = isl_aff_eq_set(isl_aff_copy(aff), aff0);
2234 		subset1 = isl_set_is_subset(set, eq);
2235 		if (subset1 >= 0 && !subset1)
2236 			subset2 = single_is_subset(data, eq);
2237 		isl_set_free(eq);
2238 		if (subset1 < 0 || subset2 < 0)
2239 			goto error;
2240 		if (subset1)
2241 			return extend_domain(data, set, aff, 0);
2242 		if (subset2)
2243 			return extend_domain(data, set, aff, 1);
2244 	}
2245 	if (state == isl_state_single || state == isl_state_min) {
2246 		test = extends_min(data, set, aff);
2247 		if (test < 0)
2248 			goto error;
2249 		if (test)
2250 			return extend_min(data, set, aff);
2251 	}
2252 	if (state == isl_state_single || state == isl_state_max) {
2253 		test = extends_max(data, set, aff);
2254 		if (test < 0)
2255 			goto error;
2256 		if (test)
2257 			return extend_max(data, set, aff);
2258 	}
2259 	if (state != isl_state_none)
2260 		data->n++;
2261 	set_single(data, set, aff);
2262 
2263 	return isl_stat_ok;
2264 error:
2265 	isl_set_free(set);
2266 	isl_aff_free(aff);
2267 	return isl_stat_error;
2268 }
2269 
2270 /* Construct an isl_ast_expr that evaluates "pa".
2271  * The result is simplified in terms of build->domain.
2272  *
2273  * The domain of "pa" lives in the internal schedule space.
2274  */
isl_ast_build_expr_from_pw_aff_internal(__isl_keep isl_ast_build * build,__isl_take isl_pw_aff * pa)2275 __isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff_internal(
2276 	__isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
2277 {
2278 	struct isl_from_pw_aff_data data = { NULL };
2279 	isl_ast_expr *res = NULL;
2280 
2281 	pa = isl_ast_build_compute_gist_pw_aff(build, pa);
2282 	pa = isl_pw_aff_coalesce(pa);
2283 	if (!pa)
2284 		return NULL;
2285 
2286 	if (isl_from_pw_aff_data_init(&data, build, pa) < 0)
2287 		goto error;
2288 	set_none(&data);
2289 
2290 	if (isl_pw_aff_foreach_piece(pa, &ast_expr_from_pw_aff, &data) >= 0)
2291 		res = build_pieces(&data);
2292 
2293 	isl_pw_aff_free(pa);
2294 	isl_from_pw_aff_data_clear(&data);
2295 	return res;
2296 error:
2297 	isl_pw_aff_free(pa);
2298 	isl_from_pw_aff_data_clear(&data);
2299 	return NULL;
2300 }
2301 
2302 /* Construct an isl_ast_expr that evaluates "pa".
2303  * The result is simplified in terms of build->domain.
2304  *
2305  * The domain of "pa" lives in the external schedule space.
2306  */
isl_ast_build_expr_from_pw_aff(__isl_keep isl_ast_build * build,__isl_take isl_pw_aff * pa)2307 __isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
2308 	__isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
2309 {
2310 	isl_ast_expr *expr;
2311 	isl_bool needs_map;
2312 
2313 	needs_map = isl_ast_build_need_schedule_map(build);
2314 	if (needs_map < 0) {
2315 		pa = isl_pw_aff_free(pa);
2316 	} else if (needs_map) {
2317 		isl_multi_aff *ma;
2318 		ma = isl_ast_build_get_schedule_map_multi_aff(build);
2319 		pa = isl_pw_aff_pullback_multi_aff(pa, ma);
2320 	}
2321 	expr = isl_ast_build_expr_from_pw_aff_internal(build, pa);
2322 	return expr;
2323 }
2324 
2325 /* Set the ids of the input dimensions of "mpa" to the iterator ids
2326  * of "build".
2327  *
2328  * The domain of "mpa" is assumed to live in the internal schedule domain.
2329  */
set_iterator_names(__isl_keep isl_ast_build * build,__isl_take isl_multi_pw_aff * mpa)2330 static __isl_give isl_multi_pw_aff *set_iterator_names(
2331 	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
2332 {
2333 	int i;
2334 	isl_size n;
2335 
2336 	n = isl_multi_pw_aff_dim(mpa, isl_dim_in);
2337 	if (n < 0)
2338 		return isl_multi_pw_aff_free(mpa);
2339 	for (i = 0; i < n; ++i) {
2340 		isl_id *id;
2341 
2342 		id = isl_ast_build_get_iterator_id(build, i);
2343 		mpa = isl_multi_pw_aff_set_dim_id(mpa, isl_dim_in, i, id);
2344 	}
2345 
2346 	return mpa;
2347 }
2348 
2349 /* Construct an isl_ast_expr of type "type" with as first argument "arg0" and
2350  * the remaining arguments derived from "mpa".
2351  * That is, construct a call or access expression that calls/accesses "arg0"
2352  * with arguments/indices specified by "mpa".
2353  */
isl_ast_build_with_arguments(__isl_keep isl_ast_build * build,enum isl_ast_expr_op_type type,__isl_take isl_ast_expr * arg0,__isl_take isl_multi_pw_aff * mpa)2354 static __isl_give isl_ast_expr *isl_ast_build_with_arguments(
2355 	__isl_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
2356 	__isl_take isl_ast_expr *arg0, __isl_take isl_multi_pw_aff *mpa)
2357 {
2358 	int i;
2359 	isl_size n;
2360 	isl_ctx *ctx;
2361 	isl_ast_expr *expr;
2362 
2363 	ctx = isl_ast_build_get_ctx(build);
2364 
2365 	n = isl_multi_pw_aff_dim(mpa, isl_dim_out);
2366 	expr = n >= 0 ? isl_ast_expr_alloc_op(ctx, type, 1 + n) : NULL;
2367 	expr = isl_ast_expr_set_op_arg(expr, 0, arg0);
2368 	for (i = 0; i < n; ++i) {
2369 		isl_pw_aff *pa;
2370 		isl_ast_expr *arg;
2371 
2372 		pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
2373 		arg = isl_ast_build_expr_from_pw_aff_internal(build, pa);
2374 		expr = isl_ast_expr_set_op_arg(expr, 1 + i, arg);
2375 	}
2376 
2377 	isl_multi_pw_aff_free(mpa);
2378 	return expr;
2379 }
2380 
2381 static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_internal(
2382 	__isl_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
2383 	__isl_take isl_multi_pw_aff *mpa);
2384 
2385 /* Construct an isl_ast_expr that accesses the member specified by "mpa".
2386  * The range of "mpa" is assumed to be wrapped relation.
2387  * The domain of this wrapped relation specifies the structure being
2388  * accessed, while the range of this wrapped relation spacifies the
2389  * member of the structure being accessed.
2390  *
2391  * The domain of "mpa" is assumed to live in the internal schedule domain.
2392  */
isl_ast_build_from_multi_pw_aff_member(__isl_keep isl_ast_build * build,__isl_take isl_multi_pw_aff * mpa)2393 static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_member(
2394 	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
2395 {
2396 	isl_id *id;
2397 	isl_multi_pw_aff *domain;
2398 	isl_ast_expr *domain_expr, *expr;
2399 	enum isl_ast_expr_op_type type = isl_ast_expr_op_access;
2400 
2401 	domain = isl_multi_pw_aff_copy(mpa);
2402 	domain = isl_multi_pw_aff_range_factor_domain(domain);
2403 	domain_expr = isl_ast_build_from_multi_pw_aff_internal(build,
2404 								type, domain);
2405 	mpa = isl_multi_pw_aff_range_factor_range(mpa);
2406 	if (!isl_multi_pw_aff_has_tuple_id(mpa, isl_dim_out))
2407 		isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
2408 			"missing field name", goto error);
2409 	id = isl_multi_pw_aff_get_tuple_id(mpa, isl_dim_out);
2410 	expr = isl_ast_expr_from_id(id);
2411 	expr = isl_ast_expr_alloc_binary(isl_ast_expr_op_member,
2412 					domain_expr, expr);
2413 	return isl_ast_build_with_arguments(build, type, expr, mpa);
2414 error:
2415 	isl_multi_pw_aff_free(mpa);
2416 	return NULL;
2417 }
2418 
2419 /* Construct an isl_ast_expr of type "type" that calls or accesses
2420  * the element specified by "mpa".
2421  * The first argument is obtained from the output tuple name.
2422  * The remaining arguments are given by the piecewise affine expressions.
2423  *
2424  * If the range of "mpa" is a mapped relation, then we assume it
2425  * represents an access to a member of a structure.
2426  *
2427  * The domain of "mpa" is assumed to live in the internal schedule domain.
2428  */
isl_ast_build_from_multi_pw_aff_internal(__isl_keep isl_ast_build * build,enum isl_ast_expr_op_type type,__isl_take isl_multi_pw_aff * mpa)2429 static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_internal(
2430 	__isl_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
2431 	__isl_take isl_multi_pw_aff *mpa)
2432 {
2433 	isl_ctx *ctx;
2434 	isl_id *id;
2435 	isl_ast_expr *expr;
2436 
2437 	if (!mpa)
2438 		goto error;
2439 
2440 	if (type == isl_ast_expr_op_access &&
2441 	    isl_multi_pw_aff_range_is_wrapping(mpa))
2442 		return isl_ast_build_from_multi_pw_aff_member(build, mpa);
2443 
2444 	mpa = set_iterator_names(build, mpa);
2445 	if (!build || !mpa)
2446 		goto error;
2447 
2448 	ctx = isl_ast_build_get_ctx(build);
2449 
2450 	if (isl_multi_pw_aff_has_tuple_id(mpa, isl_dim_out))
2451 		id = isl_multi_pw_aff_get_tuple_id(mpa, isl_dim_out);
2452 	else
2453 		id = isl_id_alloc(ctx, "", NULL);
2454 
2455 	expr = isl_ast_expr_from_id(id);
2456 	return isl_ast_build_with_arguments(build, type, expr, mpa);
2457 error:
2458 	isl_multi_pw_aff_free(mpa);
2459 	return NULL;
2460 }
2461 
2462 /* Construct an isl_ast_expr of type "type" that calls or accesses
2463  * the element specified by "pma".
2464  * The first argument is obtained from the output tuple name.
2465  * The remaining arguments are given by the piecewise affine expressions.
2466  *
2467  * The domain of "pma" is assumed to live in the internal schedule domain.
2468  */
isl_ast_build_from_pw_multi_aff_internal(__isl_keep isl_ast_build * build,enum isl_ast_expr_op_type type,__isl_take isl_pw_multi_aff * pma)2469 static __isl_give isl_ast_expr *isl_ast_build_from_pw_multi_aff_internal(
2470 	__isl_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
2471 	__isl_take isl_pw_multi_aff *pma)
2472 {
2473 	isl_multi_pw_aff *mpa;
2474 
2475 	mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
2476 	return isl_ast_build_from_multi_pw_aff_internal(build, type, mpa);
2477 }
2478 
2479 /* Construct an isl_ast_expr of type "type" that calls or accesses
2480  * the element specified by "mpa".
2481  * The first argument is obtained from the output tuple name.
2482  * The remaining arguments are given by the piecewise affine expressions.
2483  *
2484  * The domain of "mpa" is assumed to live in the external schedule domain.
2485  */
isl_ast_build_from_multi_pw_aff(__isl_keep isl_ast_build * build,enum isl_ast_expr_op_type type,__isl_take isl_multi_pw_aff * mpa)2486 static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff(
2487 	__isl_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
2488 	__isl_take isl_multi_pw_aff *mpa)
2489 {
2490 	isl_bool is_domain;
2491 	isl_bool needs_map;
2492 	isl_ast_expr *expr;
2493 	isl_space *space_build, *space_mpa;
2494 
2495 	space_build = isl_ast_build_get_space(build, 0);
2496 	space_mpa = isl_multi_pw_aff_get_space(mpa);
2497 	is_domain = isl_space_tuple_is_equal(space_build, isl_dim_set,
2498 					space_mpa, isl_dim_in);
2499 	isl_space_free(space_build);
2500 	isl_space_free(space_mpa);
2501 	if (is_domain < 0)
2502 		goto error;
2503 	if (!is_domain)
2504 		isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
2505 			"spaces don't match", goto error);
2506 
2507 	needs_map = isl_ast_build_need_schedule_map(build);
2508 	if (needs_map < 0)
2509 		goto error;
2510 	if (needs_map) {
2511 		isl_multi_aff *ma;
2512 		ma = isl_ast_build_get_schedule_map_multi_aff(build);
2513 		mpa = isl_multi_pw_aff_pullback_multi_aff(mpa, ma);
2514 	}
2515 
2516 	expr = isl_ast_build_from_multi_pw_aff_internal(build, type, mpa);
2517 	return expr;
2518 error:
2519 	isl_multi_pw_aff_free(mpa);
2520 	return NULL;
2521 }
2522 
2523 /* Construct an isl_ast_expr that calls the domain element specified by "mpa".
2524  * The name of the function is obtained from the output tuple name.
2525  * The arguments are given by the piecewise affine expressions.
2526  *
2527  * The domain of "mpa" is assumed to live in the external schedule domain.
2528  */
isl_ast_build_call_from_multi_pw_aff(__isl_keep isl_ast_build * build,__isl_take isl_multi_pw_aff * mpa)2529 __isl_give isl_ast_expr *isl_ast_build_call_from_multi_pw_aff(
2530 	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
2531 {
2532 	return isl_ast_build_from_multi_pw_aff(build,
2533 						isl_ast_expr_op_call, mpa);
2534 }
2535 
2536 /* Construct an isl_ast_expr that accesses the array element specified by "mpa".
2537  * The name of the array is obtained from the output tuple name.
2538  * The index expressions are given by the piecewise affine expressions.
2539  *
2540  * The domain of "mpa" is assumed to live in the external schedule domain.
2541  */
isl_ast_build_access_from_multi_pw_aff(__isl_keep isl_ast_build * build,__isl_take isl_multi_pw_aff * mpa)2542 __isl_give isl_ast_expr *isl_ast_build_access_from_multi_pw_aff(
2543 	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
2544 {
2545 	return isl_ast_build_from_multi_pw_aff(build,
2546 						isl_ast_expr_op_access, mpa);
2547 }
2548 
2549 /* Construct an isl_ast_expr of type "type" that calls or accesses
2550  * the element specified by "pma".
2551  * The first argument is obtained from the output tuple name.
2552  * The remaining arguments are given by the piecewise affine expressions.
2553  *
2554  * The domain of "pma" is assumed to live in the external schedule domain.
2555  */
isl_ast_build_from_pw_multi_aff(__isl_keep isl_ast_build * build,enum isl_ast_expr_op_type type,__isl_take isl_pw_multi_aff * pma)2556 static __isl_give isl_ast_expr *isl_ast_build_from_pw_multi_aff(
2557 	__isl_keep isl_ast_build *build, enum isl_ast_expr_op_type type,
2558 	__isl_take isl_pw_multi_aff *pma)
2559 {
2560 	isl_multi_pw_aff *mpa;
2561 
2562 	mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
2563 	return isl_ast_build_from_multi_pw_aff(build, type, mpa);
2564 }
2565 
2566 /* Construct an isl_ast_expr that calls the domain element specified by "pma".
2567  * The name of the function is obtained from the output tuple name.
2568  * The arguments are given by the piecewise affine expressions.
2569  *
2570  * The domain of "pma" is assumed to live in the external schedule domain.
2571  */
isl_ast_build_call_from_pw_multi_aff(__isl_keep isl_ast_build * build,__isl_take isl_pw_multi_aff * pma)2572 __isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
2573 	__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
2574 {
2575 	return isl_ast_build_from_pw_multi_aff(build,
2576 						isl_ast_expr_op_call, pma);
2577 }
2578 
2579 /* Construct an isl_ast_expr that accesses the array element specified by "pma".
2580  * The name of the array is obtained from the output tuple name.
2581  * The index expressions are given by the piecewise affine expressions.
2582  *
2583  * The domain of "pma" is assumed to live in the external schedule domain.
2584  */
isl_ast_build_access_from_pw_multi_aff(__isl_keep isl_ast_build * build,__isl_take isl_pw_multi_aff * pma)2585 __isl_give isl_ast_expr *isl_ast_build_access_from_pw_multi_aff(
2586 	__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
2587 {
2588 	return isl_ast_build_from_pw_multi_aff(build,
2589 						isl_ast_expr_op_access, pma);
2590 }
2591 
2592 /* Construct an isl_ast_expr that calls the domain element
2593  * specified by "executed".
2594  *
2595  * "executed" is assumed to be single-valued, with a domain that lives
2596  * in the internal schedule space.
2597  */
isl_ast_build_call_from_executed(__isl_keep isl_ast_build * build,__isl_take isl_map * executed)2598 __isl_give isl_ast_node *isl_ast_build_call_from_executed(
2599 	__isl_keep isl_ast_build *build, __isl_take isl_map *executed)
2600 {
2601 	isl_pw_multi_aff *iteration;
2602 	isl_ast_expr *expr;
2603 
2604 	iteration = isl_pw_multi_aff_from_map(executed);
2605 	iteration = isl_ast_build_compute_gist_pw_multi_aff(build, iteration);
2606 	iteration = isl_pw_multi_aff_intersect_domain(iteration,
2607 					isl_ast_build_get_domain(build));
2608 	expr = isl_ast_build_from_pw_multi_aff_internal(build,
2609 					isl_ast_expr_op_call, iteration);
2610 	return isl_ast_node_alloc_user(expr);
2611 }
2612