1 1.1 mrg /* 2 1.1 mrg * Copyright 2010-2011 INRIA Saclay 3 1.1 mrg * Copyright 2012-2013 Ecole Normale Superieure 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, INRIA Saclay - Ile-de-France, 8 1.1 mrg * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, 9 1.1 mrg * 91893 Orsay, France 10 1.1 mrg * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France 11 1.1 mrg */ 12 1.1 mrg 13 1.1 mrg #include <isl/val.h> 14 1.1 mrg #include <isl/space.h> 15 1.1 mrg #include <isl_map_private.h> 16 1.1 mrg #include <isl_aff_private.h> 17 1.1 mrg #include <isl/constraint.h> 18 1.1 mrg #include <isl/ilp.h> 19 1.1 mrg #include <isl/fixed_box.h> 20 1.1 mrg #include <isl/stream.h> 21 1.1 mrg 22 1.1 mrg /* Representation of a box of fixed size containing the elements 23 1.1 mrg * [offset, offset + size). 24 1.1 mrg * "size" lives in the target space of "offset". 25 1.1 mrg * 26 1.1 mrg * If any of the "offsets" is NaN, then the object represents 27 1.1 mrg * the failure of finding a fixed-size box. 28 1.1 mrg */ 29 1.1 mrg struct isl_fixed_box { 30 1.1 mrg isl_multi_aff *offset; 31 1.1 mrg isl_multi_val *size; 32 1.1 mrg }; 33 1.1 mrg 34 1.1 mrg /* Free "box" and return NULL. 35 1.1 mrg */ 36 1.1 mrg __isl_null isl_fixed_box *isl_fixed_box_free(__isl_take isl_fixed_box *box) 37 1.1 mrg { 38 1.1 mrg if (!box) 39 1.1 mrg return NULL; 40 1.1 mrg isl_multi_aff_free(box->offset); 41 1.1 mrg isl_multi_val_free(box->size); 42 1.1 mrg free(box); 43 1.1 mrg return NULL; 44 1.1 mrg } 45 1.1 mrg 46 1.1 mrg /* Construct an isl_fixed_box with the given offset and size. 47 1.1 mrg */ 48 1.1 mrg static __isl_give isl_fixed_box *isl_fixed_box_alloc( 49 1.1 mrg __isl_take isl_multi_aff *offset, __isl_take isl_multi_val *size) 50 1.1 mrg { 51 1.1 mrg isl_ctx *ctx; 52 1.1 mrg isl_fixed_box *box; 53 1.1 mrg 54 1.1 mrg if (!offset || !size) 55 1.1 mrg goto error; 56 1.1 mrg ctx = isl_multi_aff_get_ctx(offset); 57 1.1 mrg box = isl_alloc_type(ctx, struct isl_fixed_box); 58 1.1 mrg if (!box) 59 1.1 mrg goto error; 60 1.1 mrg box->offset = offset; 61 1.1 mrg box->size = size; 62 1.1 mrg 63 1.1 mrg return box; 64 1.1 mrg error: 65 1.1 mrg isl_multi_aff_free(offset); 66 1.1 mrg isl_multi_val_free(size); 67 1.1 mrg return NULL; 68 1.1 mrg } 69 1.1 mrg 70 1.1 mrg /* Construct an initial isl_fixed_box with zero offsets 71 1.1 mrg * in the given space and zero corresponding sizes. 72 1.1 mrg */ 73 1.1 mrg static __isl_give isl_fixed_box *isl_fixed_box_init( 74 1.1 mrg __isl_take isl_space *space) 75 1.1 mrg { 76 1.1 mrg isl_multi_aff *offset; 77 1.1 mrg isl_multi_val *size; 78 1.1 mrg 79 1.1 mrg offset = isl_multi_aff_zero(isl_space_copy(space)); 80 1.1 mrg space = isl_space_drop_all_params(isl_space_range(space)); 81 1.1 mrg size = isl_multi_val_zero(space); 82 1.1 mrg return isl_fixed_box_alloc(offset, size); 83 1.1 mrg } 84 1.1 mrg 85 1.1 mrg /* Return a copy of "box". 86 1.1 mrg */ 87 1.1 mrg __isl_give isl_fixed_box *isl_fixed_box_copy(__isl_keep isl_fixed_box *box) 88 1.1 mrg { 89 1.1 mrg isl_multi_aff *offset; 90 1.1 mrg isl_multi_val *size; 91 1.1 mrg 92 1.1 mrg offset = isl_fixed_box_get_offset(box); 93 1.1 mrg size = isl_fixed_box_get_size(box); 94 1.1 mrg return isl_fixed_box_alloc(offset, size); 95 1.1 mrg } 96 1.1 mrg 97 1.1 mrg /* Replace the offset and size in direction "pos" by "offset" and "size" 98 1.1 mrg * (without checking whether "box" is a valid box). 99 1.1 mrg */ 100 1.1 mrg static __isl_give isl_fixed_box *isl_fixed_box_set_extent( 101 1.1 mrg __isl_take isl_fixed_box *box, int pos, __isl_keep isl_aff *offset, 102 1.1 mrg __isl_keep isl_val *size) 103 1.1 mrg { 104 1.1 mrg if (!box) 105 1.1 mrg return NULL; 106 1.1 mrg box->offset = isl_multi_aff_set_aff(box->offset, pos, 107 1.1 mrg isl_aff_copy(offset)); 108 1.1 mrg box->size = isl_multi_val_set_val(box->size, pos, isl_val_copy(size)); 109 1.1 mrg if (!box->offset || !box->size) 110 1.1 mrg return isl_fixed_box_free(box); 111 1.1 mrg return box; 112 1.1 mrg } 113 1.1 mrg 114 1.1 mrg /* Replace the offset and size in direction "pos" by "offset" and "size", 115 1.1 mrg * if "box" is a valid box. 116 1.1 mrg */ 117 1.1 mrg static __isl_give isl_fixed_box *isl_fixed_box_set_valid_extent( 118 1.1 mrg __isl_take isl_fixed_box *box, int pos, __isl_keep isl_aff *offset, 119 1.1 mrg __isl_keep isl_val *size) 120 1.1 mrg { 121 1.1 mrg isl_bool valid; 122 1.1 mrg 123 1.1 mrg valid = isl_fixed_box_is_valid(box); 124 1.1 mrg if (valid < 0 || !valid) 125 1.1 mrg return box; 126 1.1 mrg return isl_fixed_box_set_extent(box, pos, offset, size); 127 1.1 mrg } 128 1.1 mrg 129 1.1 mrg /* Replace "box" by an invalid box, by setting all offsets to NaN 130 1.1 mrg * (and all sizes to infinity). 131 1.1 mrg */ 132 1.1 mrg static __isl_give isl_fixed_box *isl_fixed_box_invalidate( 133 1.1 mrg __isl_take isl_fixed_box *box) 134 1.1 mrg { 135 1.1 mrg int i; 136 1.1 mrg isl_size n; 137 1.1 mrg isl_space *space; 138 1.1 mrg isl_val *infty; 139 1.1 mrg isl_aff *nan; 140 1.1 mrg 141 1.1 mrg if (!box) 142 1.1 mrg return NULL; 143 1.1 mrg n = isl_multi_val_dim(box->size, isl_dim_set); 144 1.1 mrg if (n < 0) 145 1.1 mrg return isl_fixed_box_free(box); 146 1.1 mrg 147 1.1 mrg infty = isl_val_infty(isl_fixed_box_get_ctx(box)); 148 1.1 mrg space = isl_space_domain(isl_fixed_box_get_space(box)); 149 1.1 mrg nan = isl_aff_nan_on_domain(isl_local_space_from_space(space)); 150 1.1 mrg for (i = 0; i < n; ++i) 151 1.1 mrg box = isl_fixed_box_set_extent(box, i, nan, infty); 152 1.1 mrg isl_aff_free(nan); 153 1.1 mrg isl_val_free(infty); 154 1.1 mrg 155 1.1 mrg if (!box->offset || !box->size) 156 1.1 mrg return isl_fixed_box_free(box); 157 1.1 mrg return box; 158 1.1 mrg } 159 1.1 mrg 160 1.1 mrg /* Project the domain of the fixed box onto its parameter space. 161 1.1 mrg * In particular, project out the domain of the offset. 162 1.1 mrg */ 163 1.1 mrg static __isl_give isl_fixed_box *isl_fixed_box_project_domain_on_params( 164 1.1 mrg __isl_take isl_fixed_box *box) 165 1.1 mrg { 166 1.1 mrg isl_bool valid; 167 1.1 mrg 168 1.1 mrg valid = isl_fixed_box_is_valid(box); 169 1.1 mrg if (valid < 0) 170 1.1 mrg return isl_fixed_box_free(box); 171 1.1 mrg if (!valid) 172 1.1 mrg return box; 173 1.1 mrg 174 1.1 mrg box->offset = isl_multi_aff_project_domain_on_params(box->offset); 175 1.1 mrg if (!box->offset) 176 1.1 mrg return isl_fixed_box_free(box); 177 1.1 mrg 178 1.1 mrg return box; 179 1.1 mrg } 180 1.1 mrg 181 1.1 mrg /* Return the isl_ctx to which "box" belongs. 182 1.1 mrg */ 183 1.1 mrg isl_ctx *isl_fixed_box_get_ctx(__isl_keep isl_fixed_box *box) 184 1.1 mrg { 185 1.1 mrg if (!box) 186 1.1 mrg return NULL; 187 1.1 mrg return isl_multi_aff_get_ctx(box->offset); 188 1.1 mrg } 189 1.1 mrg 190 1.1 mrg /* Return the space in which "box" lives. 191 1.1 mrg */ 192 1.1 mrg __isl_give isl_space *isl_fixed_box_get_space(__isl_keep isl_fixed_box *box) 193 1.1 mrg { 194 1.1 mrg if (!box) 195 1.1 mrg return NULL; 196 1.1 mrg return isl_multi_aff_get_space(box->offset); 197 1.1 mrg } 198 1.1 mrg 199 1.1 mrg /* Does "box" contain valid information? 200 1.1 mrg */ 201 1.1 mrg isl_bool isl_fixed_box_is_valid(__isl_keep isl_fixed_box *box) 202 1.1 mrg { 203 1.1 mrg if (!box) 204 1.1 mrg return isl_bool_error; 205 1.1 mrg return isl_bool_not(isl_multi_aff_involves_nan(box->offset)); 206 1.1 mrg } 207 1.1 mrg 208 1.1 mrg /* Return the offsets of the box "box". 209 1.1 mrg */ 210 1.1 mrg __isl_give isl_multi_aff *isl_fixed_box_get_offset( 211 1.1 mrg __isl_keep isl_fixed_box *box) 212 1.1 mrg { 213 1.1 mrg if (!box) 214 1.1 mrg return NULL; 215 1.1 mrg return isl_multi_aff_copy(box->offset); 216 1.1 mrg } 217 1.1 mrg 218 1.1 mrg /* Return the sizes of the box "box". 219 1.1 mrg */ 220 1.1 mrg __isl_give isl_multi_val *isl_fixed_box_get_size(__isl_keep isl_fixed_box *box) 221 1.1 mrg { 222 1.1 mrg if (!box) 223 1.1 mrg return NULL; 224 1.1 mrg return isl_multi_val_copy(box->size); 225 1.1 mrg } 226 1.1 mrg 227 1.1 mrg /* Data used in set_dim_extent and compute_size_in_direction. 228 1.1 mrg * 229 1.1 mrg * "bset" is a wrapped copy of the basic map that has the selected 230 1.1 mrg * output dimension as range. 231 1.1 mrg * "pos" is the position of the variable representing the output dimension, 232 1.1 mrg * i.e., the variable for which the size should be computed. This variable 233 1.1 mrg * is also the last variable in "bset". 234 1.1 mrg * "size" is the best size found so far 235 1.1 mrg * (infinity if no offset was found so far). 236 1.1 mrg * "offset" is the offset corresponding to the best size 237 1.1 mrg * (NULL if no offset was found so far). 238 1.1 mrg */ 239 1.1 mrg struct isl_size_info { 240 1.1 mrg isl_basic_set *bset; 241 1.1 mrg isl_size pos; 242 1.1 mrg isl_val *size; 243 1.1 mrg isl_aff *offset; 244 1.1 mrg }; 245 1.1 mrg 246 1.1 mrg /* Is "c" a suitable bound on dimension "pos" for use as a lower bound 247 1.1 mrg * of a fixed-size range. 248 1.1 mrg * In particular, it needs to be a lower bound on "pos". 249 1.1 mrg * In order for the final offset not to be too complicated, 250 1.1 mrg * the constraint itself should also not involve any integer divisions. 251 1.1 mrg */ 252 1.1 mrg static isl_bool is_suitable_bound(__isl_keep isl_constraint *c, unsigned pos) 253 1.1 mrg { 254 1.1 mrg isl_size n_div; 255 1.1 mrg isl_bool is_bound, any_divs; 256 1.1 mrg 257 1.1 mrg is_bound = isl_constraint_is_lower_bound(c, isl_dim_set, pos); 258 1.1 mrg if (is_bound < 0 || !is_bound) 259 1.1 mrg return is_bound; 260 1.1 mrg 261 1.1 mrg n_div = isl_constraint_dim(c, isl_dim_div); 262 1.1 mrg if (n_div < 0) 263 1.1 mrg return isl_bool_error; 264 1.1 mrg any_divs = isl_constraint_involves_dims(c, isl_dim_div, 0, n_div); 265 1.1 mrg return isl_bool_not(any_divs); 266 1.1 mrg } 267 1.1 mrg 268 1.1 mrg /* Given a constraint from the basic set describing the bounds on 269 1.1 mrg * an array index, check if it is a lower bound, say m i >= b(x), and, 270 1.1 mrg * if so, check whether the expression "i - ceil(b(x)/m) + 1" has a constant 271 1.1 mrg * upper bound. If so, and if this bound is smaller than any bound 272 1.1 mrg * derived from earlier constraints, set the size to this bound on 273 1.1 mrg * the expression and the lower bound to ceil(b(x)/m). 274 1.1 mrg */ 275 1.1 mrg static isl_stat compute_size_in_direction(__isl_take isl_constraint *c, 276 1.1 mrg void *user) 277 1.1 mrg { 278 1.1 mrg struct isl_size_info *info = user; 279 1.1 mrg isl_val *v; 280 1.1 mrg isl_aff *aff; 281 1.1 mrg isl_aff *lb; 282 1.1 mrg isl_bool is_bound, better; 283 1.1 mrg 284 1.1 mrg is_bound = is_suitable_bound(c, info->pos); 285 1.1 mrg if (is_bound < 0 || !is_bound) { 286 1.1 mrg isl_constraint_free(c); 287 1.1 mrg return is_bound < 0 ? isl_stat_error : isl_stat_ok; 288 1.1 mrg } 289 1.1 mrg 290 1.1 mrg aff = isl_constraint_get_bound(c, isl_dim_set, info->pos); 291 1.1 mrg aff = isl_aff_ceil(aff); 292 1.1 mrg 293 1.1 mrg lb = isl_aff_copy(aff); 294 1.1 mrg 295 1.1 mrg aff = isl_aff_neg(aff); 296 1.1 mrg aff = isl_aff_add_coefficient_si(aff, isl_dim_in, info->pos, 1); 297 1.1 mrg 298 1.1 mrg v = isl_basic_set_max_val(info->bset, aff); 299 1.1 mrg isl_aff_free(aff); 300 1.1 mrg 301 1.1 mrg v = isl_val_add_ui(v, 1); 302 1.1 mrg better = isl_val_lt(v, info->size); 303 1.1 mrg if (better >= 0 && better) { 304 1.1 mrg isl_val_free(info->size); 305 1.1 mrg info->size = isl_val_copy(v); 306 1.1 mrg lb = isl_aff_domain_factor_domain(lb); 307 1.1 mrg isl_aff_free(info->offset); 308 1.1 mrg info->offset = isl_aff_copy(lb); 309 1.1 mrg } 310 1.1 mrg isl_val_free(v); 311 1.1 mrg isl_aff_free(lb); 312 1.1 mrg 313 1.1 mrg isl_constraint_free(c); 314 1.1 mrg 315 1.1 mrg return better < 0 ? isl_stat_error : isl_stat_ok; 316 1.1 mrg } 317 1.1 mrg 318 1.1 mrg /* Look for a fixed-size range of values for the output dimension "pos" 319 1.1 mrg * of "map", by looking for a lower-bound expression in the parameters 320 1.1 mrg * and input dimensions such that the range of the output dimension 321 1.1 mrg * is a constant shifted by this expression. 322 1.1 mrg * 323 1.1 mrg * In particular, look through the explicit lower bounds on the output dimension 324 1.1 mrg * for candidate expressions and pick the one that results in the smallest size. 325 1.1 mrg * Initialize the size with infinity and if no better size is found 326 1.1 mrg * then invalidate the box. Otherwise, set the offset and size 327 1.1 mrg * in the given direction by those that correspond to the smallest size. 328 1.1 mrg * 329 1.1 mrg * Note that while evaluating the size corresponding to a lower bound, 330 1.1 mrg * an affine expression is constructed from the lower bound. 331 1.1 mrg * This lower bound may therefore not have any unknown local variables. 332 1.1 mrg * Eliminate any unknown local variables up front. 333 1.1 mrg * No such restriction needs to be imposed on the set over which 334 1.1 mrg * the size is computed. 335 1.1 mrg */ 336 1.1 mrg static __isl_give isl_fixed_box *set_dim_extent(__isl_take isl_fixed_box *box, 337 1.1 mrg __isl_keep isl_map *map, int pos) 338 1.1 mrg { 339 1.1 mrg struct isl_size_info info; 340 1.1 mrg isl_bool valid; 341 1.1 mrg isl_ctx *ctx; 342 1.1 mrg isl_basic_set *bset; 343 1.1 mrg 344 1.1 mrg if (!box || !map) 345 1.1 mrg return isl_fixed_box_free(box); 346 1.1 mrg 347 1.1 mrg ctx = isl_map_get_ctx(map); 348 1.1 mrg map = isl_map_copy(map); 349 1.1 mrg map = isl_map_project_onto(map, isl_dim_out, pos, 1); 350 1.1 mrg info.size = isl_val_infty(ctx); 351 1.1 mrg info.offset = NULL; 352 1.1 mrg info.pos = isl_map_dim(map, isl_dim_in); 353 1.1 mrg info.bset = isl_basic_map_wrap(isl_map_simple_hull(map)); 354 1.1 mrg bset = isl_basic_set_copy(info.bset); 355 1.1 mrg bset = isl_basic_set_remove_unknown_divs(bset); 356 1.1 mrg if (info.pos < 0) 357 1.1 mrg bset = isl_basic_set_free(bset); 358 1.1 mrg if (isl_basic_set_foreach_constraint(bset, 359 1.1 mrg &compute_size_in_direction, &info) < 0) 360 1.1 mrg box = isl_fixed_box_free(box); 361 1.1 mrg isl_basic_set_free(bset); 362 1.1 mrg valid = isl_val_is_int(info.size); 363 1.1 mrg if (valid < 0) 364 1.1 mrg box = isl_fixed_box_free(box); 365 1.1 mrg else if (valid) 366 1.1 mrg box = isl_fixed_box_set_valid_extent(box, pos, 367 1.1 mrg info.offset, info.size); 368 1.1 mrg else 369 1.1 mrg box = isl_fixed_box_invalidate(box); 370 1.1 mrg isl_val_free(info.size); 371 1.1 mrg isl_aff_free(info.offset); 372 1.1 mrg isl_basic_set_free(info.bset); 373 1.1 mrg 374 1.1 mrg return box; 375 1.1 mrg } 376 1.1 mrg 377 1.1 mrg /* Try and construct a fixed-size rectangular box with an offset 378 1.1 mrg * in terms of the domain of "map" that contains the range of "map". 379 1.1 mrg * If no such box can be constructed, then return an invalidated box, 380 1.1 mrg * i.e., one where isl_fixed_box_is_valid returns false. 381 1.1 mrg * 382 1.1 mrg * Iterate over the dimensions in the range 383 1.1 mrg * setting the corresponding offset and extent. 384 1.1 mrg */ 385 1.1 mrg __isl_give isl_fixed_box *isl_map_get_range_simple_fixed_box_hull( 386 1.1 mrg __isl_keep isl_map *map) 387 1.1 mrg { 388 1.1 mrg int i; 389 1.1 mrg isl_size n; 390 1.1 mrg isl_space *space; 391 1.1 mrg isl_fixed_box *box; 392 1.1 mrg 393 1.1 mrg n = isl_map_dim(map, isl_dim_out); 394 1.1 mrg if (n < 0) 395 1.1 mrg return NULL; 396 1.1 mrg space = isl_map_get_space(map); 397 1.1 mrg box = isl_fixed_box_init(space); 398 1.1 mrg 399 1.1 mrg map = isl_map_detect_equalities(isl_map_copy(map)); 400 1.1 mrg for (i = 0; i < n; ++i) { 401 1.1 mrg isl_bool valid; 402 1.1 mrg 403 1.1 mrg box = set_dim_extent(box, map, i); 404 1.1 mrg valid = isl_fixed_box_is_valid(box); 405 1.1 mrg if (valid < 0 || !valid) 406 1.1 mrg break; 407 1.1 mrg } 408 1.1 mrg isl_map_free(map); 409 1.1 mrg 410 1.1 mrg return box; 411 1.1 mrg } 412 1.1 mrg 413 1.1 mrg /* Compute a fixed box from "set" using "map_box" by treating it as a map 414 1.1 mrg * with a zero-dimensional domain and 415 1.1 mrg * project out the domain again from the result. 416 1.1 mrg */ 417 1.1 mrg static __isl_give isl_fixed_box *fixed_box_as_map(__isl_keep isl_set *set, 418 1.1 mrg __isl_give isl_fixed_box *(*map_box)(__isl_keep isl_map *map)) 419 1.1 mrg { 420 1.1 mrg isl_map *map; 421 1.1 mrg isl_fixed_box *box; 422 1.1 mrg 423 1.1 mrg map = isl_map_from_range(isl_set_copy(set)); 424 1.1 mrg box = map_box(map); 425 1.1 mrg isl_map_free(map); 426 1.1 mrg box = isl_fixed_box_project_domain_on_params(box); 427 1.1 mrg 428 1.1 mrg return box; 429 1.1 mrg } 430 1.1 mrg 431 1.1 mrg /* Try and construct a fixed-size rectangular box with an offset 432 1.1 mrg * in terms of the parameters of "set" that contains "set". 433 1.1 mrg * If no such box can be constructed, then return an invalidated box, 434 1.1 mrg * i.e., one where isl_fixed_box_is_valid returns false. 435 1.1 mrg * 436 1.1 mrg * Compute the box using isl_map_get_range_simple_fixed_box_hull 437 1.1 mrg * by constructing a map from the set and 438 1.1 mrg * project out the domain again from the result. 439 1.1 mrg */ 440 1.1 mrg __isl_give isl_fixed_box *isl_set_get_simple_fixed_box_hull( 441 1.1 mrg __isl_keep isl_set *set) 442 1.1 mrg { 443 1.1 mrg return fixed_box_as_map(set, &isl_map_get_range_simple_fixed_box_hull); 444 1.1 mrg } 445 1.1 mrg 446 1.1 mrg /* Check whether the output elements lie on a rectangular lattice, 447 1.1 mrg * possibly depending on the parameters and the input dimensions. 448 1.1 mrg * Return a tile in this lattice. 449 1.1 mrg * If no stride information can be found, then return a tile of size 1 450 1.1 mrg * (and offset 0). 451 1.1 mrg * 452 1.1 mrg * Obtain stride information in each output dimension separately and 453 1.1 mrg * combine the results. 454 1.1 mrg */ 455 1.1 mrg __isl_give isl_fixed_box *isl_map_get_range_lattice_tile( 456 1.1 mrg __isl_keep isl_map *map) 457 1.1 mrg { 458 1.1 mrg int i; 459 1.1 mrg isl_size n; 460 1.1 mrg isl_space *space; 461 1.1 mrg isl_fixed_box *box; 462 1.1 mrg 463 1.1 mrg n = isl_map_dim(map, isl_dim_out); 464 1.1 mrg if (n < 0) 465 1.1 mrg return NULL; 466 1.1 mrg space = isl_map_get_space(map); 467 1.1 mrg box = isl_fixed_box_init(space); 468 1.1 mrg 469 1.1 mrg for (i = 0; i < n; ++i) { 470 1.1 mrg isl_val *stride; 471 1.1 mrg isl_aff *offset; 472 1.1 mrg isl_stride_info *si; 473 1.1 mrg 474 1.1 mrg si = isl_map_get_range_stride_info(map, i); 475 1.1 mrg stride = isl_stride_info_get_stride(si); 476 1.1 mrg offset = isl_stride_info_get_offset(si); 477 1.1 mrg isl_stride_info_free(si); 478 1.1 mrg 479 1.1 mrg box = isl_fixed_box_set_valid_extent(box, i, offset, stride); 480 1.1 mrg 481 1.1 mrg isl_aff_free(offset); 482 1.1 mrg isl_val_free(stride); 483 1.1 mrg } 484 1.1 mrg 485 1.1 mrg return box; 486 1.1 mrg } 487 1.1 mrg 488 1.1 mrg /* Check whether the elements lie on a rectangular lattice, 489 1.1 mrg * possibly depending on the parameters. 490 1.1 mrg * Return a tile in this lattice. 491 1.1 mrg * If no stride information can be found, then return a tile of size 1 492 1.1 mrg * (and offset 0). 493 1.1 mrg * 494 1.1 mrg * Consider the set as a map with a zero-dimensional domain and 495 1.1 mrg * obtain a lattice tile of that map. 496 1.1 mrg */ 497 1.1 mrg __isl_give isl_fixed_box *isl_set_get_lattice_tile(__isl_keep isl_set *set) 498 1.1 mrg { 499 1.1 mrg return fixed_box_as_map(set, &isl_map_get_range_lattice_tile); 500 1.1 mrg } 501 1.1 mrg 502 1.1 mrg /* An enumeration of the keys that may appear in a YAML mapping 503 1.1 mrg * of an isl_fixed_box object. 504 1.1 mrg */ 505 1.1 mrg enum isl_fb_key { 506 1.1 mrg isl_fb_key_error = -1, 507 1.1 mrg isl_fb_key_offset, 508 1.1 mrg isl_fb_key_size, 509 1.1 mrg isl_fb_key_end, 510 1.1 mrg }; 511 1.1 mrg 512 1.1 mrg /* Textual representations of the YAML keys for an isl_fixed_box object. 513 1.1 mrg */ 514 1.1 mrg static char *key_str[] = { 515 1.1 mrg [isl_fb_key_offset] = "offset", 516 1.1 mrg [isl_fb_key_size] = "size", 517 1.1 mrg }; 518 1.1 mrg 519 1.1 mrg #undef BASE 520 1.1 mrg #define BASE multi_val 521 1.1 mrg #include "print_yaml_field_templ.c" 522 1.1 mrg 523 1.1 mrg #undef BASE 524 1.1 mrg #define BASE multi_aff 525 1.1 mrg #include "print_yaml_field_templ.c" 526 1.1 mrg 527 1.1 mrg /* Print the information contained in "box" to "p". 528 1.1 mrg * The information is printed as a YAML document. 529 1.1 mrg */ 530 1.1 mrg __isl_give isl_printer *isl_printer_print_fixed_box( 531 1.1 mrg __isl_take isl_printer *p, __isl_keep isl_fixed_box *box) 532 1.1 mrg { 533 1.1 mrg if (!box) 534 1.1 mrg return isl_printer_free(p); 535 1.1 mrg 536 1.1 mrg p = isl_printer_yaml_start_mapping(p); 537 1.1 mrg p = print_yaml_field_multi_aff(p, key_str[isl_fb_key_offset], 538 1.1 mrg box->offset); 539 1.1 mrg p = print_yaml_field_multi_val(p, key_str[isl_fb_key_size], box->size); 540 1.1 mrg p = isl_printer_yaml_end_mapping(p); 541 1.1 mrg 542 1.1 mrg return p; 543 1.1 mrg } 544 1.1 mrg 545 1.1 mrg #undef BASE 546 1.1 mrg #define BASE fixed_box 547 1.1 mrg #include <print_templ_yaml.c> 548 1.1 mrg 549 1.1 mrg #undef KEY 550 1.1 mrg #define KEY enum isl_fb_key 551 1.1 mrg #undef KEY_ERROR 552 1.1 mrg #define KEY_ERROR isl_fb_key_error 553 1.1 mrg #undef KEY_END 554 1.1 mrg #define KEY_END isl_fb_key_end 555 1.1 mrg #undef KEY_STR 556 1.1 mrg #define KEY_STR key_str 557 1.1 mrg #undef KEY_EXTRACT 558 1.1 mrg #define KEY_EXTRACT extract_key 559 1.1 mrg #undef KEY_GET 560 1.1 mrg #define KEY_GET get_key 561 1.1 mrg #include "extract_key.c" 562 1.1 mrg 563 1.1 mrg #undef BASE 564 1.1 mrg #define BASE multi_val 565 1.1 mrg #include "read_in_string_templ.c" 566 1.1 mrg 567 1.1 mrg #undef BASE 568 1.1 mrg #define BASE multi_aff 569 1.1 mrg #include "read_in_string_templ.c" 570 1.1 mrg 571 1.1 mrg /* Read an isl_fixed_box object from "s". 572 1.1 mrg * 573 1.1 mrg * The input needs to contain both an offset and a size. 574 1.1 mrg * If either is specified multiple times, then the last specification 575 1.1 mrg * overrides all previous ones. This is simpler than checking 576 1.1 mrg * that each is only specified once. 577 1.1 mrg */ 578 1.1 mrg static __isl_give isl_fixed_box *isl_stream_read_fixed_box(isl_stream *s) 579 1.1 mrg { 580 1.1 mrg isl_bool more; 581 1.1 mrg isl_multi_aff *offset = NULL; 582 1.1 mrg isl_multi_val *size = NULL; 583 1.1 mrg 584 1.1 mrg if (isl_stream_yaml_read_start_mapping(s) < 0) 585 1.1 mrg return NULL; 586 1.1 mrg 587 1.1 mrg while ((more = isl_stream_yaml_next(s)) == isl_bool_true) { 588 1.1 mrg enum isl_fb_key key; 589 1.1 mrg 590 1.1 mrg key = get_key(s); 591 1.1 mrg if (isl_stream_yaml_next(s) < 0) 592 1.1 mrg goto error; 593 1.1 mrg switch (key) { 594 1.1 mrg case isl_fb_key_end: 595 1.1 mrg case isl_fb_key_error: 596 1.1 mrg goto error; 597 1.1 mrg case isl_fb_key_offset: 598 1.1 mrg isl_multi_aff_free(offset); 599 1.1 mrg offset = read_multi_aff(s); 600 1.1 mrg if (!offset) 601 1.1 mrg goto error; 602 1.1 mrg break; 603 1.1 mrg case isl_fb_key_size: 604 1.1 mrg isl_multi_val_free(size); 605 1.1 mrg size = read_multi_val(s); 606 1.1 mrg if (!size) 607 1.1 mrg goto error; 608 1.1 mrg break; 609 1.1 mrg } 610 1.1 mrg } 611 1.1 mrg if (more < 0) 612 1.1 mrg goto error; 613 1.1 mrg 614 1.1 mrg if (isl_stream_yaml_read_end_mapping(s) < 0) 615 1.1 mrg goto error; 616 1.1 mrg 617 1.1 mrg if (!offset) { 618 1.1 mrg isl_stream_error(s, NULL, "no offset specified"); 619 1.1 mrg goto error; 620 1.1 mrg } 621 1.1 mrg 622 1.1 mrg if (!size) { 623 1.1 mrg isl_stream_error(s, NULL, "no size specified"); 624 1.1 mrg goto error; 625 1.1 mrg } 626 1.1 mrg 627 1.1 mrg return isl_fixed_box_alloc(offset, size); 628 1.1 mrg error: 629 1.1 mrg isl_multi_aff_free(offset); 630 1.1 mrg isl_multi_val_free(size); 631 1.1 mrg return NULL; 632 1.1 mrg } 633 1.1 mrg 634 1.1 mrg #undef TYPE_BASE 635 1.1 mrg #define TYPE_BASE fixed_box 636 1.1 mrg #include "isl_read_from_str_templ.c" 637