1 /* 2 * Copyright 2011 INRIA Saclay 3 * Copyright 2014 Ecole Normale Superieure 4 * Copyright 2015 Sven Verdoolaege 5 * 6 * Use of this software is governed by the MIT license 7 * 8 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, 9 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, 10 * 91893 Orsay, France 11 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France 12 */ 13 14 #include <isl/space.h> 15 #include <isl_vec_private.h> 16 #include <isl_mat_private.h> 17 #include <isl_reordering.h> 18 #include <isl_seq.h> 19 #include <isl_local_private.h> 20 21 /* Return the isl_ctx to which "local" belongs. 22 */ 23 isl_ctx *isl_local_get_ctx(__isl_keep isl_local *local) 24 { 25 if (!local) 26 return NULL; 27 28 return isl_mat_get_ctx(local); 29 } 30 31 /* Create an isl_local object from a matrix describing 32 * integer divisions. 33 * 34 * An isl_local object is current defined as exactly such a matrix, 35 * so simply return the input. 36 */ 37 __isl_give isl_local *isl_local_alloc_from_mat(__isl_take isl_mat *mat) 38 { 39 return mat; 40 } 41 42 /* Return a new reference to "local". 43 */ 44 __isl_give isl_local *isl_local_copy(__isl_keep isl_local *local) 45 { 46 return isl_local_alloc_from_mat(isl_mat_copy(local)); 47 } 48 49 /* Free "local" and return NULL. 50 */ 51 __isl_null isl_local *isl_local_free(__isl_take isl_local *local) 52 { 53 isl_mat_free(local); 54 return NULL; 55 } 56 57 /* Return the number of local variables (isl_dim_div), 58 * the number of other variables (isl_dim_set) or 59 * the total number of variables (isl_dim_all) in "local". 60 * 61 * Other types do not have any meaning for an isl_local object. 62 */ 63 isl_size isl_local_dim(__isl_keep isl_local *local, enum isl_dim_type type) 64 { 65 isl_mat *mat = local; 66 67 if (!local) 68 return isl_size_error; 69 if (type == isl_dim_div) 70 return isl_mat_rows(mat); 71 if (type == isl_dim_all) { 72 isl_size cols = isl_mat_cols(mat); 73 if (cols < 0) 74 return isl_size_error; 75 return cols - 2; 76 } 77 if (type == isl_dim_set) { 78 isl_size total, n_div; 79 80 total = isl_local_dim(local, isl_dim_all); 81 n_div = isl_local_dim(local, isl_dim_div); 82 if (total < 0 || n_div < 0) 83 return isl_size_error; 84 return total - n_div; 85 } 86 isl_die(isl_local_get_ctx(local), isl_error_unsupported, 87 "unsupported dimension type", return isl_size_error); 88 } 89 90 #undef TYPE 91 #define TYPE isl_local 92 static 93 #include "check_type_range_templ.c" 94 95 /* Check that "pos" is a valid position for a variable in "local". 96 */ 97 static isl_stat isl_local_check_pos(__isl_keep isl_local *local, int pos) 98 { 99 return isl_local_check_range(local, isl_dim_div, pos, 1); 100 } 101 102 /* Given local variables "local", 103 * is the variable at position "pos" marked as not having 104 * an explicit representation? 105 * Note that even if this variable is not marked in this way and therefore 106 * does have an explicit representation, this representation may still 107 * depend (indirectly) on other local variables that do not 108 * have an explicit representation. 109 */ 110 isl_bool isl_local_div_is_marked_unknown(__isl_keep isl_local *local, int pos) 111 { 112 isl_mat *mat = local; 113 114 if (isl_local_check_pos(local, pos) < 0) 115 return isl_bool_error; 116 return isl_bool_ok(isl_int_is_zero(mat->row[pos][0])); 117 } 118 119 /* Given local variables "local", 120 * does the variable at position "pos" have a complete explicit representation? 121 * Having a complete explicit representation requires not only 122 * an explicit representation, but also that all local variables 123 * that appear in this explicit representation in turn have 124 * a complete explicit representation. 125 */ 126 isl_bool isl_local_div_is_known(__isl_keep isl_local *local, int pos) 127 { 128 isl_bool marked; 129 int i, off; 130 isl_size n, cols; 131 isl_mat *mat = local; 132 133 if (isl_local_check_pos(local, pos) < 0) 134 return isl_bool_error; 135 136 marked = isl_local_div_is_marked_unknown(local, pos); 137 if (marked < 0 || marked) 138 return isl_bool_not(marked); 139 140 n = isl_local_dim(local, isl_dim_div); 141 cols = isl_mat_cols(mat); 142 if (n < 0 || cols < 0) 143 return isl_bool_error; 144 off = cols - n; 145 146 for (i = n - 1; i >= 0; --i) { 147 isl_bool known; 148 149 if (isl_int_is_zero(mat->row[pos][off + i])) 150 continue; 151 known = isl_local_div_is_known(local, i); 152 if (known < 0 || !known) 153 return known; 154 } 155 156 return isl_bool_true; 157 } 158 159 /* Does "local" have an explicit representation for all local variables? 160 */ 161 isl_bool isl_local_divs_known(__isl_keep isl_local *local) 162 { 163 int i; 164 isl_size n; 165 166 n = isl_local_dim(local, isl_dim_div); 167 if (n < 0) 168 return isl_bool_error; 169 170 for (i = 0; i < n; ++i) { 171 isl_bool unknown = isl_local_div_is_marked_unknown(local, i); 172 if (unknown < 0 || unknown) 173 return isl_bool_not(unknown); 174 } 175 176 return isl_bool_true; 177 } 178 179 /* Compare two sets of local variables, defined over 180 * the same space. 181 * 182 * Return -1 if "local1" is "smaller" than "local2", 1 if "local1" is "greater" 183 * than "local2" and 0 if they are equal. 184 * 185 * The order is fairly arbitrary. We do "prefer" divs that only involve 186 * earlier dimensions in the sense that we consider matrices where 187 * the first differing div involves earlier dimensions to be smaller. 188 */ 189 int isl_local_cmp(__isl_keep isl_local *local1, __isl_keep isl_local *local2) 190 { 191 int i; 192 int cmp; 193 isl_bool unknown1, unknown2; 194 int last1, last2; 195 isl_size n_col; 196 isl_mat *mat1 = local1; 197 isl_mat *mat2 = local2; 198 199 if (local1 == local2) 200 return 0; 201 if (!local1) 202 return -1; 203 if (!local2) 204 return 1; 205 206 if (mat1->n_row != mat2->n_row) 207 return mat1->n_row - mat2->n_row; 208 209 n_col = isl_mat_cols(mat1); 210 if (n_col < 0) 211 return -1; 212 for (i = 0; i < mat1->n_row; ++i) { 213 unknown1 = isl_local_div_is_marked_unknown(local1, i); 214 unknown2 = isl_local_div_is_marked_unknown(local2, i); 215 if (unknown1 && unknown2) 216 continue; 217 if (unknown1) 218 return 1; 219 if (unknown2) 220 return -1; 221 last1 = isl_seq_last_non_zero(mat1->row[i] + 1, n_col - 1); 222 last2 = isl_seq_last_non_zero(mat2->row[i] + 1, n_col - 1); 223 if (last1 != last2) 224 return last1 - last2; 225 cmp = isl_seq_cmp(mat1->row[i], mat2->row[i], n_col); 226 if (cmp != 0) 227 return cmp; 228 } 229 230 return 0; 231 } 232 233 /* Return the position of the variables of the given type 234 * within the sequence of variables of "local". 235 * 236 * Only the position of the local variables can be obtained. 237 * It is equal to the total number of variables minus 238 * the number of local variables. 239 */ 240 isl_size isl_local_var_offset(__isl_keep isl_local *local, 241 enum isl_dim_type type) 242 { 243 isl_size n_div, n_all; 244 245 if (!local) 246 return isl_size_error; 247 if (type != isl_dim_div) 248 isl_die(isl_local_get_ctx(local), isl_error_unsupported, 249 "only the offset of the local variables " 250 "can be obtained", return isl_size_error); 251 252 n_div = isl_local_dim(local, isl_dim_div); 253 n_all = isl_local_dim(local, isl_dim_all); 254 if (n_div < 0 || n_all < 0) 255 return isl_size_error; 256 return n_all - n_div; 257 } 258 259 /* Reorder the columns of the given local variables according to the 260 * given reordering. 261 * The order of the local variables themselves is assumed not to change. 262 */ 263 __isl_give isl_local *isl_local_reorder(__isl_take isl_local *local, 264 __isl_take isl_reordering *r) 265 { 266 isl_mat *div = local; 267 int i, j; 268 isl_mat *mat; 269 int extra; 270 271 if (!local || !r) 272 goto error; 273 274 extra = r->dst_len - r->src_len; 275 mat = isl_mat_alloc(div->ctx, div->n_row, div->n_col + extra); 276 if (!mat) 277 goto error; 278 279 for (i = 0; i < div->n_row; ++i) { 280 isl_seq_cpy(mat->row[i], div->row[i], 2); 281 isl_seq_clr(mat->row[i] + 2, mat->n_col - 2); 282 for (j = 0; j < r->src_len; ++j) 283 isl_int_set(mat->row[i][2 + r->pos[j]], 284 div->row[i][2 + j]); 285 } 286 287 isl_reordering_free(r); 288 isl_local_free(local); 289 return isl_local_alloc_from_mat(mat); 290 error: 291 isl_reordering_free(r); 292 isl_local_free(local); 293 return NULL; 294 } 295 296 /* Move the "n" variables starting at "src_pos" of "local" to "dst_pos". 297 * 298 * Moving local variables is not allowed. 299 */ 300 __isl_give isl_local *isl_local_move_vars(__isl_take isl_local *local, 301 unsigned dst_pos, unsigned src_pos, unsigned n) 302 { 303 isl_mat *mat = local; 304 isl_size v_div; 305 306 v_div = isl_local_var_offset(local, isl_dim_div); 307 if (v_div < 0) 308 return isl_local_free(local); 309 if (n == 0) 310 return local; 311 312 if (dst_pos >= v_div || src_pos >= v_div) 313 isl_die(isl_local_get_ctx(local), isl_error_invalid, 314 "cannot move local variables", 315 return isl_local_free(local)); 316 317 mat = isl_mat_move_cols(mat, 2 + dst_pos, 2 + src_pos, n); 318 319 return isl_local_alloc_from_mat(mat); 320 } 321 322 /* Does "local" depend on the specified variables? 323 * 324 * If the specified variables are local variables themselves, 325 * then only later local variables could possibly depend on them. 326 */ 327 isl_bool isl_local_involves_vars(__isl_keep isl_local *local, 328 unsigned first, unsigned n) 329 { 330 isl_mat *mat = local; 331 int i, first_div; 332 isl_size v_div, n_div; 333 334 v_div = isl_local_var_offset(local, isl_dim_div); 335 n_div = isl_local_dim(local, isl_dim_div); 336 if (v_div < 0 || n_div < 0 || 337 isl_local_check_range(local, isl_dim_all, first, n) < 0) 338 return isl_bool_error; 339 340 first_div = (first >= v_div) ? first - v_div + 1 : 0; 341 for (i = first_div; i < n_div; ++i) { 342 isl_bool unknown; 343 344 unknown = isl_local_div_is_marked_unknown(local, i); 345 if (unknown < 0) 346 return isl_bool_error; 347 if (unknown) 348 continue; 349 if (isl_seq_first_non_zero(mat->row[i] + 1 + 1 + first, n) >= 0) 350 return isl_bool_true; 351 } 352 353 return isl_bool_false; 354 } 355 356 /* Extend a vector "v" representing an integer point 357 * in the domain space of "local" 358 * to one that also includes values for the local variables. 359 * All local variables are required to have an explicit representation. 360 * If there are no local variables, then the point is not required 361 * to be integral. 362 */ 363 __isl_give isl_vec *isl_local_extend_point_vec(__isl_keep isl_local *local, 364 __isl_take isl_vec *v) 365 { 366 isl_size dim, n_div, size; 367 isl_bool known; 368 isl_mat *mat = local; 369 370 if (!local || !v) 371 return isl_vec_free(v); 372 known = isl_local_divs_known(local); 373 if (known < 0) 374 return isl_vec_free(v); 375 if (!known) 376 isl_die(isl_local_get_ctx(local), isl_error_invalid, 377 "unknown local variables", return isl_vec_free(v)); 378 dim = isl_local_dim(local, isl_dim_set); 379 n_div = isl_local_dim(local, isl_dim_div); 380 size = isl_vec_size(v); 381 if (dim < 0 || n_div < 0 || size < 0) 382 return isl_vec_free(v); 383 if (size != 1 + dim) 384 isl_die(isl_local_get_ctx(local), isl_error_invalid, 385 "incorrect size", return isl_vec_free(v)); 386 if (n_div == 0) 387 return v; 388 if (!isl_int_is_one(v->el[0])) 389 isl_die(isl_local_get_ctx(local), isl_error_invalid, 390 "expecting integer point", return isl_vec_free(v)); 391 { 392 int i; 393 v = isl_vec_add_els(v, n_div); 394 if (!v) 395 return NULL; 396 397 for (i = 0; i < n_div; ++i) { 398 isl_seq_inner_product(mat->row[i] + 1, v->el, 399 1 + dim + i, &v->el[1+dim+i]); 400 isl_int_fdiv_q(v->el[1+dim+i], v->el[1+dim+i], 401 mat->row[i][0]); 402 } 403 } 404 405 return v; 406 } 407