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