1 /* 2 * Copyright 2008-2009 Katholieke Universiteit Leuven 3 * Copyright 2010 INRIA Saclay 4 * Copyright 2012-2013 Ecole Normale Superieure 5 * Copyright 2014 INRIA Rocquencourt 6 * Copyright 2022 Cerebras Systems 7 * 8 * Use of this software is governed by the MIT license 9 * 10 * Written by Sven Verdoolaege, K.U.Leuven, Departement 11 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium 12 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite, 13 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 14 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France 15 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt, 16 * B.P. 105 - 78153 Le Chesnay, France 17 * and Cerebras Systems, 1237 E Arques Ave, Sunnyvale, CA, USA 18 */ 19 20 #include <assert.h> 21 #include <stdio.h> 22 #include <limits.h> 23 #include <isl_ctx_private.h> 24 #include <isl_map_private.h> 25 #include <isl_aff_private.h> 26 #include <isl_space_private.h> 27 #include <isl/id.h> 28 #include <isl/set.h> 29 #include <isl/flow.h> 30 #include <isl_constraint_private.h> 31 #include <isl/polynomial.h> 32 #include <isl/union_set.h> 33 #include <isl/union_map.h> 34 #include <isl_factorization.h> 35 #include <isl/schedule.h> 36 #include <isl/schedule_node.h> 37 #include <isl_options_private.h> 38 #include <isl_vertices_private.h> 39 #include <isl/ast_build.h> 40 #include <isl/val.h> 41 #include <isl/ilp.h> 42 #include <isl_ast_build_expr.h> 43 #include <isl/options.h> 44 45 #include "isl_srcdir.c" 46 47 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array)) 48 49 static char *get_filename(isl_ctx *ctx, const char *name, const char *suffix) { 50 char *filename; 51 int length; 52 char *pattern = "%s/test_inputs/%s.%s"; 53 54 length = strlen(pattern) - 6 + strlen(srcdir) + strlen(name) 55 + strlen(suffix) + 1; 56 filename = isl_alloc_array(ctx, char, length); 57 58 if (!filename) 59 return NULL; 60 61 sprintf(filename, pattern, srcdir, name, suffix); 62 63 return filename; 64 } 65 66 void test_parse_map(isl_ctx *ctx, const char *str) 67 { 68 isl_map *map; 69 70 map = isl_map_read_from_str(ctx, str); 71 assert(map); 72 isl_map_free(map); 73 } 74 75 int test_parse_map_equal(isl_ctx *ctx, const char *str, const char *str2) 76 { 77 isl_map *map, *map2; 78 int equal; 79 80 map = isl_map_read_from_str(ctx, str); 81 map2 = isl_map_read_from_str(ctx, str2); 82 equal = isl_map_is_equal(map, map2); 83 isl_map_free(map); 84 isl_map_free(map2); 85 86 if (equal < 0) 87 return -1; 88 if (!equal) 89 isl_die(ctx, isl_error_unknown, "maps not equal", 90 return -1); 91 92 return 0; 93 } 94 95 void test_parse_pwqp(isl_ctx *ctx, const char *str) 96 { 97 isl_pw_qpolynomial *pwqp; 98 99 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str); 100 assert(pwqp); 101 isl_pw_qpolynomial_free(pwqp); 102 } 103 104 static void test_parse_pwaff(isl_ctx *ctx, const char *str) 105 { 106 isl_pw_aff *pwaff; 107 108 pwaff = isl_pw_aff_read_from_str(ctx, str); 109 assert(pwaff); 110 isl_pw_aff_free(pwaff); 111 } 112 113 /* Check that we can read an isl_multi_val from "str" without errors. 114 */ 115 static int test_parse_multi_val(isl_ctx *ctx, const char *str) 116 { 117 isl_multi_val *mv; 118 119 mv = isl_multi_val_read_from_str(ctx, str); 120 isl_multi_val_free(mv); 121 122 return mv ? 0 : -1; 123 } 124 125 /* String descriptions of multi piecewise affine expressions 126 * that are used for testing printing and parsing. 127 */ 128 static const char *reparse_multi_pw_aff_tests[] = { 129 "{ A[x, y] -> [] : x + y >= 0 }", 130 "{ A[x, y] -> B[] : x + y >= 0 }", 131 "{ A[x, y] -> [x] : x + y >= 0 }", 132 "[N] -> { A[x, y] -> [x] : x + y <= N }", 133 "{ A[x, y] -> [x, y] : x + y >= 0 }", 134 "{ A[x, y] -> [(x : x >= 0), (y : y >= 0)] : x + y >= 0 }", 135 "[N] -> { [] : N >= 0 }", 136 "[N] -> { [] : N >= 0 }", 137 "[N] -> { [N] : N >= 0 }", 138 "[N] -> { [N, N + 1] : N >= 0 }", 139 "[N, M] -> { [(N : N >= 0), (M : M >= 0)] : N + M >= 0 }", 140 "{ [a] -> [b = a] }", 141 "{ [a] -> [b = a] : a >= 0 }", 142 }; 143 144 #undef BASE 145 #define BASE multi_pw_aff 146 147 #include "check_reparse_templ.c" 148 #include "check_reparse_test_templ.c" 149 150 /* String descriptions that cannot be parsed 151 * as multi piecewise affine expressions. 152 */ 153 static const char *parse_multi_pw_aff_fail_tests[] = { 154 "{ [a] -> [b] : b = a }", 155 "{ [a] -> [b = a] : b >= 0 }", 156 }; 157 158 #include "check_parse_fail_test_templ.c" 159 160 /* String descriptions of piecewise multi affine expressions 161 * that are used for testing printing and parsing. 162 */ 163 static const char *reparse_pw_multi_aff_tests[] = { 164 "{ [x] -> [x] }", 165 "{ [x] -> [x % 4] }", 166 "{ [x] -> [x % 4] : x mod 3 = 1 }", 167 "{ [x, x] -> [x % 4] }", 168 "{ [x, x + 1] -> [x % 4] : x mod 3 = 1 }", 169 "{ [x, x mod 2] -> [x % 4] }", 170 "{ [a] -> [a//2] : exists (e0: 8*floor((-a + e0)/8) <= -8 - a + 8e0) }", 171 "{ [a, b] -> [(2*floor((a)/8) + floor((b)/6))] }", 172 }; 173 174 #undef BASE 175 #define BASE pw_multi_aff 176 177 #include "check_reparse_templ.c" 178 #include "check_reparse_test_templ.c" 179 180 /* Test parsing of piecewise multi affine expressions by printing 181 * the expressions and checking that parsing the output results 182 * in the same expression. 183 * Do this for an expression converted from a map with an output 184 * dimension name that is equal to an automatically generated name, and 185 * a set of expressions parsed from strings. 186 */ 187 static isl_stat test_parse_pma(isl_ctx *ctx) 188 { 189 isl_map *map; 190 isl_pw_multi_aff *pma; 191 192 map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }"); 193 pma = isl_pw_multi_aff_from_map(map); 194 if (check_reparse_pw_multi_aff(ctx, pma) < 0) 195 return isl_stat_error; 196 197 if (check_reparse_pw_multi_aff_tests(ctx) < 0) 198 return isl_stat_error; 199 200 return isl_stat_ok; 201 } 202 203 /* String descriptions that cannot be parsed 204 * as union piecewise multi affine expressions. 205 */ 206 static const char *parse_union_pw_multi_aff_fail_tests[] = { 207 "{ [a] -> [b] : b = a }", 208 "{ [a] -> [b = a] : b >= 0 }", 209 }; 210 211 #undef BASE 212 #define BASE union_pw_multi_aff 213 214 #include "check_parse_fail_test_templ.c" 215 216 /* Test parsing of union piecewise multi affine expressions. 217 * 218 * In particular, check some cases where parsing is supposed to fail. 219 */ 220 static isl_stat test_parse_upma(isl_ctx *ctx) 221 { 222 if (check_parse_union_pw_multi_aff_fail_tests(ctx) < 0) 223 return isl_stat_error; 224 225 return isl_stat_ok; 226 } 227 228 /* Test parsing of multi piecewise affine expressions by printing 229 * the expressions and checking that parsing the output results 230 * in the same expression. 231 * Do this for a couple of manually constructed expressions, 232 * an expression converted from a map with an output dimension name 233 * that is equal to an automatically generated name, and 234 * a set of expressions parsed from strings. 235 * 236 * Additionally, check some cases where parsing is supposed to fail. 237 */ 238 static int test_parse_mpa(isl_ctx *ctx) 239 { 240 isl_space *space; 241 isl_set *dom; 242 isl_map *map; 243 isl_pw_multi_aff *pma; 244 isl_multi_pw_aff *mpa; 245 isl_stat r; 246 247 space = isl_space_set_alloc(ctx, 0, 0); 248 space = isl_space_set_tuple_name(space, isl_dim_set, "A"); 249 mpa = isl_multi_pw_aff_zero(space); 250 r = check_reparse_multi_pw_aff(ctx, mpa); 251 if (r < 0) 252 return -1; 253 254 space = isl_space_set_alloc(ctx, 1, 0); 255 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N"); 256 space = isl_space_set_tuple_name(space, isl_dim_set, "A"); 257 dom = isl_set_universe(isl_space_params(isl_space_copy(space))); 258 dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5); 259 mpa = isl_multi_pw_aff_zero(space); 260 mpa = isl_multi_pw_aff_intersect_domain(mpa, dom); 261 r = check_reparse_multi_pw_aff(ctx, mpa); 262 if (r < 0) 263 return -1; 264 265 map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }"); 266 pma = isl_pw_multi_aff_from_map(map); 267 mpa = isl_multi_pw_aff_from_pw_multi_aff(pma); 268 if (check_reparse_multi_pw_aff(ctx, mpa) < 0) 269 return -1; 270 271 if (check_reparse_multi_pw_aff_tests(ctx) < 0) 272 return -1; 273 if (check_parse_multi_pw_aff_fail_tests(ctx) < 0) 274 return -1; 275 276 return 0; 277 } 278 279 /* String descriptions of multi union piecewise affine expressions 280 * that are used for testing printing and parsing. 281 */ 282 static const char *reparse_multi_union_pw_aff_tests[] = { 283 "[]", 284 "A[]", 285 "A[B[] -> C[]]", 286 "(A[] : { S[x] : x > 0; T[y] : y >= 0 })", 287 "(A[] : { })", 288 "[N] -> (A[] : { })", 289 "[N] -> (A[] : { : N >= 0 })", 290 "[N] -> (A[] : { S[x] : x > N; T[y] : y >= 0 })", 291 "(A[] : [N] -> { S[x] : x > N; T[y] : y >= 0 })", 292 "A[{ S[x] -> [x + 1]; T[x] -> [x] }]", 293 "(A[{ S[x] -> [x + 1]; T[x] -> [x] }] : " 294 "{ S[x] : x > 0; T[y] : y >= 0 })", 295 }; 296 297 #undef BASE 298 #define BASE multi_union_pw_aff 299 300 #include "check_reparse_templ.c" 301 #include "check_reparse_test_templ.c" 302 303 /* Test parsing of multi union piecewise affine expressions by printing 304 * the expressions and checking that parsing the output results 305 * in the same expression. 306 * Do this for a couple of manually constructed expressions and 307 * a set of expressions parsed from strings. 308 */ 309 static int test_parse_mupa(isl_ctx *ctx) 310 { 311 isl_space *space; 312 isl_multi_union_pw_aff *mupa; 313 isl_set *dom; 314 isl_union_set *uset; 315 isl_stat r; 316 317 space = isl_space_set_alloc(ctx, 0, 0); 318 space = isl_space_set_tuple_name(space, isl_dim_set, "A"); 319 mupa = isl_multi_union_pw_aff_zero(space); 320 r = check_reparse_multi_union_pw_aff(ctx, mupa); 321 if (r < 0) 322 return -1; 323 324 space = isl_space_set_alloc(ctx, 1, 0); 325 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N"); 326 space = isl_space_set_tuple_name(space, isl_dim_set, "A"); 327 dom = isl_set_universe(space); 328 dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5); 329 uset = isl_union_set_from_set(dom); 330 space = isl_space_set_alloc(ctx, 1, 0); 331 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N"); 332 space = isl_space_set_tuple_name(space, isl_dim_set, "B"); 333 mupa = isl_multi_union_pw_aff_zero(space); 334 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, uset); 335 r = check_reparse_multi_union_pw_aff(ctx, mupa); 336 if (r < 0) 337 return -1; 338 339 if (check_reparse_multi_union_pw_aff_tests(ctx) < 0) 340 return -1; 341 342 return 0; 343 } 344 345 /* Test parsing of multi expressions. 346 */ 347 static int test_parse_multi(isl_ctx *ctx) 348 { 349 if (test_parse_mpa(ctx) < 0) 350 return -1; 351 if (test_parse_mupa(ctx) < 0) 352 return -1; 353 354 return 0; 355 } 356 357 /* Pairs of binary relation representations that should represent 358 * the same binary relations. 359 */ 360 struct { 361 const char *map1; 362 const char *map2; 363 } parse_map_equal_tests[] = { 364 { "{ [x,y] : [([x/2]+y)/3] >= 1 }", 365 "{ [x, y] : 2y >= 6 - x }" }, 366 { "{ [x,y] : x <= min(y, 2*y+3) }", 367 "{ [x,y] : x <= y, 2*y + 3 }" }, 368 { "{ [x,y] : x >= min(y, 2*y+3) }", 369 "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }" }, 370 { "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }", 371 "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }" }, 372 { "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }", 373 "{ [i,j] -> [min(i,j)] }" }, 374 { "{ [i,j] : i != j }", 375 "{ [i,j] : i < j or i > j }" }, 376 { "{ [i,j] : (i+1)*2 >= j }", 377 "{ [i, j] : j <= 2 + 2i }" }, 378 { "{ [i] -> [i > 0 ? 4 : 5] }", 379 "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }" }, 380 { "[N=2,M] -> { [i=[(M+N)/4]] }", 381 "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }" }, 382 { "{ [x] : x >= 0 }", 383 "{ [x] : x-0 >= 0 }" }, 384 { "{ [i] : ((i > 10)) }", 385 "{ [i] : i >= 11 }" }, 386 { "{ [i] -> [0] }", 387 "{ [i] -> [0 * i] }" }, 388 { "{ [a] -> [b] : (not false) }", 389 "{ [a] -> [b] : true }" }, 390 { "{ [i] : i/2 <= 5 }", 391 "{ [i] : i <= 10 }" }, 392 { "{Sym=[n] [i] : i <= n }", 393 "[n] -> { [i] : i <= n }" }, 394 { "{ [*] }", 395 "{ [a] }" }, 396 { "{ [i] : 2*floor(i/2) = i }", 397 "{ [i] : exists a : i = 2 a }" }, 398 { "{ [a] -> [b] : a = 5 implies b = 5 }", 399 "{ [a] -> [b] : a != 5 or b = 5 }" }, 400 { "{ [a] -> [a - 1 : a > 0] }", 401 "{ [a] -> [a - 1] : a > 0 }" }, 402 { "{ [a] -> [a - 1 : a > 0; a : a <= 0] }", 403 "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }" }, 404 { "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }", 405 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" }, 406 { "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }", 407 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" }, 408 { "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }", 409 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" }, 410 { "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }", 411 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" }, 412 { "{ [a,b] -> [i,j] : a,b << i,j }", 413 "{ [a,b] -> [i,j] : a < i or (a = i and b < j) }" }, 414 { "{ [a,b] -> [i,j] : a,b <<= i,j }", 415 "{ [a,b] -> [i,j] : a < i or (a = i and b <= j) }" }, 416 { "{ [a,b] -> [i,j] : a,b >> i,j }", 417 "{ [a,b] -> [i,j] : a > i or (a = i and b > j) }" }, 418 { "{ [a,b] -> [i,j] : a,b >>= i,j }", 419 "{ [a,b] -> [i,j] : a > i or (a = i and b >= j) }" }, 420 { "{ [n] -> [i] : exists (a, b, c: 8b <= i - 32a and " 421 "8b >= -7 + i - 32 a and b >= 0 and b <= 3 and " 422 "8c < n - 32a and i < n and c >= 0 and " 423 "c <= 3 and c >= -4a) }", 424 "{ [n] -> [i] : 0 <= i < n }" }, 425 { "{ [x] -> [] : exists (a, b: 0 <= a <= 1 and 0 <= b <= 3 and " 426 "2b <= x - 8a and 2b >= -1 + x - 8a) }", 427 "{ [x] -> [] : 0 <= x <= 15 }" }, 428 { "{ [x] -> [x] : }", 429 "{ [x] -> [x] }" }, 430 { "{ [x=4:5] -> [x + 1] }", 431 "{ [x] -> [x + 1] : 4 <= x <= 5 }" }, 432 { "{ [x=4:5] -> [x + 1 : x + 1] }", 433 "{ [x=4:5] -> [x + 1] }" }, 434 { "{ [x] -> [x - 1 : x + 1] }", 435 "{ [x] -> [y] : x - 1 <= y <= x + 1 }" }, 436 { "{ [x=4:] -> [x + 1] }", 437 "{ [x] -> [x + 1] : 4 <= x }" }, 438 { "{ [x=:5] -> [x + 1] }", 439 "{ [x] -> [x + 1] : x <= 5 }" }, 440 { "{ [x=:] -> [x + 1] }", 441 "{ [x] -> [x + 1] }" }, 442 { "{ [:] -> [:] }", 443 "{ [x] -> [y] }" }, 444 { "{ [x, x//4] }", 445 "{ [x, floor(x/4)] }" }, 446 { "{ [10//4] }", 447 "{ [2] }" }, 448 { "{ [-1//4] }", 449 "{ [-1] }" }, 450 { "{ [0-1//4] }", 451 "{ [0] }" }, 452 { "{ [- 1//4] }", 453 "{ [-1] }" }, 454 { "{ [0 - 1//4] }", 455 "{ [0] }" }, 456 { "{ [0--1//4] }", 457 "{ [1] }" }, 458 { "{ [0 - -1//4] }", 459 "{ [1] }" }, 460 { "{ [-2^2:2^2-1] }", 461 "{ [-4:3] }" }, 462 { "{ [2*-2] }", 463 "{ [-4] }" }, 464 { "{ [i,i*-2] }", 465 "{ [i,-2i] }" }, 466 { "[a, b, c, d] -> { [max(a,b,c,d)] }", 467 "[a, b, c, d] -> { [a] : b < a and c < a and d < a; " 468 "[b] : b >= a and c < b and d < b; " 469 "[c] : c >= a and c >= b and d < c; " 470 "[d] : d >= a and d >= b and d >= c }" }, 471 { "[a, b, c, d] -> { [min(a,b,c,d)] }", 472 "[a, b, c, d] -> { [a] : b >= a and c >= a and d >= a; " 473 "[b] : b < a and c >= b and d >= b; " 474 "[c] : c < b and c < a and d >= c; " 475 "[d] : d < c and d < b and d < a }" }, 476 }; 477 478 int test_parse(struct isl_ctx *ctx) 479 { 480 int i; 481 isl_map *map, *map2; 482 const char *str, *str2; 483 484 if (test_parse_multi_val(ctx, "{ A[B[2] -> C[5, 7]] }") < 0) 485 return -1; 486 if (test_parse_multi_val(ctx, "[n] -> { [2] }") < 0) 487 return -1; 488 if (test_parse_multi_val(ctx, "{ A[4, infty, NaN, -1/2, 2/3] }") < 0) 489 return -1; 490 if (test_parse_multi(ctx) < 0) 491 return -1; 492 if (test_parse_pma(ctx) < 0) 493 return -1; 494 if (test_parse_upma(ctx) < 0) 495 return -1; 496 497 str = "{ [i] -> [-i] }"; 498 map = isl_map_read_from_str(ctx, str); 499 assert(map); 500 isl_map_free(map); 501 502 str = "{ A[i] -> L[([i/3])] }"; 503 map = isl_map_read_from_str(ctx, str); 504 assert(map); 505 isl_map_free(map); 506 507 test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}"); 508 test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : " 509 "p1 = 1 && (y1 <= y2 || y2 = 0) }"); 510 511 for (i = 0; i < ARRAY_SIZE(parse_map_equal_tests); ++i) { 512 str = parse_map_equal_tests[i].map1; 513 str2 = parse_map_equal_tests[i].map2; 514 if (test_parse_map_equal(ctx, str, str2) < 0) 515 return -1; 516 } 517 518 str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}"; 519 map = isl_map_read_from_str(ctx, str); 520 str = "{ [new, old] -> [o0, o1] : " 521 "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: " 522 "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and " 523 "o0 <= 1 and o1 >= 0 and o1 <= 1) }"; 524 map2 = isl_map_read_from_str(ctx, str); 525 assert(isl_map_is_equal(map, map2)); 526 isl_map_free(map); 527 isl_map_free(map2); 528 529 str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}"; 530 map = isl_map_read_from_str(ctx, str); 531 str = "{[new,old] -> [(new+1)%2,(old+1)%2]}"; 532 map2 = isl_map_read_from_str(ctx, str); 533 assert(isl_map_is_equal(map, map2)); 534 isl_map_free(map); 535 isl_map_free(map2); 536 537 test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }"); 538 test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }"); 539 test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }"); 540 test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }"); 541 test_parse_pwaff(ctx, "{ [] -> [(100)] }"); 542 543 return 0; 544 } 545 546 static int test_read(isl_ctx *ctx) 547 { 548 char *filename; 549 FILE *input; 550 isl_basic_set *bset1, *bset2; 551 const char *str = "{[y]: Exists ( alpha : 2alpha = y)}"; 552 int equal; 553 554 filename = get_filename(ctx, "set", "omega"); 555 assert(filename); 556 input = fopen(filename, "r"); 557 assert(input); 558 559 bset1 = isl_basic_set_read_from_file(ctx, input); 560 bset2 = isl_basic_set_read_from_str(ctx, str); 561 562 equal = isl_basic_set_is_equal(bset1, bset2); 563 564 isl_basic_set_free(bset1); 565 isl_basic_set_free(bset2); 566 free(filename); 567 568 fclose(input); 569 570 if (equal < 0) 571 return -1; 572 if (!equal) 573 isl_die(ctx, isl_error_unknown, 574 "read sets not equal", return -1); 575 576 return 0; 577 } 578 579 static int test_bounded(isl_ctx *ctx) 580 { 581 isl_set *set; 582 isl_bool bounded; 583 584 set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }"); 585 bounded = isl_set_is_bounded(set); 586 isl_set_free(set); 587 588 if (bounded < 0) 589 return -1; 590 if (!bounded) 591 isl_die(ctx, isl_error_unknown, 592 "set not considered bounded", return -1); 593 594 set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }"); 595 bounded = isl_set_is_bounded(set); 596 assert(!bounded); 597 isl_set_free(set); 598 599 if (bounded < 0) 600 return -1; 601 if (bounded) 602 isl_die(ctx, isl_error_unknown, 603 "set considered bounded", return -1); 604 605 set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }"); 606 bounded = isl_set_is_bounded(set); 607 isl_set_free(set); 608 609 if (bounded < 0) 610 return -1; 611 if (bounded) 612 isl_die(ctx, isl_error_unknown, 613 "set considered bounded", return -1); 614 615 return 0; 616 } 617 618 /* Construct the basic set { [i] : 5 <= i <= N } */ 619 static int test_construction_1(isl_ctx *ctx) 620 { 621 isl_space *space; 622 isl_local_space *ls; 623 isl_basic_set *bset; 624 isl_constraint *c; 625 626 space = isl_space_set_alloc(ctx, 1, 1); 627 bset = isl_basic_set_universe(isl_space_copy(space)); 628 ls = isl_local_space_from_space(space); 629 630 c = isl_constraint_alloc_inequality(isl_local_space_copy(ls)); 631 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 632 c = isl_constraint_set_coefficient_si(c, isl_dim_param, 0, 1); 633 bset = isl_basic_set_add_constraint(bset, c); 634 635 c = isl_constraint_alloc_inequality(isl_local_space_copy(ls)); 636 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); 637 c = isl_constraint_set_constant_si(c, -5); 638 bset = isl_basic_set_add_constraint(bset, c); 639 640 isl_local_space_free(ls); 641 isl_basic_set_free(bset); 642 643 return 0; 644 } 645 646 /* Construct the basic set { [x] : -100 <= x <= 100 } 647 * using isl_basic_set_{lower,upper}_bound_val and 648 * check that it is equal the same basic set parsed from a string. 649 */ 650 static int test_construction_2(isl_ctx *ctx) 651 { 652 isl_bool equal; 653 isl_val *v; 654 isl_space *space; 655 isl_basic_set *bset1, *bset2; 656 657 v = isl_val_int_from_si(ctx, 100); 658 space = isl_space_set_alloc(ctx, 0, 1); 659 bset1 = isl_basic_set_universe(space); 660 bset1 = isl_basic_set_upper_bound_val(bset1, isl_dim_set, 0, 661 isl_val_copy(v)); 662 bset1 = isl_basic_set_lower_bound_val(bset1, isl_dim_set, 0, 663 isl_val_neg(v)); 664 bset2 = isl_basic_set_read_from_str(ctx, "{ [x] : -100 <= x <= 100 }"); 665 equal = isl_basic_set_is_equal(bset1, bset2); 666 isl_basic_set_free(bset1); 667 isl_basic_set_free(bset2); 668 669 if (equal < 0) 670 return -1; 671 if (!equal) 672 isl_die(ctx, isl_error_unknown, 673 "failed construction", return -1); 674 675 return 0; 676 } 677 678 /* Basic tests for constructing basic sets. 679 */ 680 static int test_construction(isl_ctx *ctx) 681 { 682 if (test_construction_1(ctx) < 0) 683 return -1; 684 if (test_construction_2(ctx) < 0) 685 return -1; 686 return 0; 687 } 688 689 static int test_dim(isl_ctx *ctx) 690 { 691 const char *str; 692 isl_map *map1, *map2; 693 int equal; 694 695 map1 = isl_map_read_from_str(ctx, 696 "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }"); 697 map1 = isl_map_add_dims(map1, isl_dim_in, 1); 698 map2 = isl_map_read_from_str(ctx, 699 "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }"); 700 equal = isl_map_is_equal(map1, map2); 701 isl_map_free(map2); 702 703 map1 = isl_map_project_out(map1, isl_dim_in, 0, 1); 704 map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }"); 705 if (equal >= 0 && equal) 706 equal = isl_map_is_equal(map1, map2); 707 708 isl_map_free(map1); 709 isl_map_free(map2); 710 711 if (equal < 0) 712 return -1; 713 if (!equal) 714 isl_die(ctx, isl_error_unknown, 715 "unexpected result", return -1); 716 717 str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }"; 718 map1 = isl_map_read_from_str(ctx, str); 719 str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }"; 720 map2 = isl_map_read_from_str(ctx, str); 721 map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1); 722 equal = isl_map_is_equal(map1, map2); 723 isl_map_free(map1); 724 isl_map_free(map2); 725 726 if (equal < 0) 727 return -1; 728 if (!equal) 729 isl_die(ctx, isl_error_unknown, 730 "unexpected result", return -1); 731 732 return 0; 733 } 734 735 #undef BASE 736 #define BASE multi_val 737 #include "isl_test_plain_equal_templ.c" 738 739 #undef BASE 740 #define BASE multi_aff 741 #include "isl_test_plain_equal_templ.c" 742 743 /* Check that "val" is equal to the value described by "str". 744 * If "str" is "NaN", then check for a NaN value explicitly. 745 */ 746 static isl_stat val_check_equal(__isl_keep isl_val *val, const char *str) 747 { 748 isl_bool ok, is_nan; 749 isl_ctx *ctx; 750 isl_val *res; 751 752 if (!val) 753 return isl_stat_error; 754 755 ctx = isl_val_get_ctx(val); 756 res = isl_val_read_from_str(ctx, str); 757 is_nan = isl_val_is_nan(res); 758 if (is_nan < 0) 759 ok = isl_bool_error; 760 else if (is_nan) 761 ok = isl_val_is_nan(val); 762 else 763 ok = isl_val_eq(val, res); 764 isl_val_free(res); 765 if (ok < 0) 766 return isl_stat_error; 767 if (!ok) 768 isl_die(ctx, isl_error_unknown, 769 "unexpected result", return isl_stat_error); 770 return isl_stat_ok; 771 } 772 773 struct { 774 __isl_give isl_val *(*op)(__isl_take isl_val *v); 775 const char *arg; 776 const char *res; 777 } val_un_tests[] = { 778 { &isl_val_neg, "0", "0" }, 779 { &isl_val_abs, "0", "0" }, 780 { &isl_val_pow2, "0", "1" }, 781 { &isl_val_floor, "0", "0" }, 782 { &isl_val_ceil, "0", "0" }, 783 { &isl_val_neg, "1", "-1" }, 784 { &isl_val_neg, "-1", "1" }, 785 { &isl_val_neg, "1/2", "-1/2" }, 786 { &isl_val_neg, "-1/2", "1/2" }, 787 { &isl_val_neg, "infty", "-infty" }, 788 { &isl_val_neg, "-infty", "infty" }, 789 { &isl_val_neg, "NaN", "NaN" }, 790 { &isl_val_abs, "1", "1" }, 791 { &isl_val_abs, "-1", "1" }, 792 { &isl_val_abs, "1/2", "1/2" }, 793 { &isl_val_abs, "-1/2", "1/2" }, 794 { &isl_val_abs, "infty", "infty" }, 795 { &isl_val_abs, "-infty", "infty" }, 796 { &isl_val_abs, "NaN", "NaN" }, 797 { &isl_val_floor, "1", "1" }, 798 { &isl_val_floor, "-1", "-1" }, 799 { &isl_val_floor, "1/2", "0" }, 800 { &isl_val_floor, "-1/2", "-1" }, 801 { &isl_val_floor, "infty", "infty" }, 802 { &isl_val_floor, "-infty", "-infty" }, 803 { &isl_val_floor, "NaN", "NaN" }, 804 { &isl_val_ceil, "1", "1" }, 805 { &isl_val_ceil, "-1", "-1" }, 806 { &isl_val_ceil, "1/2", "1" }, 807 { &isl_val_ceil, "-1/2", "0" }, 808 { &isl_val_ceil, "infty", "infty" }, 809 { &isl_val_ceil, "-infty", "-infty" }, 810 { &isl_val_ceil, "NaN", "NaN" }, 811 { &isl_val_pow2, "-3", "1/8" }, 812 { &isl_val_pow2, "-1", "1/2" }, 813 { &isl_val_pow2, "1", "2" }, 814 { &isl_val_pow2, "2", "4" }, 815 { &isl_val_pow2, "3", "8" }, 816 { &isl_val_inv, "1", "1" }, 817 { &isl_val_inv, "2", "1/2" }, 818 { &isl_val_inv, "1/2", "2" }, 819 { &isl_val_inv, "-2", "-1/2" }, 820 { &isl_val_inv, "-1/2", "-2" }, 821 { &isl_val_inv, "0", "NaN" }, 822 { &isl_val_inv, "NaN", "NaN" }, 823 { &isl_val_inv, "infty", "0" }, 824 { &isl_val_inv, "-infty", "0" }, 825 }; 826 827 /* Perform some basic tests of unary operations on isl_val objects. 828 */ 829 static int test_un_val(isl_ctx *ctx) 830 { 831 int i; 832 isl_val *v; 833 __isl_give isl_val *(*fn)(__isl_take isl_val *v); 834 835 for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) { 836 isl_stat r; 837 838 v = isl_val_read_from_str(ctx, val_un_tests[i].arg); 839 fn = val_un_tests[i].op; 840 v = fn(v); 841 r = val_check_equal(v, val_un_tests[i].res); 842 isl_val_free(v); 843 if (r < 0) 844 return -1; 845 } 846 847 return 0; 848 } 849 850 struct { 851 __isl_give isl_val *(*fn)(__isl_take isl_val *v1, 852 __isl_take isl_val *v2); 853 } val_bin_op[] = { 854 ['+'] = { &isl_val_add }, 855 ['-'] = { &isl_val_sub }, 856 ['*'] = { &isl_val_mul }, 857 ['/'] = { &isl_val_div }, 858 ['g'] = { &isl_val_gcd }, 859 ['m'] = { &isl_val_min }, 860 ['M'] = { &isl_val_max }, 861 }; 862 863 struct { 864 const char *arg1; 865 unsigned char op; 866 const char *arg2; 867 const char *res; 868 } val_bin_tests[] = { 869 { "0", '+', "0", "0" }, 870 { "1", '+', "0", "1" }, 871 { "1", '+', "1", "2" }, 872 { "1", '-', "1", "0" }, 873 { "1", '*', "1", "1" }, 874 { "1", '/', "1", "1" }, 875 { "2", '*', "3", "6" }, 876 { "2", '*', "1/2", "1" }, 877 { "2", '*', "1/3", "2/3" }, 878 { "2/3", '*', "3/5", "2/5" }, 879 { "2/3", '*', "7/5", "14/15" }, 880 { "2", '/', "1/2", "4" }, 881 { "-2", '/', "-1/2", "4" }, 882 { "-2", '/', "1/2", "-4" }, 883 { "2", '/', "-1/2", "-4" }, 884 { "2", '/', "2", "1" }, 885 { "2", '/', "3", "2/3" }, 886 { "2/3", '/', "5/3", "2/5" }, 887 { "2/3", '/', "5/7", "14/15" }, 888 { "0", '/', "0", "NaN" }, 889 { "42", '/', "0", "NaN" }, 890 { "-42", '/', "0", "NaN" }, 891 { "infty", '/', "0", "NaN" }, 892 { "-infty", '/', "0", "NaN" }, 893 { "NaN", '/', "0", "NaN" }, 894 { "0", '/', "NaN", "NaN" }, 895 { "42", '/', "NaN", "NaN" }, 896 { "-42", '/', "NaN", "NaN" }, 897 { "infty", '/', "NaN", "NaN" }, 898 { "-infty", '/', "NaN", "NaN" }, 899 { "NaN", '/', "NaN", "NaN" }, 900 { "0", '/', "infty", "0" }, 901 { "42", '/', "infty", "0" }, 902 { "-42", '/', "infty", "0" }, 903 { "infty", '/', "infty", "NaN" }, 904 { "-infty", '/', "infty", "NaN" }, 905 { "NaN", '/', "infty", "NaN" }, 906 { "0", '/', "-infty", "0" }, 907 { "42", '/', "-infty", "0" }, 908 { "-42", '/', "-infty", "0" }, 909 { "infty", '/', "-infty", "NaN" }, 910 { "-infty", '/', "-infty", "NaN" }, 911 { "NaN", '/', "-infty", "NaN" }, 912 { "1", '-', "1/3", "2/3" }, 913 { "1/3", '+', "1/2", "5/6" }, 914 { "1/2", '+', "1/2", "1" }, 915 { "3/4", '-', "1/4", "1/2" }, 916 { "1/2", '-', "1/3", "1/6" }, 917 { "infty", '+', "42", "infty" }, 918 { "infty", '+', "infty", "infty" }, 919 { "42", '+', "infty", "infty" }, 920 { "infty", '-', "infty", "NaN" }, 921 { "infty", '*', "infty", "infty" }, 922 { "infty", '*', "-infty", "-infty" }, 923 { "-infty", '*', "infty", "-infty" }, 924 { "-infty", '*', "-infty", "infty" }, 925 { "0", '*', "infty", "NaN" }, 926 { "1", '*', "infty", "infty" }, 927 { "infty", '*', "0", "NaN" }, 928 { "infty", '*', "42", "infty" }, 929 { "42", '-', "infty", "-infty" }, 930 { "infty", '+', "-infty", "NaN" }, 931 { "4", 'g', "6", "2" }, 932 { "5", 'g', "6", "1" }, 933 { "42", 'm', "3", "3" }, 934 { "42", 'M', "3", "42" }, 935 { "3", 'm', "42", "3" }, 936 { "3", 'M', "42", "42" }, 937 { "42", 'm', "infty", "42" }, 938 { "42", 'M', "infty", "infty" }, 939 { "42", 'm', "-infty", "-infty" }, 940 { "42", 'M', "-infty", "42" }, 941 { "42", 'm', "NaN", "NaN" }, 942 { "42", 'M', "NaN", "NaN" }, 943 { "infty", 'm', "-infty", "-infty" }, 944 { "infty", 'M', "-infty", "infty" }, 945 }; 946 947 /* Perform some basic tests of binary operations on isl_val objects. 948 */ 949 static int test_bin_val(isl_ctx *ctx) 950 { 951 int i; 952 isl_val *v1, *v2, *res; 953 __isl_give isl_val *(*fn)(__isl_take isl_val *v1, 954 __isl_take isl_val *v2); 955 int ok; 956 957 for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) { 958 v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1); 959 v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2); 960 res = isl_val_read_from_str(ctx, val_bin_tests[i].res); 961 fn = val_bin_op[val_bin_tests[i].op].fn; 962 v1 = fn(v1, v2); 963 if (isl_val_is_nan(res)) 964 ok = isl_val_is_nan(v1); 965 else 966 ok = isl_val_eq(v1, res); 967 isl_val_free(v1); 968 isl_val_free(res); 969 if (ok < 0) 970 return -1; 971 if (!ok) 972 isl_die(ctx, isl_error_unknown, 973 "unexpected result", return -1); 974 } 975 976 return 0; 977 } 978 979 /* Perform some basic tests on isl_val objects. 980 */ 981 static int test_val(isl_ctx *ctx) 982 { 983 if (test_un_val(ctx) < 0) 984 return -1; 985 if (test_bin_val(ctx) < 0) 986 return -1; 987 return 0; 988 } 989 990 /* Sets described using existentially quantified variables that 991 * can also be described without. 992 */ 993 static const char *elimination_tests[] = { 994 "{ [i,j] : 2 * [i/2] + 3 * [j/4] <= 10 and 2 i = j }", 995 "{ [m, w] : exists a : w - 2m - 5 <= 3a <= m - 2w }", 996 "{ [m, w] : exists a : w >= 0 and a < m and -1 + w <= a <= 2m - w }", 997 }; 998 999 /* Check that redundant existentially quantified variables are 1000 * getting removed. 1001 */ 1002 static int test_elimination(isl_ctx *ctx) 1003 { 1004 int i; 1005 isl_size n; 1006 isl_basic_set *bset; 1007 1008 for (i = 0; i < ARRAY_SIZE(elimination_tests); ++i) { 1009 bset = isl_basic_set_read_from_str(ctx, elimination_tests[i]); 1010 n = isl_basic_set_dim(bset, isl_dim_div); 1011 isl_basic_set_free(bset); 1012 if (n < 0) 1013 return -1; 1014 if (n != 0) 1015 isl_die(ctx, isl_error_unknown, 1016 "expecting no existentials", return -1); 1017 } 1018 1019 return 0; 1020 } 1021 1022 static int test_div(isl_ctx *ctx) 1023 { 1024 const char *str; 1025 int empty; 1026 isl_space *space; 1027 isl_set *set; 1028 isl_local_space *ls; 1029 struct isl_basic_set *bset; 1030 struct isl_constraint *c; 1031 1032 /* test 1 */ 1033 space = isl_space_set_alloc(ctx, 0, 3); 1034 bset = isl_basic_set_universe(isl_space_copy(space)); 1035 ls = isl_local_space_from_space(space); 1036 1037 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1038 c = isl_constraint_set_constant_si(c, -1); 1039 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); 1040 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3); 1041 bset = isl_basic_set_add_constraint(bset, c); 1042 1043 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1044 c = isl_constraint_set_constant_si(c, 1); 1045 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1046 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3); 1047 bset = isl_basic_set_add_constraint(bset, c); 1048 1049 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2); 1050 1051 assert(bset && bset->n_div == 1); 1052 isl_local_space_free(ls); 1053 isl_basic_set_free(bset); 1054 1055 /* test 2 */ 1056 space = isl_space_set_alloc(ctx, 0, 3); 1057 bset = isl_basic_set_universe(isl_space_copy(space)); 1058 ls = isl_local_space_from_space(space); 1059 1060 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1061 c = isl_constraint_set_constant_si(c, 1); 1062 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1063 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3); 1064 bset = isl_basic_set_add_constraint(bset, c); 1065 1066 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1067 c = isl_constraint_set_constant_si(c, -1); 1068 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); 1069 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3); 1070 bset = isl_basic_set_add_constraint(bset, c); 1071 1072 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2); 1073 1074 assert(bset && bset->n_div == 1); 1075 isl_local_space_free(ls); 1076 isl_basic_set_free(bset); 1077 1078 /* test 3 */ 1079 space = isl_space_set_alloc(ctx, 0, 3); 1080 bset = isl_basic_set_universe(isl_space_copy(space)); 1081 ls = isl_local_space_from_space(space); 1082 1083 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1084 c = isl_constraint_set_constant_si(c, 1); 1085 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1086 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3); 1087 bset = isl_basic_set_add_constraint(bset, c); 1088 1089 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1090 c = isl_constraint_set_constant_si(c, -3); 1091 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); 1092 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 4); 1093 bset = isl_basic_set_add_constraint(bset, c); 1094 1095 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2); 1096 1097 assert(bset && bset->n_div == 1); 1098 isl_local_space_free(ls); 1099 isl_basic_set_free(bset); 1100 1101 /* test 4 */ 1102 space = isl_space_set_alloc(ctx, 0, 3); 1103 bset = isl_basic_set_universe(isl_space_copy(space)); 1104 ls = isl_local_space_from_space(space); 1105 1106 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1107 c = isl_constraint_set_constant_si(c, 2); 1108 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1109 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3); 1110 bset = isl_basic_set_add_constraint(bset, c); 1111 1112 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1113 c = isl_constraint_set_constant_si(c, -1); 1114 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); 1115 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6); 1116 bset = isl_basic_set_add_constraint(bset, c); 1117 1118 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2); 1119 1120 assert(isl_basic_set_is_empty(bset)); 1121 isl_local_space_free(ls); 1122 isl_basic_set_free(bset); 1123 1124 /* test 5 */ 1125 space = isl_space_set_alloc(ctx, 0, 3); 1126 bset = isl_basic_set_universe(isl_space_copy(space)); 1127 ls = isl_local_space_from_space(space); 1128 1129 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1130 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1131 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3); 1132 bset = isl_basic_set_add_constraint(bset, c); 1133 1134 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1135 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); 1136 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3); 1137 bset = isl_basic_set_add_constraint(bset, c); 1138 1139 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1); 1140 1141 assert(bset && bset->n_div == 0); 1142 isl_basic_set_free(bset); 1143 isl_local_space_free(ls); 1144 1145 /* test 6 */ 1146 space = isl_space_set_alloc(ctx, 0, 3); 1147 bset = isl_basic_set_universe(isl_space_copy(space)); 1148 ls = isl_local_space_from_space(space); 1149 1150 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1151 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1152 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6); 1153 bset = isl_basic_set_add_constraint(bset, c); 1154 1155 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1156 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); 1157 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3); 1158 bset = isl_basic_set_add_constraint(bset, c); 1159 1160 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1); 1161 1162 assert(bset && bset->n_div == 1); 1163 isl_basic_set_free(bset); 1164 isl_local_space_free(ls); 1165 1166 /* test 7 */ 1167 /* This test is a bit tricky. We set up an equality 1168 * a + 3b + 3c = 6 e0 1169 * Normalization of divs creates _two_ divs 1170 * a = 3 e0 1171 * c - b - e0 = 2 e1 1172 * Afterwards e0 is removed again because it has coefficient -1 1173 * and we end up with the original equality and div again. 1174 * Perhaps we can avoid the introduction of this temporary div. 1175 */ 1176 space = isl_space_set_alloc(ctx, 0, 4); 1177 bset = isl_basic_set_universe(isl_space_copy(space)); 1178 ls = isl_local_space_from_space(space); 1179 1180 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1181 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1182 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3); 1183 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -3); 1184 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 6); 1185 bset = isl_basic_set_add_constraint(bset, c); 1186 1187 bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1); 1188 1189 /* Test disabled for now */ 1190 /* 1191 assert(bset && bset->n_div == 1); 1192 */ 1193 isl_local_space_free(ls); 1194 isl_basic_set_free(bset); 1195 1196 /* test 8 */ 1197 space = isl_space_set_alloc(ctx, 0, 5); 1198 bset = isl_basic_set_universe(isl_space_copy(space)); 1199 ls = isl_local_space_from_space(space); 1200 1201 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1202 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1203 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3); 1204 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, -3); 1205 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 4, 6); 1206 bset = isl_basic_set_add_constraint(bset, c); 1207 1208 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1209 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1210 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 1); 1211 c = isl_constraint_set_constant_si(c, 1); 1212 bset = isl_basic_set_add_constraint(bset, c); 1213 1214 bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1); 1215 1216 /* Test disabled for now */ 1217 /* 1218 assert(bset && bset->n_div == 1); 1219 */ 1220 isl_local_space_free(ls); 1221 isl_basic_set_free(bset); 1222 1223 /* test 9 */ 1224 space = isl_space_set_alloc(ctx, 0, 4); 1225 bset = isl_basic_set_universe(isl_space_copy(space)); 1226 ls = isl_local_space_from_space(space); 1227 1228 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1229 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); 1230 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -1); 1231 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2); 1232 bset = isl_basic_set_add_constraint(bset, c); 1233 1234 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1235 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); 1236 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 3); 1237 c = isl_constraint_set_constant_si(c, 2); 1238 bset = isl_basic_set_add_constraint(bset, c); 1239 1240 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2); 1241 1242 bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2); 1243 1244 assert(!isl_basic_set_is_empty(bset)); 1245 1246 isl_local_space_free(ls); 1247 isl_basic_set_free(bset); 1248 1249 /* test 10 */ 1250 space = isl_space_set_alloc(ctx, 0, 3); 1251 bset = isl_basic_set_universe(isl_space_copy(space)); 1252 ls = isl_local_space_from_space(space); 1253 1254 c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); 1255 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); 1256 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2); 1257 bset = isl_basic_set_add_constraint(bset, c); 1258 1259 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1); 1260 1261 bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2); 1262 1263 isl_local_space_free(ls); 1264 isl_basic_set_free(bset); 1265 1266 str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and " 1267 "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }"; 1268 set = isl_set_read_from_str(ctx, str); 1269 set = isl_set_compute_divs(set); 1270 isl_set_free(set); 1271 if (!set) 1272 return -1; 1273 1274 if (test_elimination(ctx) < 0) 1275 return -1; 1276 1277 str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }"; 1278 set = isl_set_read_from_str(ctx, str); 1279 set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2); 1280 set = isl_set_fix_si(set, isl_dim_set, 2, -3); 1281 empty = isl_set_is_empty(set); 1282 isl_set_free(set); 1283 if (empty < 0) 1284 return -1; 1285 if (!empty) 1286 isl_die(ctx, isl_error_unknown, 1287 "result not as accurate as expected", return -1); 1288 1289 return 0; 1290 } 1291 1292 void test_application_case(struct isl_ctx *ctx, const char *name) 1293 { 1294 char *filename; 1295 FILE *input; 1296 struct isl_basic_set *bset1, *bset2; 1297 struct isl_basic_map *bmap; 1298 1299 filename = get_filename(ctx, name, "omega"); 1300 assert(filename); 1301 input = fopen(filename, "r"); 1302 assert(input); 1303 1304 bset1 = isl_basic_set_read_from_file(ctx, input); 1305 bmap = isl_basic_map_read_from_file(ctx, input); 1306 1307 bset1 = isl_basic_set_apply(bset1, bmap); 1308 1309 bset2 = isl_basic_set_read_from_file(ctx, input); 1310 1311 assert(isl_basic_set_is_equal(bset1, bset2) == 1); 1312 1313 isl_basic_set_free(bset1); 1314 isl_basic_set_free(bset2); 1315 free(filename); 1316 1317 fclose(input); 1318 } 1319 1320 static int test_application(isl_ctx *ctx) 1321 { 1322 test_application_case(ctx, "application"); 1323 test_application_case(ctx, "application2"); 1324 1325 return 0; 1326 } 1327 1328 void test_affine_hull_case(struct isl_ctx *ctx, const char *name) 1329 { 1330 char *filename; 1331 FILE *input; 1332 struct isl_basic_set *bset1, *bset2; 1333 1334 filename = get_filename(ctx, name, "polylib"); 1335 assert(filename); 1336 input = fopen(filename, "r"); 1337 assert(input); 1338 1339 bset1 = isl_basic_set_read_from_file(ctx, input); 1340 bset2 = isl_basic_set_read_from_file(ctx, input); 1341 1342 bset1 = isl_basic_set_affine_hull(bset1); 1343 1344 assert(isl_basic_set_is_equal(bset1, bset2) == 1); 1345 1346 isl_basic_set_free(bset1); 1347 isl_basic_set_free(bset2); 1348 free(filename); 1349 1350 fclose(input); 1351 } 1352 1353 /* Pairs of sets and the corresponding expected results of 1354 * isl_basic_set_recession_cone. 1355 */ 1356 struct { 1357 const char *set; 1358 const char *cone; 1359 } recession_cone_tests[] = { 1360 { "{ [i] : 0 <= i <= 10 }", "{ [0] }" }, 1361 { "{ [i] : 0 <= i }", "{ [i] : 0 <= i }" }, 1362 { "{ [i] : i <= 10 }", "{ [i] : i <= 0 }" }, 1363 { "{ [i] : false }", "{ [i] : false }" }, 1364 }; 1365 1366 /* Perform some basic isl_basic_set_recession_cone tests. 1367 */ 1368 static int test_recession_cone(struct isl_ctx *ctx) 1369 { 1370 int i; 1371 1372 for (i = 0; i < ARRAY_SIZE(recession_cone_tests); ++i) { 1373 const char *str; 1374 isl_basic_set *bset; 1375 isl_basic_set *cone, *expected; 1376 isl_bool equal; 1377 1378 str = recession_cone_tests[i].set; 1379 bset = isl_basic_set_read_from_str(ctx, str); 1380 str = recession_cone_tests[i].cone; 1381 expected = isl_basic_set_read_from_str(ctx, str); 1382 cone = isl_basic_set_recession_cone(bset); 1383 equal = isl_basic_set_is_equal(cone, expected); 1384 isl_basic_set_free(cone); 1385 isl_basic_set_free(expected); 1386 if (equal < 0) 1387 return -1; 1388 if (!equal) 1389 isl_die(ctx, isl_error_unknown, "unexpected cone", 1390 return -1); 1391 } 1392 1393 return 0; 1394 } 1395 1396 int test_affine_hull(struct isl_ctx *ctx) 1397 { 1398 const char *str; 1399 isl_set *set; 1400 isl_basic_set *bset, *bset2; 1401 isl_size n; 1402 isl_bool subset; 1403 1404 test_affine_hull_case(ctx, "affine2"); 1405 test_affine_hull_case(ctx, "affine"); 1406 test_affine_hull_case(ctx, "affine3"); 1407 1408 str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and " 1409 "m >= 3 and 4i0 <= 2 + m and e1 >= i0 and " 1410 "e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and " 1411 "2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }"; 1412 set = isl_set_read_from_str(ctx, str); 1413 bset = isl_set_affine_hull(set); 1414 n = isl_basic_set_dim(bset, isl_dim_div); 1415 isl_basic_set_free(bset); 1416 if (n < 0) 1417 return -1; 1418 if (n != 0) 1419 isl_die(ctx, isl_error_unknown, "not expecting any divs", 1420 return -1); 1421 1422 /* Check that isl_map_affine_hull is not confused by 1423 * the reordering of divs in isl_map_align_divs. 1424 */ 1425 str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: " 1426 "32e0 = b and 32e1 = c); " 1427 "[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }"; 1428 set = isl_set_read_from_str(ctx, str); 1429 bset = isl_set_affine_hull(set); 1430 isl_basic_set_free(bset); 1431 if (!bset) 1432 return -1; 1433 1434 str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and " 1435 "32e2 = 31 + 31e0 }"; 1436 set = isl_set_read_from_str(ctx, str); 1437 bset = isl_set_affine_hull(set); 1438 str = "{ [a] : exists e : a = 32 e }"; 1439 bset2 = isl_basic_set_read_from_str(ctx, str); 1440 subset = isl_basic_set_is_subset(bset, bset2); 1441 isl_basic_set_free(bset); 1442 isl_basic_set_free(bset2); 1443 if (subset < 0) 1444 return -1; 1445 if (!subset) 1446 isl_die(ctx, isl_error_unknown, "not as accurate as expected", 1447 return -1); 1448 1449 return 0; 1450 } 1451 1452 /* Test a special case of isl_set_plain_unshifted_simple_hull 1453 * where older versions of isl would include a redundant constraint 1454 * in the result. 1455 * Check that the result does not have any constraints. 1456 */ 1457 static isl_stat test_plain_unshifted_simple_hull_special(isl_ctx *ctx) 1458 { 1459 const char *str; 1460 isl_bool is_universe; 1461 isl_set *set; 1462 isl_basic_set *bset; 1463 1464 str = "{[x, y] : x = 0 or 2*((x+y)//2) <= y + 2 }"; 1465 set = isl_set_read_from_str(ctx, str); 1466 bset = isl_set_plain_unshifted_simple_hull(set); 1467 is_universe = isl_basic_set_plain_is_universe(bset); 1468 isl_basic_set_free(bset); 1469 1470 if (is_universe < 0) 1471 return isl_stat_error; 1472 if (!is_universe) 1473 isl_die(ctx, isl_error_unknown, 1474 "hull should not have any constraints", 1475 return isl_stat_error); 1476 1477 return isl_stat_ok; 1478 } 1479 1480 /* Inputs for simple hull tests, consisting of 1481 * the specific simple hull function, the input set and the expected result. 1482 */ 1483 struct { 1484 __isl_give isl_basic_set *(*fn)(__isl_take isl_set *set); 1485 const char *set; 1486 const char *hull; 1487 } simple_hull_tests[] = { 1488 { &isl_set_plain_unshifted_simple_hull, 1489 "{ [i,j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }", 1490 "{ [i,j] : i >= 1 }" }, 1491 { &isl_set_plain_unshifted_simple_hull, 1492 "{ [n,i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or " 1493 "(j mod 4 = 2 and k mod 6 = n) }", 1494 "{ [n,i,j,k] : j mod 4 = 2 }" }, 1495 { &isl_set_unshifted_simple_hull, 1496 "{ [0,x,y] : x <= -1; [1,x,y] : x <= y <= -x; [2,x,y] : x <= 1 }", 1497 "{ [t,x,y] : 0 <= t <= 2 and x <= 1 }" }, 1498 { &isl_set_simple_hull, 1499 "{ [a, b] : b <= 0 and " 1500 "2*floor((-2*floor((b)/2))/5) >= a - floor((b)/2); " 1501 "[a, b] : a mod 2 = 0 }", 1502 "{ [a, b] }" }, 1503 }; 1504 1505 /* Basic tests for various simple hull functions. 1506 */ 1507 static int test_various_simple_hull(isl_ctx *ctx) 1508 { 1509 int i; 1510 isl_set *set; 1511 isl_basic_set *hull, *expected; 1512 isl_bool equal; 1513 1514 for (i = 0; i < ARRAY_SIZE(simple_hull_tests); ++i) { 1515 const char *str; 1516 str = simple_hull_tests[i].set; 1517 set = isl_set_read_from_str(ctx, str); 1518 str = simple_hull_tests[i].hull; 1519 expected = isl_basic_set_read_from_str(ctx, str); 1520 hull = simple_hull_tests[i].fn(set); 1521 equal = isl_basic_set_is_equal(hull, expected); 1522 isl_basic_set_free(hull); 1523 isl_basic_set_free(expected); 1524 if (equal < 0) 1525 return -1; 1526 if (!equal) 1527 isl_die(ctx, isl_error_unknown, "unexpected hull", 1528 return -1); 1529 } 1530 1531 return 0; 1532 } 1533 1534 static int test_simple_hull(struct isl_ctx *ctx) 1535 { 1536 const char *str; 1537 isl_set *set; 1538 isl_basic_set *bset; 1539 isl_bool is_empty; 1540 1541 str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;" 1542 "[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }"; 1543 set = isl_set_read_from_str(ctx, str); 1544 bset = isl_set_simple_hull(set); 1545 is_empty = isl_basic_set_is_empty(bset); 1546 isl_basic_set_free(bset); 1547 1548 if (is_empty == isl_bool_error) 1549 return -1; 1550 1551 if (is_empty == isl_bool_false) 1552 isl_die(ctx, isl_error_unknown, "Empty set should be detected", 1553 return -1); 1554 1555 if (test_plain_unshifted_simple_hull_special(ctx) < 0) 1556 return -1; 1557 if (test_various_simple_hull(ctx) < 0) 1558 return -1; 1559 1560 return 0; 1561 } 1562 1563 /* Inputs for isl_set_get_simple_fixed_box_hull tests. 1564 * "set" is the input set. 1565 * "offset" is the expected box offset. 1566 * "size" is the expected box size. 1567 */ 1568 static struct { 1569 const char *set; 1570 const char *offset; 1571 const char *size; 1572 } box_hull_tests[] = { 1573 { "{ S[x, y] : 0 <= x, y < 10 }", "{ S[0, 0] }", "{ S[10, 10] }" }, 1574 { "[N] -> { S[x, y] : N <= x, y < N + 10 }", 1575 "[N] -> { S[N, N] }", "{ S[10, 10] }" }, 1576 { "{ S[x, y] : 0 <= x + y, x - y < 10 }", 1577 "{ S[0, -4] }", "{ S[10, 9] }" }, 1578 { "{ [i=0:10] : exists (e0, e1: 3e1 >= 1 + 2e0 and " 1579 "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }", 1580 "{ [3] }", "{ [8] }" }, 1581 { "[N] -> { [w = 0:17] : exists (e0: w < 2N and " 1582 "-1 + w <= e0 <= w and 2e0 >= N + w and w <= 2e0 <= 15 + w) }", 1583 "[N] -> { [N] }", "{ [9] }" }, 1584 }; 1585 1586 /* Perform basic isl_set_get_simple_fixed_box_hull tests. 1587 */ 1588 static int test_box_hull(struct isl_ctx *ctx) 1589 { 1590 int i; 1591 1592 for (i = 0; i < ARRAY_SIZE(box_hull_tests); ++i) { 1593 const char *str; 1594 isl_stat r; 1595 isl_set *set; 1596 isl_multi_aff *offset; 1597 isl_multi_val *size; 1598 isl_fixed_box *box; 1599 1600 set = isl_set_read_from_str(ctx, box_hull_tests[i].set); 1601 box = isl_set_get_simple_fixed_box_hull(set); 1602 offset = isl_fixed_box_get_offset(box); 1603 size = isl_fixed_box_get_size(box); 1604 str = box_hull_tests[i].offset; 1605 r = multi_aff_check_plain_equal(offset, str); 1606 str = box_hull_tests[i].size; 1607 if (r >= 0) 1608 r = multi_val_check_plain_equal(size, str); 1609 isl_multi_aff_free(offset); 1610 isl_multi_val_free(size); 1611 isl_fixed_box_free(box); 1612 isl_set_free(set); 1613 if (r < 0) 1614 return -1; 1615 } 1616 1617 return 0; 1618 } 1619 1620 void test_convex_hull_case(struct isl_ctx *ctx, const char *name) 1621 { 1622 char *filename; 1623 FILE *input; 1624 struct isl_basic_set *bset1, *bset2; 1625 struct isl_set *set; 1626 1627 filename = get_filename(ctx, name, "polylib"); 1628 assert(filename); 1629 input = fopen(filename, "r"); 1630 assert(input); 1631 1632 bset1 = isl_basic_set_read_from_file(ctx, input); 1633 bset2 = isl_basic_set_read_from_file(ctx, input); 1634 1635 set = isl_basic_set_union(bset1, bset2); 1636 bset1 = isl_set_convex_hull(set); 1637 1638 bset2 = isl_basic_set_read_from_file(ctx, input); 1639 1640 assert(isl_basic_set_is_equal(bset1, bset2) == 1); 1641 1642 isl_basic_set_free(bset1); 1643 isl_basic_set_free(bset2); 1644 free(filename); 1645 1646 fclose(input); 1647 } 1648 1649 struct { 1650 const char *set; 1651 const char *hull; 1652 } convex_hull_tests[] = { 1653 { "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or " 1654 "(i0 = 1 and i1 = 0 and i2 = 1) or " 1655 "(i0 = 0 and i1 = 0 and i2 = 0) }", 1656 "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" }, 1657 { "[n] -> { [i0, i1, i0] : i0 <= -4 + n; " 1658 "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and " 1659 "i2 <= 5 and i2 >= 4; " 1660 "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }", 1661 "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and " 1662 "i2 <= 5 + i0 and i2 >= i0 }" }, 1663 { "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }", 1664 "{ [x, y] : 1 = 0 }" }, 1665 { "{ [x, y, z] : 0 <= x, y, z <= 10; [x, y, 0] : x >= 0 and y > 0; " 1666 "[x, y, 0] : x >= 0 and y < 0 }", 1667 "{ [x, y, z] : x >= 0 and 0 <= z <= 10 }" }, 1668 { "{ [a, b, c] : a <= 1 and -a < b <= 1 and 0 <= c <= 2 - a - b and " 1669 "c <= a; " 1670 "[0, 2, 0]; [3, 1, 0] }", 1671 "{ [a, b, c] : b > -a and 2b >= -1 + a and 0 <= c <= a and " 1672 "5c <= 6 - a - 3b }" }, 1673 }; 1674 1675 static int test_convex_hull_algo(isl_ctx *ctx, int convex) 1676 { 1677 int i; 1678 int orig_convex = ctx->opt->convex; 1679 ctx->opt->convex = convex; 1680 1681 test_convex_hull_case(ctx, "convex0"); 1682 test_convex_hull_case(ctx, "convex1"); 1683 test_convex_hull_case(ctx, "convex2"); 1684 test_convex_hull_case(ctx, "convex3"); 1685 test_convex_hull_case(ctx, "convex4"); 1686 test_convex_hull_case(ctx, "convex5"); 1687 test_convex_hull_case(ctx, "convex6"); 1688 test_convex_hull_case(ctx, "convex7"); 1689 test_convex_hull_case(ctx, "convex8"); 1690 test_convex_hull_case(ctx, "convex9"); 1691 test_convex_hull_case(ctx, "convex10"); 1692 test_convex_hull_case(ctx, "convex11"); 1693 test_convex_hull_case(ctx, "convex12"); 1694 test_convex_hull_case(ctx, "convex13"); 1695 test_convex_hull_case(ctx, "convex14"); 1696 test_convex_hull_case(ctx, "convex15"); 1697 1698 for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) { 1699 isl_set *set1, *set2; 1700 int equal; 1701 1702 set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set); 1703 set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull); 1704 set1 = isl_set_from_basic_set(isl_set_convex_hull(set1)); 1705 equal = isl_set_is_equal(set1, set2); 1706 isl_set_free(set1); 1707 isl_set_free(set2); 1708 1709 if (equal < 0) 1710 return -1; 1711 if (!equal) 1712 isl_die(ctx, isl_error_unknown, 1713 "unexpected convex hull", return -1); 1714 } 1715 1716 ctx->opt->convex = orig_convex; 1717 1718 return 0; 1719 } 1720 1721 static int test_convex_hull(isl_ctx *ctx) 1722 { 1723 if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM) < 0) 1724 return -1; 1725 if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP) < 0) 1726 return -1; 1727 return 0; 1728 } 1729 1730 /* Check that computing the gist of "map" with respect to "context" 1731 * does not make any copy of "map" get marked empty. 1732 * Earlier versions of isl would end up doing that. 1733 */ 1734 static isl_stat test_gist_empty_pair(isl_ctx *ctx, const char *map, 1735 const char *context) 1736 { 1737 isl_map *m1, *m2, *m3; 1738 isl_bool empty_before, empty_after; 1739 1740 m1 = isl_map_read_from_str(ctx, map); 1741 m2 = isl_map_read_from_str(ctx, context); 1742 m3 = isl_map_copy(m1); 1743 empty_before = isl_map_is_empty(m3); 1744 m1 = isl_map_gist(m1, m2); 1745 empty_after = isl_map_is_empty(m3); 1746 isl_map_free(m1); 1747 isl_map_free(m3); 1748 1749 if (empty_before < 0 || empty_after < 0) 1750 return isl_stat_error; 1751 if (empty_before) 1752 isl_die(ctx, isl_error_unknown, "map should not be empty", 1753 return isl_stat_error); 1754 if (empty_after) 1755 isl_die(ctx, isl_error_unknown, "map should still not be empty", 1756 return isl_stat_error); 1757 1758 return isl_stat_ok; 1759 } 1760 1761 /* Check that computing a gist does not make any copy of the input 1762 * get marked empty. 1763 * Earlier versions of isl would end up doing that on some pairs of inputs. 1764 */ 1765 static isl_stat test_gist_empty(isl_ctx *ctx) 1766 { 1767 const char *map, *context; 1768 1769 map = "{ [] -> [a, b, c] : 2b = 1 + a }"; 1770 context = "{ [] -> [a, b, c] : 2c = 2 + a }"; 1771 if (test_gist_empty_pair(ctx, map, context) < 0) 1772 return isl_stat_error; 1773 map = "{ [] -> [0, 0] }"; 1774 context = "{ [] -> [a, b] : a > b }"; 1775 if (test_gist_empty_pair(ctx, map, context) < 0) 1776 return isl_stat_error; 1777 1778 return isl_stat_ok; 1779 } 1780 1781 /* Inputs to isl_map_plain_gist_basic_map, along with the expected output. 1782 */ 1783 struct { 1784 const char *map; 1785 const char *context; 1786 const char *gist; 1787 } plain_gist_tests[] = { 1788 { "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }", 1789 "{ [i] -> [j] : i >= 1 }", 1790 "{ [i] -> [j] : j >= 1 or i >= 2 and j <= 10 }" }, 1791 { "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or " 1792 "(j mod 4 = 2 and k mod 6 = n) }", 1793 "{ [n] -> [i,j,k] : j mod 4 = 2 }", 1794 "{ [n] -> [i,j,k] : (i mod 3 = 2) or (k mod 6 = n) }" }, 1795 { "{ [i] -> [j] : i > j and (exists a,b : i <= 2a + 5b <= 2) }", 1796 "{ [i] -> [j] : i > j }", 1797 "{ [i] -> [j] : exists a,b : i <= 2a + 5b <= 2 }" }, 1798 }; 1799 1800 /* Basic tests for isl_map_plain_gist_basic_map. 1801 */ 1802 static int test_plain_gist(isl_ctx *ctx) 1803 { 1804 int i; 1805 1806 for (i = 0; i < ARRAY_SIZE(plain_gist_tests); ++i) { 1807 const char *str; 1808 int equal; 1809 isl_map *map, *gist; 1810 isl_basic_map *context; 1811 1812 map = isl_map_read_from_str(ctx, plain_gist_tests[i].map); 1813 str = plain_gist_tests[i].context; 1814 context = isl_basic_map_read_from_str(ctx, str); 1815 map = isl_map_plain_gist_basic_map(map, context); 1816 gist = isl_map_read_from_str(ctx, plain_gist_tests[i].gist); 1817 equal = isl_map_is_equal(map, gist); 1818 isl_map_free(map); 1819 isl_map_free(gist); 1820 if (equal < 0) 1821 return -1; 1822 if (!equal) 1823 isl_die(ctx, isl_error_unknown, 1824 "incorrect gist result", return -1); 1825 } 1826 1827 return 0; 1828 } 1829 1830 /* Inputs for isl_basic_set_gist tests that are expected to fail. 1831 */ 1832 struct { 1833 const char *set; 1834 const char *context; 1835 } gist_fail_tests[] = { 1836 { "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and " 1837 "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }", 1838 "{ [i] : i >= 0 }" }, 1839 }; 1840 1841 /* Check that isl_basic_set_gist fails (gracefully) when expected. 1842 * In particular, the user should be able to recover from the failure. 1843 */ 1844 static isl_stat test_gist_fail(struct isl_ctx *ctx) 1845 { 1846 int i, n; 1847 int on_error; 1848 1849 on_error = isl_options_get_on_error(ctx); 1850 isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE); 1851 n = ARRAY_SIZE(gist_fail_tests); 1852 for (i = 0; i < n; ++i) { 1853 const char *str; 1854 isl_basic_set *bset, *context; 1855 1856 bset = isl_basic_set_read_from_str(ctx, gist_fail_tests[i].set); 1857 str = gist_fail_tests[i].context; 1858 context = isl_basic_set_read_from_str(ctx, str); 1859 bset = isl_basic_set_gist(bset, context); 1860 isl_basic_set_free(bset); 1861 if (bset) 1862 break; 1863 } 1864 isl_options_set_on_error(ctx, on_error); 1865 if (i < n) 1866 isl_die(ctx, isl_error_unknown, 1867 "operation not expected to succeed", 1868 return isl_stat_error); 1869 1870 return isl_stat_ok; 1871 } 1872 1873 struct { 1874 const char *set; 1875 const char *context; 1876 const char *gist; 1877 } gist_tests[] = { 1878 { "{ [1, -1, 3] }", 1879 "{ [1, b, 2 - b] : -1 <= b <= 2 }", 1880 "{ [a, -1, c] }" }, 1881 { "{ [a, b, c] : a <= 15 and a >= 1 }", 1882 "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and " 1883 "c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }", 1884 "{ [a, b, c] : a <= 15 }" }, 1885 { "{ : }", "{ : 1 = 0 }", "{ : }" }, 1886 { "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" }, 1887 { "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }", 1888 "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" }, 1889 { "{ [m, n, a, b] : a <= 2147 + n }", 1890 "{ [m, n, a, b] : (m >= 1 and n >= 1 and a <= 2148 - m and " 1891 "b <= 2148 - n and b >= 0 and b >= 2149 - n - a) or " 1892 "(n >= 1 and a >= 0 and b <= 2148 - n - a and " 1893 "b >= 0) }", 1894 "{ [m, n, ku, kl] }" }, 1895 { "{ [a, a, b] : a >= 10 }", 1896 "{ [a, b, c] : c >= a and c <= b and c >= 2 }", 1897 "{ [a, a, b] : a >= 10 }" }, 1898 { "{ [i, j] : i >= 0 and i + j >= 0 }", "{ [i, j] : i <= 0 }", 1899 "{ [0, j] : j >= 0 }" }, 1900 /* Check that no constraints on i6 are introduced in the gist */ 1901 { "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): " 1902 "20e0 <= 1530 - 4t1 - 5i4 and 20e0 >= 1511 - 4t1 - 5i4 and " 1903 "5e0 <= 381 - t1 and i4 <= 1) }", 1904 "[t1] -> { [i4, i6] : exists (e0 = floor((-t1 + i6)/5): " 1905 "5e0 = -t1 + i6 and i6 <= 6 and i6 >= 3) }", 1906 "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): " 1907 "i4 <= 1 and 5e0 <= 381 - t1 and 20e0 <= 1530 - 4t1 - 5i4 and " 1908 "20e0 >= 1511 - 4t1 - 5i4) }" }, 1909 /* Check that no constraints on i6 are introduced in the gist */ 1910 { "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((1 + i4)/2), " 1911 "e1 = floor((1530 - 4t1 - 5i4)/20), " 1912 "e2 = floor((-4t1 - 5i4 + 10*floor((1 + i4)/2))/20), " 1913 "e3 = floor((-1 + i4)/2): t2 = 0 and 2e3 = -1 + i4 and " 1914 "20e2 >= -19 - 4t1 - 5i4 + 10e0 and 5e2 <= 1 - t1 and " 1915 "2e0 <= 1 + i4 and 2e0 >= i4 and " 1916 "20e1 <= 1530 - 4t1 - 5i4 and " 1917 "20e1 >= 1511 - 4t1 - 5i4 and i4 <= 1 and " 1918 "5e1 <= 381 - t1 and 20e2 <= -4t1 - 5i4 + 10e0) }", 1919 "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((-17 + i4)/2), " 1920 "e1 = floor((-t1 + i6)/5): 5e1 = -t1 + i6 and " 1921 "2e0 <= -17 + i4 and 2e0 >= -18 + i4 and " 1922 "10e0 <= -91 + 5i4 + 4i6 and " 1923 "10e0 >= -105 + 5i4 + 4i6) }", 1924 "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((381 - t1)/5), " 1925 "e1 = floor((-1 + i4)/2): t2 = 0 and 2e1 = -1 + i4 and " 1926 "i4 <= 1 and 5e0 <= 381 - t1 and 20e0 >= 1511 - 4t1 - 5i4) }" }, 1927 { "{ [0, 0, q, p] : -5 <= q <= 5 and p >= 0 }", 1928 "{ [a, b, q, p] : b >= 1 + a }", 1929 "{ [a, b, q, p] : false }" }, 1930 { "[n] -> { [x] : x = n && x mod 32 = 0 }", 1931 "[n] -> { [x] : x mod 32 = 0 }", 1932 "[n] -> { [x = n] }" }, 1933 { "{ [x] : x mod 6 = 0 }", "{ [x] : x mod 3 = 0 }", 1934 "{ [x] : x mod 2 = 0 }" }, 1935 { "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10000 = 0 }", 1936 "{ [x] : x mod 128 = 0 }" }, 1937 { "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10 = 0 }", 1938 "{ [x] : x mod 3200 = 0 }" }, 1939 { "{ [a, b, c] : a mod 2 = 0 and a = c }", 1940 "{ [a, b, c] : b mod 2 = 0 and b = c }", 1941 "{ [a, b, c = a] }" }, 1942 { "{ [a, b, c] : a mod 6 = 0 and a = c }", 1943 "{ [a, b, c] : b mod 2 = 0 and b = c }", 1944 "{ [a, b, c = a] : a mod 3 = 0 }" }, 1945 { "{ [x] : 0 <= x <= 4 or 6 <= x <= 9 }", 1946 "{ [x] : 1 <= x <= 3 or 7 <= x <= 8 }", 1947 "{ [x] }" }, 1948 { "{ [x,y] : x < 0 and 0 <= y <= 4 or x >= -2 and -x <= y <= 10 + x }", 1949 "{ [x,y] : 1 <= y <= 3 }", 1950 "{ [x,y] }" }, 1951 }; 1952 1953 /* Check that isl_set_gist behaves as expected. 1954 * 1955 * For the test cases in gist_tests, besides checking that the result 1956 * is as expected, also check that applying the gist operation does 1957 * not modify the input set (an earlier version of isl would do that) and 1958 * that the test case is consistent, i.e., that the gist has the same 1959 * intersection with the context as the input set. 1960 */ 1961 static int test_gist(struct isl_ctx *ctx) 1962 { 1963 int i; 1964 const char *str; 1965 isl_basic_set *bset1, *bset2; 1966 isl_map *map1, *map2; 1967 isl_bool equal; 1968 isl_size n_div; 1969 1970 for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) { 1971 isl_bool equal_input, equal_intersection; 1972 isl_set *set1, *set2, *copy, *context; 1973 1974 set1 = isl_set_read_from_str(ctx, gist_tests[i].set); 1975 context = isl_set_read_from_str(ctx, gist_tests[i].context); 1976 copy = isl_set_copy(set1); 1977 set1 = isl_set_gist(set1, isl_set_copy(context)); 1978 set2 = isl_set_read_from_str(ctx, gist_tests[i].gist); 1979 equal = isl_set_is_equal(set1, set2); 1980 isl_set_free(set1); 1981 set1 = isl_set_read_from_str(ctx, gist_tests[i].set); 1982 equal_input = isl_set_is_equal(set1, copy); 1983 isl_set_free(copy); 1984 set1 = isl_set_intersect(set1, isl_set_copy(context)); 1985 set2 = isl_set_intersect(set2, context); 1986 equal_intersection = isl_set_is_equal(set1, set2); 1987 isl_set_free(set2); 1988 isl_set_free(set1); 1989 if (equal < 0 || equal_input < 0 || equal_intersection < 0) 1990 return -1; 1991 if (!equal) 1992 isl_die(ctx, isl_error_unknown, 1993 "incorrect gist result", return -1); 1994 if (!equal_input) 1995 isl_die(ctx, isl_error_unknown, 1996 "gist modified input", return -1); 1997 if (!equal_input) 1998 isl_die(ctx, isl_error_unknown, 1999 "inconsistent gist test case", return -1); 2000 } 2001 2002 if (test_gist_fail(ctx) < 0) 2003 return -1; 2004 2005 str = "[p0, p2, p3, p5, p6, p10] -> { [] : " 2006 "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], " 2007 "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], " 2008 "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and " 2009 "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and " 2010 "16e0 >= 16 + 16p6 + 15p10 and p2 <= 15 and p3 >= 0 and " 2011 "p3 <= 31 and p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and " 2012 "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and " 2013 "p10 <= 15 and p10 <= -1 + p0 - p6) }"; 2014 bset1 = isl_basic_set_read_from_str(ctx, str); 2015 str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], " 2016 "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], " 2017 "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and " 2018 "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and " 2019 "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and " 2020 "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and " 2021 "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and " 2022 "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }"; 2023 bset2 = isl_basic_set_read_from_str(ctx, str); 2024 bset1 = isl_basic_set_gist(bset1, bset2); 2025 assert(bset1 && bset1->n_div == 0); 2026 isl_basic_set_free(bset1); 2027 2028 /* Check that the integer divisions of the second disjunct 2029 * do not spread to the first disjunct. 2030 */ 2031 str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: " 2032 "16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or " 2033 "(exists (e0 = [(-1 + t1)/16], " 2034 "e1 = [(-16 + t1 - 16e0)/4294967296]: " 2035 "4294967296e1 = -16 + t1 - o0 - 16e0 and " 2036 "16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and " 2037 "o0 <= 4294967295 and t1 <= -1)) }"; 2038 map1 = isl_map_read_from_str(ctx, str); 2039 str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }"; 2040 map2 = isl_map_read_from_str(ctx, str); 2041 map1 = isl_map_gist(map1, map2); 2042 if (!map1) 2043 return -1; 2044 if (map1->n != 1) 2045 isl_die(ctx, isl_error_unknown, "expecting single disjunct", 2046 isl_map_free(map1); return -1); 2047 n_div = isl_basic_map_dim(map1->p[0], isl_dim_div); 2048 isl_map_free(map1); 2049 if (n_div < 0) 2050 return -1; 2051 if (n_div != 1) 2052 isl_die(ctx, isl_error_unknown, "expecting single div", 2053 return -1); 2054 2055 if (test_gist_empty(ctx) < 0) 2056 return -1; 2057 if (test_plain_gist(ctx) < 0) 2058 return -1; 2059 2060 return 0; 2061 } 2062 2063 int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one) 2064 { 2065 isl_set *set, *set2; 2066 int equal; 2067 int one; 2068 2069 set = isl_set_read_from_str(ctx, str); 2070 set = isl_set_coalesce(set); 2071 set2 = isl_set_read_from_str(ctx, str); 2072 equal = isl_set_is_equal(set, set2); 2073 one = set && set->n == 1; 2074 isl_set_free(set); 2075 isl_set_free(set2); 2076 2077 if (equal < 0) 2078 return -1; 2079 if (!equal) 2080 isl_die(ctx, isl_error_unknown, 2081 "coalesced set not equal to input", return -1); 2082 if (check_one && !one) 2083 isl_die(ctx, isl_error_unknown, 2084 "coalesced set should not be a union", return -1); 2085 2086 return 0; 2087 } 2088 2089 /* Inputs for coalescing tests with unbounded wrapping. 2090 * "str" is a string representation of the input set. 2091 * "single_disjunct" is set if we expect the result to consist of 2092 * a single disjunct. 2093 */ 2094 struct { 2095 int single_disjunct; 2096 const char *str; 2097 } coalesce_unbounded_tests[] = { 2098 { 1, "{ [x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and " 2099 "-x - y + 1 >= 0 and -3 <= z <= 3;" 2100 "[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and " 2101 "x-z + 20 >= 0 and x+z + 20 >= 0 and " 2102 "-10 <= y <= 0}" }, 2103 { 1, "{ [x,y] : 0 <= x,y <= 10; [5,y]: 4 <= y <= 11 }" }, 2104 { 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" }, 2105 { 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" }, 2106 { 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" }, 2107 { 0, "{ [x, y, z] : 0 <= x,y,z <= 100 and 0 < z <= 2 + 2x + 2y; " 2108 "[x, y, 0] : x,y <= 100 and y <= 9 + 11x and x <= 9 + 11y }" }, 2109 { 1, "{ [0:1, 0:1]; [0, 2:3] }" }, 2110 { 1, "{ [0:1, 0:1]; [0, 2:3]; [1, -2:-1] }" }, 2111 { 1, "{ [0:3, 0:1]; [1:2, 2:5] }" }, 2112 { 1, "{ [0:3, 0:1]; [0:2, 2:5] }" }, 2113 { 1, "{ [0:3, 0:1]; [1:3, 2:5] }" }, 2114 { 0, "{ [0:3, 0:1]; [1:4, 2:5] }" }, 2115 { 0, "{ [0:3, 0:1]; [1:5, 2:5] }" }, 2116 }; 2117 2118 /* Test the functionality of isl_set_coalesce with the bounded wrapping 2119 * option turned off. 2120 */ 2121 int test_coalesce_unbounded_wrapping(isl_ctx *ctx) 2122 { 2123 int i; 2124 int r = 0; 2125 int bounded; 2126 2127 bounded = isl_options_get_coalesce_bounded_wrapping(ctx); 2128 isl_options_set_coalesce_bounded_wrapping(ctx, 0); 2129 2130 for (i = 0; i < ARRAY_SIZE(coalesce_unbounded_tests); ++i) { 2131 const char *str = coalesce_unbounded_tests[i].str; 2132 int check_one = coalesce_unbounded_tests[i].single_disjunct; 2133 if (test_coalesce_set(ctx, str, check_one) >= 0) 2134 continue; 2135 r = -1; 2136 break; 2137 } 2138 2139 isl_options_set_coalesce_bounded_wrapping(ctx, bounded); 2140 2141 return r; 2142 } 2143 2144 /* Inputs for coalescing tests. 2145 * "str" is a string representation of the input set. 2146 * "single_disjunct" is set if we expect the result to consist of 2147 * a single disjunct. 2148 */ 2149 struct { 2150 int single_disjunct; 2151 const char *str; 2152 } coalesce_tests[] = { 2153 { 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or " 2154 "y >= x & x >= 2 & 5 >= y }" }, 2155 { 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or " 2156 "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" }, 2157 { 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or " 2158 "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" }, 2159 { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or " 2160 "y >= 0 & x >= 6 & x <= 10 & y <= x}" }, 2161 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or " 2162 "y >= 0 & x >= 7 & x <= 10 & y <= x}" }, 2163 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or " 2164 "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" }, 2165 { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" }, 2166 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" }, 2167 { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" }, 2168 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" }, 2169 { 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" }, 2170 { 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" }, 2171 { 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" }, 2172 { 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], " 2173 "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], " 2174 "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and " 2175 "4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and " 2176 "o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and " 2177 "i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and " 2178 "4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and " 2179 "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);" 2180 "[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], " 2181 "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], " 2182 "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and " 2183 "4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and " 2184 "2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and " 2185 "2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and " 2186 "i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and " 2187 "4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and " 2188 "o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and " 2189 "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" }, 2190 { 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and " 2191 "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or " 2192 "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and " 2193 "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" }, 2194 { 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> " 2195 "[o0, o1, o2, o3, o4, o5, o6]] : " 2196 "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and " 2197 "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and " 2198 "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and " 2199 "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 " 2200 "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and " 2201 "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 " 2202 "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and " 2203 "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 " 2204 "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or " 2205 "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and " 2206 "o6 >= i3 + i6 - o3 and M >= 0 and " 2207 "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and " 2208 "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" }, 2209 { 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or " 2210 "(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or " 2211 "(o0 = 0 and M >= 2 and N >= 3) or " 2212 "(M = 0 and o0 = 0 and N >= 3) }" }, 2213 { 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and " 2214 "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or " 2215 "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and " 2216 "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" }, 2217 { 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" }, 2218 { 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" }, 2219 { 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or " 2220 "(y = 3 and x = 1) }" }, 2221 { 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and " 2222 "i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and " 2223 "i1 <= M and i3 <= M and i4 <= M) or " 2224 "(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and " 2225 "i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and " 2226 "i4 <= -1 + M) }" }, 2227 { 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or " 2228 "(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" }, 2229 { 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" }, 2230 { 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" }, 2231 { 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" }, 2232 { 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" }, 2233 { 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" }, 2234 { 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" }, 2235 { 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" }, 2236 { 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" }, 2237 { 0, "{ [a, b] : exists e : 2e = a and " 2238 "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" }, 2239 { 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and " 2240 "j' >= -1 + 2i + j - 2i' and i' <= -1 + i and " 2241 "j >= 1 and j' <= i + j - i' and i >= 1; " 2242 "[1, 1, 1, 1] }" }, 2243 { 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; " 2244 "[i,j] : exists a : j = 3a }" }, 2245 { 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and " 2246 "c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and " 2247 "a >= 3) or " 2248 "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and " 2249 "b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" }, 2250 { 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and " 2251 "c <= 6 + 8a and a >= 3; " 2252 "[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and " 2253 "c <= 7 + 8a and a >= 3 and a <= 4 }" }, 2254 { 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; " 2255 "[x,0] : 3 <= x <= 4 }" }, 2256 { 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; " 2257 "[x,0] : 4 <= x <= 5 }" }, 2258 { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; " 2259 "[x,0] : 3 <= x <= 5 }" }, 2260 { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; " 2261 "[x,0] : 3 <= x <= 4 }" }, 2262 { 1, "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and " 2263 "i1 <= 0; " 2264 "[i0, 0] : i0 >= 123 and i0 <= 124 }" }, 2265 { 1, "{ [0,0]; [1,1] }" }, 2266 { 1, "[n] -> { [k] : 16k <= -1 + n and k >= 1; [0] : n >= 2 }" }, 2267 { 1, "{ [k, ii, k - ii] : ii >= -6 + k and ii <= 6 and ii >= 1 and " 2268 "ii <= k;" 2269 "[k, 0, k] : k <= 6 and k >= 1 }" }, 2270 { 1, "{ [i,j] : i = 4 j and 0 <= i <= 100;" 2271 "[i,j] : 1 <= i <= 100 and i >= 4j + 1 and i <= 4j + 2 }" }, 2272 { 1, "{ [x,y] : x % 2 = 0 and y % 2 = 0; [x,x] : x % 2 = 0 }" }, 2273 { 1, "[n] -> { [1] : n >= 0;" 2274 "[x] : exists (e0 = floor((x)/2): x >= 2 and " 2275 "2e0 >= -1 + x and 2e0 <= x and 2e0 <= n) }" }, 2276 { 1, "[n] -> { [x, y] : exists (e0 = floor((x)/2), e1 = floor((y)/3): " 2277 "3e1 = y and x >= 2 and 2e0 >= -1 + x and " 2278 "2e0 <= x and 2e0 <= n);" 2279 "[1, y] : exists (e0 = floor((y)/3): 3e0 = y and " 2280 "n >= 0) }" }, 2281 { 1, "[t1] -> { [i0] : (exists (e0 = floor((63t1)/64): " 2282 "128e0 >= -134 + 127t1 and t1 >= 2 and " 2283 "64e0 <= 63t1 and 64e0 >= -63 + 63t1)) or " 2284 "t1 = 1 }" }, 2285 { 1, "{ [i, i] : exists (e0 = floor((1 + 2i)/3): 3e0 <= 2i and " 2286 "3e0 >= -1 + 2i and i <= 9 and i >= 1);" 2287 "[0, 0] }" }, 2288 { 1, "{ [t1] : exists (e0 = floor((-11 + t1)/2): 2e0 = -11 + t1 and " 2289 "t1 >= 13 and t1 <= 16);" 2290 "[t1] : t1 <= 15 and t1 >= 12 }" }, 2291 { 1, "{ [x,y] : x = 3y and 0 <= y <= 2; [-3,-1] }" }, 2292 { 1, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-2] }" }, 2293 { 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-2,-2] }" }, 2294 { 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-1] }" }, 2295 { 1, "{ [i] : exists j : i = 4 j and 0 <= i <= 100;" 2296 "[i] : exists j : 1 <= i <= 100 and i >= 4j + 1 and " 2297 "i <= 4j + 2 }" }, 2298 { 1, "{ [c0] : (exists (e0 : c0 - 1 <= 3e0 <= c0)) or " 2299 "(exists (e0 : 3e0 = -2 + c0)) }" }, 2300 { 0, "[n, b0, t0] -> " 2301 "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : " 2302 "(exists (e0 = floor((-32b0 + i4)/1048576), " 2303 "e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and " 2304 "n <= 2147483647 and b0 <= 32767 and b0 >= 0 and " 2305 "32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 >= 8 + n and " 2306 "3i4 <= -96 + 3t0 + i0 and 3i4 >= -95 - n + 3t0 + i0 and " 2307 "i8 >= -157 + i0 - 4i4 and i8 >= 0 and " 2308 "i8 <= -33 + i0 - 4i4 and 3i8 <= -91 + 4n - i0)) or " 2309 "(exists (e0 = floor((-32b0 + i4)/1048576), " 2310 "e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and " 2311 "n <= 2147483647 and b0 <= 32767 and b0 >= 0 and " 2312 "32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 <= 7 + n and " 2313 "4i4 <= -3 + i0 and 3i4 <= -96 + 3t0 + i0 and " 2314 "3i4 >= -95 - n + 3t0 + i0 and i8 >= -157 + i0 - 4i4 and " 2315 "i8 >= 0 and i8 <= -4 + i0 - 3i4 and i8 <= -41 + i0));" 2316 "[i0, i1, i2, i3, 0, i5, i6, i7, i8, i9, i10, i11, i12] : " 2317 "(exists (e0 = floor((i8)/32): b0 = 0 and 32e0 = i8 and " 2318 "n <= 2147483647 and t0 <= 31 and t0 >= 0 and i0 >= 11 and " 2319 "i0 >= 96 - 3t0 and i0 <= 95 + n - 3t0 and i0 <= 7 + n and " 2320 "i8 >= -40 + i0 and i8 <= -10 + i0)) }" }, 2321 { 0, "{ [i0, i1, i2] : " 2322 "(exists (e0, e1 = floor((i0)/32), e2 = floor((i1)/32): " 2323 "32e1 = i0 and 32e2 = i1 and i1 >= -31 + i0 and " 2324 "i1 <= 31 + i0 and i2 >= -30 + i0 and i2 >= -30 + i1 and " 2325 "32e0 >= -30 + i0 and 32e0 >= -30 + i1 and " 2326 "32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and " 2327 "32e0 <= 31 + i0)) or " 2328 "i0 >= 0 }" }, 2329 { 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" }, 2330 { 1, "{ [a, a, b, c] : 32*floor((a)/32) = a and 2*floor((b)/2) = b and " 2331 "2*floor((c)/2) = c and 0 <= a <= 192;" 2332 "[224, 224, b, c] : 2*floor((b)/2) = b and 2*floor((c)/2) = c }" 2333 }, 2334 { 1, "[n] -> { [a,b] : (exists e : 1 <= a <= 7e and 9e <= b <= n) or " 2335 "(0 <= a <= b <= n) }" }, 2336 { 1, "{ [a, b] : 0 <= a <= 2 and b >= 0 and " 2337 "((0 < b <= 13) or (2*floor((a + b)/2) >= -5 + a + 2b)) }" }, 2338 { 1, "{ [a] : (2 <= a <= 5) or (a mod 2 = 1 and 1 <= a <= 5) }" }, 2339 { 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and " 2340 "9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or " 2341 "(exists (e0 = floor((-16 + 2c)/9): a = 4 and " 2342 "b = 3 and 9e0 <= -19 + 2c)) }" }, 2343 { 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and " 2344 "9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or " 2345 "(a = 4 and b = 3 and " 2346 "9*floor((-16 + 2c)/9) <= -19 + 2c) }" }, 2347 { 0, "{ [a, b, c] : (b <= 2 and b <= -2 + a) or " 2348 "(b = -1 + a and 0 < a <= 3 and " 2349 "9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or " 2350 "(exists (e0 = floor((-16 + 2c)/9): a = 4 and " 2351 "b = 3 and 9e0 <= -19 + 2c)) }" }, 2352 { 1, "{ [y, x] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;" 2353 "[1, 0] }" }, 2354 { 1, "{ [x, y] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;" 2355 "[0, 1] }" }, 2356 { 1, "{ [1, y] : -1 <= y <= 1; [x, -x] : 0 <= x <= 1 }" }, 2357 { 1, "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }" }, 2358 { 1, "{ [x, y] : 0 <= x <= 10 and x - 4*floor(x/4) <= 1 and y <= 0; " 2359 "[x, y] : 0 <= x <= 10 and x - 4*floor(x/4) > 1 and y <= 0; " 2360 "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) <= 1 and 0 < y; " 2361 "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) > 1 and 0 < y }" }, 2362 { 1, "{ [x, 0] : 0 <= x <= 10 and x mod 2 = 0; " 2363 "[x, 0] : 0 <= x <= 10 and x mod 2 = 1; " 2364 "[x, y] : 0 <= x <= 10 and 1 <= y <= 10 }" }, 2365 { 1, "{ [a] : a <= 8 and " 2366 "(a mod 10 = 7 or a mod 10 = 8 or a mod 10 = 9) }" }, 2367 { 1, "{ [x, y] : 2y = -x and x <= 0 or " 2368 "x <= -1 and 2y <= -x - 1 and 2y >= x - 1 }" }, 2369 { 0, "{ [x, y] : 2y = -x and x <= 0 or " 2370 "x <= -2 and 2y <= -x - 1 and 2y >= x - 1 }" }, 2371 { 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or " 2372 "(a < 0 and 3*floor((a)/3) < a) }" }, 2373 { 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or " 2374 "(a < -1 and 3*floor((a)/3) < a) }" }, 2375 { 1, "{ [a, b] : a <= 1024 and b >= 0 and " 2376 "((-31 - a + b <= 32*floor((-1 - a)/32) <= -33 + b and " 2377 "32*floor((-1 - a)/32) <= -16 + b + 16*floor((-1 - a)/16))" 2378 "or (2 <= a <= 15 and b < a)) }" }, 2379 { 1, "{ [a] : a > 0 and ((16*floor((a)/16) < a and " 2380 "32*floor((a)/32) < a) or a <= 15) }" }, 2381 { 1, "{ [a, b, c, d] : (-a + d) mod 64 = 0 and a <= 8 and b <= 1 and " 2382 "10 - a <= c <= 3 and d >= 5 and 9 - 64b <= d <= 70;" 2383 "[a, b = 1, c, d] : (-a + d) mod 64 = 0 and a <= 8 and c >= 4 and " 2384 "10 - a <= c <= 5 and 5 <= d <= 73 - c }" }, 2385 { 1, "[n, m] -> { S_0[i] : (-n + i) mod 3 = 0 and m >= 3 + n and " 2386 "i >= n and 3*floor((2 + n + 2m)/3) <= n + 3m - i; " 2387 "S_0[n] : n <= m <= 2 + n }" }, 2388 { 1, "{ [a, b] : exists (e0: 0 <= a <= 1 and b >= 0 and " 2389 "2e0 >= -5 + a + 2b and 2e0 >= -1 + a + b and " 2390 "2e0 <= a + b); " 2391 "[a, b] : exists (e0: 0 <= a <= 1 and 2e0 >= -5 + a + 2b and " 2392 "2e0 >= -1 - a + b and 2e0 <= -a + b and " 2393 "2e0 < -a + 2b) }" }, 2394 { 1, "{ [i, j, i - 8j] : 8 <= i <= 63 and -7 + i <= 8j <= i; " 2395 "[i, 0, i] : 0 <= i <= 7 }" }, 2396 { 1, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [1, 1] }" }, 2397 { 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [0, 2] }" }, 2398 { 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [-1, 3] }" }, 2399 { 1, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [1, 1] }" }, 2400 { 0, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [2, 1] }" }, 2401 { 0, "{ [a, c] : (2 + a) mod 4 = 0 or " 2402 "(c = 4 + a and 4 * floor((a)/4) = a and a >= 0 and a <= 4) or " 2403 "(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and " 2404 "a > 0 and a <= 5) }" }, 2405 { 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" }, 2406 { 0, "{ [j, a, l] : a mod 2 = 0 and j <= 29 and a >= 2 and " 2407 "2a <= -5 + j and 32j + 2a + 2 <= 4l < 33j; " 2408 "[j, 0, l] : 4 <= j <= 29 and -3 + 33j <= 4l <= 33j }" }, 2409 { 0, "{ [0:1, 0:1]; [0, 2:3] }" }, 2410 { 1, "{ [a] : (a = 0 or ((1 + a) mod 2 = 0 and 0 < a <= 15) or " 2411 "((a) mod 2 = 0 and 0 < a <= 15)) }" }, 2412 { 1, "{ rat: [0:2]; rat: [1:3] }" }, 2413 }; 2414 2415 /* A specialized coalescing test case that would result 2416 * in a segmentation fault or a failed assertion in earlier versions of isl. 2417 */ 2418 static int test_coalesce_special(struct isl_ctx *ctx) 2419 { 2420 const char *str; 2421 isl_map *map1, *map2; 2422 2423 str = "[y] -> { [S_L220_OUT[] -> T7[]] -> " 2424 "[[S_L309_IN[] -> T11[]] -> ce_imag2[1, o1]] : " 2425 "(y = 201 and o1 <= 239 and o1 >= 212) or " 2426 "(exists (e0 = [(y)/3]: 3e0 = y and y <= 198 and y >= 3 and " 2427 "o1 <= 239 and o1 >= 212)) or " 2428 "(exists (e0 = [(y)/3]: 3e0 = y and y <= 201 and y >= 3 and " 2429 "o1 <= 241 and o1 >= 240));" 2430 "[S_L220_OUT[] -> T7[]] -> " 2431 "[[S_L309_IN[] -> T11[]] -> ce_imag2[0, o1]] : " 2432 "(y = 2 and o1 <= 241 and o1 >= 212) or " 2433 "(exists (e0 = [(-2 + y)/3]: 3e0 = -2 + y and y <= 200 and " 2434 "y >= 5 and o1 <= 241 and o1 >= 212)) }"; 2435 map1 = isl_map_read_from_str(ctx, str); 2436 map1 = isl_map_align_divs_internal(map1); 2437 map1 = isl_map_coalesce(map1); 2438 str = "[y] -> { [S_L220_OUT[] -> T7[]] -> " 2439 "[[S_L309_IN[] -> T11[]] -> ce_imag2[o0, o1]] : " 2440 "exists (e0 = [(-1 - y + o0)/3]: 3e0 = -1 - y + o0 and " 2441 "y <= 201 and o0 <= 2 and o1 >= 212 and o1 <= 241 and " 2442 "o0 >= 3 - y and o0 <= -2 + y and o0 >= 0) }"; 2443 map2 = isl_map_read_from_str(ctx, str); 2444 map2 = isl_map_union(map2, map1); 2445 map2 = isl_map_align_divs_internal(map2); 2446 map2 = isl_map_coalesce(map2); 2447 isl_map_free(map2); 2448 if (!map2) 2449 return -1; 2450 2451 return 0; 2452 } 2453 2454 /* Check that the union of the basic sets described by "str1" and "str2" 2455 * can be coalesced and that the result is equal to the union. 2456 * The explicit call to isl_basic_set_union prevents the implicit 2457 * equality constraints in the basic maps from being detected prior 2458 * to the call to isl_set_coalesce, at least at the point 2459 * where this function was introduced. 2460 */ 2461 static isl_stat test_coalesce_union(isl_ctx *ctx, const char *str1, 2462 const char *str2) 2463 { 2464 isl_basic_set *bset1, *bset2; 2465 isl_set *set, *set2; 2466 isl_bool equal; 2467 2468 bset1 = isl_basic_set_read_from_str(ctx, str1); 2469 bset2 = isl_basic_set_read_from_str(ctx, str2); 2470 set = isl_basic_set_union(bset1, bset2); 2471 set = isl_set_coalesce(set); 2472 2473 bset1 = isl_basic_set_read_from_str(ctx, str1); 2474 bset2 = isl_basic_set_read_from_str(ctx, str2); 2475 set2 = isl_basic_set_union(bset1, bset2); 2476 2477 equal = isl_set_is_equal(set, set2); 2478 isl_set_free(set); 2479 isl_set_free(set2); 2480 2481 if (equal < 0) 2482 return isl_stat_error; 2483 if (!equal) 2484 isl_die(ctx, isl_error_unknown, 2485 "coalesced set not equal to input", 2486 return isl_stat_error); 2487 2488 return isl_stat_non_null(set); 2489 } 2490 2491 /* A specialized coalescing test case that would result in an assertion 2492 * in an earlier version of isl. Use test_coalesce_union with 2493 * an explicit call to isl_basic_set_union to prevent the implicit 2494 * equality constraints in the first basic map from being detected prior 2495 * to the call to isl_set_coalesce, at least at the point 2496 * where this test case was introduced. 2497 */ 2498 static isl_stat test_coalesce_special2(struct isl_ctx *ctx) 2499 { 2500 const char *str1; 2501 const char *str2; 2502 2503 str1 = "{ [x, y] : x, y >= 0 and x + 2y <= 1 and 2x + y <= 1 }"; 2504 str2 = "{ [x,0] : -1 <= x <= 1 and x mod 2 = 1 }"; 2505 return test_coalesce_union(ctx, str1, str2); 2506 } 2507 2508 /* Check that calling isl_set_coalesce does not leave other sets 2509 * that may share some information with the input to isl_set_coalesce 2510 * in an inconsistent state. 2511 * In particular, older versions of isl would modify all copies 2512 * of the basic sets in the isl_set_coalesce input in a way 2513 * that could leave them in an inconsistent state. 2514 * The result of printing any other set containing one of these 2515 * basic sets would then result in an invalid set description. 2516 */ 2517 static int test_coalesce_special3(isl_ctx *ctx) 2518 { 2519 const char *str; 2520 char *s; 2521 isl_set *set1, *set2; 2522 isl_printer *p; 2523 2524 set1 = isl_set_read_from_str(ctx, "{ [0, 0, 0] }"); 2525 str = "{ [a, b, a + b] : a >= 0 and b >= 0 and 0 < a + b }"; 2526 set2 = isl_set_read_from_str(ctx, str); 2527 set1 = isl_set_union(set1, isl_set_copy(set2)); 2528 set1 = isl_set_coalesce(set1); 2529 isl_set_free(set1); 2530 2531 p = isl_printer_to_str(ctx); 2532 p = isl_printer_print_set(p, set2); 2533 isl_set_free(set2); 2534 s = isl_printer_get_str(p); 2535 isl_printer_free(p); 2536 set1 = isl_set_read_from_str(ctx, s); 2537 free(s); 2538 isl_set_free(set1); 2539 2540 if (!set1) 2541 return -1; 2542 2543 return 0; 2544 } 2545 2546 /* Check that calling isl_set_coalesce on the intersection of 2547 * the sets described by "s1" and "s2" does not leave other sets 2548 * that may share some information with the input to isl_set_coalesce 2549 * in an inconsistent state. 2550 * In particular, when isl_set_coalesce detects equality constraints, 2551 * it does not immediately perform Gaussian elimination on them, 2552 * but then it needs to ensure that it is performed at some point. 2553 * The input set has implicit equality constraints in the first disjunct. 2554 * It is constructed as an intersection, because otherwise 2555 * those equality constraints would already be detected during parsing. 2556 */ 2557 static isl_stat test_coalesce_intersection(isl_ctx *ctx, 2558 const char *s1, const char *s2) 2559 { 2560 isl_set *set1, *set2; 2561 2562 set1 = isl_set_read_from_str(ctx, s1); 2563 set2 = isl_set_read_from_str(ctx, s2); 2564 set1 = isl_set_intersect(set1, set2); 2565 isl_set_free(isl_set_coalesce(isl_set_copy(set1))); 2566 set1 = isl_set_coalesce(set1); 2567 isl_set_free(set1); 2568 2569 if (!set1) 2570 return isl_stat_error; 2571 2572 return isl_stat_ok; 2573 } 2574 2575 /* Check that calling isl_set_coalesce does not leave other sets 2576 * that may share some information with the input to isl_set_coalesce 2577 * in an inconsistent state, for the case where one disjunct 2578 * is a subset of the other. 2579 */ 2580 static isl_stat test_coalesce_special4(isl_ctx *ctx) 2581 { 2582 const char *s1, *s2; 2583 2584 s1 = "{ [a, b] : b <= 0 or a <= 1 }"; 2585 s2 = "{ [a, b] : -1 <= -a < b }"; 2586 return test_coalesce_intersection(ctx, s1, s2); 2587 } 2588 2589 /* Check that calling isl_set_coalesce does not leave other sets 2590 * that may share some information with the input to isl_set_coalesce 2591 * in an inconsistent state, for the case where two disjuncts 2592 * can be fused. 2593 */ 2594 static isl_stat test_coalesce_special5(isl_ctx *ctx) 2595 { 2596 const char *s1, *s2; 2597 2598 s1 = "{ [a, b, c] : b <= 0 }"; 2599 s2 = "{ [a, b, c] : -1 <= -a < b and (c >= 0 or c < 0) }"; 2600 return test_coalesce_intersection(ctx, s1, s2); 2601 } 2602 2603 /* Check that calling isl_set_coalesce does not leave other sets 2604 * that may share some information with the input to isl_set_coalesce 2605 * in an inconsistent state, for the case where two disjuncts 2606 * can be fused and where both disjuncts have implicit equality constraints. 2607 */ 2608 static isl_stat test_coalesce_special6(isl_ctx *ctx) 2609 { 2610 const char *s1, *s2; 2611 2612 s1 = "{ [a, b, c] : c <= 0 }"; 2613 s2 = "{ [a, b, c] : 0 <= a <= b <= c or (0 <= b <= c and a > 0) }"; 2614 return test_coalesce_intersection(ctx, s1, s2); 2615 } 2616 2617 /* A specialized coalescing test case that would result in an assertion failure 2618 * in an earlier version of isl. Use test_coalesce_union with 2619 * an explicit call to isl_basic_set_union to prevent the implicit 2620 * equality constraints in the basic maps from being detected prior 2621 * to the call to isl_set_coalesce, at least at the point 2622 * where this test case was introduced. 2623 */ 2624 static isl_stat test_coalesce_special7(isl_ctx *ctx) 2625 { 2626 const char *str1; 2627 const char *str2; 2628 2629 str1 = "{ [a, b, c=0:17] : a <= 7 and 2b <= 11 - a and " 2630 "c <= -7 + 2a and 2c >= - 3 + 3a - 2b }"; 2631 str2 = "{ [a, b, c] : c > -15a and c >= -7 + 2a and c < 0 and " 2632 "3c <= -5 + 5a - 3b and 2b >= 11 - a }"; 2633 return test_coalesce_union(ctx, str1, str2); 2634 } 2635 2636 /* A specialized coalescing test case that would result in a disjunct 2637 * getting dropped in an earlier version of isl. Use test_coalesce_union with 2638 * an explicit call to isl_basic_set_union to prevent the implicit 2639 * equality constraints in the basic maps from being detected prior 2640 * to the call to isl_set_coalesce, at least at the point 2641 * where this test case was introduced. 2642 */ 2643 static isl_stat test_coalesce_special8(isl_ctx *ctx) 2644 { 2645 const char *str1; 2646 const char *str2; 2647 2648 str1 = "{ [a, b, c] : 2c <= -a and b >= -a and b <= 5 and " 2649 "6c > -7a and 11c >= -5a - b and a <= 3 }"; 2650 str2 = "{ [a, b, c] : 6c > -7a and b >= -a and b <= 5 and " 2651 "11c >= -5a - b and a >= 4 and 2b <= a and 2c <= -a }"; 2652 return test_coalesce_union(ctx, str1, str2); 2653 } 2654 2655 /* Test the functionality of isl_set_coalesce. 2656 * That is, check that the output is always equal to the input 2657 * and in some cases that the result consists of a single disjunct. 2658 */ 2659 static int test_coalesce(struct isl_ctx *ctx) 2660 { 2661 int i; 2662 2663 for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) { 2664 const char *str = coalesce_tests[i].str; 2665 int check_one = coalesce_tests[i].single_disjunct; 2666 if (test_coalesce_set(ctx, str, check_one) < 0) 2667 return -1; 2668 } 2669 2670 if (test_coalesce_unbounded_wrapping(ctx) < 0) 2671 return -1; 2672 if (test_coalesce_special(ctx) < 0) 2673 return -1; 2674 if (test_coalesce_special2(ctx) < 0) 2675 return -1; 2676 if (test_coalesce_special3(ctx) < 0) 2677 return -1; 2678 if (test_coalesce_special4(ctx) < 0) 2679 return -1; 2680 if (test_coalesce_special5(ctx) < 0) 2681 return -1; 2682 if (test_coalesce_special6(ctx) < 0) 2683 return -1; 2684 if (test_coalesce_special7(ctx) < 0) 2685 return -1; 2686 if (test_coalesce_special8(ctx) < 0) 2687 return -1; 2688 2689 return 0; 2690 } 2691 2692 /* Construct a representation of the graph on the right of Figure 1 2693 * in "Computing the Transitive Closure of a Union of 2694 * Affine Integer Tuple Relations". 2695 */ 2696 static __isl_give isl_map *cocoa_fig_1_right_graph(isl_ctx *ctx) 2697 { 2698 isl_set *dom; 2699 isl_map *up, *right; 2700 2701 dom = isl_set_read_from_str(ctx, 2702 "{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and " 2703 "2 x - 3 y + 3 >= 0 }"); 2704 right = isl_map_read_from_str(ctx, 2705 "{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }"); 2706 up = isl_map_read_from_str(ctx, 2707 "{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }"); 2708 right = isl_map_intersect_domain(right, isl_set_copy(dom)); 2709 right = isl_map_intersect_range(right, isl_set_copy(dom)); 2710 up = isl_map_intersect_domain(up, isl_set_copy(dom)); 2711 up = isl_map_intersect_range(up, dom); 2712 return isl_map_union(up, right); 2713 } 2714 2715 /* Construct a representation of the power of the graph 2716 * on the right of Figure 1 in "Computing the Transitive Closure of 2717 * a Union of Affine Integer Tuple Relations". 2718 */ 2719 static __isl_give isl_map *cocoa_fig_1_right_power(isl_ctx *ctx) 2720 { 2721 return isl_map_read_from_str(ctx, 2722 "{ [1] -> [[0,0] -> [0,1]]; [2] -> [[0,0] -> [1,1]]; " 2723 " [1] -> [[0,1] -> [1,1]]; [1] -> [[2,2] -> [3,2]]; " 2724 " [2] -> [[2,2] -> [3,3]]; [1] -> [[3,2] -> [3,3]] }"); 2725 } 2726 2727 /* Construct a representation of the transitive closure of the graph 2728 * on the right of Figure 1 in "Computing the Transitive Closure of 2729 * a Union of Affine Integer Tuple Relations". 2730 */ 2731 static __isl_give isl_map *cocoa_fig_1_right_tc(isl_ctx *ctx) 2732 { 2733 return isl_set_unwrap(isl_map_range(cocoa_fig_1_right_power(ctx))); 2734 } 2735 2736 static int test_closure(isl_ctx *ctx) 2737 { 2738 const char *str; 2739 isl_map *map, *map2; 2740 isl_bool exact, equal; 2741 2742 /* COCOA example 1 */ 2743 map = isl_map_read_from_str(ctx, 2744 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and " 2745 "1 <= i and i < n and 1 <= j and j < n or " 2746 "i2 = i + 1 and j2 = j - 1 and " 2747 "1 <= i and i < n and 2 <= j and j <= n }"); 2748 map = isl_map_power(map, &exact); 2749 assert(exact); 2750 isl_map_free(map); 2751 2752 /* COCOA example 1 */ 2753 map = isl_map_read_from_str(ctx, 2754 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and " 2755 "1 <= i and i < n and 1 <= j and j < n or " 2756 "i2 = i + 1 and j2 = j - 1 and " 2757 "1 <= i and i < n and 2 <= j and j <= n }"); 2758 map = isl_map_transitive_closure(map, &exact); 2759 assert(exact); 2760 map2 = isl_map_read_from_str(ctx, 2761 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : " 2762 "1 <= i and i < n and 1 <= j and j <= n and " 2763 "2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and " 2764 "i2 = i + k1 + k2 and j2 = j + k1 - k2 and " 2765 "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}"); 2766 assert(isl_map_is_equal(map, map2)); 2767 isl_map_free(map2); 2768 isl_map_free(map); 2769 2770 map = isl_map_read_from_str(ctx, 2771 "[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and " 2772 " 0 <= y and y <= n }"); 2773 map = isl_map_transitive_closure(map, &exact); 2774 map2 = isl_map_read_from_str(ctx, 2775 "[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and " 2776 " 0 <= y and y <= n }"); 2777 assert(isl_map_is_equal(map, map2)); 2778 isl_map_free(map2); 2779 isl_map_free(map); 2780 2781 /* COCOA example 2 */ 2782 map = isl_map_read_from_str(ctx, 2783 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and " 2784 "1 <= i and i < n - 1 and 1 <= j and j < n - 1 or " 2785 "i2 = i + 2 and j2 = j - 2 and " 2786 "1 <= i and i < n - 1 and 3 <= j and j <= n }"); 2787 map = isl_map_transitive_closure(map, &exact); 2788 assert(exact); 2789 map2 = isl_map_read_from_str(ctx, 2790 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : " 2791 "1 <= i and i < n - 1 and 1 <= j and j <= n and " 2792 "3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and " 2793 "i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and " 2794 "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }"); 2795 assert(isl_map_is_equal(map, map2)); 2796 isl_map_free(map); 2797 isl_map_free(map2); 2798 2799 /* COCOA Fig.2 left */ 2800 map = isl_map_read_from_str(ctx, 2801 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and " 2802 "i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and " 2803 "j <= n or " 2804 "i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and " 2805 "j <= 2 i - 3 and j <= n - 2 or " 2806 "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and " 2807 "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }"); 2808 map = isl_map_transitive_closure(map, &exact); 2809 assert(exact); 2810 isl_map_free(map); 2811 2812 /* COCOA Fig.2 right */ 2813 map = isl_map_read_from_str(ctx, 2814 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and " 2815 "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and " 2816 "j <= n or " 2817 "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and " 2818 "j <= 2 i - 4 and j <= n - 3 or " 2819 "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and " 2820 "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }"); 2821 map = isl_map_power(map, &exact); 2822 assert(exact); 2823 isl_map_free(map); 2824 2825 /* COCOA Fig.2 right */ 2826 map = isl_map_read_from_str(ctx, 2827 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and " 2828 "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and " 2829 "j <= n or " 2830 "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and " 2831 "j <= 2 i - 4 and j <= n - 3 or " 2832 "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and " 2833 "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }"); 2834 map = isl_map_transitive_closure(map, &exact); 2835 assert(exact); 2836 map2 = isl_map_read_from_str(ctx, 2837 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : " 2838 "i <= 2 j - 1 and i <= n and j <= 2 i - 1 and " 2839 "j <= n and 3 + i + 2 j <= 3 n and " 2840 "3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and " 2841 "i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and " 2842 "13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and " 2843 "j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and " 2844 "k3 >= 0 and k1 + k2 + k3 = k and k > 0) }"); 2845 assert(isl_map_is_equal(map, map2)); 2846 isl_map_free(map2); 2847 isl_map_free(map); 2848 2849 map = cocoa_fig_1_right_graph(ctx); 2850 map = isl_map_transitive_closure(map, &exact); 2851 assert(exact); 2852 map2 = cocoa_fig_1_right_tc(ctx); 2853 assert(isl_map_is_equal(map, map2)); 2854 isl_map_free(map2); 2855 isl_map_free(map); 2856 2857 map = cocoa_fig_1_right_graph(ctx); 2858 map = isl_map_power(map, &exact); 2859 map2 = cocoa_fig_1_right_power(ctx); 2860 equal = isl_map_is_equal(map, map2); 2861 isl_map_free(map2); 2862 isl_map_free(map); 2863 if (equal < 0) 2864 return -1; 2865 if (!exact) 2866 isl_die(ctx, isl_error_unknown, "power not exact", return -1); 2867 if (!equal) 2868 isl_die(ctx, isl_error_unknown, "unexpected power", return -1); 2869 2870 /* COCOA Theorem 1 counter example */ 2871 map = isl_map_read_from_str(ctx, 2872 "{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and " 2873 "i2 = 1 and j2 = j or " 2874 "i = 0 and j = 0 and i2 = 0 and j2 = 1 }"); 2875 map = isl_map_transitive_closure(map, &exact); 2876 assert(exact); 2877 isl_map_free(map); 2878 2879 map = isl_map_read_from_str(ctx, 2880 "[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and " 2881 "1 <= i,i2 <= n and 1 <= j,j2 <= m or " 2882 "i2 = i + 1 and 3 <= j2 - j <= 4 and " 2883 "1 <= i,i2 <= n and 1 <= j,j2 <= m }"); 2884 map = isl_map_transitive_closure(map, &exact); 2885 assert(exact); 2886 isl_map_free(map); 2887 2888 /* Kelly et al 1996, fig 12 */ 2889 map = isl_map_read_from_str(ctx, 2890 "[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and " 2891 "1 <= i,j,j+1 <= n or " 2892 "j = n and j2 = 1 and i2 = i + 1 and " 2893 "1 <= i,i+1 <= n }"); 2894 map = isl_map_transitive_closure(map, &exact); 2895 assert(exact); 2896 map2 = isl_map_read_from_str(ctx, 2897 "[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and " 2898 "1 <= i <= n and i = i2 or " 2899 "1 <= i < i2 <= n and 1 <= j <= n and " 2900 "1 <= j2 <= n }"); 2901 assert(isl_map_is_equal(map, map2)); 2902 isl_map_free(map2); 2903 isl_map_free(map); 2904 2905 /* Omega's closure4 */ 2906 map = isl_map_read_from_str(ctx, 2907 "[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and " 2908 "1 <= x,y <= 10 or " 2909 "x2 = x + 1 and y2 = y and " 2910 "1 <= x <= 20 && 5 <= y <= 15 }"); 2911 map = isl_map_transitive_closure(map, &exact); 2912 assert(exact); 2913 isl_map_free(map); 2914 2915 map = isl_map_read_from_str(ctx, 2916 "[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }"); 2917 map = isl_map_transitive_closure(map, &exact); 2918 assert(!exact); 2919 map2 = isl_map_read_from_str(ctx, 2920 "[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }"); 2921 assert(isl_map_is_equal(map, map2)); 2922 isl_map_free(map); 2923 isl_map_free(map2); 2924 2925 str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : " 2926 "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and " 2927 "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and " 2928 "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }"; 2929 map = isl_map_read_from_str(ctx, str); 2930 map = isl_map_transitive_closure(map, &exact); 2931 assert(exact); 2932 map2 = isl_map_read_from_str(ctx, str); 2933 assert(isl_map_is_equal(map, map2)); 2934 isl_map_free(map); 2935 isl_map_free(map2); 2936 2937 str = "{[0] -> [1]; [2] -> [3]}"; 2938 map = isl_map_read_from_str(ctx, str); 2939 map = isl_map_transitive_closure(map, &exact); 2940 assert(exact); 2941 map2 = isl_map_read_from_str(ctx, str); 2942 assert(isl_map_is_equal(map, map2)); 2943 isl_map_free(map); 2944 isl_map_free(map2); 2945 2946 str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> " 2947 "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : " 2948 "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and " 2949 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and " 2950 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); " 2951 "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> " 2952 "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : " 2953 "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and " 2954 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and " 2955 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); " 2956 "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> " 2957 "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : " 2958 "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and " 2959 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and " 2960 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); " 2961 "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> " 2962 "[[i0, i1, 1, 0, i0] -> [i5, 1]] : " 2963 "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and " 2964 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and " 2965 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }"; 2966 map = isl_map_read_from_str(ctx, str); 2967 map = isl_map_transitive_closure(map, NULL); 2968 assert(map); 2969 isl_map_free(map); 2970 2971 return 0; 2972 } 2973 2974 /* Check that the actual result of a boolean operation is equal 2975 * to the expected result. 2976 */ 2977 static isl_stat check_bool(isl_ctx *ctx, isl_bool actual, isl_bool expected) 2978 { 2979 if (actual != expected) 2980 isl_die(ctx, isl_error_unknown, 2981 "incorrect boolean operation", return isl_stat_error); 2982 return isl_stat_ok; 2983 } 2984 2985 /* Test operations on isl_bool values. 2986 * 2987 * This tests: 2988 * 2989 * isl_bool_not 2990 * isl_bool_ok 2991 */ 2992 static int test_isl_bool(isl_ctx *ctx) 2993 { 2994 if (check_bool(ctx, isl_bool_not(isl_bool_true), isl_bool_false) < 0) 2995 return -1; 2996 if (check_bool(ctx, isl_bool_not(isl_bool_false), isl_bool_true) < 0) 2997 return -1; 2998 if (check_bool(ctx, isl_bool_not(isl_bool_error), isl_bool_error) < 0) 2999 return -1; 3000 if (check_bool(ctx, isl_bool_ok(0), isl_bool_false) < 0) 3001 return -1; 3002 if (check_bool(ctx, isl_bool_ok(1), isl_bool_true) < 0) 3003 return -1; 3004 if (check_bool(ctx, isl_bool_ok(-1), isl_bool_true) < 0) 3005 return -1; 3006 if (check_bool(ctx, isl_bool_ok(2), isl_bool_true) < 0) 3007 return -1; 3008 if (check_bool(ctx, isl_bool_ok(-2), isl_bool_true) < 0) 3009 return -1; 3010 3011 return 0; 3012 } 3013 3014 static int test_lex(struct isl_ctx *ctx) 3015 { 3016 isl_space *space; 3017 isl_map *map; 3018 int empty; 3019 3020 space = isl_space_set_alloc(ctx, 0, 0); 3021 map = isl_map_lex_le(space); 3022 empty = isl_map_is_empty(map); 3023 isl_map_free(map); 3024 3025 if (empty < 0) 3026 return -1; 3027 if (empty) 3028 isl_die(ctx, isl_error_unknown, 3029 "expecting non-empty result", return -1); 3030 3031 return 0; 3032 } 3033 3034 /* Inputs for isl_map_lexmin tests. 3035 * "map" is the input and "lexmin" is the expected result. 3036 */ 3037 struct { 3038 const char *map; 3039 const char *lexmin; 3040 } lexmin_tests [] = { 3041 { "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }", 3042 "{ [x] -> [5] : 6 <= x <= 8; " 3043 "[x] -> [x] : x <= 5 or (9 <= x <= 10) }" }, 3044 { "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }", 3045 "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }" }, 3046 { "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }", 3047 "{ [x] -> [y] : (4y = x and x >= 0) or " 3048 "(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and " 3049 "4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or " 3050 "(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }" }, 3051 { "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }", 3052 "{ T[a] -> S[b, c] : 2b = a and 2c = a }" }, 3053 /* Check that empty pieces are properly combined. */ 3054 { "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and " 3055 "2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and " 3056 "b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }", 3057 "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and " 3058 "x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and " 3059 "x >= 4 }" }, 3060 { "{ [i, k, j] -> [a, b, c, d] : 8*floor((b)/8) = b and k <= 255 and " 3061 "a <= 255 and c <= 255 and d <= 255 - j and " 3062 "255 - j <= 7d <= 7 - i and 240d <= 239 + a and " 3063 "247d <= 247 + k - j and 247d <= 247 + k - b and " 3064 "247d <= 247 + i and 248 - b <= 248d <= c and " 3065 "254d >= i - a + b and 254d >= -a + b and " 3066 "255d >= -i + a - b and 1792d >= -63736 + 257b }", 3067 "{ [i, k, j] -> " 3068 "[-127762 + i + 502j, -62992 + 248j, 63240 - 248j, 255 - j] : " 3069 "k <= 255 and 7j >= 1778 + i and 246j >= 62738 - k and " 3070 "247j >= 62738 - i and 509j <= 129795 + i and " 3071 "742j >= 188724 - i; " 3072 "[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" }, 3073 { "{ [a] -> [b] : 0 <= b <= 255 and -509 + a <= 512b < a and " 3074 "16*floor((8 + b)/16) <= 7 + b; " 3075 "[a] -> [1] }", 3076 "{ [a] -> [b = 1] : a >= 510 or a <= 0; " 3077 "[a] -> [b = 0] : 0 < a <= 509 }" }, 3078 { "{ rat: [i] : 1 <= 2i <= 9 }", "{ rat: [i] : 2i = 1 }" }, 3079 { "{ rat: [i] : 1 <= 2i <= 9 or i >= 10 }", "{ rat: [i] : 2i = 1 }" }, 3080 { "{ rat: [i] : 21 <= 2i <= 29 or i = 5 }", "{ rat: [5] }" }, 3081 }; 3082 3083 static int test_lexmin(struct isl_ctx *ctx) 3084 { 3085 int i; 3086 int equal; 3087 const char *str; 3088 isl_basic_map *bmap; 3089 isl_map *map, *map2; 3090 isl_set *set; 3091 isl_set *set2; 3092 isl_pw_multi_aff *pma; 3093 3094 str = "[p0, p1] -> { [] -> [] : " 3095 "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], " 3096 "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: " 3097 "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and " 3098 "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and " 3099 "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and " 3100 "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and " 3101 "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and " 3102 "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and " 3103 "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and " 3104 "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and " 3105 "e2 <= e1 and e3 >= 1 and e4 <= e2) }"; 3106 map = isl_map_read_from_str(ctx, str); 3107 map = isl_map_lexmin(map); 3108 isl_map_free(map); 3109 if (!map) 3110 return -1; 3111 3112 str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and " 3113 "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }"; 3114 set = isl_set_read_from_str(ctx, str); 3115 set = isl_set_lexmax(set); 3116 str = "[C] -> { [obj,a,b,c] : C = 8 }"; 3117 set2 = isl_set_read_from_str(ctx, str); 3118 set = isl_set_intersect(set, set2); 3119 assert(!isl_set_is_empty(set)); 3120 isl_set_free(set); 3121 3122 for (i = 0; i < ARRAY_SIZE(lexmin_tests); ++i) { 3123 map = isl_map_read_from_str(ctx, lexmin_tests[i].map); 3124 map = isl_map_lexmin(map); 3125 map2 = isl_map_read_from_str(ctx, lexmin_tests[i].lexmin); 3126 equal = isl_map_is_equal(map, map2); 3127 isl_map_free(map); 3128 isl_map_free(map2); 3129 3130 if (equal < 0) 3131 return -1; 3132 if (!equal) 3133 isl_die(ctx, isl_error_unknown, 3134 "unexpected result", return -1); 3135 } 3136 3137 str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and " 3138 " 8i' <= i and 8i' >= -7 + i }"; 3139 bmap = isl_basic_map_read_from_str(ctx, str); 3140 pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap)); 3141 map2 = isl_map_from_pw_multi_aff(pma); 3142 map = isl_map_from_basic_map(bmap); 3143 assert(isl_map_is_equal(map, map2)); 3144 isl_map_free(map); 3145 isl_map_free(map2); 3146 3147 str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and " 3148 " 8i' <= i and 8i' >= -7 + i }"; 3149 set = isl_set_read_from_str(ctx, str); 3150 pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set)); 3151 set2 = isl_set_from_pw_multi_aff(pma); 3152 equal = isl_set_is_equal(set, set2); 3153 isl_set_free(set); 3154 isl_set_free(set2); 3155 if (equal < 0) 3156 return -1; 3157 if (!equal) 3158 isl_die(ctx, isl_error_unknown, 3159 "unexpected difference between set and " 3160 "piecewise affine expression", return -1); 3161 3162 return 0; 3163 } 3164 3165 /* Inputs for isl_pw_multi_aff_max_multi_val tests. 3166 * "pma" is the input. 3167 * "res" is the expected result. 3168 */ 3169 static struct { 3170 const char *pma; 3171 const char *res; 3172 } opt_pw_tests[] = { 3173 { "{ [-1] -> [-1]; [1] -> [1] }", "{ [1] }" }, 3174 { "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] : " 3175 "0 <= a, b <= 100 and b mod 2 = 0}", "{ [30] }" }, 3176 { "[N] -> { [i,j] -> A[i, -i, i + j] : 0 <= i,j <= N <= 10 }", 3177 "{ A[10, 0, 20] }" }, 3178 { "[N] -> {A[N, -N, 2N] : 0 <= N }", "{ A[infty, 0, infty] }" }, 3179 }; 3180 3181 /* Perform basic isl_pw_multi_aff_max_multi_val tests. 3182 */ 3183 static isl_stat test_pw_max(struct isl_ctx *ctx) 3184 { 3185 int i; 3186 isl_pw_multi_aff *pma; 3187 isl_multi_val *mv; 3188 isl_stat r; 3189 3190 for (i = 0; i < ARRAY_SIZE(opt_pw_tests); ++i) { 3191 pma = isl_pw_multi_aff_read_from_str(ctx, opt_pw_tests[i].pma); 3192 mv = isl_pw_multi_aff_max_multi_val(pma); 3193 r = multi_val_check_plain_equal(mv, opt_pw_tests[i].res); 3194 isl_multi_val_free(mv); 3195 3196 if (r < 0) 3197 return isl_stat_error; 3198 } 3199 3200 return isl_stat_ok; 3201 } 3202 3203 /* A specialized isl_set_min_val test case that would return the wrong result 3204 * in earlier versions of isl. 3205 * The explicit call to isl_basic_set_union prevents the second basic set 3206 * from being determined to be empty prior to the call to isl_set_min_val, 3207 * at least at the point where this test case was introduced. 3208 */ 3209 static int test_min_special(isl_ctx *ctx) 3210 { 3211 const char *str; 3212 isl_basic_set *bset1, *bset2; 3213 isl_set *set; 3214 isl_aff *obj; 3215 isl_val *res; 3216 int ok; 3217 3218 str = "{ [a, b] : a >= 2 and b >= 0 and 14 - a <= b <= 9 }"; 3219 bset1 = isl_basic_set_read_from_str(ctx, str); 3220 str = "{ [a, b] : 1 <= a, b and a + b <= 1 }"; 3221 bset2 = isl_basic_set_read_from_str(ctx, str); 3222 set = isl_basic_set_union(bset1, bset2); 3223 obj = isl_aff_read_from_str(ctx, "{ [a, b] -> [a] }"); 3224 3225 res = isl_set_min_val(set, obj); 3226 ok = isl_val_cmp_si(res, 5) == 0; 3227 3228 isl_aff_free(obj); 3229 isl_set_free(set); 3230 isl_val_free(res); 3231 3232 if (!res) 3233 return -1; 3234 if (!ok) 3235 isl_die(ctx, isl_error_unknown, "unexpected minimum", 3236 return -1); 3237 3238 return 0; 3239 } 3240 3241 /* A specialized isl_set_min_val test case that would return an error 3242 * in earlier versions of isl. 3243 */ 3244 static int test_min_special2(isl_ctx *ctx) 3245 { 3246 const char *str; 3247 isl_basic_set *bset; 3248 isl_aff *obj; 3249 isl_val *res; 3250 3251 str = "{ [i, j, k] : 2j = i and 2k = i + 1 and i >= 2 }"; 3252 bset = isl_basic_set_read_from_str(ctx, str); 3253 3254 obj = isl_aff_read_from_str(ctx, "{ [i, j, k] -> [i] }"); 3255 3256 res = isl_basic_set_max_val(bset, obj); 3257 3258 isl_basic_set_free(bset); 3259 isl_aff_free(obj); 3260 isl_val_free(res); 3261 3262 if (!res) 3263 return -1; 3264 3265 return 0; 3266 } 3267 3268 /* Check that the result of isl_set_min_multi_pw_aff 3269 * on the union of the sets with string descriptions "s1" and "s2" 3270 * consists of a single expression (on a single cell). 3271 */ 3272 static isl_stat check_single_expr_min(isl_ctx *ctx, const char *s1, 3273 const char *s2) 3274 { 3275 isl_size n; 3276 isl_set *set1, *set2; 3277 isl_multi_pw_aff *mpa; 3278 isl_pw_multi_aff *pma; 3279 3280 set1 = isl_set_read_from_str(ctx, s1); 3281 set2 = isl_set_read_from_str(ctx, s2); 3282 set1 = isl_set_union(set1, set2); 3283 mpa = isl_set_min_multi_pw_aff(set1); 3284 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa); 3285 n = isl_pw_multi_aff_n_piece(pma); 3286 isl_pw_multi_aff_free(pma); 3287 3288 if (n < 0) 3289 return isl_stat_error; 3290 if (n != 1) 3291 isl_die(ctx, isl_error_unknown, "expecting single expression", 3292 return isl_stat_error); 3293 return isl_stat_ok; 3294 } 3295 3296 /* A specialized isl_set_min_multi_pw_aff test that checks 3297 * that the minimum of 2N and 3N for N >= 0 is represented 3298 * by a single expression, without splitting off the special case N = 0. 3299 * Do this for both orderings. 3300 */ 3301 static int test_min_mpa(isl_ctx *ctx) 3302 { 3303 const char *s1, *s2; 3304 3305 s1 = "[N=0:] -> { [1, 3N:] }"; 3306 s2 = "[N=0:] -> { [10, 2N:] }"; 3307 if (check_single_expr_min(ctx, s1, s2) < 0) 3308 return -1; 3309 if (check_single_expr_min(ctx, s2, s1) < 0) 3310 return -1; 3311 3312 return 0; 3313 } 3314 3315 struct { 3316 const char *set; 3317 const char *obj; 3318 __isl_give isl_val *(*fn)(__isl_keep isl_set *set, 3319 __isl_keep isl_aff *obj); 3320 const char *res; 3321 } opt_tests[] = { 3322 { "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_min_val, "-1" }, 3323 { "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_max_val, "1" }, 3324 { "{ [a, b] : 0 <= a, b <= 100 and b mod 2 = 0}", 3325 "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] }", 3326 &isl_set_max_val, "30" }, 3327 3328 }; 3329 3330 /* Perform basic isl_set_min_val and isl_set_max_val tests. 3331 * In particular, check the results on non-convex inputs. 3332 */ 3333 static int test_min(struct isl_ctx *ctx) 3334 { 3335 int i; 3336 isl_set *set; 3337 isl_aff *obj; 3338 isl_val *val, *res; 3339 isl_bool ok; 3340 3341 for (i = 0; i < ARRAY_SIZE(opt_tests); ++i) { 3342 set = isl_set_read_from_str(ctx, opt_tests[i].set); 3343 obj = isl_aff_read_from_str(ctx, opt_tests[i].obj); 3344 res = isl_val_read_from_str(ctx, opt_tests[i].res); 3345 val = opt_tests[i].fn(set, obj); 3346 ok = isl_val_eq(res, val); 3347 isl_val_free(res); 3348 isl_val_free(val); 3349 isl_aff_free(obj); 3350 isl_set_free(set); 3351 3352 if (ok < 0) 3353 return -1; 3354 if (!ok) 3355 isl_die(ctx, isl_error_unknown, 3356 "unexpected optimum", return -1); 3357 } 3358 3359 if (test_pw_max(ctx) < 0) 3360 return -1; 3361 if (test_min_special(ctx) < 0) 3362 return -1; 3363 if (test_min_special2(ctx) < 0) 3364 return -1; 3365 3366 return 0; 3367 } 3368 3369 struct must_may { 3370 isl_map *must; 3371 isl_map *may; 3372 }; 3373 3374 static isl_stat collect_must_may(__isl_take isl_map *dep, int must, 3375 void *dep_user, void *user) 3376 { 3377 struct must_may *mm = (struct must_may *)user; 3378 3379 if (must) 3380 mm->must = isl_map_union(mm->must, dep); 3381 else 3382 mm->may = isl_map_union(mm->may, dep); 3383 3384 return isl_stat_ok; 3385 } 3386 3387 static int common_space(void *first, void *second) 3388 { 3389 int depth = *(int *)first; 3390 return 2 * depth; 3391 } 3392 3393 static int map_is_equal(__isl_keep isl_map *map, const char *str) 3394 { 3395 isl_map *map2; 3396 int equal; 3397 3398 if (!map) 3399 return -1; 3400 3401 map2 = isl_map_read_from_str(map->ctx, str); 3402 equal = isl_map_is_equal(map, map2); 3403 isl_map_free(map2); 3404 3405 return equal; 3406 } 3407 3408 static int map_check_equal(__isl_keep isl_map *map, const char *str) 3409 { 3410 int equal; 3411 3412 equal = map_is_equal(map, str); 3413 if (equal < 0) 3414 return -1; 3415 if (!equal) 3416 isl_die(isl_map_get_ctx(map), isl_error_unknown, 3417 "result not as expected", return -1); 3418 return 0; 3419 } 3420 3421 /* Is "set" equal to the set described by "str"? 3422 */ 3423 static isl_bool set_is_equal(__isl_keep isl_set *set, const char *str) 3424 { 3425 isl_set *set2; 3426 isl_bool equal; 3427 3428 if (!set) 3429 return isl_bool_error; 3430 3431 set2 = isl_set_read_from_str(isl_set_get_ctx(set), str); 3432 equal = isl_set_is_equal(set, set2); 3433 isl_set_free(set2); 3434 3435 return equal; 3436 } 3437 3438 /* Check that "set" is equal to the set described by "str". 3439 */ 3440 static isl_stat set_check_equal(__isl_keep isl_set *set, const char *str) 3441 { 3442 isl_bool equal; 3443 3444 equal = set_is_equal(set, str); 3445 if (equal < 0) 3446 return isl_stat_error; 3447 if (!equal) 3448 isl_die(isl_set_get_ctx(set), isl_error_unknown, 3449 "result not as expected", return isl_stat_error); 3450 return isl_stat_ok; 3451 } 3452 3453 /* Is "uset" equal to the union set described by "str"? 3454 */ 3455 static isl_bool uset_is_equal(__isl_keep isl_union_set *uset, const char *str) 3456 { 3457 isl_union_set *uset2; 3458 isl_bool equal; 3459 3460 if (!uset) 3461 return isl_bool_error; 3462 3463 uset2 = isl_union_set_read_from_str(isl_union_set_get_ctx(uset), str); 3464 equal = isl_union_set_is_equal(uset, uset2); 3465 isl_union_set_free(uset2); 3466 3467 return equal; 3468 } 3469 3470 /* Check that "uset" is equal to the union set described by "str". 3471 */ 3472 static isl_stat uset_check_equal(__isl_keep isl_union_set *uset, 3473 const char *str) 3474 { 3475 isl_bool equal; 3476 3477 equal = uset_is_equal(uset, str); 3478 if (equal < 0) 3479 return isl_stat_error; 3480 if (!equal) 3481 isl_die(isl_union_set_get_ctx(uset), isl_error_unknown, 3482 "result not as expected", return isl_stat_error); 3483 return isl_stat_ok; 3484 } 3485 3486 static int test_dep(struct isl_ctx *ctx) 3487 { 3488 const char *str; 3489 isl_space *space; 3490 isl_map *map; 3491 isl_access_info *ai; 3492 isl_flow *flow; 3493 int depth; 3494 struct must_may mm; 3495 3496 depth = 3; 3497 3498 str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }"; 3499 map = isl_map_read_from_str(ctx, str); 3500 ai = isl_access_info_alloc(map, &depth, &common_space, 2); 3501 3502 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }"; 3503 map = isl_map_read_from_str(ctx, str); 3504 ai = isl_access_info_add_source(ai, map, 1, &depth); 3505 3506 str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }"; 3507 map = isl_map_read_from_str(ctx, str); 3508 ai = isl_access_info_add_source(ai, map, 1, &depth); 3509 3510 flow = isl_access_info_compute_flow(ai); 3511 space = isl_space_alloc(ctx, 0, 3, 3); 3512 mm.must = isl_map_empty(isl_space_copy(space)); 3513 mm.may = isl_map_empty(space); 3514 3515 isl_flow_foreach(flow, collect_must_may, &mm); 3516 3517 str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); " 3518 " [1,10,0] -> [2,5,0] }"; 3519 assert(map_is_equal(mm.must, str)); 3520 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }"; 3521 assert(map_is_equal(mm.may, str)); 3522 3523 isl_map_free(mm.must); 3524 isl_map_free(mm.may); 3525 isl_flow_free(flow); 3526 3527 3528 str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }"; 3529 map = isl_map_read_from_str(ctx, str); 3530 ai = isl_access_info_alloc(map, &depth, &common_space, 2); 3531 3532 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }"; 3533 map = isl_map_read_from_str(ctx, str); 3534 ai = isl_access_info_add_source(ai, map, 1, &depth); 3535 3536 str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }"; 3537 map = isl_map_read_from_str(ctx, str); 3538 ai = isl_access_info_add_source(ai, map, 0, &depth); 3539 3540 flow = isl_access_info_compute_flow(ai); 3541 space = isl_space_alloc(ctx, 0, 3, 3); 3542 mm.must = isl_map_empty(isl_space_copy(space)); 3543 mm.may = isl_map_empty(space); 3544 3545 isl_flow_foreach(flow, collect_must_may, &mm); 3546 3547 str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }"; 3548 assert(map_is_equal(mm.must, str)); 3549 str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }"; 3550 assert(map_is_equal(mm.may, str)); 3551 3552 isl_map_free(mm.must); 3553 isl_map_free(mm.may); 3554 isl_flow_free(flow); 3555 3556 3557 str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }"; 3558 map = isl_map_read_from_str(ctx, str); 3559 ai = isl_access_info_alloc(map, &depth, &common_space, 2); 3560 3561 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }"; 3562 map = isl_map_read_from_str(ctx, str); 3563 ai = isl_access_info_add_source(ai, map, 0, &depth); 3564 3565 str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }"; 3566 map = isl_map_read_from_str(ctx, str); 3567 ai = isl_access_info_add_source(ai, map, 0, &depth); 3568 3569 flow = isl_access_info_compute_flow(ai); 3570 space = isl_space_alloc(ctx, 0, 3, 3); 3571 mm.must = isl_map_empty(isl_space_copy(space)); 3572 mm.may = isl_map_empty(space); 3573 3574 isl_flow_foreach(flow, collect_must_may, &mm); 3575 3576 str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; " 3577 " [1,i,0] -> [2,5,0] : 0 <= i <= 10 }"; 3578 assert(map_is_equal(mm.may, str)); 3579 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }"; 3580 assert(map_is_equal(mm.must, str)); 3581 3582 isl_map_free(mm.must); 3583 isl_map_free(mm.may); 3584 isl_flow_free(flow); 3585 3586 3587 str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }"; 3588 map = isl_map_read_from_str(ctx, str); 3589 ai = isl_access_info_alloc(map, &depth, &common_space, 2); 3590 3591 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }"; 3592 map = isl_map_read_from_str(ctx, str); 3593 ai = isl_access_info_add_source(ai, map, 0, &depth); 3594 3595 str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }"; 3596 map = isl_map_read_from_str(ctx, str); 3597 ai = isl_access_info_add_source(ai, map, 0, &depth); 3598 3599 flow = isl_access_info_compute_flow(ai); 3600 space = isl_space_alloc(ctx, 0, 3, 3); 3601 mm.must = isl_map_empty(isl_space_copy(space)); 3602 mm.may = isl_map_empty(space); 3603 3604 isl_flow_foreach(flow, collect_must_may, &mm); 3605 3606 str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; " 3607 " [0,i,1] -> [0,5,2] : 0 <= i <= 5 }"; 3608 assert(map_is_equal(mm.may, str)); 3609 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }"; 3610 assert(map_is_equal(mm.must, str)); 3611 3612 isl_map_free(mm.must); 3613 isl_map_free(mm.may); 3614 isl_flow_free(flow); 3615 3616 3617 str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }"; 3618 map = isl_map_read_from_str(ctx, str); 3619 ai = isl_access_info_alloc(map, &depth, &common_space, 2); 3620 3621 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }"; 3622 map = isl_map_read_from_str(ctx, str); 3623 ai = isl_access_info_add_source(ai, map, 0, &depth); 3624 3625 str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }"; 3626 map = isl_map_read_from_str(ctx, str); 3627 ai = isl_access_info_add_source(ai, map, 0, &depth); 3628 3629 flow = isl_access_info_compute_flow(ai); 3630 space = isl_space_alloc(ctx, 0, 3, 3); 3631 mm.must = isl_map_empty(isl_space_copy(space)); 3632 mm.may = isl_map_empty(space); 3633 3634 isl_flow_foreach(flow, collect_must_may, &mm); 3635 3636 str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; " 3637 " [0,i,2] -> [0,5,1] : 0 <= i <= 4 }"; 3638 assert(map_is_equal(mm.may, str)); 3639 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }"; 3640 assert(map_is_equal(mm.must, str)); 3641 3642 isl_map_free(mm.must); 3643 isl_map_free(mm.may); 3644 isl_flow_free(flow); 3645 3646 3647 depth = 5; 3648 3649 str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }"; 3650 map = isl_map_read_from_str(ctx, str); 3651 ai = isl_access_info_alloc(map, &depth, &common_space, 1); 3652 3653 str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }"; 3654 map = isl_map_read_from_str(ctx, str); 3655 ai = isl_access_info_add_source(ai, map, 1, &depth); 3656 3657 flow = isl_access_info_compute_flow(ai); 3658 space = isl_space_alloc(ctx, 0, 5, 5); 3659 mm.must = isl_map_empty(isl_space_copy(space)); 3660 mm.may = isl_map_empty(space); 3661 3662 isl_flow_foreach(flow, collect_must_may, &mm); 3663 3664 str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }"; 3665 assert(map_is_equal(mm.must, str)); 3666 str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }"; 3667 assert(map_is_equal(mm.may, str)); 3668 3669 isl_map_free(mm.must); 3670 isl_map_free(mm.may); 3671 isl_flow_free(flow); 3672 3673 return 0; 3674 } 3675 3676 /* Check that the dependence analysis proceeds without errors. 3677 * Earlier versions of isl would break down during the analysis 3678 * due to the use of the wrong spaces. 3679 */ 3680 static int test_flow(isl_ctx *ctx) 3681 { 3682 const char *str; 3683 isl_union_map *access, *schedule; 3684 isl_union_map *must_dep, *may_dep; 3685 int r; 3686 3687 str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }"; 3688 access = isl_union_map_read_from_str(ctx, str); 3689 str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; " 3690 "S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; " 3691 "S2[] -> [1,0,0,0]; " 3692 "S3[] -> [-1,0,0,0] }"; 3693 schedule = isl_union_map_read_from_str(ctx, str); 3694 r = isl_union_map_compute_flow(access, isl_union_map_copy(access), 3695 isl_union_map_copy(access), schedule, 3696 &must_dep, &may_dep, NULL, NULL); 3697 isl_union_map_free(may_dep); 3698 isl_union_map_free(must_dep); 3699 3700 return r; 3701 } 3702 3703 struct { 3704 const char *map; 3705 int sv; 3706 } sv_tests[] = { 3707 { "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 }, 3708 { "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 }, 3709 { "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 }, 3710 { "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 }, 3711 { "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 }, 3712 { "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 }, 3713 { "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 }, 3714 { "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 }, 3715 { "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 }, 3716 }; 3717 3718 int test_sv(isl_ctx *ctx) 3719 { 3720 isl_union_map *umap; 3721 int i; 3722 int sv; 3723 3724 for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) { 3725 umap = isl_union_map_read_from_str(ctx, sv_tests[i].map); 3726 sv = isl_union_map_is_single_valued(umap); 3727 isl_union_map_free(umap); 3728 if (sv < 0) 3729 return -1; 3730 if (sv_tests[i].sv && !sv) 3731 isl_die(ctx, isl_error_internal, 3732 "map not detected as single valued", return -1); 3733 if (!sv_tests[i].sv && sv) 3734 isl_die(ctx, isl_error_internal, 3735 "map detected as single valued", return -1); 3736 } 3737 3738 return 0; 3739 } 3740 3741 struct { 3742 const char *str; 3743 int bijective; 3744 } bijective_tests[] = { 3745 { "[N,M]->{[i,j] -> [i]}", 0 }, 3746 { "[N,M]->{[i,j] -> [i] : j=i}", 1 }, 3747 { "[N,M]->{[i,j] -> [i] : j=0}", 1 }, 3748 { "[N,M]->{[i,j] -> [i] : j=N}", 1 }, 3749 { "[N,M]->{[i,j] -> [j,i]}", 1 }, 3750 { "[N,M]->{[i,j] -> [i+j]}", 0 }, 3751 { "[N,M]->{[i,j] -> []}", 0 }, 3752 { "[N,M]->{[i,j] -> [i,j,N]}", 1 }, 3753 { "[N,M]->{[i,j] -> [2i]}", 0 }, 3754 { "[N,M]->{[i,j] -> [i,i]}", 0 }, 3755 { "[N,M]->{[i,j] -> [2i,i]}", 0 }, 3756 { "[N,M]->{[i,j] -> [2i,j]}", 1 }, 3757 { "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1 }, 3758 }; 3759 3760 static int test_bijective(struct isl_ctx *ctx) 3761 { 3762 isl_map *map; 3763 int i; 3764 int bijective; 3765 3766 for (i = 0; i < ARRAY_SIZE(bijective_tests); ++i) { 3767 map = isl_map_read_from_str(ctx, bijective_tests[i].str); 3768 bijective = isl_map_is_bijective(map); 3769 isl_map_free(map); 3770 if (bijective < 0) 3771 return -1; 3772 if (bijective_tests[i].bijective && !bijective) 3773 isl_die(ctx, isl_error_internal, 3774 "map not detected as bijective", return -1); 3775 if (!bijective_tests[i].bijective && bijective) 3776 isl_die(ctx, isl_error_internal, 3777 "map detected as bijective", return -1); 3778 } 3779 3780 return 0; 3781 } 3782 3783 /* Inputs for isl_pw_qpolynomial_gist tests. 3784 * "pwqp" is the input, "set" is the context and "gist" is the expected result. 3785 */ 3786 struct { 3787 const char *pwqp; 3788 const char *set; 3789 const char *gist; 3790 } pwqp_gist_tests[] = { 3791 { "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" }, 3792 { "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" }, 3793 { "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }", 3794 "{ [i] -> -1/2 + 1/2 * i }" }, 3795 { "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" }, 3796 { "{ [i] -> i^2 : i > 0; [i] -> i^2 : i < 0 }", "{ [i] : i != 0 }", 3797 "{ [i] -> i^2 }" }, 3798 }; 3799 3800 /* Perform some basic isl_pw_qpolynomial_gist tests. 3801 */ 3802 static isl_stat test_pwqp_gist(isl_ctx *ctx) 3803 { 3804 int i; 3805 const char *str; 3806 isl_set *set; 3807 isl_pw_qpolynomial *pwqp1, *pwqp2; 3808 isl_bool equal; 3809 3810 for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) { 3811 str = pwqp_gist_tests[i].pwqp; 3812 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str); 3813 str = pwqp_gist_tests[i].set; 3814 set = isl_set_read_from_str(ctx, str); 3815 pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set); 3816 str = pwqp_gist_tests[i].gist; 3817 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str); 3818 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2); 3819 equal = isl_pw_qpolynomial_is_zero(pwqp1); 3820 isl_pw_qpolynomial_free(pwqp1); 3821 3822 if (equal < 0) 3823 return isl_stat_error; 3824 if (!equal) 3825 isl_die(ctx, isl_error_unknown, 3826 "unexpected result", return isl_stat_error); 3827 } 3828 3829 return isl_stat_ok; 3830 } 3831 3832 /* Perform a basic isl_pw_qpolynomial_max test. 3833 */ 3834 static isl_stat test_pwqp_max(isl_ctx *ctx) 3835 { 3836 const char *str; 3837 isl_pw_qpolynomial *pwqp; 3838 isl_val *v; 3839 int ok; 3840 3841 str = "{ [x=2:9, y] -> floor((x + 1)/4)^3 - floor((2x)/3)^2 }"; 3842 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str); 3843 v = isl_pw_qpolynomial_max(pwqp); 3844 ok = isl_val_cmp_si(v, -1) == 0; 3845 isl_val_free(v); 3846 3847 if (!v) 3848 return isl_stat_error; 3849 if (!ok) 3850 isl_die(ctx, isl_error_unknown, "unexpected maximum", 3851 return isl_stat_error); 3852 3853 return isl_stat_ok; 3854 } 3855 3856 static int test_pwqp(struct isl_ctx *ctx) 3857 { 3858 const char *str; 3859 isl_set *set; 3860 isl_pw_qpolynomial *pwqp1, *pwqp2; 3861 int equal; 3862 3863 str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }"; 3864 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str); 3865 3866 pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0, 3867 isl_dim_in, 1, 1); 3868 3869 str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }"; 3870 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str); 3871 3872 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2); 3873 3874 assert(isl_pw_qpolynomial_is_zero(pwqp1)); 3875 3876 isl_pw_qpolynomial_free(pwqp1); 3877 3878 if (test_pwqp_gist(ctx) < 0) 3879 return -1; 3880 3881 str = "{ [i] -> ([([i/2] + [i/2])/5]) }"; 3882 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str); 3883 str = "{ [i] -> ([(2 * [i/2])/5]) }"; 3884 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str); 3885 3886 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2); 3887 3888 assert(isl_pw_qpolynomial_is_zero(pwqp1)); 3889 3890 isl_pw_qpolynomial_free(pwqp1); 3891 3892 str = "{ [x] -> ([x/2] + [(x+1)/2]) }"; 3893 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str); 3894 str = "{ [x] -> x }"; 3895 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str); 3896 3897 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2); 3898 3899 assert(isl_pw_qpolynomial_is_zero(pwqp1)); 3900 3901 isl_pw_qpolynomial_free(pwqp1); 3902 3903 str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }"; 3904 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str); 3905 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str); 3906 pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1); 3907 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2); 3908 assert(isl_pw_qpolynomial_is_zero(pwqp1)); 3909 isl_pw_qpolynomial_free(pwqp1); 3910 3911 str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }"; 3912 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str); 3913 str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }"; 3914 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str); 3915 set = isl_set_read_from_str(ctx, "{ [a,b,a] }"); 3916 pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set); 3917 equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2); 3918 isl_pw_qpolynomial_free(pwqp1); 3919 isl_pw_qpolynomial_free(pwqp2); 3920 if (equal < 0) 3921 return -1; 3922 if (!equal) 3923 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 3924 3925 str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }"; 3926 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str); 3927 str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }"; 3928 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str); 3929 pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1, 3930 isl_val_one(ctx)); 3931 equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2); 3932 isl_pw_qpolynomial_free(pwqp1); 3933 isl_pw_qpolynomial_free(pwqp2); 3934 if (equal < 0) 3935 return -1; 3936 if (!equal) 3937 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 3938 3939 if (test_pwqp_max(ctx) < 0) 3940 return -1; 3941 3942 return 0; 3943 } 3944 3945 static int test_split_periods(isl_ctx *ctx) 3946 { 3947 const char *str; 3948 isl_pw_qpolynomial *pwqp; 3949 3950 str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : " 3951 "U + 2V + 3 >= 0 and - U -2V >= 0 and - U + 10 >= 0 and " 3952 "U >= 0; [U,V] -> U^2 : U >= 100 }"; 3953 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str); 3954 3955 pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2); 3956 3957 isl_pw_qpolynomial_free(pwqp); 3958 3959 if (!pwqp) 3960 return -1; 3961 3962 return 0; 3963 } 3964 3965 static int test_union(isl_ctx *ctx) 3966 { 3967 const char *str; 3968 isl_union_set *uset1, *uset2; 3969 isl_union_map *umap1, *umap2; 3970 int equal; 3971 3972 str = "{ [i] : 0 <= i <= 1 }"; 3973 uset1 = isl_union_set_read_from_str(ctx, str); 3974 str = "{ [1] -> [0] }"; 3975 umap1 = isl_union_map_read_from_str(ctx, str); 3976 3977 umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1); 3978 equal = isl_union_map_is_equal(umap1, umap2); 3979 3980 isl_union_map_free(umap1); 3981 isl_union_map_free(umap2); 3982 3983 if (equal < 0) 3984 return -1; 3985 if (!equal) 3986 isl_die(ctx, isl_error_unknown, "union maps not equal", 3987 return -1); 3988 3989 str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }"; 3990 umap1 = isl_union_map_read_from_str(ctx, str); 3991 str = "{ A[i]; B[i] }"; 3992 uset1 = isl_union_set_read_from_str(ctx, str); 3993 3994 uset2 = isl_union_map_domain(umap1); 3995 3996 equal = isl_union_set_is_equal(uset1, uset2); 3997 3998 isl_union_set_free(uset1); 3999 isl_union_set_free(uset2); 4000 4001 if (equal < 0) 4002 return -1; 4003 if (!equal) 4004 isl_die(ctx, isl_error_unknown, "union sets not equal", 4005 return -1); 4006 4007 return 0; 4008 } 4009 4010 /* Inputs for basic isl_pw_qpolynomial_bound tests. 4011 * "type" is the type of bound that should be computed. 4012 * "poly" is a string representation of the input. 4013 * "bound" is a string representation of the expected result. 4014 * "tight" is set if the result is expected to be tight. 4015 */ 4016 static struct { 4017 int tight; 4018 enum isl_fold type; 4019 const char *poly; 4020 const char *bound; 4021 } bound_tests[] = { 4022 /* Check that computing a bound of a non-zero polynomial 4023 * over an unbounded domain does not produce a rational value. 4024 * In particular, check that the upper bound is infinity. 4025 */ 4026 { 0, isl_fold_max, "{ [m, n] -> -m * n }", "{ max(infty) }" }, 4027 { 1, isl_fold_max, "{ [[a, b, c, d] -> [e]] -> 0 }", 4028 "{ [a, b, c, d] -> max(0) }" }, 4029 { 1, isl_fold_max, "{ [[x] -> [x]] -> 1 : exists a : x = 2 a }", 4030 "{ [x] -> max(1) : x mod 2 = 0 }" }, 4031 { 1, isl_fold_min, "{ [x=5:10] -> (x + 2)^2 }", "{ min(49) }" }, 4032 { 1, isl_fold_max, "{ [0:10] -> 1 }", "{ max(1) }" }, 4033 { 1, isl_fold_max, "{ [[m] -> [0:m]] -> m^2 }", 4034 "{ [m] -> max(m^2) : m >= 0 }" }, 4035 }; 4036 4037 /* Check that the bound computation can handle differences 4038 * in domain dimension names of the input polynomial and its domain. 4039 */ 4040 static isl_stat test_bound_space(isl_ctx *ctx) 4041 { 4042 const char *str; 4043 isl_set *set; 4044 isl_pw_qpolynomial *pwqp; 4045 isl_pw_qpolynomial_fold *pwf; 4046 4047 str = "{ [[c] -> [c]] }"; 4048 set = isl_set_read_from_str(ctx, str); 4049 str = "{ [[a] -> [b]] -> 1 }"; 4050 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str); 4051 pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set); 4052 pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL); 4053 isl_pw_qpolynomial_fold_free(pwf); 4054 4055 return isl_stat_non_null(pwf); 4056 } 4057 4058 /* Perform basic isl_pw_qpolynomial_bound tests. 4059 */ 4060 static int test_bound(isl_ctx *ctx) 4061 { 4062 int i; 4063 4064 if (test_bound_space(ctx) < 0) 4065 return -1; 4066 4067 for (i = 0; i < ARRAY_SIZE(bound_tests); ++i) { 4068 const char *str; 4069 enum isl_fold type; 4070 isl_bool equal, tight; 4071 isl_pw_qpolynomial *pwqp; 4072 isl_pw_qpolynomial_fold *pwf1, *pwf2; 4073 4074 str = bound_tests[i].poly; 4075 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str); 4076 type = bound_tests[i].type; 4077 pwf1 = isl_pw_qpolynomial_bound(pwqp, type, &tight); 4078 str = bound_tests[i].bound; 4079 pwf2 = isl_pw_qpolynomial_fold_read_from_str(ctx, str); 4080 equal = isl_pw_qpolynomial_fold_plain_is_equal(pwf1, pwf2); 4081 isl_pw_qpolynomial_fold_free(pwf2); 4082 isl_pw_qpolynomial_fold_free(pwf1); 4083 if (equal < 0) 4084 return -1; 4085 if (!equal) 4086 isl_die(ctx, isl_error_unknown, 4087 "incorrect bound result", return -1); 4088 if (bound_tests[i].tight && !tight) 4089 isl_die(ctx, isl_error_unknown, 4090 "bound unexpectedly not tight", return -1); 4091 } 4092 4093 return 0; 4094 } 4095 4096 /* isl_set is defined to isl_map internally, so the corresponding elements 4097 * are isl_basic_map objects. 4098 */ 4099 #undef EL_BASE 4100 #undef SET_BASE 4101 #define EL_BASE basic_map 4102 #define SET_BASE set 4103 #include "isl_test_list_templ.c" 4104 4105 #undef EL_BASE 4106 #undef SET_BASE 4107 #define EL_BASE basic_set 4108 #define SET_BASE union_set 4109 #include "isl_test_list_templ.c" 4110 4111 #undef EL_BASE 4112 #undef SET_BASE 4113 #define EL_BASE set 4114 #define SET_BASE union_set 4115 #include "isl_test_list_templ.c" 4116 4117 #undef EL_BASE 4118 #undef SET_BASE 4119 #define EL_BASE basic_map 4120 #define SET_BASE map 4121 #include "isl_test_list_templ.c" 4122 4123 #undef EL_BASE 4124 #undef SET_BASE 4125 #define EL_BASE map 4126 #define SET_BASE union_map 4127 #include "isl_test_list_templ.c" 4128 4129 /* Check that the conversion from isl objects to lists works as expected. 4130 */ 4131 static int test_get_list(isl_ctx *ctx) 4132 { 4133 if (test_get_list_basic_map_from_set(ctx, "{ [0]; [2]; [3] }")) 4134 return -1; 4135 if (test_get_list_basic_set_from_union_set(ctx, "{ A[0]; B[2]; B[3] }")) 4136 return -1; 4137 if (test_get_list_set_from_union_set(ctx, "{ A[0]; A[2]; B[3] }")) 4138 return -1; 4139 if (test_get_list_basic_map_from_map(ctx, 4140 "{ [0] -> [0]; [2] -> [0]; [3] -> [0] }")) 4141 return -1; 4142 if (test_get_list_map_from_union_map(ctx, 4143 "{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }")) 4144 return -1; 4145 4146 return 0; 4147 } 4148 4149 static int test_lift(isl_ctx *ctx) 4150 { 4151 const char *str; 4152 isl_basic_map *bmap; 4153 isl_basic_set *bset; 4154 4155 str = "{ [i0] : exists e0 : i0 = 4e0 }"; 4156 bset = isl_basic_set_read_from_str(ctx, str); 4157 bset = isl_basic_set_lift(bset); 4158 bmap = isl_basic_map_from_range(bset); 4159 bset = isl_basic_map_domain(bmap); 4160 isl_basic_set_free(bset); 4161 4162 return 0; 4163 } 4164 4165 /* Check that isl_set_is_subset is not confused by identical 4166 * integer divisions. 4167 * The call to isl_set_normalize ensures that the equality constraints 4168 * a = b = 0 are discovered, turning e0 and e1 into identical 4169 * integer divisions. Any further simplification would remove 4170 * the duplicate integer divisions. 4171 */ 4172 static isl_stat test_subset_duplicate_integer_divisions(isl_ctx *ctx) 4173 { 4174 const char *str; 4175 isl_bool is_subset; 4176 isl_set *set1, *set2; 4177 4178 str = "{ [a, b, c, d] : " 4179 "exists (e0 = floor((a + d)/4), e1 = floor((d)/4), " 4180 "e2 = floor((-a - d + 4 *floor((a + d)/4))/10), " 4181 "e3 = floor((-d + 4*floor((d)/4))/10): " 4182 "10e2 = -a - 2c - d + 4e0 and 10e3 = -2c - d + 4e1 and " 4183 "b >= 0 and a <= 0 and b <= a) }"; 4184 set1 = isl_set_read_from_str(ctx, str); 4185 set2 = isl_set_read_from_str(ctx, str); 4186 set2 = isl_set_normalize(set2); 4187 4188 is_subset = isl_set_is_subset(set1, set2); 4189 4190 isl_set_free(set1); 4191 isl_set_free(set2); 4192 4193 if (is_subset < 0) 4194 return isl_stat_error; 4195 if (!is_subset) 4196 isl_die(ctx, isl_error_unknown, 4197 "set is not considered to be a subset of itself", 4198 return isl_stat_error); 4199 4200 return isl_stat_ok; 4201 } 4202 4203 struct { 4204 const char *set1; 4205 const char *set2; 4206 int subset; 4207 } subset_tests[] = { 4208 { "{ [112, 0] }", 4209 "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: " 4210 "16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and " 4211 "16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 }, 4212 { "{ [65] }", 4213 "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], " 4214 "e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], " 4215 "e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: " 4216 "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and " 4217 "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and " 4218 "256e0 <= 255i and 256e0 >= -255 + 255i and " 4219 "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and " 4220 "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and " 4221 "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 }, 4222 { "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 }, 4223 { "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 }, 4224 { "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 }, 4225 { "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 }, 4226 { "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and " 4227 "4e0 >= -1 + t and i >= 57 and i <= 62 and " 4228 "4e0 <= 62 + t - i and 4e0 >= -61 + t + i and " 4229 "t >= 0 and t <= 511 and 4e0 <= -57 + t + i and " 4230 "4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }", 4231 "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and " 4232 "4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and " 4233 "4e0 <= -57 + i0 + i1)) or " 4234 "(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and " 4235 "4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and " 4236 "4e0 >= -61 + i0 + i1)) or " 4237 "(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 }, 4238 { "[a, b] -> { : a = 0 and b = -1 }", "[b, a] -> { : b >= -10 }", 1 }, 4239 }; 4240 4241 static int test_subset(isl_ctx *ctx) 4242 { 4243 int i; 4244 isl_set *set1, *set2; 4245 int subset; 4246 4247 if (test_subset_duplicate_integer_divisions(ctx) < 0) 4248 return -1; 4249 4250 for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) { 4251 set1 = isl_set_read_from_str(ctx, subset_tests[i].set1); 4252 set2 = isl_set_read_from_str(ctx, subset_tests[i].set2); 4253 subset = isl_set_is_subset(set1, set2); 4254 isl_set_free(set1); 4255 isl_set_free(set2); 4256 if (subset < 0) 4257 return -1; 4258 if (subset != subset_tests[i].subset) 4259 isl_die(ctx, isl_error_unknown, 4260 "incorrect subset result", return -1); 4261 } 4262 4263 return 0; 4264 } 4265 4266 /* Perform a set subtraction with a set that has a non-obviously empty disjunct. 4267 * Older versions of isl would fail on such cases. 4268 */ 4269 static isl_stat test_subtract_empty(isl_ctx *ctx) 4270 { 4271 const char *str; 4272 isl_set *s1, *s2; 4273 4274 s1 = isl_set_read_from_str(ctx, "{ [0] }"); 4275 str = "{ [a] : (exists (e0, e1, e2: 1056e1 <= 32 + a - 33e0 and " 4276 "1089e1 >= a - 33e0 and 1089e1 <= 1 + a - 33e0 and " 4277 "33e2 >= -a + 33e0 + 1056e1 and " 4278 "33e2 < -2a + 66e0 + 2112e1)) or a = 0 }"; 4279 s2 = isl_set_read_from_str(ctx, str); 4280 s1 = isl_set_subtract(s1, s2); 4281 isl_set_free(s1); 4282 4283 return isl_stat_non_null(s1); 4284 } 4285 4286 struct { 4287 const char *minuend; 4288 const char *subtrahend; 4289 const char *difference; 4290 } subtract_domain_tests[] = { 4291 { "{ A[i] -> B[i] }", "{ A[i] }", "{ }" }, 4292 { "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" }, 4293 { "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" }, 4294 }; 4295 4296 static int test_subtract(isl_ctx *ctx) 4297 { 4298 int i; 4299 isl_union_map *umap1, *umap2; 4300 isl_union_pw_multi_aff *upma1, *upma2; 4301 isl_union_set *uset; 4302 int equal; 4303 4304 if (test_subtract_empty(ctx) < 0) 4305 return -1; 4306 4307 for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) { 4308 umap1 = isl_union_map_read_from_str(ctx, 4309 subtract_domain_tests[i].minuend); 4310 uset = isl_union_set_read_from_str(ctx, 4311 subtract_domain_tests[i].subtrahend); 4312 umap2 = isl_union_map_read_from_str(ctx, 4313 subtract_domain_tests[i].difference); 4314 umap1 = isl_union_map_subtract_domain(umap1, uset); 4315 equal = isl_union_map_is_equal(umap1, umap2); 4316 isl_union_map_free(umap1); 4317 isl_union_map_free(umap2); 4318 if (equal < 0) 4319 return -1; 4320 if (!equal) 4321 isl_die(ctx, isl_error_unknown, 4322 "incorrect subtract domain result", return -1); 4323 } 4324 4325 for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) { 4326 upma1 = isl_union_pw_multi_aff_read_from_str(ctx, 4327 subtract_domain_tests[i].minuend); 4328 uset = isl_union_set_read_from_str(ctx, 4329 subtract_domain_tests[i].subtrahend); 4330 upma2 = isl_union_pw_multi_aff_read_from_str(ctx, 4331 subtract_domain_tests[i].difference); 4332 upma1 = isl_union_pw_multi_aff_subtract_domain(upma1, uset); 4333 equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2); 4334 isl_union_pw_multi_aff_free(upma1); 4335 isl_union_pw_multi_aff_free(upma2); 4336 if (equal < 0) 4337 return -1; 4338 if (!equal) 4339 isl_die(ctx, isl_error_unknown, 4340 "incorrect subtract domain result", return -1); 4341 } 4342 4343 return 0; 4344 } 4345 4346 /* Check that intersecting the empty basic set with another basic set 4347 * does not increase the number of constraints. In particular, 4348 * the empty basic set should maintain its canonical representation. 4349 */ 4350 static int test_intersect_1(isl_ctx *ctx) 4351 { 4352 isl_size n1, n2; 4353 isl_basic_set *bset1, *bset2; 4354 4355 bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }"); 4356 bset2 = isl_basic_set_read_from_str(ctx, "{ [1,2,3] }"); 4357 n1 = isl_basic_set_n_constraint(bset1); 4358 bset1 = isl_basic_set_intersect(bset1, bset2); 4359 n2 = isl_basic_set_n_constraint(bset1); 4360 isl_basic_set_free(bset1); 4361 if (n1 < 0 || n2 < 0) 4362 return -1; 4363 if (n1 != n2) 4364 isl_die(ctx, isl_error_unknown, 4365 "number of constraints of empty set changed", 4366 return -1); 4367 4368 return 0; 4369 } 4370 4371 /* Check that intersecting a set with itself does not cause 4372 * an explosion in the number of disjuncts. 4373 */ 4374 static isl_stat test_intersect_2(isl_ctx *ctx) 4375 { 4376 int i; 4377 isl_set *set; 4378 4379 set = isl_set_read_from_str(ctx, "{ [x,y] : x >= 0 or y >= 0 }"); 4380 for (i = 0; i < 100; ++i) 4381 set = isl_set_intersect(set, isl_set_copy(set)); 4382 isl_set_free(set); 4383 if (!set) 4384 return isl_stat_error; 4385 return isl_stat_ok; 4386 } 4387 4388 /* Perform some intersection tests. 4389 */ 4390 static int test_intersect(isl_ctx *ctx) 4391 { 4392 if (test_intersect_1(ctx) < 0) 4393 return -1; 4394 if (test_intersect_2(ctx) < 0) 4395 return -1; 4396 4397 return 0; 4398 } 4399 4400 int test_factorize(isl_ctx *ctx) 4401 { 4402 const char *str; 4403 isl_basic_set *bset; 4404 isl_factorizer *f; 4405 4406 str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and " 4407 "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and " 4408 "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and " 4409 "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and " 4410 "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and " 4411 "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and " 4412 "3i5 >= -2i0 - i2 + 3i4 }"; 4413 bset = isl_basic_set_read_from_str(ctx, str); 4414 f = isl_basic_set_factorizer(bset); 4415 isl_basic_set_free(bset); 4416 isl_factorizer_free(f); 4417 if (!f) 4418 isl_die(ctx, isl_error_unknown, 4419 "failed to construct factorizer", return -1); 4420 4421 str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : " 4422 "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and " 4423 "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and " 4424 "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and " 4425 "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and " 4426 "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and " 4427 "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and " 4428 "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and " 4429 "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and " 4430 "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }"; 4431 bset = isl_basic_set_read_from_str(ctx, str); 4432 f = isl_basic_set_factorizer(bset); 4433 isl_basic_set_free(bset); 4434 isl_factorizer_free(f); 4435 if (!f) 4436 isl_die(ctx, isl_error_unknown, 4437 "failed to construct factorizer", return -1); 4438 4439 return 0; 4440 } 4441 4442 static isl_stat check_injective(__isl_take isl_map *map, void *user) 4443 { 4444 int *injective = user; 4445 4446 *injective = isl_map_is_injective(map); 4447 isl_map_free(map); 4448 4449 if (*injective < 0 || !*injective) 4450 return isl_stat_error; 4451 4452 return isl_stat_ok; 4453 } 4454 4455 int test_one_schedule(isl_ctx *ctx, const char *d, const char *w, 4456 const char *r, const char *s, int tilable, int parallel) 4457 { 4458 int i; 4459 isl_union_set *D; 4460 isl_union_map *W, *R, *S; 4461 isl_union_map *empty; 4462 isl_union_map *dep_raw, *dep_war, *dep_waw, *dep; 4463 isl_union_map *validity, *proximity, *coincidence; 4464 isl_union_map *schedule; 4465 isl_union_map *test; 4466 isl_union_set *delta; 4467 isl_union_set *domain; 4468 isl_set *delta_set; 4469 isl_set *slice; 4470 isl_set *origin; 4471 isl_schedule_constraints *sc; 4472 isl_schedule *sched; 4473 int is_nonneg, is_parallel, is_tilable, is_injection, is_complete; 4474 isl_size n; 4475 4476 D = isl_union_set_read_from_str(ctx, d); 4477 W = isl_union_map_read_from_str(ctx, w); 4478 R = isl_union_map_read_from_str(ctx, r); 4479 S = isl_union_map_read_from_str(ctx, s); 4480 4481 W = isl_union_map_intersect_domain(W, isl_union_set_copy(D)); 4482 R = isl_union_map_intersect_domain(R, isl_union_set_copy(D)); 4483 4484 empty = isl_union_map_empty(isl_union_map_get_space(S)); 4485 isl_union_map_compute_flow(isl_union_map_copy(R), 4486 isl_union_map_copy(W), empty, 4487 isl_union_map_copy(S), 4488 &dep_raw, NULL, NULL, NULL); 4489 isl_union_map_compute_flow(isl_union_map_copy(W), 4490 isl_union_map_copy(W), 4491 isl_union_map_copy(R), 4492 isl_union_map_copy(S), 4493 &dep_waw, &dep_war, NULL, NULL); 4494 4495 dep = isl_union_map_union(dep_waw, dep_war); 4496 dep = isl_union_map_union(dep, dep_raw); 4497 validity = isl_union_map_copy(dep); 4498 coincidence = isl_union_map_copy(dep); 4499 proximity = isl_union_map_copy(dep); 4500 4501 sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D)); 4502 sc = isl_schedule_constraints_set_validity(sc, validity); 4503 sc = isl_schedule_constraints_set_coincidence(sc, coincidence); 4504 sc = isl_schedule_constraints_set_proximity(sc, proximity); 4505 sched = isl_schedule_constraints_compute_schedule(sc); 4506 schedule = isl_schedule_get_map(sched); 4507 isl_schedule_free(sched); 4508 isl_union_map_free(W); 4509 isl_union_map_free(R); 4510 isl_union_map_free(S); 4511 4512 is_injection = 1; 4513 isl_union_map_foreach_map(schedule, &check_injective, &is_injection); 4514 4515 domain = isl_union_map_domain(isl_union_map_copy(schedule)); 4516 is_complete = isl_union_set_is_subset(D, domain); 4517 isl_union_set_free(D); 4518 isl_union_set_free(domain); 4519 4520 test = isl_union_map_reverse(isl_union_map_copy(schedule)); 4521 test = isl_union_map_apply_range(test, dep); 4522 test = isl_union_map_apply_range(test, schedule); 4523 4524 delta = isl_union_map_deltas(test); 4525 n = isl_union_set_n_set(delta); 4526 if (n < 0) { 4527 isl_union_set_free(delta); 4528 return -1; 4529 } 4530 if (n == 0) { 4531 is_tilable = 1; 4532 is_parallel = 1; 4533 is_nonneg = 1; 4534 isl_union_set_free(delta); 4535 } else { 4536 isl_size dim; 4537 4538 delta_set = isl_set_from_union_set(delta); 4539 4540 slice = isl_set_universe(isl_set_get_space(delta_set)); 4541 for (i = 0; i < tilable; ++i) 4542 slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0); 4543 is_tilable = isl_set_is_subset(delta_set, slice); 4544 isl_set_free(slice); 4545 4546 slice = isl_set_universe(isl_set_get_space(delta_set)); 4547 for (i = 0; i < parallel; ++i) 4548 slice = isl_set_fix_si(slice, isl_dim_set, i, 0); 4549 is_parallel = isl_set_is_subset(delta_set, slice); 4550 isl_set_free(slice); 4551 4552 origin = isl_set_universe(isl_set_get_space(delta_set)); 4553 dim = isl_set_dim(origin, isl_dim_set); 4554 if (dim < 0) 4555 origin = isl_set_free(origin); 4556 for (i = 0; i < dim; ++i) 4557 origin = isl_set_fix_si(origin, isl_dim_set, i, 0); 4558 4559 delta_set = isl_set_union(delta_set, isl_set_copy(origin)); 4560 delta_set = isl_set_lexmin(delta_set); 4561 4562 is_nonneg = isl_set_is_equal(delta_set, origin); 4563 4564 isl_set_free(origin); 4565 isl_set_free(delta_set); 4566 } 4567 4568 if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 || 4569 is_injection < 0 || is_complete < 0) 4570 return -1; 4571 if (!is_complete) 4572 isl_die(ctx, isl_error_unknown, 4573 "generated schedule incomplete", return -1); 4574 if (!is_injection) 4575 isl_die(ctx, isl_error_unknown, 4576 "generated schedule not injective on each statement", 4577 return -1); 4578 if (!is_nonneg) 4579 isl_die(ctx, isl_error_unknown, 4580 "negative dependences in generated schedule", 4581 return -1); 4582 if (!is_tilable) 4583 isl_die(ctx, isl_error_unknown, 4584 "generated schedule not as tilable as expected", 4585 return -1); 4586 if (!is_parallel) 4587 isl_die(ctx, isl_error_unknown, 4588 "generated schedule not as parallel as expected", 4589 return -1); 4590 4591 return 0; 4592 } 4593 4594 /* Compute a schedule for the given instance set, validity constraints, 4595 * proximity constraints and context and return a corresponding union map 4596 * representation. 4597 */ 4598 static __isl_give isl_union_map *compute_schedule_with_context(isl_ctx *ctx, 4599 const char *domain, const char *validity, const char *proximity, 4600 const char *context) 4601 { 4602 isl_set *con; 4603 isl_union_set *dom; 4604 isl_union_map *dep; 4605 isl_union_map *prox; 4606 isl_schedule_constraints *sc; 4607 isl_schedule *schedule; 4608 isl_union_map *sched; 4609 4610 con = isl_set_read_from_str(ctx, context); 4611 dom = isl_union_set_read_from_str(ctx, domain); 4612 dep = isl_union_map_read_from_str(ctx, validity); 4613 prox = isl_union_map_read_from_str(ctx, proximity); 4614 sc = isl_schedule_constraints_on_domain(dom); 4615 sc = isl_schedule_constraints_set_context(sc, con); 4616 sc = isl_schedule_constraints_set_validity(sc, dep); 4617 sc = isl_schedule_constraints_set_proximity(sc, prox); 4618 schedule = isl_schedule_constraints_compute_schedule(sc); 4619 sched = isl_schedule_get_map(schedule); 4620 isl_schedule_free(schedule); 4621 4622 return sched; 4623 } 4624 4625 /* Compute a schedule for the given instance set, validity constraints and 4626 * proximity constraints and return a corresponding union map representation. 4627 */ 4628 static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx, 4629 const char *domain, const char *validity, const char *proximity) 4630 { 4631 return compute_schedule_with_context(ctx, domain, validity, proximity, 4632 "{ : }"); 4633 } 4634 4635 /* Check that a schedule can be constructed on the given domain 4636 * with the given validity and proximity constraints. 4637 */ 4638 static int test_has_schedule(isl_ctx *ctx, const char *domain, 4639 const char *validity, const char *proximity) 4640 { 4641 isl_union_map *sched; 4642 4643 sched = compute_schedule(ctx, domain, validity, proximity); 4644 if (!sched) 4645 return -1; 4646 4647 isl_union_map_free(sched); 4648 return 0; 4649 } 4650 4651 int test_special_schedule(isl_ctx *ctx, const char *domain, 4652 const char *validity, const char *proximity, const char *expected_sched) 4653 { 4654 isl_union_map *sched1, *sched2; 4655 int equal; 4656 4657 sched1 = compute_schedule(ctx, domain, validity, proximity); 4658 sched2 = isl_union_map_read_from_str(ctx, expected_sched); 4659 4660 equal = isl_union_map_is_equal(sched1, sched2); 4661 isl_union_map_free(sched1); 4662 isl_union_map_free(sched2); 4663 4664 if (equal < 0) 4665 return -1; 4666 if (!equal) 4667 isl_die(ctx, isl_error_unknown, "unexpected schedule", 4668 return -1); 4669 4670 return 0; 4671 } 4672 4673 /* Check that the schedule map is properly padded, i.e., that the range 4674 * lives in a single space. 4675 */ 4676 static int test_padded_schedule(isl_ctx *ctx) 4677 { 4678 const char *str; 4679 isl_union_set *D; 4680 isl_union_map *validity, *proximity; 4681 isl_schedule_constraints *sc; 4682 isl_schedule *sched; 4683 isl_union_map *umap; 4684 isl_union_set *range; 4685 isl_set *set; 4686 4687 str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }"; 4688 D = isl_union_set_read_from_str(ctx, str); 4689 validity = isl_union_map_empty(isl_union_set_get_space(D)); 4690 proximity = isl_union_map_copy(validity); 4691 sc = isl_schedule_constraints_on_domain(D); 4692 sc = isl_schedule_constraints_set_validity(sc, validity); 4693 sc = isl_schedule_constraints_set_proximity(sc, proximity); 4694 sched = isl_schedule_constraints_compute_schedule(sc); 4695 umap = isl_schedule_get_map(sched); 4696 isl_schedule_free(sched); 4697 range = isl_union_map_range(umap); 4698 set = isl_set_from_union_set(range); 4699 isl_set_free(set); 4700 4701 if (!set) 4702 return -1; 4703 4704 return 0; 4705 } 4706 4707 /* Check that conditional validity constraints are also taken into 4708 * account across bands. 4709 * In particular, try to make sure that live ranges D[1,0]->C[2,1] and 4710 * D[2,0]->C[3,0] are not local in the outer band of the generated schedule 4711 * and then check that the adjacent order constraint C[2,1]->D[2,0] 4712 * is enforced by the rest of the schedule. 4713 */ 4714 static int test_special_conditional_schedule_constraints(isl_ctx *ctx) 4715 { 4716 const char *str; 4717 isl_union_set *domain; 4718 isl_union_map *validity, *proximity, *condition; 4719 isl_union_map *sink, *source, *dep; 4720 isl_schedule_constraints *sc; 4721 isl_schedule *schedule; 4722 isl_union_access_info *access; 4723 isl_union_flow *flow; 4724 int empty; 4725 4726 str = "[n] -> { C[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; " 4727 "A[k] : k >= 1 and k <= -1 + n; " 4728 "B[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; " 4729 "D[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k }"; 4730 domain = isl_union_set_read_from_str(ctx, str); 4731 sc = isl_schedule_constraints_on_domain(domain); 4732 str = "[n] -> { D[k, i] -> C[1 + k, k - i] : " 4733 "k <= -2 + n and i >= 1 and i <= -1 + k; " 4734 "D[k, i] -> C[1 + k, i] : " 4735 "k <= -2 + n and i >= 1 and i <= -1 + k; " 4736 "D[k, 0] -> C[1 + k, k] : k >= 1 and k <= -2 + n; " 4737 "D[k, 0] -> C[1 + k, 0] : k >= 1 and k <= -2 + n }"; 4738 validity = isl_union_map_read_from_str(ctx, str); 4739 sc = isl_schedule_constraints_set_validity(sc, validity); 4740 str = "[n] -> { C[k, i] -> D[k, i] : " 4741 "0 <= i <= -1 + k and k <= -1 + n }"; 4742 proximity = isl_union_map_read_from_str(ctx, str); 4743 sc = isl_schedule_constraints_set_proximity(sc, proximity); 4744 str = "[n] -> { [D[k, i] -> a[]] -> [C[1 + k, k - i] -> b[]] : " 4745 "i <= -1 + k and i >= 1 and k <= -2 + n; " 4746 "[B[k, i] -> c[]] -> [B[k, 1 + i] -> c[]] : " 4747 "k <= -1 + n and i >= 0 and i <= -2 + k }"; 4748 condition = isl_union_map_read_from_str(ctx, str); 4749 str = "[n] -> { [B[k, i] -> e[]] -> [D[k, i] -> a[]] : " 4750 "i >= 0 and i <= -1 + k and k <= -1 + n; " 4751 "[C[k, i] -> b[]] -> [D[k', -1 + k - i] -> a[]] : " 4752 "i >= 0 and i <= -1 + k and k <= -1 + n and " 4753 "k' <= -1 + n and k' >= k - i and k' >= 1 + k; " 4754 "[C[k, i] -> b[]] -> [D[k, -1 + k - i] -> a[]] : " 4755 "i >= 0 and i <= -1 + k and k <= -1 + n; " 4756 "[B[k, i] -> c[]] -> [A[k'] -> d[]] : " 4757 "k <= -1 + n and i >= 0 and i <= -1 + k and " 4758 "k' >= 1 and k' <= -1 + n and k' >= 1 + k }"; 4759 validity = isl_union_map_read_from_str(ctx, str); 4760 sc = isl_schedule_constraints_set_conditional_validity(sc, condition, 4761 validity); 4762 schedule = isl_schedule_constraints_compute_schedule(sc); 4763 str = "{ D[2,0] -> [] }"; 4764 sink = isl_union_map_read_from_str(ctx, str); 4765 access = isl_union_access_info_from_sink(sink); 4766 str = "{ C[2,1] -> [] }"; 4767 source = isl_union_map_read_from_str(ctx, str); 4768 access = isl_union_access_info_set_must_source(access, source); 4769 access = isl_union_access_info_set_schedule(access, schedule); 4770 flow = isl_union_access_info_compute_flow(access); 4771 dep = isl_union_flow_get_must_dependence(flow); 4772 isl_union_flow_free(flow); 4773 empty = isl_union_map_is_empty(dep); 4774 isl_union_map_free(dep); 4775 4776 if (empty < 0) 4777 return -1; 4778 if (empty) 4779 isl_die(ctx, isl_error_unknown, 4780 "conditional validity not respected", return -1); 4781 4782 return 0; 4783 } 4784 4785 /* Check that the test for violated conditional validity constraints 4786 * is not confused by domain compression. 4787 * In particular, earlier versions of isl would apply 4788 * a schedule on the compressed domains to the original domains, 4789 * resulting in a failure to detect that the default schedule 4790 * violates the conditional validity constraints. 4791 */ 4792 static int test_special_conditional_schedule_constraints_2(isl_ctx *ctx) 4793 { 4794 const char *str; 4795 isl_bool empty; 4796 isl_union_set *domain; 4797 isl_union_map *validity, *condition; 4798 isl_schedule_constraints *sc; 4799 isl_schedule *schedule; 4800 isl_union_map *umap; 4801 isl_map *map, *ge; 4802 4803 str = "{ A[0, i] : 0 <= i <= 10; B[1, i] : 0 <= i <= 10 }"; 4804 domain = isl_union_set_read_from_str(ctx, str); 4805 sc = isl_schedule_constraints_on_domain(domain); 4806 str = "{ B[1, i] -> A[0, i + 1] }"; 4807 condition = isl_union_map_read_from_str(ctx, str); 4808 str = "{ A[0, i] -> B[1, i - 1] }"; 4809 validity = isl_union_map_read_from_str(ctx, str); 4810 sc = isl_schedule_constraints_set_conditional_validity(sc, condition, 4811 isl_union_map_copy(validity)); 4812 schedule = isl_schedule_constraints_compute_schedule(sc); 4813 umap = isl_schedule_get_map(schedule); 4814 isl_schedule_free(schedule); 4815 validity = isl_union_map_apply_domain(validity, 4816 isl_union_map_copy(umap)); 4817 validity = isl_union_map_apply_range(validity, umap); 4818 map = isl_map_from_union_map(validity); 4819 ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map))); 4820 map = isl_map_intersect(map, ge); 4821 empty = isl_map_is_empty(map); 4822 isl_map_free(map); 4823 4824 if (empty < 0) 4825 return -1; 4826 if (!empty) 4827 isl_die(ctx, isl_error_unknown, 4828 "conditional validity constraints not satisfied", 4829 return -1); 4830 4831 return 0; 4832 } 4833 4834 /* Input for testing of schedule construction based on 4835 * conditional constraints. 4836 * 4837 * domain is the iteration domain 4838 * flow are the flow dependences, which determine the validity and 4839 * proximity constraints 4840 * condition are the conditions on the conditional validity constraints 4841 * conditional_validity are the conditional validity constraints 4842 * outer_band_n is the expected number of members in the outer band 4843 */ 4844 struct { 4845 const char *domain; 4846 const char *flow; 4847 const char *condition; 4848 const char *conditional_validity; 4849 int outer_band_n; 4850 } live_range_tests[] = { 4851 /* Contrived example that illustrates that we need to keep 4852 * track of tagged condition dependences and 4853 * tagged conditional validity dependences 4854 * in isl_sched_edge separately. 4855 * In particular, the conditional validity constraints on A 4856 * cannot be satisfied, 4857 * but they can be ignored because there are no corresponding 4858 * condition constraints. However, we do have an additional 4859 * conditional validity constraint that maps to the same 4860 * dependence relation 4861 * as the condition constraint on B. If we did not make a distinction 4862 * between tagged condition and tagged conditional validity 4863 * dependences, then we 4864 * could end up treating this shared dependence as an condition 4865 * constraint on A, forcing a localization of the conditions, 4866 * which is impossible. 4867 */ 4868 { "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }", 4869 "{ S[i] -> S[i+1] : 0 <= i < 99 }", 4870 "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }", 4871 "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';" 4872 "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';" 4873 "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }", 4874 1 4875 }, 4876 /* TACO 2013 Fig. 7 */ 4877 { "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }", 4878 "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;" 4879 "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }", 4880 "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;" 4881 "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : " 4882 "0 <= i < n and 0 <= j < n - 1 }", 4883 "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : " 4884 "0 <= i < n and 0 <= j < j' < n;" 4885 "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : " 4886 "0 <= i < i' < n and 0 <= j,j' < n;" 4887 "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : " 4888 "0 <= i,j,j' < n and j < j' }", 4889 2 4890 }, 4891 /* TACO 2013 Fig. 7, without tags */ 4892 { "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }", 4893 "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;" 4894 "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }", 4895 "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;" 4896 "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }", 4897 "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;" 4898 "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;" 4899 "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }", 4900 1 4901 }, 4902 /* TACO 2013 Fig. 12 */ 4903 { "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;" 4904 "S3[i,3] : 0 <= i <= 1 }", 4905 "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;" 4906 "S2[i,1] -> S2[i,2] : 0 <= i <= 1;" 4907 "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }", 4908 "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;" 4909 "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;" 4910 "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }", 4911 "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;" 4912 "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;" 4913 "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;" 4914 "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;" 4915 "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }", 4916 1 4917 } 4918 }; 4919 4920 /* Test schedule construction based on conditional constraints. 4921 * In particular, check the number of members in the outer band node 4922 * as an indication of whether tiling is possible or not. 4923 */ 4924 static int test_conditional_schedule_constraints(isl_ctx *ctx) 4925 { 4926 int i; 4927 isl_union_set *domain; 4928 isl_union_map *condition; 4929 isl_union_map *flow; 4930 isl_union_map *validity; 4931 isl_schedule_constraints *sc; 4932 isl_schedule *schedule; 4933 isl_schedule_node *node; 4934 isl_size n_member; 4935 4936 if (test_special_conditional_schedule_constraints(ctx) < 0) 4937 return -1; 4938 if (test_special_conditional_schedule_constraints_2(ctx) < 0) 4939 return -1; 4940 4941 for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) { 4942 domain = isl_union_set_read_from_str(ctx, 4943 live_range_tests[i].domain); 4944 flow = isl_union_map_read_from_str(ctx, 4945 live_range_tests[i].flow); 4946 condition = isl_union_map_read_from_str(ctx, 4947 live_range_tests[i].condition); 4948 validity = isl_union_map_read_from_str(ctx, 4949 live_range_tests[i].conditional_validity); 4950 sc = isl_schedule_constraints_on_domain(domain); 4951 sc = isl_schedule_constraints_set_validity(sc, 4952 isl_union_map_copy(flow)); 4953 sc = isl_schedule_constraints_set_proximity(sc, flow); 4954 sc = isl_schedule_constraints_set_conditional_validity(sc, 4955 condition, validity); 4956 schedule = isl_schedule_constraints_compute_schedule(sc); 4957 node = isl_schedule_get_root(schedule); 4958 while (node && 4959 isl_schedule_node_get_type(node) != isl_schedule_node_band) 4960 node = isl_schedule_node_first_child(node); 4961 n_member = isl_schedule_node_band_n_member(node); 4962 isl_schedule_node_free(node); 4963 isl_schedule_free(schedule); 4964 4965 if (!schedule || n_member < 0) 4966 return -1; 4967 if (n_member != live_range_tests[i].outer_band_n) 4968 isl_die(ctx, isl_error_unknown, 4969 "unexpected number of members in outer band", 4970 return -1); 4971 } 4972 return 0; 4973 } 4974 4975 /* Check that the schedule computed for the given instance set and 4976 * dependence relation strongly satisfies the dependences. 4977 * In particular, check that no instance is scheduled before 4978 * or together with an instance on which it depends. 4979 * Earlier versions of isl would produce a schedule that 4980 * only weakly satisfies the dependences. 4981 */ 4982 static int test_strongly_satisfying_schedule(isl_ctx *ctx) 4983 { 4984 const char *domain, *dep; 4985 isl_union_map *D, *schedule; 4986 isl_map *map, *ge; 4987 int empty; 4988 4989 domain = "{ B[i0, i1] : 0 <= i0 <= 1 and 0 <= i1 <= 11; " 4990 "A[i0] : 0 <= i0 <= 1 }"; 4991 dep = "{ B[i0, i1] -> B[i0, 1 + i1] : 0 <= i0 <= 1 and 0 <= i1 <= 10; " 4992 "B[0, 11] -> A[1]; A[i0] -> B[i0, 0] : 0 <= i0 <= 1 }"; 4993 schedule = compute_schedule(ctx, domain, dep, dep); 4994 D = isl_union_map_read_from_str(ctx, dep); 4995 D = isl_union_map_apply_domain(D, isl_union_map_copy(schedule)); 4996 D = isl_union_map_apply_range(D, schedule); 4997 map = isl_map_from_union_map(D); 4998 ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map))); 4999 map = isl_map_intersect(map, ge); 5000 empty = isl_map_is_empty(map); 5001 isl_map_free(map); 5002 5003 if (empty < 0) 5004 return -1; 5005 if (!empty) 5006 isl_die(ctx, isl_error_unknown, 5007 "dependences not strongly satisfied", return -1); 5008 5009 return 0; 5010 } 5011 5012 /* Compute a schedule for input where the instance set constraints 5013 * conflict with the context constraints. 5014 * Earlier versions of isl did not properly handle this situation. 5015 */ 5016 static int test_conflicting_context_schedule(isl_ctx *ctx) 5017 { 5018 isl_union_map *schedule; 5019 const char *domain, *context; 5020 5021 domain = "[n] -> { A[] : n >= 0 }"; 5022 context = "[n] -> { : n < 0 }"; 5023 schedule = compute_schedule_with_context(ctx, 5024 domain, "{}", "{}", context); 5025 isl_union_map_free(schedule); 5026 5027 if (!schedule) 5028 return -1; 5029 5030 return 0; 5031 } 5032 5033 /* Check that a set of schedule constraints that only allow for 5034 * a coalescing schedule still produces a schedule even if the user 5035 * request a non-coalescing schedule. Earlier versions of isl 5036 * would not handle this case correctly. 5037 */ 5038 static int test_coalescing_schedule(isl_ctx *ctx) 5039 { 5040 const char *domain, *dep; 5041 isl_union_set *I; 5042 isl_union_map *D; 5043 isl_schedule_constraints *sc; 5044 isl_schedule *schedule; 5045 int treat_coalescing; 5046 5047 domain = "{ S[a, b] : 0 <= a <= 1 and 0 <= b <= 1 }"; 5048 dep = "{ S[a, b] -> S[a + b, 1 - b] }"; 5049 I = isl_union_set_read_from_str(ctx, domain); 5050 D = isl_union_map_read_from_str(ctx, dep); 5051 sc = isl_schedule_constraints_on_domain(I); 5052 sc = isl_schedule_constraints_set_validity(sc, D); 5053 treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx); 5054 isl_options_set_schedule_treat_coalescing(ctx, 1); 5055 schedule = isl_schedule_constraints_compute_schedule(sc); 5056 isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing); 5057 isl_schedule_free(schedule); 5058 if (!schedule) 5059 return -1; 5060 return 0; 5061 } 5062 5063 /* Check that the scheduler does not perform any needless 5064 * compound skewing. Earlier versions of isl would compute 5065 * schedules in terms of transformed schedule coefficients and 5066 * would not accurately keep track of the sum of the original 5067 * schedule coefficients. It could then produce the schedule 5068 * S[t,i,j,k] -> [t, 2t + i, 2t + i + j, 2t + i + j + k] 5069 * for the input below instead of the schedule below. 5070 */ 5071 static int test_skewing_schedule(isl_ctx *ctx) 5072 { 5073 const char *D, *V, *P, *S; 5074 5075 D = "[n] -> { S[t,i,j,k] : 0 <= t,i,j,k < n }"; 5076 V = "[n] -> { S[t,i,j,k] -> S[t+1,a,b,c] : 0 <= t,i,j,k,a,b,c < n and " 5077 "-2 <= a-i <= 2 and -1 <= a-i + b-j <= 1 and " 5078 "-1 <= a-i + b-j + c-k <= 1 }"; 5079 P = "{ }"; 5080 S = "{ S[t,i,j,k] -> [t, 2t + i, t + i + j, 2t + k] }"; 5081 5082 return test_special_schedule(ctx, D, V, P, S); 5083 } 5084 5085 int test_schedule(isl_ctx *ctx) 5086 { 5087 const char *D, *W, *R, *V, *P, *S; 5088 int max_coincidence; 5089 int treat_coalescing; 5090 5091 /* Handle resulting schedule with zero bands. */ 5092 if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0) 5093 return -1; 5094 5095 /* Jacobi */ 5096 D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }"; 5097 W = "{ S1[t,i] -> a[t,i] }"; 5098 R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; " 5099 "S1[t,i] -> a[t-1,i+1] }"; 5100 S = "{ S1[t,i] -> [t,i] }"; 5101 if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0) 5102 return -1; 5103 5104 /* Fig. 5 of CC2008 */ 5105 D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and " 5106 "j <= -1 + N }"; 5107 W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and " 5108 "j >= 2 and j <= -1 + N }"; 5109 R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and " 5110 "j >= 2 and j <= -1 + N; " 5111 "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and " 5112 "j >= 2 and j <= -1 + N }"; 5113 S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }"; 5114 if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0) 5115 return -1; 5116 5117 D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }"; 5118 W = "{ S1[i] -> a[i] }"; 5119 R = "{ S2[i] -> a[i+1] }"; 5120 S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }"; 5121 if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0) 5122 return -1; 5123 5124 D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }"; 5125 W = "{ S1[i] -> a[i] }"; 5126 R = "{ S2[i] -> a[9-i] }"; 5127 S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }"; 5128 if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0) 5129 return -1; 5130 5131 D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }"; 5132 W = "{ S1[i] -> a[i] }"; 5133 R = "[N] -> { S2[i] -> a[N-1-i] }"; 5134 S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }"; 5135 if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0) 5136 return -1; 5137 5138 D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }"; 5139 W = "{ S1[i] -> a[i]; S2[i] -> b[i] }"; 5140 R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }"; 5141 S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }"; 5142 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0) 5143 return -1; 5144 5145 D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }"; 5146 W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }"; 5147 R = "{ S2[i,j] -> a[i-1,j] }"; 5148 S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }"; 5149 if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0) 5150 return -1; 5151 5152 D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }"; 5153 W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }"; 5154 R = "{ S2[i,j] -> a[i,j-1] }"; 5155 S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }"; 5156 if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0) 5157 return -1; 5158 5159 D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }"; 5160 W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; " 5161 "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }"; 5162 R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }"; 5163 S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; " 5164 "S_0[] -> [0, 0, 0] }"; 5165 if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0) 5166 return -1; 5167 ctx->opt->schedule_parametric = 0; 5168 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0) 5169 return -1; 5170 ctx->opt->schedule_parametric = 1; 5171 5172 D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; " 5173 "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }"; 5174 W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }"; 5175 R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; " 5176 "S4[i] -> a[i,N] }"; 5177 S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; " 5178 "S4[i] -> [4,i,0] }"; 5179 max_coincidence = isl_options_get_schedule_maximize_coincidence(ctx); 5180 isl_options_set_schedule_maximize_coincidence(ctx, 0); 5181 if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0) 5182 return -1; 5183 isl_options_set_schedule_maximize_coincidence(ctx, max_coincidence); 5184 5185 D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }"; 5186 W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and " 5187 "j <= N }"; 5188 R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and " 5189 "j <= N; " 5190 "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and " 5191 "j <= N }"; 5192 S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }"; 5193 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0) 5194 return -1; 5195 5196 D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; " 5197 " S_2[t] : t >= 0 and t <= -1 + N; " 5198 " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and " 5199 "i <= -1 + N }"; 5200 W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; " 5201 " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; " 5202 " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and " 5203 "i >= 0 and i <= -1 + N }"; 5204 R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and " 5205 "i >= 0 and i <= -1 + N; " 5206 " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }"; 5207 S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; " 5208 " S_0[t] -> [0, t, 0] }"; 5209 5210 if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0) 5211 return -1; 5212 ctx->opt->schedule_parametric = 0; 5213 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0) 5214 return -1; 5215 ctx->opt->schedule_parametric = 1; 5216 5217 D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }"; 5218 S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }"; 5219 if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0) 5220 return -1; 5221 5222 D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; " 5223 "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }"; 5224 W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and " 5225 "j >= 0 and j <= -1 + N; " 5226 "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }"; 5227 R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and " 5228 "j >= 0 and j <= -1 + N; " 5229 "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }"; 5230 S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }"; 5231 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0) 5232 return -1; 5233 5234 D = "{ S_0[i] : i >= 0 }"; 5235 W = "{ S_0[i] -> a[i] : i >= 0 }"; 5236 R = "{ S_0[i] -> a[0] : i >= 0 }"; 5237 S = "{ S_0[i] -> [0, i, 0] }"; 5238 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0) 5239 return -1; 5240 5241 D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }"; 5242 W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }"; 5243 R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }"; 5244 S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }"; 5245 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0) 5246 return -1; 5247 5248 D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and " 5249 "k <= -1 + n and k >= 0 }"; 5250 W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and " "k <= -1 + n and k >= 0 }"; 5251 R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and " 5252 "k <= -1 + n and k >= 0; " 5253 "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and " 5254 "k <= -1 + n and k >= 0; " 5255 "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and " 5256 "k <= -1 + n and k >= 0 }"; 5257 S = "[n] -> { S_0[j, k] -> [2, j, k] }"; 5258 ctx->opt->schedule_outer_coincidence = 1; 5259 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0) 5260 return -1; 5261 ctx->opt->schedule_outer_coincidence = 0; 5262 5263 D = "{Stmt_for_body24[i0, i1, i2, i3]:" 5264 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and " 5265 "i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;" 5266 "Stmt_for_body24[i0, i1, 1, 0]:" 5267 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;" 5268 "Stmt_for_body7[i0, i1, i2]:" 5269 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and " 5270 "i2 <= 7 }"; 5271 5272 V = "{Stmt_for_body24[0, i1, i2, i3] -> " 5273 "Stmt_for_body24[1, i1, i2, i3]:" 5274 "i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and " 5275 "i2 >= 1;" 5276 "Stmt_for_body24[0, i1, i2, i3] -> " 5277 "Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:" 5278 "i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and " 5279 "i3 >= 0;" 5280 "Stmt_for_body24[0, i1, i2, i3] ->" 5281 "Stmt_for_body7[1, i1, 1 + i1 + i3]:" 5282 "i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;" 5283 "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:" 5284 "(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or " 5285 "(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or " 5286 "(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);" 5287 "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:" 5288 "i1 <= 6 and i1 >= 0;" 5289 "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];" 5290 "Stmt_for_body7[i0, i1, i2] -> " 5291 "Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:" 5292 "i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and " 5293 "o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;" 5294 "Stmt_for_body7[i0, i1, i2] -> " 5295 "Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:" 5296 "i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and " 5297 "o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }"; 5298 P = V; 5299 5300 treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx); 5301 isl_options_set_schedule_treat_coalescing(ctx, 0); 5302 if (test_has_schedule(ctx, D, V, P) < 0) 5303 return -1; 5304 isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing); 5305 5306 D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }"; 5307 V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and " 5308 "j >= 1 and j <= 7;" 5309 "S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and " 5310 "j >= 1 and j <= 8 }"; 5311 P = "{ }"; 5312 S = "{ S_0[i, j] -> [i + j, i] }"; 5313 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER; 5314 if (test_special_schedule(ctx, D, V, P, S) < 0) 5315 return -1; 5316 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL; 5317 5318 /* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */ 5319 D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and " 5320 "j >= 0 and j <= -1 + i }"; 5321 V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and " 5322 "i <= -1 + N and j >= 0;" 5323 "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and " 5324 "i <= -2 + N }"; 5325 P = "{ }"; 5326 S = "{ S_0[i, j] -> [i, j] }"; 5327 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER; 5328 if (test_special_schedule(ctx, D, V, P, S) < 0) 5329 return -1; 5330 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL; 5331 5332 /* Test both algorithms on a case with only proximity dependences. */ 5333 D = "{ S[i,j] : 0 <= i <= 10 }"; 5334 V = "{ }"; 5335 P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }"; 5336 S = "{ S[i, j] -> [j, i] }"; 5337 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER; 5338 if (test_special_schedule(ctx, D, V, P, S) < 0) 5339 return -1; 5340 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL; 5341 if (test_special_schedule(ctx, D, V, P, S) < 0) 5342 return -1; 5343 5344 D = "{ A[a]; B[] }"; 5345 V = "{}"; 5346 P = "{ A[a] -> B[] }"; 5347 if (test_has_schedule(ctx, D, V, P) < 0) 5348 return -1; 5349 5350 if (test_padded_schedule(ctx) < 0) 5351 return -1; 5352 5353 /* Check that check for progress is not confused by rational 5354 * solution. 5355 */ 5356 D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }"; 5357 V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and " 5358 "i0 <= -2 + N; " 5359 "S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and " 5360 "i0 <= N and i1 >= 0 and i1 <= -1 + N }"; 5361 P = "{}"; 5362 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER; 5363 if (test_has_schedule(ctx, D, V, P) < 0) 5364 return -1; 5365 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL; 5366 5367 /* Check that we allow schedule rows that are only non-trivial 5368 * on some full-dimensional domains. 5369 */ 5370 D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }"; 5371 V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];" 5372 "S1[j] -> S2[1] : 0 <= j <= 1 }"; 5373 P = "{}"; 5374 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER; 5375 if (test_has_schedule(ctx, D, V, P) < 0) 5376 return -1; 5377 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL; 5378 5379 if (test_conditional_schedule_constraints(ctx) < 0) 5380 return -1; 5381 5382 if (test_strongly_satisfying_schedule(ctx) < 0) 5383 return -1; 5384 5385 if (test_conflicting_context_schedule(ctx) < 0) 5386 return -1; 5387 5388 if (test_coalescing_schedule(ctx) < 0) 5389 return -1; 5390 if (test_skewing_schedule(ctx) < 0) 5391 return -1; 5392 5393 return 0; 5394 } 5395 5396 /* Perform scheduling tests using the whole component scheduler. 5397 */ 5398 static int test_schedule_whole(isl_ctx *ctx) 5399 { 5400 int whole; 5401 int r; 5402 5403 whole = isl_options_get_schedule_whole_component(ctx); 5404 isl_options_set_schedule_whole_component(ctx, 1); 5405 r = test_schedule(ctx); 5406 isl_options_set_schedule_whole_component(ctx, whole); 5407 5408 return r; 5409 } 5410 5411 /* Perform scheduling tests using the incremental scheduler. 5412 */ 5413 static int test_schedule_incremental(isl_ctx *ctx) 5414 { 5415 int whole; 5416 int r; 5417 5418 whole = isl_options_get_schedule_whole_component(ctx); 5419 isl_options_set_schedule_whole_component(ctx, 0); 5420 r = test_schedule(ctx); 5421 isl_options_set_schedule_whole_component(ctx, whole); 5422 5423 return r; 5424 } 5425 5426 int test_plain_injective(isl_ctx *ctx, const char *str, int injective) 5427 { 5428 isl_union_map *umap; 5429 int test; 5430 5431 umap = isl_union_map_read_from_str(ctx, str); 5432 test = isl_union_map_plain_is_injective(umap); 5433 isl_union_map_free(umap); 5434 if (test < 0) 5435 return -1; 5436 if (test == injective) 5437 return 0; 5438 if (injective) 5439 isl_die(ctx, isl_error_unknown, 5440 "map not detected as injective", return -1); 5441 else 5442 isl_die(ctx, isl_error_unknown, 5443 "map detected as injective", return -1); 5444 } 5445 5446 int test_injective(isl_ctx *ctx) 5447 { 5448 const char *str; 5449 5450 if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0)) 5451 return -1; 5452 if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1)) 5453 return -1; 5454 if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1)) 5455 return -1; 5456 if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0)) 5457 return -1; 5458 if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1)) 5459 return -1; 5460 if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0)) 5461 return -1; 5462 if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1)) 5463 return -1; 5464 if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1)) 5465 return -1; 5466 5467 str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}"; 5468 if (test_plain_injective(ctx, str, 1)) 5469 return -1; 5470 str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}"; 5471 if (test_plain_injective(ctx, str, 0)) 5472 return -1; 5473 5474 return 0; 5475 } 5476 5477 #undef BASE 5478 #define BASE aff 5479 #include "isl_test_plain_equal_templ.c" 5480 5481 #undef BASE 5482 #define BASE pw_multi_aff 5483 #include "isl_test_plain_equal_templ.c" 5484 5485 #undef BASE 5486 #define BASE union_pw_aff 5487 #include "isl_test_plain_equal_templ.c" 5488 5489 /* Basic tests on isl_union_pw_aff. 5490 * 5491 * In particular, check that isl_union_pw_aff_aff_on_domain 5492 * aligns the parameters of the input objects and 5493 * that isl_union_pw_aff_param_on_domain_id properly 5494 * introduces the parameter. 5495 */ 5496 static int test_upa(isl_ctx *ctx) 5497 { 5498 const char *str; 5499 isl_id *id; 5500 isl_aff *aff; 5501 isl_union_set *domain; 5502 isl_union_pw_aff *upa; 5503 isl_stat ok; 5504 5505 aff = isl_aff_read_from_str(ctx, "[N] -> { [N] }"); 5506 str = "[M] -> { A[i] : 0 <= i < M; B[] }"; 5507 domain = isl_union_set_read_from_str(ctx, str); 5508 upa = isl_union_pw_aff_aff_on_domain(domain, aff); 5509 str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }"; 5510 ok = union_pw_aff_check_plain_equal(upa, str); 5511 isl_union_pw_aff_free(upa); 5512 if (ok < 0) 5513 return -1; 5514 5515 id = isl_id_alloc(ctx, "N", NULL); 5516 str = "[M] -> { A[i] : 0 <= i < M; B[] }"; 5517 domain = isl_union_set_read_from_str(ctx, str); 5518 upa = isl_union_pw_aff_param_on_domain_id(domain, id); 5519 str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }"; 5520 ok = union_pw_aff_check_plain_equal(upa, str); 5521 isl_union_pw_aff_free(upa); 5522 if (ok < 0) 5523 return -1; 5524 5525 return 0; 5526 } 5527 5528 struct { 5529 __isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1, 5530 __isl_take isl_aff *aff2); 5531 } aff_bin_op[] = { 5532 ['+'] = { &isl_aff_add }, 5533 ['-'] = { &isl_aff_sub }, 5534 ['*'] = { &isl_aff_mul }, 5535 ['/'] = { &isl_aff_div }, 5536 }; 5537 5538 struct { 5539 const char *arg1; 5540 unsigned char op; 5541 const char *arg2; 5542 const char *res; 5543 } aff_bin_tests[] = { 5544 { "{ [i] -> [i] }", '+', "{ [i] -> [i] }", 5545 "{ [i] -> [2i] }" }, 5546 { "{ [i] -> [i] }", '-', "{ [i] -> [i] }", 5547 "{ [i] -> [0] }" }, 5548 { "{ [i] -> [i] }", '*', "{ [i] -> [2] }", 5549 "{ [i] -> [2i] }" }, 5550 { "{ [i] -> [2] }", '*', "{ [i] -> [i] }", 5551 "{ [i] -> [2i] }" }, 5552 { "{ [i] -> [i] }", '/', "{ [i] -> [2] }", 5553 "{ [i] -> [i/2] }" }, 5554 { "{ [i] -> [2i] }", '/', "{ [i] -> [2] }", 5555 "{ [i] -> [i] }" }, 5556 { "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }", 5557 "{ [i] -> [NaN] }" }, 5558 { "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }", 5559 "{ [i] -> [NaN] }" }, 5560 { "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }", 5561 "{ [i] -> [NaN] }" }, 5562 { "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }", 5563 "{ [i] -> [NaN] }" }, 5564 { "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }", 5565 "{ [i] -> [NaN] }" }, 5566 { "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }", 5567 "{ [i] -> [NaN] }" }, 5568 { "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }", 5569 "{ [i] -> [NaN] }" }, 5570 { "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }", 5571 "{ [i] -> [NaN] }" }, 5572 { "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }", 5573 "{ [i] -> [NaN] }" }, 5574 { "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }", 5575 "{ [i] -> [NaN] }" }, 5576 { "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }", 5577 "{ [i] -> [NaN] }" }, 5578 { "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }", 5579 "{ [i] -> [NaN] }" }, 5580 { "{ [i] -> [i] }", '/', "{ [i] -> [0] }", 5581 "{ [i] -> [NaN] }" }, 5582 }; 5583 5584 /* Perform some basic tests of binary operations on isl_aff objects. 5585 */ 5586 static int test_bin_aff(isl_ctx *ctx) 5587 { 5588 int i; 5589 isl_aff *aff1, *aff2, *res; 5590 __isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1, 5591 __isl_take isl_aff *aff2); 5592 int ok; 5593 5594 for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) { 5595 aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1); 5596 aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2); 5597 res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res); 5598 fn = aff_bin_op[aff_bin_tests[i].op].fn; 5599 aff1 = fn(aff1, aff2); 5600 if (isl_aff_is_nan(res)) 5601 ok = isl_aff_is_nan(aff1); 5602 else 5603 ok = isl_aff_plain_is_equal(aff1, res); 5604 isl_aff_free(aff1); 5605 isl_aff_free(res); 5606 if (ok < 0) 5607 return -1; 5608 if (!ok) 5609 isl_die(ctx, isl_error_unknown, 5610 "unexpected result", return -1); 5611 } 5612 5613 return 0; 5614 } 5615 5616 struct { 5617 __isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pa1, 5618 __isl_take isl_pw_aff *pa2); 5619 } pw_aff_bin_op[] = { 5620 ['m'] = { &isl_pw_aff_min }, 5621 ['M'] = { &isl_pw_aff_max }, 5622 }; 5623 5624 /* Inputs for binary isl_pw_aff operation tests. 5625 * "arg1" and "arg2" are the two arguments, "op" identifies the operation 5626 * defined by pw_aff_bin_op, and "res" is the expected result. 5627 */ 5628 struct { 5629 const char *arg1; 5630 unsigned char op; 5631 const char *arg2; 5632 const char *res; 5633 } pw_aff_bin_tests[] = { 5634 { "{ [i] -> [i] }", 'm', "{ [i] -> [i] }", 5635 "{ [i] -> [i] }" }, 5636 { "{ [i] -> [i] }", 'M', "{ [i] -> [i] }", 5637 "{ [i] -> [i] }" }, 5638 { "{ [i] -> [i] }", 'm', "{ [i] -> [0] }", 5639 "{ [i] -> [i] : i <= 0; [i] -> [0] : i > 0 }" }, 5640 { "{ [i] -> [i] }", 'M', "{ [i] -> [0] }", 5641 "{ [i] -> [i] : i >= 0; [i] -> [0] : i < 0 }" }, 5642 { "{ [i] -> [i] }", 'm', "{ [i] -> [NaN] }", 5643 "{ [i] -> [NaN] }" }, 5644 { "{ [i] -> [NaN] }", 'm', "{ [i] -> [i] }", 5645 "{ [i] -> [NaN] }" }, 5646 }; 5647 5648 /* Perform some basic tests of binary operations on isl_pw_aff objects. 5649 */ 5650 static int test_bin_pw_aff(isl_ctx *ctx) 5651 { 5652 int i; 5653 isl_bool ok; 5654 isl_pw_aff *pa1, *pa2, *res; 5655 5656 for (i = 0; i < ARRAY_SIZE(pw_aff_bin_tests); ++i) { 5657 pa1 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg1); 5658 pa2 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg2); 5659 res = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].res); 5660 pa1 = pw_aff_bin_op[pw_aff_bin_tests[i].op].fn(pa1, pa2); 5661 if (isl_pw_aff_involves_nan(res)) 5662 ok = isl_pw_aff_involves_nan(pa1); 5663 else 5664 ok = isl_pw_aff_plain_is_equal(pa1, res); 5665 isl_pw_aff_free(pa1); 5666 isl_pw_aff_free(res); 5667 if (ok < 0) 5668 return -1; 5669 if (!ok) 5670 isl_die(ctx, isl_error_unknown, 5671 "unexpected result", return -1); 5672 } 5673 5674 return 0; 5675 } 5676 5677 /* Inputs for basic tests of test operations on 5678 * isl_union_pw_multi_aff objects. 5679 * "fn" is the function that is being tested. 5680 * "arg" is a string description of the input. 5681 * "res" is the expected result. 5682 */ 5683 static struct { 5684 isl_bool (*fn)(__isl_keep isl_union_pw_multi_aff *upma1); 5685 const char *arg; 5686 isl_bool res; 5687 } upma_test_tests[] = { 5688 { &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [1] }", 5689 isl_bool_false }, 5690 { &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [NaN]; B[0] -> [1] }", 5691 isl_bool_true }, 5692 { &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [NaN] }", 5693 isl_bool_true }, 5694 { &isl_union_pw_multi_aff_involves_nan, 5695 "{ A[] -> [0]; B[0] -> [1, NaN, 5] }", 5696 isl_bool_true }, 5697 { &isl_union_pw_multi_aff_involves_locals, 5698 "{ A[] -> [0]; B[0] -> [1] }", 5699 isl_bool_false }, 5700 { &isl_union_pw_multi_aff_involves_locals, 5701 "{ A[] -> [0]; B[x] -> [1] : x mod 2 = 0 }", 5702 isl_bool_true }, 5703 { &isl_union_pw_multi_aff_involves_locals, 5704 "{ A[] -> [0]; B[x] -> [x // 2] }", 5705 isl_bool_true }, 5706 { &isl_union_pw_multi_aff_involves_locals, 5707 "{ A[i] -> [i // 2]; B[0] -> [1] }", 5708 isl_bool_true }, 5709 }; 5710 5711 /* Perform some basic tests of test operations on 5712 * isl_union_pw_multi_aff objects. 5713 */ 5714 static isl_stat test_upma_test(isl_ctx *ctx) 5715 { 5716 int i; 5717 isl_union_pw_multi_aff *upma; 5718 isl_bool res; 5719 5720 for (i = 0; i < ARRAY_SIZE(upma_test_tests); ++i) { 5721 const char *str; 5722 5723 str = upma_test_tests[i].arg; 5724 upma = isl_union_pw_multi_aff_read_from_str(ctx, str); 5725 res = upma_test_tests[i].fn(upma); 5726 isl_union_pw_multi_aff_free(upma); 5727 if (res < 0) 5728 return isl_stat_error; 5729 if (res != upma_test_tests[i].res) 5730 isl_die(ctx, isl_error_unknown, 5731 "unexpected result", return isl_stat_error); 5732 } 5733 5734 return isl_stat_ok; 5735 } 5736 5737 struct { 5738 __isl_give isl_union_pw_multi_aff *(*fn)( 5739 __isl_take isl_union_pw_multi_aff *upma1, 5740 __isl_take isl_union_pw_multi_aff *upma2); 5741 const char *arg1; 5742 const char *arg2; 5743 const char *res; 5744 } upma_bin_tests[] = { 5745 { &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }", 5746 "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" }, 5747 { &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }", 5748 "{ B[x] -> [2] : x >= 0 }", 5749 "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" }, 5750 { &isl_union_pw_multi_aff_pullback_union_pw_multi_aff, 5751 "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }", 5752 "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }", 5753 "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; " 5754 "D[i] -> B[2] : i >= 5 }" }, 5755 { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }", 5756 "{ B[x] -> C[2] : x > 0 }", 5757 "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" }, 5758 { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }", 5759 "{ B[x] -> A[2] : x >= 0 }", 5760 "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" }, 5761 { 5762 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff, 5763 "{ B[x] -> C[x + 2] }", 5764 "{ D[y] -> B[2y] }", 5765 "{ }" }, 5766 { 5767 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff, 5768 "{ [A[x] -> B[x + 1]] -> C[x + 2] }", 5769 "{ D[y] -> B[2y] }", 5770 "{ }" }, 5771 { 5772 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff, 5773 "{ [A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }", 5774 "{ D[y] -> A[2y] }", 5775 "{ [D[y] -> B[2y + 1]] -> C[2y + 2] }" }, 5776 { 5777 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff, 5778 "{ T[A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }", 5779 "{ D[y] -> A[2y] }", 5780 "{ T[D[y] -> B[2y + 1]] -> C[2y + 2] }" }, 5781 }; 5782 5783 /* Perform some basic tests of binary operations on 5784 * isl_union_pw_multi_aff objects. 5785 */ 5786 static int test_bin_upma(isl_ctx *ctx) 5787 { 5788 int i; 5789 isl_union_pw_multi_aff *upma1, *upma2, *res; 5790 int ok; 5791 5792 for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) { 5793 upma1 = isl_union_pw_multi_aff_read_from_str(ctx, 5794 upma_bin_tests[i].arg1); 5795 upma2 = isl_union_pw_multi_aff_read_from_str(ctx, 5796 upma_bin_tests[i].arg2); 5797 res = isl_union_pw_multi_aff_read_from_str(ctx, 5798 upma_bin_tests[i].res); 5799 upma1 = upma_bin_tests[i].fn(upma1, upma2); 5800 ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res); 5801 isl_union_pw_multi_aff_free(upma1); 5802 isl_union_pw_multi_aff_free(res); 5803 if (ok < 0) 5804 return -1; 5805 if (!ok) 5806 isl_die(ctx, isl_error_unknown, 5807 "unexpected result", return -1); 5808 } 5809 5810 return 0; 5811 } 5812 5813 struct { 5814 __isl_give isl_union_pw_multi_aff *(*fn)( 5815 __isl_take isl_union_pw_multi_aff *upma1, 5816 __isl_take isl_union_pw_multi_aff *upma2); 5817 const char *arg1; 5818 const char *arg2; 5819 } upma_bin_fail_tests[] = { 5820 { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }", 5821 "{ B[x] -> C[2] : x >= 0 }" }, 5822 }; 5823 5824 /* Perform some basic tests of binary operations on 5825 * isl_union_pw_multi_aff objects that are expected to fail. 5826 */ 5827 static int test_bin_upma_fail(isl_ctx *ctx) 5828 { 5829 int i, n; 5830 isl_union_pw_multi_aff *upma1, *upma2; 5831 int on_error; 5832 5833 on_error = isl_options_get_on_error(ctx); 5834 isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE); 5835 n = ARRAY_SIZE(upma_bin_fail_tests); 5836 for (i = 0; i < n; ++i) { 5837 upma1 = isl_union_pw_multi_aff_read_from_str(ctx, 5838 upma_bin_fail_tests[i].arg1); 5839 upma2 = isl_union_pw_multi_aff_read_from_str(ctx, 5840 upma_bin_fail_tests[i].arg2); 5841 upma1 = upma_bin_fail_tests[i].fn(upma1, upma2); 5842 isl_union_pw_multi_aff_free(upma1); 5843 if (upma1) 5844 break; 5845 } 5846 isl_options_set_on_error(ctx, on_error); 5847 if (i < n) 5848 isl_die(ctx, isl_error_unknown, 5849 "operation not expected to succeed", return -1); 5850 5851 return 0; 5852 } 5853 5854 /* Inputs for basic tests of binary operations on 5855 * pairs of isl_union_pw_multi_aff and isl_union_set objects. 5856 * "fn" is the function that is being tested. 5857 * "arg1" and "arg2" are string descriptions of the inputs. 5858 * "res" is a string description of the expected result. 5859 */ 5860 struct { 5861 __isl_give isl_union_pw_multi_aff *(*fn)( 5862 __isl_take isl_union_pw_multi_aff *upma, 5863 __isl_take isl_union_set *uset); 5864 const char *arg1; 5865 const char *arg2; 5866 const char *res; 5867 } upma_uset_tests[] = { 5868 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range, 5869 "{ A[i] -> B[i] }", "{ B[0] }", 5870 "{ }" }, 5871 { &isl_union_pw_multi_aff_intersect_domain_wrapped_domain, 5872 "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }", 5873 "{ [A[1] -> B[1]] -> C[2] }" }, 5874 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range, 5875 "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }", 5876 "{ [A[0] -> B[0]] -> C[1] }" }, 5877 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range, 5878 "{ [A[i] -> B[i]] -> C[i + 1] }", "[N] -> { B[N] }", 5879 "[N] -> { [A[N] -> B[N]] -> C[N + 1] }" }, 5880 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range, 5881 "[M] -> { [A[M] -> B[M]] -> C[M + 1] }", "[N] -> { B[N] }", 5882 "[N, M] -> { [A[N] -> B[N]] -> C[N + 1] : N = M }" }, 5883 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range, 5884 "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[]; [B[] -> A[]] -> E[] }", 5885 "{ B[] }", 5886 "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[] }" }, 5887 }; 5888 5889 /* Perform some basic tests of binary operations on 5890 * pairs of isl_union_pw_multi_aff and isl_union_set objects. 5891 */ 5892 static isl_stat test_upma_uset(isl_ctx *ctx) 5893 { 5894 int i; 5895 isl_bool ok; 5896 isl_union_pw_multi_aff *upma, *res; 5897 isl_union_set *uset; 5898 5899 for (i = 0; i < ARRAY_SIZE(upma_uset_tests); ++i) { 5900 upma = isl_union_pw_multi_aff_read_from_str(ctx, 5901 upma_uset_tests[i].arg1); 5902 uset = isl_union_set_read_from_str(ctx, 5903 upma_uset_tests[i].arg2); 5904 res = isl_union_pw_multi_aff_read_from_str(ctx, 5905 upma_uset_tests[i].res); 5906 upma = upma_uset_tests[i].fn(upma, uset); 5907 ok = isl_union_pw_multi_aff_plain_is_equal(upma, res); 5908 isl_union_pw_multi_aff_free(upma); 5909 isl_union_pw_multi_aff_free(res); 5910 if (ok < 0) 5911 return isl_stat_error; 5912 if (!ok) 5913 isl_die(ctx, isl_error_unknown, 5914 "unexpected result", return isl_stat_error); 5915 } 5916 5917 return isl_stat_ok; 5918 } 5919 5920 /* Inputs for basic tests of unary operations on isl_multi_pw_aff objects. 5921 * "fn" is the function that is tested. 5922 * "arg" is a string description of the input. 5923 * "res" is a string description of the expected result. 5924 */ 5925 struct { 5926 __isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa); 5927 const char *arg; 5928 const char *res; 5929 } mpa_un_tests[] = { 5930 { &isl_multi_pw_aff_range_factor_domain, 5931 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }", 5932 "{ A[x] -> B[(1 : x >= 5)] }" }, 5933 { &isl_multi_pw_aff_range_factor_range, 5934 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }", 5935 "{ A[y] -> C[(2 : y <= 10)] }" }, 5936 { &isl_multi_pw_aff_range_factor_domain, 5937 "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }", 5938 "{ A[x] -> B[(1 : x >= 5)] }" }, 5939 { &isl_multi_pw_aff_range_factor_range, 5940 "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }", 5941 "{ A[y] -> C[] }" }, 5942 { &isl_multi_pw_aff_range_factor_domain, 5943 "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }", 5944 "{ A[x] -> B[] }" }, 5945 { &isl_multi_pw_aff_range_factor_range, 5946 "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }", 5947 "{ A[y] -> C[(2 : y <= 10)] }" }, 5948 { &isl_multi_pw_aff_range_factor_domain, 5949 "{ A[x] -> [B[] -> C[]] }", 5950 "{ A[x] -> B[] }" }, 5951 { &isl_multi_pw_aff_range_factor_range, 5952 "{ A[x] -> [B[] -> C[]] }", 5953 "{ A[y] -> C[] }" }, 5954 { &isl_multi_pw_aff_factor_range, 5955 "{ [B[] -> C[]] }", 5956 "{ C[] }" }, 5957 { &isl_multi_pw_aff_range_factor_domain, 5958 "{ A[x] -> [B[] -> C[]] : x >= 0 }", 5959 "{ A[x] -> B[] : x >= 0 }" }, 5960 { &isl_multi_pw_aff_range_factor_range, 5961 "{ A[x] -> [B[] -> C[]] : x >= 0 }", 5962 "{ A[y] -> C[] : y >= 0 }" }, 5963 { &isl_multi_pw_aff_factor_range, 5964 "[N] -> { [B[] -> C[]] : N >= 0 }", 5965 "[N] -> { C[] : N >= 0 }" }, 5966 }; 5967 5968 /* Perform some basic tests of unary operations on isl_multi_pw_aff objects. 5969 */ 5970 static int test_un_mpa(isl_ctx *ctx) 5971 { 5972 int i; 5973 isl_bool ok; 5974 isl_multi_pw_aff *mpa, *res; 5975 5976 for (i = 0; i < ARRAY_SIZE(mpa_un_tests); ++i) { 5977 mpa = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].arg); 5978 res = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].res); 5979 mpa = mpa_un_tests[i].fn(mpa); 5980 ok = isl_multi_pw_aff_plain_is_equal(mpa, res); 5981 isl_multi_pw_aff_free(mpa); 5982 isl_multi_pw_aff_free(res); 5983 if (ok < 0) 5984 return -1; 5985 if (!ok) 5986 isl_die(ctx, isl_error_unknown, 5987 "unexpected result", return -1); 5988 } 5989 5990 return 0; 5991 } 5992 5993 /* Inputs for basic tests of binary operations on isl_multi_pw_aff objects. 5994 * "fn" is the function that is tested. 5995 * "arg1" and "arg2" are string descriptions of the inputs. 5996 * "res" is a string description of the expected result. 5997 */ 5998 struct { 5999 __isl_give isl_multi_pw_aff *(*fn)( 6000 __isl_take isl_multi_pw_aff *mpa1, 6001 __isl_take isl_multi_pw_aff *mpa2); 6002 const char *arg1; 6003 const char *arg2; 6004 const char *res; 6005 } mpa_bin_tests[] = { 6006 { &isl_multi_pw_aff_add, "{ A[] -> [1] }", "{ A[] -> [2] }", 6007 "{ A[] -> [3] }" }, 6008 { &isl_multi_pw_aff_add, "{ A[x] -> [(1 : x >= 5)] }", 6009 "{ A[x] -> [(x : x <= 10)] }", 6010 "{ A[x] -> [(1 + x : 5 <= x <= 10)] }" }, 6011 { &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }", 6012 "{ A[x] -> [] : x <= 10 }", 6013 "{ A[x] -> [] : 5 <= x <= 10 }" }, 6014 { &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }", 6015 "[N] -> { A[x] -> [] : x <= N }", 6016 "[N] -> { A[x] -> [] : 5 <= x <= N }" }, 6017 { &isl_multi_pw_aff_add, 6018 "[N] -> { A[x] -> [] : x <= N }", 6019 "{ A[x] -> [] : x >= 5 }", 6020 "[N] -> { A[x] -> [] : 5 <= x <= N }" }, 6021 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }", 6022 "{ A[y] -> C[(2 : y <= 10)] }", 6023 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" }, 6024 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }", 6025 "{ A[y] -> C[2] : y <= 10 }", 6026 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" }, 6027 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }", 6028 "[N] -> { A[y] -> C[2] : y <= N }", 6029 "[N] -> { A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= N)]] }" }, 6030 { &isl_multi_pw_aff_range_product, "[N] -> { A[x] -> B[1] : x >= N }", 6031 "{ A[y] -> C[2] : y <= 10 }", 6032 "[N] -> { A[x] -> [B[(1 : x >= N)] -> C[(2 : x <= 10)]] }" }, 6033 { &isl_multi_pw_aff_range_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }", 6034 "{ A[] -> [B[1] -> C[2]] }" }, 6035 { &isl_multi_pw_aff_range_product, "{ A[] -> B[] }", "{ A[] -> C[] }", 6036 "{ A[] -> [B[] -> C[]] }" }, 6037 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }", 6038 "{ A[y] -> C[] : y <= 10 }", 6039 "{ A[x] -> [B[(1 : x >= 5)] -> C[]] : x <= 10 }" }, 6040 { &isl_multi_pw_aff_range_product, "{ A[y] -> C[] : y <= 10 }", 6041 "{ A[x] -> B[(1 : x >= 5)] }", 6042 "{ A[x] -> [C[] -> B[(1 : x >= 5)]] : x <= 10 }" }, 6043 { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }", 6044 "{ A[y] -> C[(2 : y <= 10)] }", 6045 "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[(2 : y <= 10)]] }" }, 6046 { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }", 6047 "{ A[y] -> C[] : y <= 10 }", 6048 "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= 10 }" }, 6049 { &isl_multi_pw_aff_product, "{ A[y] -> C[] : y <= 10 }", 6050 "{ A[x] -> B[(1 : x >= 5)] }", 6051 "{ [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= 10 }" }, 6052 { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }", 6053 "[N] -> { A[y] -> C[] : y <= N }", 6054 "[N] -> { [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= N }" }, 6055 { &isl_multi_pw_aff_product, "[N] -> { A[y] -> C[] : y <= N }", 6056 "{ A[x] -> B[(1 : x >= 5)] }", 6057 "[N] -> { [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= N }" }, 6058 { &isl_multi_pw_aff_product, "{ A[x] -> B[] : x >= 5 }", 6059 "{ A[y] -> C[] : y <= 10 }", 6060 "{ [A[x] -> A[y]] -> [B[] -> C[]] : x >= 5 and y <= 10 }" }, 6061 { &isl_multi_pw_aff_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }", 6062 "{ [A[] -> A[]] -> [B[1] -> C[2]] }" }, 6063 { &isl_multi_pw_aff_product, "{ A[] -> B[] }", "{ A[] -> C[] }", 6064 "{ [A[] -> A[]] -> [B[] -> C[]] }" }, 6065 { &isl_multi_pw_aff_pullback_multi_pw_aff, 6066 "{ B[i,j] -> C[i + 2j] }", "{ A[a,b] -> B[b,a] }", 6067 "{ A[a,b] -> C[b + 2a] }" }, 6068 { &isl_multi_pw_aff_pullback_multi_pw_aff, 6069 "{ B[i,j] -> C[i + 2j] }", 6070 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }", 6071 "{ A[a,b] -> C[(b + 2a : b > a)] }" }, 6072 { &isl_multi_pw_aff_pullback_multi_pw_aff, 6073 "{ B[i,j] -> C[(i + 2j : j > 4)] }", 6074 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }", 6075 "{ A[a,b] -> C[(b + 2a : b > a > 4)] }" }, 6076 { &isl_multi_pw_aff_pullback_multi_pw_aff, 6077 "{ B[i,j] -> C[] }", 6078 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }", 6079 "{ A[a,b] -> C[] }" }, 6080 { &isl_multi_pw_aff_pullback_multi_pw_aff, 6081 "{ B[i,j] -> C[] : i > j }", 6082 "{ A[a,b] -> B[b,a] }", 6083 "{ A[a,b] -> C[] : b > a }" }, 6084 { &isl_multi_pw_aff_pullback_multi_pw_aff, 6085 "{ B[i,j] -> C[] : j > 5 }", 6086 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }", 6087 "{ A[a,b] -> C[] : b > a > 5 }" }, 6088 { &isl_multi_pw_aff_pullback_multi_pw_aff, 6089 "[N] -> { B[i,j] -> C[] : j > N }", 6090 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }", 6091 "[N] -> { A[a,b] -> C[] : b > a > N }" }, 6092 { &isl_multi_pw_aff_pullback_multi_pw_aff, 6093 "[M,N] -> { B[] -> C[] : N > 5 }", 6094 "[M,N] -> { A[] -> B[] : M > N }", 6095 "[M,N] -> { A[] -> C[] : M > N > 5 }" }, 6096 }; 6097 6098 /* Perform some basic tests of binary operations on isl_multi_pw_aff objects. 6099 */ 6100 static int test_bin_mpa(isl_ctx *ctx) 6101 { 6102 int i; 6103 isl_bool ok; 6104 isl_multi_pw_aff *mpa1, *mpa2, *res; 6105 6106 for (i = 0; i < ARRAY_SIZE(mpa_bin_tests); ++i) { 6107 mpa1 = isl_multi_pw_aff_read_from_str(ctx, 6108 mpa_bin_tests[i].arg1); 6109 mpa2 = isl_multi_pw_aff_read_from_str(ctx, 6110 mpa_bin_tests[i].arg2); 6111 res = isl_multi_pw_aff_read_from_str(ctx, 6112 mpa_bin_tests[i].res); 6113 mpa1 = mpa_bin_tests[i].fn(mpa1, mpa2); 6114 ok = isl_multi_pw_aff_plain_is_equal(mpa1, res); 6115 isl_multi_pw_aff_free(mpa1); 6116 isl_multi_pw_aff_free(res); 6117 if (ok < 0) 6118 return -1; 6119 if (!ok) 6120 isl_die(ctx, isl_error_unknown, 6121 "unexpected result", return -1); 6122 } 6123 6124 return 0; 6125 } 6126 6127 /* Inputs for basic tests of unary operations on 6128 * isl_multi_union_pw_aff objects. 6129 * "fn" is the function that is tested. 6130 * "arg" is a string description of the input. 6131 * "res" is a string description of the expected result. 6132 */ 6133 struct { 6134 __isl_give isl_multi_union_pw_aff *(*fn)( 6135 __isl_take isl_multi_union_pw_aff *mupa); 6136 const char *arg; 6137 const char *res; 6138 } mupa_un_tests[] = { 6139 { &isl_multi_union_pw_aff_factor_range, 6140 "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]", 6141 "C[{ A[] -> [2] }]" }, 6142 { &isl_multi_union_pw_aff_factor_range, 6143 "[B[] -> C[{ A[] -> [2] }]]", 6144 "C[{ A[] -> [2] }]" }, 6145 { &isl_multi_union_pw_aff_factor_range, 6146 "[B[{ A[] -> [1] }] -> C[]]", 6147 "C[]" }, 6148 { &isl_multi_union_pw_aff_factor_range, 6149 "[B[] -> C[]]", 6150 "C[]" }, 6151 { &isl_multi_union_pw_aff_factor_range, 6152 "([B[] -> C[]] : { A[x] : x >= 0 })", 6153 "(C[] : { A[x] : x >= 0 })" }, 6154 { &isl_multi_union_pw_aff_factor_range, 6155 "[N] -> ([B[] -> C[]] : { A[x] : x <= N })", 6156 "[N] -> (C[] : { A[x] : x <= N })" }, 6157 { &isl_multi_union_pw_aff_factor_range, 6158 "[N] -> ([B[] -> C[]] : { : N >= 0 })", 6159 "[N] -> (C[] : { : N >= 0 })" }, 6160 }; 6161 6162 /* Perform some basic tests of unary operations on 6163 * isl_multi_union_pw_aff objects. 6164 */ 6165 static int test_un_mupa(isl_ctx *ctx) 6166 { 6167 int i; 6168 isl_bool ok; 6169 isl_multi_union_pw_aff *mupa, *res; 6170 6171 for (i = 0; i < ARRAY_SIZE(mupa_un_tests); ++i) { 6172 mupa = isl_multi_union_pw_aff_read_from_str(ctx, 6173 mupa_un_tests[i].arg); 6174 res = isl_multi_union_pw_aff_read_from_str(ctx, 6175 mupa_un_tests[i].res); 6176 mupa = mupa_un_tests[i].fn(mupa); 6177 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res); 6178 isl_multi_union_pw_aff_free(mupa); 6179 isl_multi_union_pw_aff_free(res); 6180 if (ok < 0) 6181 return -1; 6182 if (!ok) 6183 isl_die(ctx, isl_error_unknown, 6184 "unexpected result", return -1); 6185 } 6186 6187 return 0; 6188 } 6189 6190 /* Inputs for basic tests of binary operations on 6191 * isl_multi_union_pw_aff objects. 6192 * "fn" is the function that is tested. 6193 * "arg1" and "arg2" are string descriptions of the inputs. 6194 * "res" is a string description of the expected result. 6195 */ 6196 struct { 6197 __isl_give isl_multi_union_pw_aff *(*fn)( 6198 __isl_take isl_multi_union_pw_aff *mupa1, 6199 __isl_take isl_multi_union_pw_aff *mupa2); 6200 const char *arg1; 6201 const char *arg2; 6202 const char *res; 6203 } mupa_bin_tests[] = { 6204 { &isl_multi_union_pw_aff_add, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]", 6205 "[{ A[] -> [3] }]" }, 6206 { &isl_multi_union_pw_aff_sub, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]", 6207 "[{ A[] -> [-1] }]" }, 6208 { &isl_multi_union_pw_aff_add, 6209 "[{ A[] -> [1]; B[] -> [4] }]", 6210 "[{ A[] -> [2]; C[] -> [5] }]", 6211 "[{ A[] -> [3] }]" }, 6212 { &isl_multi_union_pw_aff_union_add, 6213 "[{ A[] -> [1]; B[] -> [4] }]", 6214 "[{ A[] -> [2]; C[] -> [5] }]", 6215 "[{ A[] -> [3]; B[] -> [4]; C[] -> [5] }]" }, 6216 { &isl_multi_union_pw_aff_add, "[{ A[x] -> [(1)] : x >= 5 }]", 6217 "[{ A[x] -> [(x)] : x <= 10 }]", 6218 "[{ A[x] -> [(1 + x)] : 5 <= x <= 10 }]" }, 6219 { &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })", 6220 "([] : { A[x] : x <= 10 })", 6221 "([] : { A[x] : 5 <= x <= 10 })" }, 6222 { &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })", 6223 "[N] -> ([] : { A[x] : x <= N })", 6224 "[N] -> ([] : { A[x] : 5 <= x <= N })" }, 6225 { &isl_multi_union_pw_aff_add, "[N] -> ([] : { A[x] : x >= N })", 6226 "([] : { A[x] : x <= 10 })", 6227 "[N] -> ([] : { A[x] : N <= x <= 10 })" }, 6228 { &isl_multi_union_pw_aff_union_add, "[{ A[x] -> [(1)] : x >= 5 }]", 6229 "[{ A[x] -> [(x)] : x <= 10 }]", 6230 "[{ A[x] -> [(1 + x)] : 5 <= x <= 10; " 6231 "A[x] -> [(1)] : x > 10; A[x] -> [(x)] : x < 5 }]" }, 6232 { &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 5 })", 6233 "([] : { A[x] : x <= 10 })", 6234 "([] : { A[x] })" }, 6235 { &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 0 })", 6236 "[N] -> ([] : { A[x] : x >= N })", 6237 "[N] -> ([] : { A[x] : x >= 0 or x >= N })" }, 6238 { &isl_multi_union_pw_aff_union_add, 6239 "[N] -> ([] : { A[] : N >= 0})", 6240 "[N] -> ([] : { A[] : N <= 0})", 6241 "[N] -> ([] : { A[] })" }, 6242 { &isl_multi_union_pw_aff_union_add, 6243 "[N] -> ([] : { A[] })", 6244 "[N] -> ([] : { : })", 6245 "[N] -> ([] : { : })" }, 6246 { &isl_multi_union_pw_aff_union_add, 6247 "[N] -> ([] : { : })", 6248 "[N] -> ([] : { A[] })", 6249 "[N] -> ([] : { : })" }, 6250 { &isl_multi_union_pw_aff_union_add, 6251 "[N] -> ([] : { : N >= 0})", 6252 "[N] -> ([] : { : N <= 0})", 6253 "[N] -> ([] : { : })" }, 6254 { &isl_multi_union_pw_aff_range_product, 6255 "B[{ A[] -> [1] }]", 6256 "C[{ A[] -> [2] }]", 6257 "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]" }, 6258 { &isl_multi_union_pw_aff_range_product, 6259 "(B[] : { A[x] : x >= 5 })", 6260 "(C[] : { A[x] : x <= 10 })", 6261 "([B[] -> C[]] : { A[x] : 5 <= x <= 10 })" }, 6262 { &isl_multi_union_pw_aff_range_product, 6263 "B[{ A[x] -> [x + 1] : x >= 5 }]", 6264 "(C[] : { A[x] : x <= 10 })", 6265 "[B[{ A[x] -> [x + 1] : 5 <= x <= 10 }] -> C[]]" }, 6266 { &isl_multi_union_pw_aff_range_product, 6267 "(C[] : { A[x] : x <= 10 })", 6268 "B[{ A[x] -> [x + 1] : x >= 5 }]", 6269 "[C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= 10 }]]" }, 6270 { &isl_multi_union_pw_aff_range_product, 6271 "B[{ A[x] -> [x + 1] : x >= 5 }]", 6272 "[N] -> (C[] : { A[x] : x <= N })", 6273 "[N] -> [B[{ A[x] -> [x + 1] : 5 <= x <= N }] -> C[]]" }, 6274 { &isl_multi_union_pw_aff_range_product, 6275 "[N] -> (C[] : { A[x] : x <= N })", 6276 "B[{ A[x] -> [x + 1] : x >= 5 }]", 6277 "[N] -> [C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= N }]]" }, 6278 { &isl_multi_union_pw_aff_range_product, 6279 "B[{ A[] -> [1]; D[] -> [3] }]", 6280 "C[{ A[] -> [2] }]", 6281 "[B[{ A[] -> [1]; D[] -> [3] }] -> C[{ A[] -> [2] }]]" }, 6282 { &isl_multi_union_pw_aff_range_product, 6283 "B[] }]", 6284 "(C[] : { A[x] })", 6285 "([B[] -> C[]] : { A[x] })" }, 6286 { &isl_multi_union_pw_aff_range_product, 6287 "(B[] : { A[x] })", 6288 "C[] }]", 6289 "([B[] -> C[]] : { A[x] })" }, 6290 }; 6291 6292 /* Perform some basic tests of binary operations on 6293 * isl_multi_union_pw_aff objects. 6294 */ 6295 static int test_bin_mupa(isl_ctx *ctx) 6296 { 6297 int i; 6298 isl_bool ok; 6299 isl_multi_union_pw_aff *mupa1, *mupa2, *res; 6300 6301 for (i = 0; i < ARRAY_SIZE(mupa_bin_tests); ++i) { 6302 mupa1 = isl_multi_union_pw_aff_read_from_str(ctx, 6303 mupa_bin_tests[i].arg1); 6304 mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, 6305 mupa_bin_tests[i].arg2); 6306 res = isl_multi_union_pw_aff_read_from_str(ctx, 6307 mupa_bin_tests[i].res); 6308 mupa1 = mupa_bin_tests[i].fn(mupa1, mupa2); 6309 ok = isl_multi_union_pw_aff_plain_is_equal(mupa1, res); 6310 isl_multi_union_pw_aff_free(mupa1); 6311 isl_multi_union_pw_aff_free(res); 6312 if (ok < 0) 6313 return -1; 6314 if (!ok) 6315 isl_die(ctx, isl_error_unknown, 6316 "unexpected result", return -1); 6317 } 6318 6319 return 0; 6320 } 6321 6322 /* Inputs for basic tests of binary operations on 6323 * pairs of isl_multi_union_pw_aff and isl_set objects. 6324 * "fn" is the function that is tested. 6325 * "arg1" and "arg2" are string descriptions of the inputs. 6326 * "res" is a string description of the expected result. 6327 */ 6328 struct { 6329 __isl_give isl_multi_union_pw_aff *(*fn)( 6330 __isl_take isl_multi_union_pw_aff *mupa, 6331 __isl_take isl_set *set); 6332 const char *arg1; 6333 const char *arg2; 6334 const char *res; 6335 } mupa_set_tests[] = { 6336 { &isl_multi_union_pw_aff_intersect_range, 6337 "C[{ B[i,j] -> [i + 2j] }]", "{ C[1] }", 6338 "C[{ B[i,j] -> [i + 2j] : i + 2j = 1 }]" }, 6339 { &isl_multi_union_pw_aff_intersect_range, 6340 "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[N] }", 6341 "[N] -> C[{ B[i,j] -> [i + 2j] : i + 2j = N }]" }, 6342 { &isl_multi_union_pw_aff_intersect_range, 6343 "[N] -> C[{ B[i,j] -> [i + 2j + N] }]", "{ C[1] }", 6344 "[N] -> C[{ B[i,j] -> [i + 2j + N] : i + 2j + N = 1 }]" }, 6345 { &isl_multi_union_pw_aff_intersect_range, 6346 "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[x] : N >= 0 }", 6347 "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0 }]" }, 6348 { &isl_multi_union_pw_aff_intersect_range, 6349 "C[]", "{ C[] }", "C[]" }, 6350 { &isl_multi_union_pw_aff_intersect_range, 6351 "[N] -> (C[] : { : N >= 0 })", 6352 "{ C[] }", 6353 "[N] -> (C[] : { : N >= 0 })" }, 6354 { &isl_multi_union_pw_aff_intersect_range, 6355 "(C[] : { A[a,b] })", 6356 "{ C[] }", 6357 "(C[] : { A[a,b] })" }, 6358 { &isl_multi_union_pw_aff_intersect_range, 6359 "[N] -> (C[] : { A[a,b] : a,b <= N })", 6360 "{ C[] }", 6361 "[N] -> (C[] : { A[a,b] : a,b <= N })" }, 6362 { &isl_multi_union_pw_aff_intersect_range, 6363 "C[]", 6364 "[N] -> { C[] : N >= 0 }", 6365 "[N] -> (C[] : { : N >= 0 })" }, 6366 { &isl_multi_union_pw_aff_intersect_range, 6367 "(C[] : { A[a,b] })", 6368 "[N] -> { C[] : N >= 0 }", 6369 "[N] -> (C[] : { A[a,b] : N >= 0 })" }, 6370 { &isl_multi_union_pw_aff_intersect_range, 6371 "[N] -> (C[] : { : N >= 0 })", 6372 "[N] -> { C[] : N < 1024 }", 6373 "[N] -> (C[] : { : 0 <= N < 1024 })" }, 6374 { &isl_multi_union_pw_aff_intersect_params, 6375 "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { : N >= 0 }", 6376 "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0}]" }, 6377 { &isl_multi_union_pw_aff_intersect_params, 6378 "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "[N] -> { : N >= 0 }", 6379 "[N] -> C[{ B[i,j] -> [i + 2j] : 0 <= N <= 256 }]" }, 6380 { &isl_multi_union_pw_aff_intersect_params, 6381 "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "{ : }", 6382 "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]" }, 6383 { &isl_multi_union_pw_aff_intersect_params, 6384 "C[]", "[N] -> { : N >= 0 }", 6385 "[N] -> (C[] : { : N >= 0 })" }, 6386 { &isl_multi_union_pw_aff_intersect_params, 6387 "(C[] : { A[a,b] })", "[N] -> { : N >= 0 }", 6388 "[N] -> (C[] : { A[a,b] : N >= 0 })" }, 6389 { &isl_multi_union_pw_aff_intersect_params, 6390 "[N] -> (C[] : { A[a,N] })", "{ : }", 6391 "[N] -> (C[] : { A[a,N] })" }, 6392 { &isl_multi_union_pw_aff_intersect_params, 6393 "[N] -> (C[] : { A[a,b] : N <= 256 })", "[N] -> { : N >= 0 }", 6394 "[N] -> (C[] : { A[a,b] : 0 <= N <= 256 })" }, 6395 }; 6396 6397 /* Perform some basic tests of binary operations on 6398 * pairs of isl_multi_union_pw_aff and isl_set objects. 6399 */ 6400 static int test_mupa_set(isl_ctx *ctx) 6401 { 6402 int i; 6403 isl_bool ok; 6404 isl_multi_union_pw_aff *mupa, *res; 6405 isl_set *set; 6406 6407 for (i = 0; i < ARRAY_SIZE(mupa_set_tests); ++i) { 6408 mupa = isl_multi_union_pw_aff_read_from_str(ctx, 6409 mupa_set_tests[i].arg1); 6410 set = isl_set_read_from_str(ctx, mupa_set_tests[i].arg2); 6411 res = isl_multi_union_pw_aff_read_from_str(ctx, 6412 mupa_set_tests[i].res); 6413 mupa = mupa_set_tests[i].fn(mupa, set); 6414 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res); 6415 isl_multi_union_pw_aff_free(mupa); 6416 isl_multi_union_pw_aff_free(res); 6417 if (ok < 0) 6418 return -1; 6419 if (!ok) 6420 isl_die(ctx, isl_error_unknown, 6421 "unexpected result", return -1); 6422 } 6423 6424 return 0; 6425 } 6426 6427 /* Inputs for basic tests of binary operations on 6428 * pairs of isl_multi_union_pw_aff and isl_union_set objects. 6429 * "fn" is the function that is tested. 6430 * "arg1" and "arg2" are string descriptions of the inputs. 6431 * "res" is a string description of the expected result. 6432 */ 6433 struct { 6434 __isl_give isl_multi_union_pw_aff *(*fn)( 6435 __isl_take isl_multi_union_pw_aff *mupa, 6436 __isl_take isl_union_set *uset); 6437 const char *arg1; 6438 const char *arg2; 6439 const char *res; 6440 } mupa_uset_tests[] = { 6441 { &isl_multi_union_pw_aff_intersect_domain, 6442 "C[{ B[i,j] -> [i + 2j] }]", "{ B[i,i] }", 6443 "C[{ B[i,i] -> [3i] }]" }, 6444 { &isl_multi_union_pw_aff_intersect_domain, 6445 "(C[] : { B[i,j] })", "{ B[i,i] }", 6446 "(C[] : { B[i,i] })" }, 6447 { &isl_multi_union_pw_aff_intersect_domain, 6448 "(C[] : { B[i,j] })", "[N] -> { B[N,N] }", 6449 "[N] -> (C[] : { B[N,N] })" }, 6450 { &isl_multi_union_pw_aff_intersect_domain, 6451 "C[]", "{ B[i,i] }", 6452 "(C[] : { B[i,i] })" }, 6453 { &isl_multi_union_pw_aff_intersect_domain, 6454 "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }", 6455 "[N] -> (C[] : { B[i,i] : N >= 0 })" }, 6456 }; 6457 6458 /* Perform some basic tests of binary operations on 6459 * pairs of isl_multi_union_pw_aff and isl_union_set objects. 6460 */ 6461 static int test_mupa_uset(isl_ctx *ctx) 6462 { 6463 int i; 6464 isl_bool ok; 6465 isl_multi_union_pw_aff *mupa, *res; 6466 isl_union_set *uset; 6467 6468 for (i = 0; i < ARRAY_SIZE(mupa_uset_tests); ++i) { 6469 mupa = isl_multi_union_pw_aff_read_from_str(ctx, 6470 mupa_uset_tests[i].arg1); 6471 uset = isl_union_set_read_from_str(ctx, 6472 mupa_uset_tests[i].arg2); 6473 res = isl_multi_union_pw_aff_read_from_str(ctx, 6474 mupa_uset_tests[i].res); 6475 mupa = mupa_uset_tests[i].fn(mupa, uset); 6476 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res); 6477 isl_multi_union_pw_aff_free(mupa); 6478 isl_multi_union_pw_aff_free(res); 6479 if (ok < 0) 6480 return -1; 6481 if (!ok) 6482 isl_die(ctx, isl_error_unknown, 6483 "unexpected result", return -1); 6484 } 6485 6486 return 0; 6487 } 6488 6489 /* Inputs for basic tests of binary operations on 6490 * pairs of isl_multi_union_pw_aff and isl_multi_aff objects. 6491 * "fn" is the function that is tested. 6492 * "arg1" and "arg2" are string descriptions of the inputs. 6493 * "res" is a string description of the expected result. 6494 */ 6495 struct { 6496 __isl_give isl_multi_union_pw_aff *(*fn)( 6497 __isl_take isl_multi_union_pw_aff *mupa, 6498 __isl_take isl_multi_aff *ma); 6499 const char *arg1; 6500 const char *arg2; 6501 const char *res; 6502 } mupa_ma_tests[] = { 6503 { &isl_multi_union_pw_aff_apply_multi_aff, 6504 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, " 6505 "{ A[i,j] -> [j]; B[i,j] -> [i] }]", 6506 "{ C[a,b] -> D[b,a] }", 6507 "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, " 6508 "{ A[i,j] -> [i]; B[i,j] -> [j] }]" }, 6509 { &isl_multi_union_pw_aff_apply_multi_aff, 6510 "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, " 6511 "{ A[i,j] -> [j]; B[i,j] -> [i] }]", 6512 "{ C[a,b] -> D[b,a] }", 6513 "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, " 6514 "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" }, 6515 { &isl_multi_union_pw_aff_apply_multi_aff, 6516 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]", 6517 "[N] -> { C[a] -> D[a + N] }", 6518 "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }] " }, 6519 { &isl_multi_union_pw_aff_apply_multi_aff, 6520 "C[]", 6521 "{ C[] -> D[] }", 6522 "D[]" }, 6523 { &isl_multi_union_pw_aff_apply_multi_aff, 6524 "[N] -> (C[] : { : N >= 0 })", 6525 "{ C[] -> D[] }", 6526 "[N] -> (D[] : { : N >= 0 })" }, 6527 { &isl_multi_union_pw_aff_apply_multi_aff, 6528 "C[]", 6529 "[N] -> { C[] -> D[N] }", 6530 "[N] -> D[{ [N] }]" }, 6531 { &isl_multi_union_pw_aff_apply_multi_aff, 6532 "(C[] : { A[i,j] : i >= j })", 6533 "{ C[] -> D[] }", 6534 "(D[] : { A[i,j] : i >= j })" }, 6535 { &isl_multi_union_pw_aff_apply_multi_aff, 6536 "[N] -> (C[] : { A[i,j] : N >= 0 })", 6537 "{ C[] -> D[] }", 6538 "[N] -> (D[] : { A[i,j] : N >= 0 })" }, 6539 { &isl_multi_union_pw_aff_apply_multi_aff, 6540 "(C[] : { A[i,j] : i >= j })", 6541 "[N] -> { C[] -> D[N] }", 6542 "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" }, 6543 }; 6544 6545 /* Perform some basic tests of binary operations on 6546 * pairs of isl_multi_union_pw_aff and isl_multi_aff objects. 6547 */ 6548 static int test_mupa_ma(isl_ctx *ctx) 6549 { 6550 int i; 6551 isl_bool ok; 6552 isl_multi_union_pw_aff *mupa, *res; 6553 isl_multi_aff *ma; 6554 6555 for (i = 0; i < ARRAY_SIZE(mupa_ma_tests); ++i) { 6556 mupa = isl_multi_union_pw_aff_read_from_str(ctx, 6557 mupa_ma_tests[i].arg1); 6558 ma = isl_multi_aff_read_from_str(ctx, mupa_ma_tests[i].arg2); 6559 res = isl_multi_union_pw_aff_read_from_str(ctx, 6560 mupa_ma_tests[i].res); 6561 mupa = mupa_ma_tests[i].fn(mupa, ma); 6562 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res); 6563 isl_multi_union_pw_aff_free(mupa); 6564 isl_multi_union_pw_aff_free(res); 6565 if (ok < 0) 6566 return -1; 6567 if (!ok) 6568 isl_die(ctx, isl_error_unknown, 6569 "unexpected result", return -1); 6570 } 6571 6572 return 0; 6573 } 6574 6575 /* Inputs for basic tests of binary operations on 6576 * pairs of isl_multi_union_pw_aff and isl_pw_aff objects. 6577 * "fn" is the function that is tested. 6578 * "arg1" and "arg2" are string descriptions of the inputs. 6579 * "res" is a string description of the expected result. 6580 */ 6581 struct { 6582 __isl_give isl_union_pw_aff *(*fn)( 6583 __isl_take isl_multi_union_pw_aff *mupa, 6584 __isl_take isl_pw_aff *pa); 6585 const char *arg1; 6586 const char *arg2; 6587 const char *res; 6588 } mupa_pa_tests[] = { 6589 { &isl_multi_union_pw_aff_apply_pw_aff, 6590 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]", 6591 "[N] -> { C[a] -> [a + N] }", 6592 "[N] -> { A[i,j] -> [i + N]; B[i,j] -> [j + N] }" }, 6593 { &isl_multi_union_pw_aff_apply_pw_aff, 6594 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]", 6595 "{ C[a] -> [a] : a >= 0; C[a] -> [-a] : a < 0 }", 6596 "{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; " 6597 "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }" }, 6598 { &isl_multi_union_pw_aff_apply_pw_aff, 6599 "C[]", 6600 "[N] -> { C[] -> [N] }", 6601 "[N] -> { [N] }" }, 6602 { &isl_multi_union_pw_aff_apply_pw_aff, 6603 "C[]", 6604 "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }", 6605 "[N] -> { [N] : N >= 0; [-N] : N < 0 }" }, 6606 { &isl_multi_union_pw_aff_apply_pw_aff, 6607 "[N] -> (C[] : { : N >= 0 })", 6608 "[N] -> { C[] -> [N] }", 6609 "[N] -> { [N] : N >= 0 }" }, 6610 { &isl_multi_union_pw_aff_apply_pw_aff, 6611 "[N] -> (C[] : { : N >= 0 })", 6612 "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }", 6613 "[N] -> { [N] : N >= 0 }" }, 6614 { &isl_multi_union_pw_aff_apply_pw_aff, 6615 "[N] -> (C[] : { : N >= 0 })", 6616 "{ C[] -> [0] }", 6617 "[N] -> { [0] : N >= 0 }" }, 6618 { &isl_multi_union_pw_aff_apply_pw_aff, 6619 "(C[] : { A[i,j] : i >= j })", 6620 "[N] -> { C[] -> [N] }", 6621 "[N] -> { A[i,j] -> [N] : i >= j }" }, 6622 { &isl_multi_union_pw_aff_apply_pw_aff, 6623 "(C[] : { A[i,j] : i >= j })", 6624 "[N] -> { C[] -> [N] : N >= 0 }", 6625 "[N] -> { A[i,j] -> [N] : i >= j and N >= 0 }" }, 6626 }; 6627 6628 /* Perform some basic tests of binary operations on 6629 * pairs of isl_multi_union_pw_aff and isl_pw_aff objects. 6630 */ 6631 static int test_mupa_pa(isl_ctx *ctx) 6632 { 6633 int i; 6634 isl_bool ok; 6635 isl_multi_union_pw_aff *mupa; 6636 isl_union_pw_aff *upa, *res; 6637 isl_pw_aff *pa; 6638 6639 for (i = 0; i < ARRAY_SIZE(mupa_pa_tests); ++i) { 6640 mupa = isl_multi_union_pw_aff_read_from_str(ctx, 6641 mupa_pa_tests[i].arg1); 6642 pa = isl_pw_aff_read_from_str(ctx, mupa_pa_tests[i].arg2); 6643 res = isl_union_pw_aff_read_from_str(ctx, 6644 mupa_pa_tests[i].res); 6645 upa = mupa_pa_tests[i].fn(mupa, pa); 6646 ok = isl_union_pw_aff_plain_is_equal(upa, res); 6647 isl_union_pw_aff_free(upa); 6648 isl_union_pw_aff_free(res); 6649 if (ok < 0) 6650 return -1; 6651 if (!ok) 6652 isl_die(ctx, isl_error_unknown, 6653 "unexpected result", return -1); 6654 } 6655 6656 return 0; 6657 } 6658 6659 /* Inputs for basic tests of binary operations on 6660 * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects. 6661 * "fn" is the function that is tested. 6662 * "arg1" and "arg2" are string descriptions of the inputs. 6663 * "res" is a string description of the expected result. 6664 */ 6665 struct { 6666 __isl_give isl_multi_union_pw_aff *(*fn)( 6667 __isl_take isl_multi_union_pw_aff *mupa, 6668 __isl_take isl_pw_multi_aff *pma); 6669 const char *arg1; 6670 const char *arg2; 6671 const char *res; 6672 } mupa_pma_tests[] = { 6673 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6674 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, " 6675 "{ A[i,j] -> [j]; B[i,j] -> [i] }]", 6676 "{ C[a,b] -> D[b,a] }", 6677 "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, " 6678 "{ A[i,j] -> [i]; B[i,j] -> [j] }]" }, 6679 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6680 "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, " 6681 "{ A[i,j] -> [j]; B[i,j] -> [i] }]", 6682 "{ C[a,b] -> D[b,a] }", 6683 "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, " 6684 "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" }, 6685 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6686 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]", 6687 "[N] -> { C[a] -> D[a + N] }", 6688 "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }]" }, 6689 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6690 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]", 6691 "{ C[a] -> D[a] : a >= 0; C[a] -> D[-a] : a < 0 }", 6692 "D[{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; " 6693 "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }]" }, 6694 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6695 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, " 6696 "{ A[i,j] -> [j]; B[i,j] -> [i] }]", 6697 "{ C[a,b] -> D[a,b] : a >= b; C[a,b] -> D[b,a] : a < b }", 6698 "D[{ A[i,j] -> [i] : i >= j; A[i,j] -> [j] : i < j; " 6699 "B[i,j] -> [j] : i <= j; B[i,j] -> [i] : i > j }, " 6700 "{ A[i,j] -> [j] : i >= j; A[i,j] -> [i] : i < j; " 6701 "B[i,j] -> [i] : i <= j; B[i,j] -> [j] : i > j }]" }, 6702 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6703 "C[]", 6704 "{ C[] -> D[] }", 6705 "D[]" }, 6706 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6707 "[N] -> (C[] : { : N >= 0 })", 6708 "{ C[] -> D[] }", 6709 "[N] -> (D[] : { : N >= 0 })" }, 6710 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6711 "C[]", 6712 "[N] -> { C[] -> D[N] }", 6713 "[N] -> D[{ [N] }]" }, 6714 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6715 "(C[] : { A[i,j] : i >= j })", 6716 "{ C[] -> D[] }", 6717 "(D[] : { A[i,j] : i >= j })" }, 6718 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6719 "[N] -> (C[] : { A[i,j] : N >= 0 })", 6720 "{ C[] -> D[] }", 6721 "[N] -> (D[] : { A[i,j] : N >= 0 })" }, 6722 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6723 "(C[] : { A[i,j] : i >= j })", 6724 "[N] -> { C[] -> D[N] }", 6725 "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" }, 6726 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6727 "C[]", 6728 "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }", 6729 "[N] -> D[{ [N] : N >= 0; [-N] : N < 0 }]" }, 6730 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6731 "[N] -> (C[] : { : N >= 0 })", 6732 "[N] -> { C[] -> D[N] }", 6733 "[N] -> D[{ [N] : N >= 0 }]" }, 6734 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6735 "[N] -> (C[] : { : N >= 0 })", 6736 "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }", 6737 "[N] -> D[{ [N] : N >= 0 }]" }, 6738 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6739 "[N] -> (C[] : { : N >= 0 })", 6740 "{ C[] -> D[0] }", 6741 "[N] -> D[{ [0] : N >= 0 }]" }, 6742 { &isl_multi_union_pw_aff_apply_pw_multi_aff, 6743 "(C[] : { A[i,j] : i >= j })", 6744 "[N] -> { C[] -> D[N] : N >= 0 }", 6745 "[N] -> D[{ A[i,j] -> [N] : i >= j and N >= 0 }]" }, 6746 }; 6747 6748 /* Perform some basic tests of binary operations on 6749 * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects. 6750 */ 6751 static int test_mupa_pma(isl_ctx *ctx) 6752 { 6753 int i; 6754 isl_bool ok; 6755 isl_multi_union_pw_aff *mupa, *res; 6756 isl_pw_multi_aff *pma; 6757 6758 for (i = 0; i < ARRAY_SIZE(mupa_pma_tests); ++i) { 6759 mupa = isl_multi_union_pw_aff_read_from_str(ctx, 6760 mupa_pma_tests[i].arg1); 6761 pma = isl_pw_multi_aff_read_from_str(ctx, 6762 mupa_pma_tests[i].arg2); 6763 res = isl_multi_union_pw_aff_read_from_str(ctx, 6764 mupa_pma_tests[i].res); 6765 mupa = mupa_pma_tests[i].fn(mupa, pma); 6766 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res); 6767 isl_multi_union_pw_aff_free(mupa); 6768 isl_multi_union_pw_aff_free(res); 6769 if (ok < 0) 6770 return -1; 6771 if (!ok) 6772 isl_die(ctx, isl_error_unknown, 6773 "unexpected result", return -1); 6774 } 6775 6776 return 0; 6777 } 6778 6779 /* Inputs for basic tests of binary operations on 6780 * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects. 6781 * "fn" is the function that is tested. 6782 * "arg1" and "arg2" are string descriptions of the inputs. 6783 * "res" is a string description of the expected result. 6784 */ 6785 struct { 6786 __isl_give isl_multi_union_pw_aff *(*fn)( 6787 __isl_take isl_multi_union_pw_aff *mupa, 6788 __isl_take isl_union_pw_multi_aff *upma); 6789 const char *arg1; 6790 const char *arg2; 6791 const char *res; 6792 } mupa_upma_tests[] = { 6793 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6794 "C[{ B[i,j] -> [i + 2j] }]", "{ A[a,b] -> B[b,a] }", 6795 "C[{ A[a,b] -> [b + 2a] }]" }, 6796 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6797 "C[{ B[i,j] -> [i + 2j] }]", 6798 "{ A[a,b] -> B[b,a] : b > a }", 6799 "C[{ A[a,b] -> [b + 2a] : b > a }]" }, 6800 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6801 "C[{ B[i,j] -> [i + 2j] : j > 4 }]", 6802 "{ A[a,b] -> B[b,a] : b > a }", 6803 "C[{ A[a,b] -> [b + 2a] : b > a > 4 }]" }, 6804 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6805 "C[{ B[i,j] -> [i + 2j] }]", 6806 "{ A[a,b] -> B[b,a] : a > b; A[a,b] -> B[a,b] : a <= b }", 6807 "C[{ A[a,b] -> [b + 2a] : a > b; A[a,b] -> [a + 2b] : a <= b }]" }, 6808 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6809 "(C[] : { B[a,b] })", 6810 "{ A[a,b] -> B[b,a] }", 6811 "(C[] : { A[a,b] })" }, 6812 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6813 "(C[] : { B[a,b] })", 6814 "{ B[a,b] -> A[b,a] }", 6815 "(C[] : { })" }, 6816 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6817 "(C[] : { B[a,b] })", 6818 "{ A[a,b] -> B[b,a] : a > b }", 6819 "(C[] : { A[a,b] : a > b })" }, 6820 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6821 "(C[] : { B[a,b] : a > b })", 6822 "{ A[a,b] -> B[b,a] }", 6823 "(C[] : { A[a,b] : b > a })" }, 6824 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6825 "[N] -> (C[] : { B[a,b] : a > N })", 6826 "{ A[a,b] -> B[b,a] : a > b }", 6827 "[N] -> (C[] : { A[a,b] : a > b > N })" }, 6828 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6829 "(C[] : { B[a,b] : a > b })", 6830 "[N] -> { A[a,b] -> B[b,a] : a > N }", 6831 "[N] -> (C[] : { A[a,b] : b > a > N })" }, 6832 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6833 "C[]", 6834 "{ A[a,b] -> B[b,a] }", 6835 "C[]" }, 6836 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6837 "[N] -> (C[] : { : N >= 0 })", 6838 "{ A[a,b] -> B[b,a] }", 6839 "[N] -> (C[] : { : N >= 0 })" }, 6840 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff, 6841 "C[]", 6842 "[N] -> { A[a,b] -> B[b,a] : N >= 0 }", 6843 "[N] -> (C[] : { : N >= 0 })" }, 6844 }; 6845 6846 /* Perform some basic tests of binary operations on 6847 * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects. 6848 */ 6849 static int test_mupa_upma(isl_ctx *ctx) 6850 { 6851 int i; 6852 isl_bool ok; 6853 isl_multi_union_pw_aff *mupa, *res; 6854 isl_union_pw_multi_aff *upma; 6855 6856 for (i = 0; i < ARRAY_SIZE(mupa_upma_tests); ++i) { 6857 mupa = isl_multi_union_pw_aff_read_from_str(ctx, 6858 mupa_upma_tests[i].arg1); 6859 upma = isl_union_pw_multi_aff_read_from_str(ctx, 6860 mupa_upma_tests[i].arg2); 6861 res = isl_multi_union_pw_aff_read_from_str(ctx, 6862 mupa_upma_tests[i].res); 6863 mupa = mupa_upma_tests[i].fn(mupa, upma); 6864 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res); 6865 isl_multi_union_pw_aff_free(mupa); 6866 isl_multi_union_pw_aff_free(res); 6867 if (ok < 0) 6868 return -1; 6869 if (!ok) 6870 isl_die(ctx, isl_error_unknown, 6871 "unexpected result", return -1); 6872 } 6873 6874 return 0; 6875 } 6876 6877 /* Check that the input tuple of an isl_aff can be set properly. 6878 */ 6879 static isl_stat test_aff_set_tuple_id(isl_ctx *ctx) 6880 { 6881 isl_id *id; 6882 isl_aff *aff; 6883 isl_stat equal; 6884 6885 aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }"); 6886 id = isl_id_alloc(ctx, "A", NULL); 6887 aff = isl_aff_set_tuple_id(aff, isl_dim_in, id); 6888 equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }"); 6889 isl_aff_free(aff); 6890 if (equal < 0) 6891 return isl_stat_error; 6892 6893 return isl_stat_ok; 6894 } 6895 6896 /* Check that affine expressions get normalized on addition/subtraction. 6897 * In particular, check that (final) unused integer divisions get removed 6898 * such that an expression derived from expressions with integer divisions 6899 * is found to be obviously equal to one that is created directly. 6900 */ 6901 static isl_stat test_aff_normalize(isl_ctx *ctx) 6902 { 6903 isl_aff *aff, *aff2; 6904 isl_stat ok; 6905 6906 aff = isl_aff_read_from_str(ctx, "{ [x] -> [x//2] }"); 6907 aff2 = isl_aff_read_from_str(ctx, "{ [x] -> [1 + x//2] }"); 6908 aff = isl_aff_sub(aff2, aff); 6909 ok = aff_check_plain_equal(aff, "{ [x] -> [1] }"); 6910 isl_aff_free(aff); 6911 6912 return ok; 6913 } 6914 6915 int test_aff(isl_ctx *ctx) 6916 { 6917 const char *str; 6918 isl_set *set; 6919 isl_space *space; 6920 isl_local_space *ls; 6921 isl_aff *aff; 6922 int zero; 6923 isl_stat equal; 6924 6925 if (test_upa(ctx) < 0) 6926 return -1; 6927 if (test_bin_aff(ctx) < 0) 6928 return -1; 6929 if (test_bin_pw_aff(ctx) < 0) 6930 return -1; 6931 if (test_upma_test(ctx) < 0) 6932 return -1; 6933 if (test_bin_upma(ctx) < 0) 6934 return -1; 6935 if (test_bin_upma_fail(ctx) < 0) 6936 return -1; 6937 if (test_upma_uset(ctx) < 0) 6938 return -1; 6939 if (test_un_mpa(ctx) < 0) 6940 return -1; 6941 if (test_bin_mpa(ctx) < 0) 6942 return -1; 6943 if (test_un_mupa(ctx) < 0) 6944 return -1; 6945 if (test_bin_mupa(ctx) < 0) 6946 return -1; 6947 if (test_mupa_set(ctx) < 0) 6948 return -1; 6949 if (test_mupa_uset(ctx) < 0) 6950 return -1; 6951 if (test_mupa_ma(ctx) < 0) 6952 return -1; 6953 if (test_mupa_pa(ctx) < 0) 6954 return -1; 6955 if (test_mupa_pma(ctx) < 0) 6956 return -1; 6957 if (test_mupa_upma(ctx) < 0) 6958 return -1; 6959 6960 space = isl_space_set_alloc(ctx, 0, 1); 6961 ls = isl_local_space_from_space(space); 6962 aff = isl_aff_zero_on_domain(ls); 6963 6964 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1); 6965 aff = isl_aff_scale_down_ui(aff, 3); 6966 aff = isl_aff_floor(aff); 6967 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1); 6968 aff = isl_aff_scale_down_ui(aff, 2); 6969 aff = isl_aff_floor(aff); 6970 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1); 6971 6972 str = "{ [10] }"; 6973 set = isl_set_read_from_str(ctx, str); 6974 aff = isl_aff_gist(aff, set); 6975 6976 aff = isl_aff_add_constant_si(aff, -16); 6977 zero = isl_aff_plain_is_zero(aff); 6978 isl_aff_free(aff); 6979 6980 if (zero < 0) 6981 return -1; 6982 if (!zero) 6983 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 6984 6985 aff = isl_aff_read_from_str(ctx, "{ [-1] }"); 6986 aff = isl_aff_scale_down_ui(aff, 64); 6987 aff = isl_aff_floor(aff); 6988 equal = aff_check_plain_equal(aff, "{ [-1] }"); 6989 isl_aff_free(aff); 6990 if (equal < 0) 6991 return -1; 6992 6993 if (test_aff_set_tuple_id(ctx) < 0) 6994 return -1; 6995 if (test_aff_normalize(ctx) < 0) 6996 return -1; 6997 6998 return 0; 6999 } 7000 7001 /* Inputs for isl_set_bind tests. 7002 * "set" is the input set. 7003 * "tuple" is the binding tuple. 7004 * "res" is the expected result. 7005 */ 7006 static 7007 struct { 7008 const char *set; 7009 const char *tuple; 7010 const char *res; 7011 } bind_set_tests[] = { 7012 { "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }", 7013 "{ A[M, N] }", 7014 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" }, 7015 { "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }", 7016 "{ B[N, M] }", 7017 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" }, 7018 { "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }", 7019 "{ C[N] }", 7020 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" }, 7021 { "[M] -> { D[x, N] : x mod 2 = 0 and N mod 8 = 3 and M >= 0 }", 7022 "{ D[M, N] }", 7023 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 and M >= 0 }" }, 7024 }; 7025 7026 /* Perform basic isl_set_bind tests. 7027 */ 7028 static isl_stat test_bind_set(isl_ctx *ctx) 7029 { 7030 int i; 7031 7032 for (i = 0; i < ARRAY_SIZE(bind_set_tests); ++i) { 7033 const char *str; 7034 isl_set *set; 7035 isl_multi_id *tuple; 7036 isl_stat r; 7037 7038 set = isl_set_read_from_str(ctx, bind_set_tests[i].set); 7039 str = bind_set_tests[i].tuple; 7040 tuple = isl_multi_id_read_from_str(ctx, str); 7041 set = isl_set_bind(set, tuple); 7042 r = set_check_equal(set, bind_set_tests[i].res); 7043 isl_set_free(set); 7044 if (r < 0) 7045 return isl_stat_error; 7046 } 7047 7048 return isl_stat_ok; 7049 } 7050 7051 /* Inputs for isl_map_bind_domain tests. 7052 * "map" is the input map. 7053 * "tuple" is the binding tuple. 7054 * "res" is the expected result. 7055 */ 7056 struct { 7057 const char *map; 7058 const char *tuple; 7059 const char *res; 7060 } bind_map_domain_tests[] = { 7061 { "{ A[M, N] -> [M + floor(N/2)] }", 7062 "{ A[M, N] }", 7063 "[M, N] -> { [M + floor(N/2)] }" }, 7064 { "{ B[N, M] -> [M + floor(N/2)] }", 7065 "{ B[N, M] }", 7066 "[N, M] -> { [M + floor(N/2)] }" }, 7067 { "[M] -> { C[N] -> [M + floor(N/2)] }", 7068 "{ C[N] }", 7069 "[M, N] -> { [M + floor(N/2)] }" }, 7070 { "[M] -> { C[x, N] -> [x + floor(N/2)] }", 7071 "{ C[M, N] }", 7072 "[M, N] -> { [M + floor(N/2)] }" }, 7073 { "[M] -> { C[x, N] -> [M + floor(N/2)] }", 7074 "{ C[M, N] }", 7075 "[M, N] -> { [M + floor(N/2)] }" }, 7076 { "[A, M] -> { C[N, x] -> [x + floor(N/2)] }", 7077 "{ C[N, M] }", 7078 "[A, N, M] -> { [M + floor(N/2)] }" }, 7079 }; 7080 7081 /* Perform basic isl_map_bind_domain tests. 7082 */ 7083 static isl_stat test_bind_map_domain(isl_ctx *ctx) 7084 { 7085 int i; 7086 7087 for (i = 0; i < ARRAY_SIZE(bind_map_domain_tests); ++i) { 7088 const char *str; 7089 isl_map *map; 7090 isl_set *set; 7091 isl_multi_id *tuple; 7092 isl_stat r; 7093 7094 str = bind_map_domain_tests[i].map; 7095 map = isl_map_read_from_str(ctx, str); 7096 str = bind_map_domain_tests[i].tuple; 7097 tuple = isl_multi_id_read_from_str(ctx, str); 7098 set = isl_map_bind_domain(map, tuple); 7099 str = bind_map_domain_tests[i].res; 7100 r = set_check_equal(set, str); 7101 isl_set_free(set); 7102 if (r < 0) 7103 return isl_stat_error; 7104 } 7105 7106 return isl_stat_ok; 7107 } 7108 7109 /* Inputs for isl_union_map_bind_range tests. 7110 * "map" is the input union map. 7111 * "tuple" is the binding tuple. 7112 * "res" is the expected result. 7113 */ 7114 struct { 7115 const char *map; 7116 const char *tuple; 7117 const char *res; 7118 } bind_umap_range_tests[] = { 7119 { "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }", 7120 "{ A[M, N] }", 7121 "[M, N] -> { B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" }, 7122 { "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }", 7123 "{ B[M, N] }", 7124 "{ }" }, 7125 { "{ A[] -> B[]; C[] -> D[]; E[] -> B[] }", 7126 "{ B[] }", 7127 "{ A[]; E[] }" }, 7128 }; 7129 7130 /* Perform basic isl_union_map_bind_range tests. 7131 */ 7132 static isl_stat test_bind_umap_range(isl_ctx *ctx) 7133 { 7134 int i; 7135 7136 for (i = 0; i < ARRAY_SIZE(bind_umap_range_tests); ++i) { 7137 const char *str; 7138 isl_union_map *umap; 7139 isl_union_set *uset; 7140 isl_multi_id *tuple; 7141 isl_stat r; 7142 7143 str = bind_umap_range_tests[i].map; 7144 umap = isl_union_map_read_from_str(ctx, str); 7145 str = bind_umap_range_tests[i].tuple; 7146 tuple = isl_multi_id_read_from_str(ctx, str); 7147 uset = isl_union_map_bind_range(umap, tuple); 7148 str = bind_umap_range_tests[i].res; 7149 r = uset_check_equal(uset, str); 7150 isl_union_set_free(uset); 7151 if (r < 0) 7152 return isl_stat_error; 7153 } 7154 7155 return isl_stat_ok; 7156 } 7157 7158 /* Inputs for isl_pw_multi_aff_bind_domain tests. 7159 * "pma" is the input expression. 7160 * "tuple" is the binding tuple. 7161 * "res" is the expected result. 7162 */ 7163 struct { 7164 const char *pma; 7165 const char *tuple; 7166 const char *res; 7167 } bind_pma_domain_tests[] = { 7168 { "{ A[M, N] -> [M + floor(N/2)] }", 7169 "{ A[M, N] }", 7170 "[M, N] -> { [M + floor(N/2)] }" }, 7171 { "{ B[N, M] -> [M + floor(N/2)] }", 7172 "{ B[N, M] }", 7173 "[N, M] -> { [M + floor(N/2)] }" }, 7174 { "[M] -> { C[N] -> [M + floor(N/2)] }", 7175 "{ C[N] }", 7176 "[M, N] -> { [M + floor(N/2)] }" }, 7177 { "[M] -> { C[x, N] -> [x + floor(N/2)] }", 7178 "{ C[M, N] }", 7179 "[M, N] -> { [M + floor(N/2)] }" }, 7180 { "[M] -> { C[x, N] -> [M + floor(N/2)] }", 7181 "{ C[M, N] }", 7182 "[M, N] -> { [M + floor(N/2)] }" }, 7183 { "[A, M] -> { C[N, x] -> [x + floor(N/2)] }", 7184 "{ C[N, M] }", 7185 "[A, N, M] -> { [M + floor(N/2)] }" }, 7186 }; 7187 7188 /* Perform basic isl_pw_multi_aff_bind_domain tests. 7189 */ 7190 static isl_stat test_bind_pma_domain(isl_ctx *ctx) 7191 { 7192 int i; 7193 7194 for (i = 0; i < ARRAY_SIZE(bind_pma_domain_tests); ++i) { 7195 const char *str; 7196 isl_pw_multi_aff *pma; 7197 isl_multi_id *tuple; 7198 isl_stat r; 7199 7200 str = bind_pma_domain_tests[i].pma; 7201 pma = isl_pw_multi_aff_read_from_str(ctx, str); 7202 str = bind_pma_domain_tests[i].tuple; 7203 tuple = isl_multi_id_read_from_str(ctx, str); 7204 pma = isl_pw_multi_aff_bind_domain(pma, tuple); 7205 str = bind_pma_domain_tests[i].res; 7206 r = pw_multi_aff_check_plain_equal(pma, str); 7207 isl_pw_multi_aff_free(pma); 7208 if (r < 0) 7209 return isl_stat_error; 7210 } 7211 7212 return isl_stat_ok; 7213 } 7214 7215 /* Inputs for isl_pw_multi_aff_bind_domain_wrapped_domain tests. 7216 * "pma" is the input expression. 7217 * "tuple" is the binding tuple. 7218 * "res" is the expected result. 7219 */ 7220 struct { 7221 const char *pma; 7222 const char *tuple; 7223 const char *res; 7224 } bind_pma_domain_wrapped_tests[] = { 7225 { "{ [A[M, N] -> B[]] -> [M + floor(N/2)] }", 7226 "{ A[M, N] }", 7227 "[M, N] -> { B[] -> [M + floor(N/2)] }" }, 7228 { "{ [B[N, M] -> D[]] -> [M + floor(N/2)] }", 7229 "{ B[N, M] }", 7230 "[N, M] -> { D[] -> [M + floor(N/2)] }" }, 7231 { "[M] -> { [C[N] -> B[x]] -> [x + M + floor(N/2)] }", 7232 "{ C[N] }", 7233 "[M, N] -> { B[x] -> [x + M + floor(N/2)] }" }, 7234 { "[M] -> { [C[x, N] -> B[]] -> [x + floor(N/2)] }", 7235 "{ C[M, N] }", 7236 "[M, N] -> { B[] -> [M + floor(N/2)] }" }, 7237 { "[M] -> { [C[x, N] -> B[]] -> [M + floor(N/2)] }", 7238 "{ C[M, N] }", 7239 "[M, N] -> { B[] -> [M + floor(N/2)] }" }, 7240 { "[A, M] -> { [C[N, x] -> B[]] -> [x + floor(N/2)] }", 7241 "{ C[N, M] }", 7242 "[A, N, M] -> { B[] -> [M + floor(N/2)] }" }, 7243 }; 7244 7245 /* Perform basic isl_pw_multi_aff_bind_domain_wrapped_domain tests. 7246 */ 7247 static isl_stat test_bind_pma_domain_wrapped(isl_ctx *ctx) 7248 { 7249 int i; 7250 7251 for (i = 0; i < ARRAY_SIZE(bind_pma_domain_wrapped_tests); ++i) { 7252 const char *str; 7253 isl_pw_multi_aff *pma; 7254 isl_multi_id *tuple; 7255 isl_stat r; 7256 7257 str = bind_pma_domain_wrapped_tests[i].pma; 7258 pma = isl_pw_multi_aff_read_from_str(ctx, str); 7259 str = bind_pma_domain_wrapped_tests[i].tuple; 7260 tuple = isl_multi_id_read_from_str(ctx, str); 7261 pma = isl_pw_multi_aff_bind_domain_wrapped_domain(pma, tuple); 7262 str = bind_pma_domain_wrapped_tests[i].res; 7263 r = pw_multi_aff_check_plain_equal(pma, str); 7264 isl_pw_multi_aff_free(pma); 7265 if (r < 0) 7266 return isl_stat_error; 7267 } 7268 7269 return isl_stat_ok; 7270 } 7271 7272 /* Inputs for isl_aff_bind_id tests. 7273 * "aff" is the input expression. 7274 * "id" is the binding id. 7275 * "res" is the expected result. 7276 */ 7277 static 7278 struct { 7279 const char *aff; 7280 const char *id; 7281 const char *res; 7282 } bind_aff_tests[] = { 7283 { "{ [4] }", "M", "[M = 4] -> { : }" }, 7284 { "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" }, 7285 { "[M] -> { [4] }", "M", "[M = 4] -> { : }" }, 7286 { "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" }, 7287 { "{ [NaN] }", "M", "{ : false }" }, 7288 { "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" }, 7289 }; 7290 7291 /* Perform basic isl_aff_bind_id tests. 7292 */ 7293 static isl_stat test_bind_aff(isl_ctx *ctx) 7294 { 7295 int i; 7296 7297 for (i = 0; i < ARRAY_SIZE(bind_aff_tests); ++i) { 7298 isl_aff *aff; 7299 isl_set *res; 7300 isl_id *id; 7301 isl_stat r; 7302 7303 aff = isl_aff_read_from_str(ctx, bind_aff_tests[i].aff); 7304 id = isl_id_read_from_str(ctx, bind_aff_tests[i].id); 7305 res = isl_set_from_basic_set(isl_aff_bind_id(aff, id)); 7306 r = set_check_equal(res, bind_aff_tests[i].res); 7307 isl_set_free(res); 7308 if (r < 0) 7309 return isl_stat_error; 7310 } 7311 7312 return isl_stat_ok; 7313 } 7314 7315 /* Inputs for isl_pw_aff_bind_id tests. 7316 * "pa" is the input expression. 7317 * "id" is the binding id. 7318 * "res" is the expected result. 7319 */ 7320 static 7321 struct { 7322 const char *pa; 7323 const char *id; 7324 const char *res; 7325 } bind_pa_tests[] = { 7326 { "{ [4] }", "M", "[M = 4] -> { : }" }, 7327 { "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" }, 7328 { "[M] -> { [4] }", "M", "[M = 4] -> { : }" }, 7329 { "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" }, 7330 { "[M] -> { [M] : M >= 0; [-M] : M < 0 }", "M", "[M] -> { : M >= 0 }" }, 7331 { "{ [NaN] }", "M", "{ : false }" }, 7332 { "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" }, 7333 }; 7334 7335 /* Perform basic isl_pw_aff_bind_id tests. 7336 */ 7337 static isl_stat test_bind_pa(isl_ctx *ctx) 7338 { 7339 int i; 7340 7341 for (i = 0; i < ARRAY_SIZE(bind_pa_tests); ++i) { 7342 isl_pw_aff *pa; 7343 isl_set *res; 7344 isl_id *id; 7345 isl_stat r; 7346 7347 pa = isl_pw_aff_read_from_str(ctx, bind_pa_tests[i].pa); 7348 id = isl_id_read_from_str(ctx, bind_pa_tests[i].id); 7349 res = isl_pw_aff_bind_id(pa, id); 7350 r = set_check_equal(res, bind_pa_tests[i].res); 7351 isl_set_free(res); 7352 if (r < 0) 7353 return isl_stat_error; 7354 } 7355 7356 return isl_stat_ok; 7357 } 7358 7359 /* Inputs for isl_multi_union_pw_aff_bind tests. 7360 * "mupa" is the input expression. 7361 * "tuple" is the binding tuple. 7362 * "res" is the expected result. 7363 */ 7364 static 7365 struct { 7366 const char *mupa; 7367 const char *tuple; 7368 const char *res; 7369 } bind_mupa_tests[] = { 7370 { "A[{ [4] }, { [5] }]", 7371 "{ A[M, N] }", 7372 "[M = 4, N = 5] -> { : }" }, 7373 { "A[{ B[x] -> [floor(x/2)] }, { B[y] -> [y + 5] }]", 7374 "{ A[M, N] }", 7375 "[M, N] -> { B[x] : M = floor(x/2) and N = x + 5 }" }, 7376 { "[M] -> A[{ [4] }, { [M + 1] }]", 7377 "{ A[M, N] }", 7378 "[M = 4, N = 5] -> { : }" }, 7379 }; 7380 7381 /* Perform basic isl_multi_union_pw_aff_bind tests. 7382 */ 7383 static isl_stat test_bind_mupa(isl_ctx *ctx) 7384 { 7385 int i; 7386 7387 for (i = 0; i < ARRAY_SIZE(bind_mupa_tests); ++i) { 7388 const char *str; 7389 isl_multi_union_pw_aff *mupa; 7390 isl_union_set *res; 7391 isl_multi_id *tuple; 7392 isl_stat r; 7393 7394 str = bind_mupa_tests[i].mupa; 7395 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str); 7396 str = bind_mupa_tests[i].tuple; 7397 tuple = isl_multi_id_read_from_str(ctx, str); 7398 res = isl_multi_union_pw_aff_bind(mupa, tuple); 7399 r = uset_check_equal(res, bind_mupa_tests[i].res); 7400 isl_union_set_free(res); 7401 if (r < 0) 7402 return isl_stat_error; 7403 } 7404 7405 return isl_stat_ok; 7406 } 7407 7408 /* Perform tests that reinterpret dimensions as parameters. 7409 */ 7410 static int test_bind(isl_ctx *ctx) 7411 { 7412 if (test_bind_set(ctx) < 0) 7413 return -1; 7414 if (test_bind_map_domain(ctx) < 0) 7415 return -1; 7416 if (test_bind_umap_range(ctx) < 0) 7417 return -1; 7418 if (test_bind_pma_domain(ctx) < 0) 7419 return -1; 7420 if (test_bind_pma_domain_wrapped(ctx) < 0) 7421 return -1; 7422 if (test_bind_aff(ctx) < 0) 7423 return -1; 7424 if (test_bind_pa(ctx) < 0) 7425 return -1; 7426 if (test_bind_mupa(ctx) < 0) 7427 return -1; 7428 7429 return 0; 7430 } 7431 7432 /* Inputs for isl_set_unbind_params tests. 7433 * "set" is the input parameter domain. 7434 * "tuple" is the tuple of the constructed set. 7435 * "res" is the expected result. 7436 */ 7437 struct { 7438 const char *set; 7439 const char *tuple; 7440 const char *res; 7441 } unbind_set_tests[] = { 7442 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }", 7443 "{ A[M, N] }", 7444 "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }" }, 7445 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }", 7446 "{ B[N, M] }", 7447 "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" }, 7448 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }", 7449 "{ C[N] }", 7450 "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }" }, 7451 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }", 7452 "{ D[T, N] }", 7453 "[M] -> { D[x, N] : M mod 2 = 0 and N mod 8 = 3 }" }, 7454 }; 7455 7456 /* Perform basic isl_set_unbind_params tests. 7457 */ 7458 static isl_stat test_unbind_set(isl_ctx *ctx) 7459 { 7460 int i; 7461 7462 for (i = 0; i < ARRAY_SIZE(unbind_set_tests); ++i) { 7463 const char *str; 7464 isl_set *set; 7465 isl_multi_id *tuple; 7466 isl_stat r; 7467 7468 set = isl_set_read_from_str(ctx, unbind_set_tests[i].set); 7469 str = unbind_set_tests[i].tuple; 7470 tuple = isl_multi_id_read_from_str(ctx, str); 7471 set = isl_set_unbind_params(set, tuple); 7472 r = set_check_equal(set, unbind_set_tests[i].res); 7473 isl_set_free(set); 7474 if (r < 0) 7475 return isl_stat_error; 7476 } 7477 7478 return isl_stat_ok; 7479 } 7480 7481 /* Inputs for isl_aff_unbind_params_insert_domain tests. 7482 * "aff" is the input affine expression defined over a parameter domain. 7483 * "tuple" is the tuple of the domain that gets introduced. 7484 * "res" is the expected result. 7485 */ 7486 struct { 7487 const char *aff; 7488 const char *tuple; 7489 const char *res; 7490 } unbind_aff_tests[] = { 7491 { "[M, N] -> { [M + floor(N/2)] }", 7492 "{ A[M, N] }", 7493 "{ A[M, N] -> [M + floor(N/2)] }" }, 7494 { "[M, N] -> { [M + floor(N/2)] }", 7495 "{ B[N, M] }", 7496 "{ B[N, M] -> [M + floor(N/2)] }" }, 7497 { "[M, N] -> { [M + floor(N/2)] }", 7498 "{ C[N] }", 7499 "[M] -> { C[N] -> [M + floor(N/2)] }" }, 7500 { "[M, N] -> { [M + floor(N/2)] }", 7501 "{ D[A, B, C, N, Z] }", 7502 "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" }, 7503 }; 7504 7505 /* Perform basic isl_aff_unbind_params_insert_domain tests. 7506 */ 7507 static isl_stat test_unbind_aff(isl_ctx *ctx) 7508 { 7509 int i; 7510 7511 for (i = 0; i < ARRAY_SIZE(unbind_aff_tests); ++i) { 7512 const char *str; 7513 isl_aff *aff; 7514 isl_multi_id *tuple; 7515 isl_stat r; 7516 7517 aff = isl_aff_read_from_str(ctx, unbind_aff_tests[i].aff); 7518 str = unbind_aff_tests[i].tuple; 7519 tuple = isl_multi_id_read_from_str(ctx, str); 7520 aff = isl_aff_unbind_params_insert_domain(aff, tuple); 7521 r = aff_check_plain_equal(aff, unbind_aff_tests[i].res); 7522 isl_aff_free(aff); 7523 if (r < 0) 7524 return isl_stat_error; 7525 } 7526 7527 return isl_stat_ok; 7528 } 7529 7530 /* Inputs for isl_multi_aff_unbind_params_insert_domain tests. 7531 * "ma" is the input multi affine expression defined over a parameter domain. 7532 * "tuple" is the tuple of the domain that gets introduced. 7533 * "res" is the expected result. 7534 */ 7535 static struct { 7536 const char *ma; 7537 const char *tuple; 7538 const char *res; 7539 } unbind_multi_aff_tests[] = { 7540 { "[M, N] -> { T[M + floor(N/2)] }", 7541 "{ A[M, N] }", 7542 "{ A[M, N] -> T[M + floor(N/2)] }" }, 7543 { "[M, N] -> { [M + floor(N/2)] }", 7544 "{ B[N, M] }", 7545 "{ B[N, M] -> [M + floor(N/2)] }" }, 7546 { "[M, N] -> { [M + floor(N/2)] }", 7547 "{ C[N] }", 7548 "[M] -> { C[N] -> [M + floor(N/2)] }" }, 7549 { "[M, N] -> { [M + floor(N/2)] }", 7550 "{ D[A, B, C, N, Z] }", 7551 "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" }, 7552 { "[M, N] -> { T[M + floor(N/2), N + floor(M/3)] }", 7553 "{ A[M, N] }", 7554 "{ A[M, N] -> T[M + floor(N/2), N + floor(M/3)] }" }, 7555 }; 7556 7557 /* Perform basic isl_multi_aff_unbind_params_insert_domain tests. 7558 */ 7559 static isl_stat test_unbind_multi_aff(isl_ctx *ctx) 7560 { 7561 int i; 7562 7563 for (i = 0; i < ARRAY_SIZE(unbind_multi_aff_tests); ++i) { 7564 const char *str; 7565 isl_multi_aff *ma; 7566 isl_multi_id *tuple; 7567 isl_stat r; 7568 7569 str = unbind_multi_aff_tests[i].ma; 7570 ma = isl_multi_aff_read_from_str(ctx, str); 7571 str = unbind_multi_aff_tests[i].tuple; 7572 tuple = isl_multi_id_read_from_str(ctx, str); 7573 ma = isl_multi_aff_unbind_params_insert_domain(ma, tuple); 7574 str = unbind_multi_aff_tests[i].res; 7575 r = multi_aff_check_plain_equal(ma, str); 7576 isl_multi_aff_free(ma); 7577 if (r < 0) 7578 return isl_stat_error; 7579 } 7580 7581 return isl_stat_ok; 7582 } 7583 7584 /* Perform tests that reinterpret parameters. 7585 */ 7586 static int test_unbind(isl_ctx *ctx) 7587 { 7588 if (test_unbind_set(ctx) < 0) 7589 return -1; 7590 if (test_unbind_aff(ctx) < 0) 7591 return -1; 7592 if (test_unbind_multi_aff(ctx) < 0) 7593 return -1; 7594 7595 return 0; 7596 } 7597 7598 /* Check that "pa" consists of a single expression. 7599 */ 7600 static int check_single_piece(isl_ctx *ctx, __isl_take isl_pw_aff *pa) 7601 { 7602 isl_size n; 7603 7604 n = isl_pw_aff_n_piece(pa); 7605 isl_pw_aff_free(pa); 7606 7607 if (n < 0) 7608 return -1; 7609 if (n != 1) 7610 isl_die(ctx, isl_error_unknown, "expecting single expression", 7611 return -1); 7612 7613 return 0; 7614 } 7615 7616 /* Check that the computation below results in a single expression. 7617 * One or two expressions may result depending on which constraint 7618 * ends up being considered as redundant with respect to the other 7619 * constraints after the projection that is performed internally 7620 * by isl_set_dim_min. 7621 */ 7622 static int test_dim_max_1(isl_ctx *ctx) 7623 { 7624 const char *str; 7625 isl_set *set; 7626 isl_pw_aff *pa; 7627 7628 str = "[n] -> { [a, b] : n >= 0 and 4a >= -4 + n and b >= 0 and " 7629 "-4a <= b <= 3 and b < n - 4a }"; 7630 set = isl_set_read_from_str(ctx, str); 7631 pa = isl_set_dim_min(set, 0); 7632 return check_single_piece(ctx, pa); 7633 } 7634 7635 /* Check that the computation below results in a single expression. 7636 * The PIP problem corresponding to these constraints has a row 7637 * that causes a split of the solution domain. The solver should 7638 * first pick rows that split off empty parts such that the actual 7639 * solution domain does not get split. 7640 * Note that the description contains some redundant constraints. 7641 * If these constraints get removed first, then the row mentioned 7642 * above does not appear in the PIP problem. 7643 */ 7644 static int test_dim_max_2(isl_ctx *ctx) 7645 { 7646 const char *str; 7647 isl_set *set; 7648 isl_pw_aff *pa; 7649 7650 str = "[P, N] -> { [a] : a < N and a >= 0 and N > P and a <= P and " 7651 "N > 0 and P >= 0 }"; 7652 set = isl_set_read_from_str(ctx, str); 7653 pa = isl_set_dim_max(set, 0); 7654 return check_single_piece(ctx, pa); 7655 } 7656 7657 int test_dim_max(isl_ctx *ctx) 7658 { 7659 int equal; 7660 const char *str; 7661 isl_set *set1, *set2; 7662 isl_set *set; 7663 isl_map *map; 7664 isl_pw_aff *pwaff; 7665 7666 if (test_dim_max_1(ctx) < 0) 7667 return -1; 7668 if (test_dim_max_2(ctx) < 0) 7669 return -1; 7670 7671 str = "[N] -> { [i] : 0 <= i <= min(N,10) }"; 7672 set = isl_set_read_from_str(ctx, str); 7673 pwaff = isl_set_dim_max(set, 0); 7674 set1 = isl_set_from_pw_aff(pwaff); 7675 str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }"; 7676 set2 = isl_set_read_from_str(ctx, str); 7677 equal = isl_set_is_equal(set1, set2); 7678 isl_set_free(set1); 7679 isl_set_free(set2); 7680 if (equal < 0) 7681 return -1; 7682 if (!equal) 7683 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7684 7685 str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }"; 7686 set = isl_set_read_from_str(ctx, str); 7687 pwaff = isl_set_dim_max(set, 0); 7688 set1 = isl_set_from_pw_aff(pwaff); 7689 str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }"; 7690 set2 = isl_set_read_from_str(ctx, str); 7691 equal = isl_set_is_equal(set1, set2); 7692 isl_set_free(set1); 7693 isl_set_free(set2); 7694 if (equal < 0) 7695 return -1; 7696 if (!equal) 7697 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7698 7699 str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }"; 7700 set = isl_set_read_from_str(ctx, str); 7701 pwaff = isl_set_dim_max(set, 0); 7702 set1 = isl_set_from_pw_aff(pwaff); 7703 str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }"; 7704 set2 = isl_set_read_from_str(ctx, str); 7705 equal = isl_set_is_equal(set1, set2); 7706 isl_set_free(set1); 7707 isl_set_free(set2); 7708 if (equal < 0) 7709 return -1; 7710 if (!equal) 7711 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7712 7713 str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : " 7714 "0 <= i < N and 0 <= j < M }"; 7715 map = isl_map_read_from_str(ctx, str); 7716 set = isl_map_range(map); 7717 7718 pwaff = isl_set_dim_max(isl_set_copy(set), 0); 7719 set1 = isl_set_from_pw_aff(pwaff); 7720 str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }"; 7721 set2 = isl_set_read_from_str(ctx, str); 7722 equal = isl_set_is_equal(set1, set2); 7723 isl_set_free(set1); 7724 isl_set_free(set2); 7725 7726 pwaff = isl_set_dim_max(isl_set_copy(set), 3); 7727 set1 = isl_set_from_pw_aff(pwaff); 7728 str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }"; 7729 set2 = isl_set_read_from_str(ctx, str); 7730 if (equal >= 0 && equal) 7731 equal = isl_set_is_equal(set1, set2); 7732 isl_set_free(set1); 7733 isl_set_free(set2); 7734 7735 isl_set_free(set); 7736 7737 if (equal < 0) 7738 return -1; 7739 if (!equal) 7740 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7741 7742 /* Check that solutions are properly merged. */ 7743 str = "[n] -> { [a, b, c] : c >= -4a - 2b and " 7744 "c <= -1 + n - 4a - 2b and c >= -2b and " 7745 "4a >= -4 + n and c >= 0 }"; 7746 set = isl_set_read_from_str(ctx, str); 7747 pwaff = isl_set_dim_min(set, 2); 7748 set1 = isl_set_from_pw_aff(pwaff); 7749 str = "[n] -> { [(0)] : n >= 1 }"; 7750 set2 = isl_set_read_from_str(ctx, str); 7751 equal = isl_set_is_equal(set1, set2); 7752 isl_set_free(set1); 7753 isl_set_free(set2); 7754 7755 if (equal < 0) 7756 return -1; 7757 if (!equal) 7758 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7759 7760 /* Check that empty solution lie in the right space. */ 7761 str = "[n] -> { [t,a] : 1 = 0 }"; 7762 set = isl_set_read_from_str(ctx, str); 7763 pwaff = isl_set_dim_max(set, 0); 7764 set1 = isl_set_from_pw_aff(pwaff); 7765 str = "[n] -> { [t] : 1 = 0 }"; 7766 set2 = isl_set_read_from_str(ctx, str); 7767 equal = isl_set_is_equal(set1, set2); 7768 isl_set_free(set1); 7769 isl_set_free(set2); 7770 7771 if (equal < 0) 7772 return -1; 7773 if (!equal) 7774 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7775 7776 return 0; 7777 } 7778 7779 /* Basic test for isl_pw_multi_aff_product. 7780 * 7781 * Check that multiple pieces are properly handled. 7782 */ 7783 static int test_product_pma(isl_ctx *ctx) 7784 { 7785 isl_stat equal; 7786 const char *str; 7787 isl_pw_multi_aff *pma1, *pma2; 7788 7789 str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }"; 7790 pma1 = isl_pw_multi_aff_read_from_str(ctx, str); 7791 str = "{ C[] -> D[] }"; 7792 pma2 = isl_pw_multi_aff_read_from_str(ctx, str); 7793 pma1 = isl_pw_multi_aff_product(pma1, pma2); 7794 str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;" 7795 "[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }"; 7796 equal = pw_multi_aff_check_plain_equal(pma1, str); 7797 isl_pw_multi_aff_free(pma1); 7798 if (equal < 0) 7799 return -1; 7800 7801 return 0; 7802 } 7803 7804 int test_product(isl_ctx *ctx) 7805 { 7806 const char *str; 7807 isl_set *set; 7808 isl_union_set *uset1, *uset2; 7809 int ok; 7810 7811 str = "{ A[i] }"; 7812 set = isl_set_read_from_str(ctx, str); 7813 set = isl_set_product(set, isl_set_copy(set)); 7814 ok = isl_set_is_wrapping(set); 7815 isl_set_free(set); 7816 if (ok < 0) 7817 return -1; 7818 if (!ok) 7819 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7820 7821 str = "{ [] }"; 7822 uset1 = isl_union_set_read_from_str(ctx, str); 7823 uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1)); 7824 str = "{ [[] -> []] }"; 7825 uset2 = isl_union_set_read_from_str(ctx, str); 7826 ok = isl_union_set_is_equal(uset1, uset2); 7827 isl_union_set_free(uset1); 7828 isl_union_set_free(uset2); 7829 if (ok < 0) 7830 return -1; 7831 if (!ok) 7832 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7833 7834 if (test_product_pma(ctx) < 0) 7835 return -1; 7836 7837 return 0; 7838 } 7839 7840 /* Check that two sets are not considered disjoint just because 7841 * they have a different set of (named) parameters. 7842 */ 7843 static int test_disjoint(isl_ctx *ctx) 7844 { 7845 const char *str; 7846 isl_set *set, *set2; 7847 int disjoint; 7848 7849 str = "[n] -> { [[]->[]] }"; 7850 set = isl_set_read_from_str(ctx, str); 7851 str = "{ [[]->[]] }"; 7852 set2 = isl_set_read_from_str(ctx, str); 7853 disjoint = isl_set_is_disjoint(set, set2); 7854 isl_set_free(set); 7855 isl_set_free(set2); 7856 if (disjoint < 0) 7857 return -1; 7858 if (disjoint) 7859 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7860 7861 return 0; 7862 } 7863 7864 /* Inputs for isl_pw_multi_aff_is_equal tests. 7865 * "f1" and "f2" are the two function that need to be compared. 7866 * "equal" is the expected result. 7867 */ 7868 struct { 7869 int equal; 7870 const char *f1; 7871 const char *f2; 7872 } pma_equal_tests[] = { 7873 { 1, "[N] -> { [floor(N/2)] : 0 <= N <= 1 }", 7874 "[N] -> { [0] : 0 <= N <= 1 }" }, 7875 { 1, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }", 7876 "[N] -> { [0] : 0 <= N <= 1; [1] : N = 2 }" }, 7877 { 0, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }", 7878 "[N] -> { [0] : 0 <= N <= 1 }" }, 7879 { 0, "{ [NaN] }", "{ [NaN] }" }, 7880 }; 7881 7882 int test_equal(isl_ctx *ctx) 7883 { 7884 int i; 7885 const char *str; 7886 isl_set *set, *set2; 7887 int equal; 7888 7889 str = "{ S_6[i] }"; 7890 set = isl_set_read_from_str(ctx, str); 7891 str = "{ S_7[i] }"; 7892 set2 = isl_set_read_from_str(ctx, str); 7893 equal = isl_set_is_equal(set, set2); 7894 isl_set_free(set); 7895 isl_set_free(set2); 7896 if (equal < 0) 7897 return -1; 7898 if (equal) 7899 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 7900 7901 for (i = 0; i < ARRAY_SIZE(pma_equal_tests); ++i) { 7902 int expected = pma_equal_tests[i].equal; 7903 isl_pw_multi_aff *f1, *f2; 7904 7905 f1 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f1); 7906 f2 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f2); 7907 equal = isl_pw_multi_aff_is_equal(f1, f2); 7908 isl_pw_multi_aff_free(f1); 7909 isl_pw_multi_aff_free(f2); 7910 if (equal < 0) 7911 return -1; 7912 if (equal != expected) 7913 isl_die(ctx, isl_error_unknown, 7914 "unexpected equality result", return -1); 7915 } 7916 7917 return 0; 7918 } 7919 7920 static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map, 7921 enum isl_dim_type type, unsigned pos, int fixed) 7922 { 7923 isl_bool test; 7924 7925 test = isl_map_plain_is_fixed(map, type, pos, NULL); 7926 isl_map_free(map); 7927 if (test < 0) 7928 return -1; 7929 if (test == fixed) 7930 return 0; 7931 if (fixed) 7932 isl_die(ctx, isl_error_unknown, 7933 "map not detected as fixed", return -1); 7934 else 7935 isl_die(ctx, isl_error_unknown, 7936 "map detected as fixed", return -1); 7937 } 7938 7939 int test_fixed(isl_ctx *ctx) 7940 { 7941 const char *str; 7942 isl_map *map; 7943 7944 str = "{ [i] -> [i] }"; 7945 map = isl_map_read_from_str(ctx, str); 7946 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0)) 7947 return -1; 7948 str = "{ [i] -> [1] }"; 7949 map = isl_map_read_from_str(ctx, str); 7950 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1)) 7951 return -1; 7952 str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }"; 7953 map = isl_map_read_from_str(ctx, str); 7954 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1)) 7955 return -1; 7956 map = isl_map_read_from_str(ctx, str); 7957 map = isl_map_neg(map); 7958 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1)) 7959 return -1; 7960 7961 return 0; 7962 } 7963 7964 struct isl_vertices_test_data { 7965 const char *set; 7966 int n; 7967 const char *vertex[6]; 7968 } vertices_tests[] = { 7969 { "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }", 7970 2, { "{ A[12, 4] }", "{ A[12, 12] }" } }, 7971 { "{ A[t, i] : t = 14 and i = 1 }", 7972 1, { "{ A[14, 1] }" } }, 7973 { "[n, m] -> { [a, b, c] : b <= a and a <= n and b > 0 and c >= b and " 7974 "c <= m and m <= n and m > 0 }", 7975 6, { 7976 "[n, m] -> { [n, m, m] : 0 < m <= n }", 7977 "[n, m] -> { [n, 1, m] : 0 < m <= n }", 7978 "[n, m] -> { [n, 1, 1] : 0 < m <= n }", 7979 "[n, m] -> { [m, m, m] : 0 < m <= n }", 7980 "[n, m] -> { [1, 1, m] : 0 < m <= n }", 7981 "[n, m] -> { [1, 1, 1] : 0 < m <= n }" 7982 } }, 7983 /* An input with implicit equality constraints among the parameters. */ 7984 { "[N, M] -> { [a, b] : M >= 3 and 9 + 3M <= a <= 29 + 2N + 11M and " 7985 "2b >= M + a and 5 - 2N - M + a <= 2b <= 3 + a and " 7986 "3b >= 15 + a }", 7987 2, { 7988 "[N, M] -> { [(21), (12)] : M = 3 and N >= 0 }", 7989 "[N, M] -> { [(61 + 2N), (32 + N)] : M = 3 and N >= 0 }", 7990 } 7991 }, 7992 }; 7993 7994 /* Check that "vertex" corresponds to one of the vertices in data->vertex. 7995 */ 7996 static isl_stat find_vertex(__isl_take isl_vertex *vertex, void *user) 7997 { 7998 struct isl_vertices_test_data *data = user; 7999 isl_ctx *ctx; 8000 isl_multi_aff *ma; 8001 isl_basic_set *bset; 8002 isl_pw_multi_aff *pma; 8003 int i; 8004 isl_bool equal; 8005 8006 ctx = isl_vertex_get_ctx(vertex); 8007 bset = isl_vertex_get_domain(vertex); 8008 ma = isl_vertex_get_expr(vertex); 8009 pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma); 8010 8011 for (i = 0; i < data->n; ++i) { 8012 isl_pw_multi_aff *pma_i; 8013 8014 pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]); 8015 equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i); 8016 isl_pw_multi_aff_free(pma_i); 8017 8018 if (equal < 0 || equal) 8019 break; 8020 } 8021 8022 isl_pw_multi_aff_free(pma); 8023 isl_vertex_free(vertex); 8024 8025 if (equal < 0) 8026 return isl_stat_error; 8027 8028 return equal ? isl_stat_ok : isl_stat_error; 8029 } 8030 8031 int test_vertices(isl_ctx *ctx) 8032 { 8033 int i; 8034 8035 for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) { 8036 isl_basic_set *bset; 8037 isl_vertices *vertices; 8038 int ok = 1; 8039 isl_size n; 8040 8041 bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set); 8042 vertices = isl_basic_set_compute_vertices(bset); 8043 n = isl_vertices_get_n_vertices(vertices); 8044 if (vertices_tests[i].n != n) 8045 ok = 0; 8046 if (isl_vertices_foreach_vertex(vertices, &find_vertex, 8047 &vertices_tests[i]) < 0) 8048 ok = 0; 8049 isl_vertices_free(vertices); 8050 isl_basic_set_free(bset); 8051 8052 if (n < 0) 8053 return -1; 8054 if (!ok) 8055 isl_die(ctx, isl_error_unknown, "unexpected vertices", 8056 return -1); 8057 } 8058 8059 return 0; 8060 } 8061 8062 /* Inputs for basic tests of binary operations on isl_union_map. 8063 * "fn" is the function that is being tested. 8064 * "arg1" and "arg2" are string descriptions of the inputs. 8065 * "res" is a string description of the expected result. 8066 */ 8067 static struct { 8068 __isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap1, 8069 __isl_take isl_union_map *umap2); 8070 const char *arg1; 8071 const char *arg2; 8072 const char *res; 8073 } umap_bin_tests[] = { 8074 { &isl_union_map_intersect, 8075 "[n] -> { A[i] -> [] : 0 <= i <= n; B[] -> [] }", 8076 "[m] -> { A[i] -> [] : 0 <= i <= m; C[] -> [] }", 8077 "[m, n] -> { A[i] -> [] : 0 <= i <= n and i <= m }" }, 8078 { &isl_union_map_intersect_domain_factor_domain, 8079 "{ [A[i] -> B[i + 1]] -> C[i + 2] }", 8080 "[N] -> { B[i] -> C[N] }", 8081 "{ }" }, 8082 { &isl_union_map_intersect_domain_factor_domain, 8083 "{ [A[i] -> B[i + 1]] -> C[i + 2] }", 8084 "[N] -> { A[i] -> C[N] }", 8085 "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" }, 8086 { &isl_union_map_intersect_domain_factor_domain, 8087 "{ T[A[i] -> B[i + 1]] -> C[i + 2] }", 8088 "[N] -> { A[i] -> C[N] }", 8089 "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" }, 8090 { &isl_union_map_intersect_domain_factor_range, 8091 "{ [A[i] -> B[i + 1]] -> C[i + 2] }", 8092 "[N] -> { B[i] -> C[N] }", 8093 "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" }, 8094 { &isl_union_map_intersect_domain_factor_range, 8095 "{ T[A[i] -> B[i + 1]] -> C[i + 2] }", 8096 "[N] -> { B[i] -> C[N] }", 8097 "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" }, 8098 { &isl_union_map_intersect_domain_factor_range, 8099 "{ [A[i] -> B[i + 1]] -> C[i + 2] }", 8100 "[N] -> { A[i] -> C[N] }", 8101 "{ }" }, 8102 { &isl_union_map_intersect_range_factor_domain, 8103 "{ A[i] -> [B[i + 1] -> C[i + 2]] }", 8104 "[N] -> { A[i] -> B[N] }", 8105 "[N] -> { A[N - 1] -> [B[N] -> C[N + 1]] }" }, 8106 { &isl_union_map_intersect_range_factor_domain, 8107 "{ A[i] -> T[B[i + 1] -> C[i + 2]] }", 8108 "[N] -> { A[i] -> B[N] }", 8109 "[N] -> { A[N - 1] -> T[B[N] -> C[N + 1]] }" }, 8110 { &isl_union_map_intersect_range_factor_domain, 8111 "{ A[i] -> [B[i + 1] -> C[i + 2]] }", 8112 "[N] -> { A[i] -> C[N] }", 8113 "{ }" }, 8114 { &isl_union_map_intersect_range_factor_range, 8115 "{ A[i] -> [B[i + 1] -> C[i + 2]] }", 8116 "[N] -> { A[i] -> C[N] }", 8117 "[N] -> { A[N - 2] -> [B[N - 1] -> C[N]] }" }, 8118 { &isl_union_map_intersect_range_factor_range, 8119 "{ A[i] -> T[B[i + 1] -> C[i + 2]] }", 8120 "[N] -> { A[i] -> C[N] }", 8121 "[N] -> { A[N - 2] -> T[B[N - 1] -> C[N]] }" }, 8122 { &isl_union_map_intersect_range_factor_range, 8123 "{ A[i] -> [B[i + 1] -> C[i + 2]] }", 8124 "[N] -> { A[i] -> B[N] }", 8125 "{ }" }, 8126 }; 8127 8128 /* Perform basic tests of binary operations on isl_union_map. 8129 */ 8130 static isl_stat test_bin_union_map(isl_ctx *ctx) 8131 { 8132 int i; 8133 8134 for (i = 0; i < ARRAY_SIZE(umap_bin_tests); ++i) { 8135 const char *str; 8136 isl_union_map *umap1, *umap2, *res; 8137 isl_bool equal; 8138 8139 str = umap_bin_tests[i].arg1; 8140 umap1 = isl_union_map_read_from_str(ctx, str); 8141 str = umap_bin_tests[i].arg2; 8142 umap2 = isl_union_map_read_from_str(ctx, str); 8143 str = umap_bin_tests[i].res; 8144 res = isl_union_map_read_from_str(ctx, str); 8145 umap1 = umap_bin_tests[i].fn(umap1, umap2); 8146 equal = isl_union_map_is_equal(umap1, res); 8147 isl_union_map_free(umap1); 8148 isl_union_map_free(res); 8149 if (equal < 0) 8150 return isl_stat_error; 8151 if (!equal) 8152 isl_die(ctx, isl_error_unknown, 8153 "unexpected result", return isl_stat_error); 8154 } 8155 8156 return isl_stat_ok; 8157 } 8158 8159 /* Check that isl_union_set_contains finds space independently 8160 * of the parameters. 8161 */ 8162 static isl_stat test_union_set_contains(isl_ctx *ctx) 8163 { 8164 const char *str; 8165 isl_bool ok; 8166 isl_space *space; 8167 isl_id *id; 8168 isl_union_set *uset; 8169 8170 str = "[N] -> { A[0:N]; B[*,*] }"; 8171 uset = isl_union_set_read_from_str(ctx, str); 8172 space = isl_space_unit(ctx); 8173 id = isl_id_alloc(ctx, "A", NULL); 8174 space = isl_space_add_named_tuple_id_ui(space, id, 1); 8175 ok = isl_union_set_contains(uset, space); 8176 isl_space_free(space); 8177 isl_union_set_free(uset); 8178 8179 if (ok < 0) 8180 return isl_stat_error; 8181 if (!ok) 8182 isl_die(ctx, isl_error_unknown, 8183 "unexpected result", return isl_stat_error); 8184 8185 return isl_stat_ok; 8186 } 8187 8188 /* Perform basic tests of operations on isl_union_map or isl_union_set. 8189 */ 8190 static int test_union_map(isl_ctx *ctx) 8191 { 8192 if (test_bin_union_map(ctx) < 0) 8193 return -1; 8194 if (test_union_set_contains(ctx) < 0) 8195 return -1; 8196 return 0; 8197 } 8198 8199 #undef BASE 8200 #define BASE union_pw_qpolynomial 8201 #include "isl_test_plain_equal_templ.c" 8202 8203 /* Check that the result of applying "fn" to "a" and "b" 8204 * in (obviously) equal to "res". 8205 */ 8206 static isl_stat test_union_pw_op(isl_ctx *ctx, const char *a, const char *b, 8207 __isl_give isl_union_pw_qpolynomial *(*fn)( 8208 __isl_take isl_union_pw_qpolynomial *upwqp1, 8209 __isl_take isl_union_pw_qpolynomial *upwqp2), 8210 const char *res) 8211 { 8212 isl_stat r; 8213 isl_union_pw_qpolynomial *upwqp1, *upwqp2; 8214 8215 upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, a); 8216 upwqp2 = isl_union_pw_qpolynomial_read_from_str(ctx, b); 8217 upwqp1 = fn(upwqp1, upwqp2); 8218 r = union_pw_qpolynomial_check_plain_equal(upwqp1, res); 8219 isl_union_pw_qpolynomial_free(upwqp1); 8220 8221 return r; 8222 } 8223 8224 int test_union_pw(isl_ctx *ctx) 8225 { 8226 int equal; 8227 isl_stat r; 8228 const char *str; 8229 isl_union_set *uset; 8230 isl_union_pw_qpolynomial *upwqp1, *upwqp2; 8231 const char *a, *b; 8232 8233 str = "{ [x] -> x^2 }"; 8234 upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str); 8235 upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1); 8236 uset = isl_union_pw_qpolynomial_domain(upwqp1); 8237 upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2); 8238 upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset); 8239 equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2); 8240 isl_union_pw_qpolynomial_free(upwqp1); 8241 isl_union_pw_qpolynomial_free(upwqp2); 8242 if (equal < 0) 8243 return -1; 8244 if (!equal) 8245 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 8246 8247 a = "{ A[x] -> x^2 : x >= 0; B[x] -> x }"; 8248 b = "{ A[x] -> x }"; 8249 str = "{ A[x] -> x^2 + x : x >= 0; A[x] -> x : x < 0; B[x] -> x }"; 8250 if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_add, str) < 0) 8251 return -1; 8252 str = "{ A[x] -> x^2 - x : x >= 0; A[x] -> -x : x < 0; B[x] -> x }"; 8253 if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_sub, str) < 0) 8254 return -1; 8255 8256 str = "{ A[x] -> 0 }"; 8257 a = "{ A[x] -> 1 }"; 8258 b = "{ A[x] -> -1 }"; 8259 if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_add, str) < 0) 8260 return -1; 8261 a = "{ A[x] -> 1 }"; 8262 b = "{ A[x] -> 1 }"; 8263 if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_sub, str) < 0) 8264 return -1; 8265 8266 str = "{ [A[x] -> B[y,z]] -> x^2 + y * floor(x/4) * floor(z/2); " 8267 "C[z] -> z^3 }"; 8268 upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str); 8269 upwqp1 = isl_union_pw_qpolynomial_domain_reverse(upwqp1); 8270 str = "{ [B[y,z] -> A[x]] -> x^2 + y * floor(x/4) * floor(z/2) }"; 8271 r = union_pw_qpolynomial_check_plain_equal(upwqp1, str); 8272 isl_union_pw_qpolynomial_free(upwqp1); 8273 if (r < 0) 8274 return -1; 8275 8276 return 0; 8277 } 8278 8279 /* Inputs for basic tests of functions that select 8280 * subparts of the domain of an isl_multi_union_pw_aff. 8281 * "fn" is the function that is tested. 8282 * "arg" is a string description of the input. 8283 * "res" is a string description of the expected result. 8284 */ 8285 struct { 8286 __isl_give isl_union_set *(*fn)( 8287 __isl_take isl_multi_union_pw_aff *mupa); 8288 const char *arg; 8289 const char *res; 8290 } un_locus_tests[] = { 8291 { &isl_multi_union_pw_aff_zero_union_set, 8292 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]", 8293 "{ A[0,j]; B[0,j] }" }, 8294 { &isl_multi_union_pw_aff_zero_union_set, 8295 "F[{ A[i,j] -> [i-j]; B[i,j] -> [i-j] : i >= 0 }]", 8296 "{ A[i,i]; B[i,i] : i >= 0 }" }, 8297 { &isl_multi_union_pw_aff_zero_union_set, 8298 "(F[] : { A[i,j]; B[i,i] : i >= 0 })", 8299 "{ A[i,j]; B[i,i] : i >= 0 }" }, 8300 }; 8301 8302 /* Perform some basic tests of functions that select 8303 * subparts of the domain of an isl_multi_union_pw_aff. 8304 */ 8305 static int test_un_locus(isl_ctx *ctx) 8306 { 8307 int i; 8308 isl_bool ok; 8309 isl_union_set *uset, *res; 8310 isl_multi_union_pw_aff *mupa; 8311 8312 for (i = 0; i < ARRAY_SIZE(un_locus_tests); ++i) { 8313 mupa = isl_multi_union_pw_aff_read_from_str(ctx, 8314 un_locus_tests[i].arg); 8315 res = isl_union_set_read_from_str(ctx, un_locus_tests[i].res); 8316 uset = un_locus_tests[i].fn(mupa); 8317 ok = isl_union_set_is_equal(uset, res); 8318 isl_union_set_free(uset); 8319 isl_union_set_free(res); 8320 if (ok < 0) 8321 return -1; 8322 if (!ok) 8323 isl_die(ctx, isl_error_unknown, 8324 "unexpected result", return -1); 8325 } 8326 8327 return 0; 8328 } 8329 8330 /* Inputs for basic tests of functions that select 8331 * subparts of an isl_union_map based on a relation 8332 * specified by an isl_multi_union_pw_aff. 8333 * "fn" is the function that is tested. 8334 * "arg1" and "arg2" are string descriptions of the inputs. 8335 * "res" is a string description of the expected result. 8336 */ 8337 struct { 8338 __isl_give isl_union_map *(*fn)( 8339 __isl_take isl_union_map *umap, 8340 __isl_take isl_multi_union_pw_aff *mupa); 8341 const char *arg1; 8342 const char *arg2; 8343 const char *res; 8344 } bin_locus_tests[] = { 8345 { &isl_union_map_eq_at_multi_union_pw_aff, 8346 "{ A[i,j] -> B[i',j'] }", 8347 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]", 8348 "{ A[i,j] -> B[i,j'] }" }, 8349 { &isl_union_map_eq_at_multi_union_pw_aff, 8350 "{ A[i,j] -> B[i',j'] }", 8351 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, " 8352 "{ A[i,j] -> [j]; B[i,j] -> [j] }]", 8353 "{ A[i,j] -> B[i,j] }" }, 8354 { &isl_union_map_eq_at_multi_union_pw_aff, 8355 "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }", 8356 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]", 8357 "{ A[i,j] -> B[i,j'] }" }, 8358 { &isl_union_map_eq_at_multi_union_pw_aff, 8359 "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }", 8360 "F[{ A[i,j] -> [i]; B[i,j] -> [i]; C[i,j] -> [0] }]", 8361 "{ A[i,j] -> B[i,j']; A[0,j] -> C[i',j'] }" }, 8362 { &isl_union_map_eq_at_multi_union_pw_aff, 8363 "{ A[i,j] -> B[i',j'] }", 8364 "F[{ A[i,j] -> [i] : i > j; B[i,j] -> [i] }]", 8365 "{ A[i,j] -> B[i,j'] : i > j }" }, 8366 { &isl_union_map_lex_le_at_multi_union_pw_aff, 8367 "{ A[i,j] -> B[i',j'] }", 8368 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, " 8369 "{ A[i,j] -> [j]; B[i,j] -> [j] }]", 8370 "{ A[i,j] -> B[i',j'] : i,j <<= i',j' }" }, 8371 { &isl_union_map_lex_lt_at_multi_union_pw_aff, 8372 "{ A[i,j] -> B[i',j'] }", 8373 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, " 8374 "{ A[i,j] -> [j]; B[i,j] -> [j] }]", 8375 "{ A[i,j] -> B[i',j'] : i,j << i',j' }" }, 8376 { &isl_union_map_lex_ge_at_multi_union_pw_aff, 8377 "{ A[i,j] -> B[i',j'] }", 8378 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, " 8379 "{ A[i,j] -> [j]; B[i,j] -> [j] }]", 8380 "{ A[i,j] -> B[i',j'] : i,j >>= i',j' }" }, 8381 { &isl_union_map_lex_gt_at_multi_union_pw_aff, 8382 "{ A[i,j] -> B[i',j'] }", 8383 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, " 8384 "{ A[i,j] -> [j]; B[i,j] -> [j] }]", 8385 "{ A[i,j] -> B[i',j'] : i,j >> i',j' }" }, 8386 { &isl_union_map_eq_at_multi_union_pw_aff, 8387 "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }", 8388 "(F[] : { A[i,j]; B[i,j] })", 8389 "{ A[i,j] -> B[i',j'] }" }, 8390 { &isl_union_map_eq_at_multi_union_pw_aff, 8391 "{ A[i,j] -> B[i',j'] }", 8392 "(F[] : { A[i,j] : i > j; B[i,j] : i < j })", 8393 "{ A[i,j] -> B[i',j'] : i > j and i' < j' }" }, 8394 { &isl_union_map_eq_at_multi_union_pw_aff, 8395 "[N] -> { A[i,j] -> B[i',j'] : i,i' <= N }", 8396 "(F[] : { A[i,j] : i > j; B[i,j] : i < j })", 8397 "[N] -> { A[i,j] -> B[i',j'] : i > j and i' < j' and i,i' <= N }" }, 8398 { &isl_union_map_eq_at_multi_union_pw_aff, 8399 "{ A[i,j] -> B[i',j'] }", 8400 "[N] -> (F[] : { A[i,j] : i < N; B[i,j] : i < N })", 8401 "[N] -> { A[i,j] -> B[i',j'] : i,i' < N }" }, 8402 { &isl_union_map_eq_at_multi_union_pw_aff, 8403 "{ A[i,j] -> B[i',j'] }", 8404 "[N] -> (F[] : { : N >= 0 })", 8405 "[N] -> { A[i,j] -> B[i',j'] : N >= 0 }" }, 8406 }; 8407 8408 /* Perform some basic tests of functions that select 8409 * subparts of an isl_union_map based on a relation 8410 * specified by an isl_multi_union_pw_aff. 8411 */ 8412 static int test_bin_locus(isl_ctx *ctx) 8413 { 8414 int i; 8415 isl_bool ok; 8416 isl_union_map *umap, *res; 8417 isl_multi_union_pw_aff *mupa; 8418 8419 for (i = 0; i < ARRAY_SIZE(bin_locus_tests); ++i) { 8420 umap = isl_union_map_read_from_str(ctx, 8421 bin_locus_tests[i].arg1); 8422 mupa = isl_multi_union_pw_aff_read_from_str(ctx, 8423 bin_locus_tests[i].arg2); 8424 res = isl_union_map_read_from_str(ctx, bin_locus_tests[i].res); 8425 umap = bin_locus_tests[i].fn(umap, mupa); 8426 ok = isl_union_map_is_equal(umap, res); 8427 isl_union_map_free(umap); 8428 isl_union_map_free(res); 8429 if (ok < 0) 8430 return -1; 8431 if (!ok) 8432 isl_die(ctx, isl_error_unknown, 8433 "unexpected result", return -1); 8434 } 8435 8436 return 0; 8437 } 8438 8439 /* Inputs for basic tests of functions that determine 8440 * the part of the domain where two isl_multi_aff objects 8441 * related to each other in a specific way. 8442 * "fn" is the function that is being tested. 8443 * "arg1" and "arg2" are string descriptions of the inputs. 8444 * "res" is a string description of the expected result. 8445 */ 8446 static struct { 8447 __isl_give isl_set *(*fn)(__isl_take isl_multi_aff *ma1, 8448 __isl_take isl_multi_aff *ma2); 8449 const char *arg1; 8450 const char *arg2; 8451 const char *res; 8452 } bin_locus_ma_tests[] = { 8453 { &isl_multi_aff_lex_le_set, "{ [] }", "{ [] }", "{ : }" }, 8454 { &isl_multi_aff_lex_lt_set, "{ [] }", "{ [] }", "{ : false }" }, 8455 { &isl_multi_aff_lex_le_set, 8456 "{ A[i] -> [i] }", "{ A[i] -> [0] }", 8457 "{ A[i] : i <= 0 }" }, 8458 { &isl_multi_aff_lex_lt_set, 8459 "{ A[i] -> [i] }", "{ A[i] -> [0] }", 8460 "{ A[i] : i < 0 }" }, 8461 { &isl_multi_aff_lex_le_set, 8462 "{ A[i] -> [i, i] }", "{ A[i] -> [0, 0] }", 8463 "{ A[i] : i <= 0 }" }, 8464 { &isl_multi_aff_lex_le_set, 8465 "{ A[i] -> [i, 0] }", "{ A[i] -> [0, 0] }", 8466 "{ A[i] : i <= 0 }" }, 8467 { &isl_multi_aff_lex_le_set, 8468 "{ A[i] -> [i, 1] }", "{ A[i] -> [0, 0] }", 8469 "{ A[i] : i < 0 }" }, 8470 }; 8471 8472 /* Perform some basic tests of functions that determine 8473 * the part of the domain where two isl_multi_aff objects 8474 * related to each other in a specific way. 8475 */ 8476 static isl_stat test_bin_locus_ma(isl_ctx *ctx) 8477 { 8478 int i; 8479 8480 for (i = 0; i < ARRAY_SIZE(bin_locus_ma_tests); ++i) { 8481 const char *str; 8482 isl_bool ok; 8483 isl_multi_aff *ma1, *ma2; 8484 isl_set *set, *res; 8485 8486 str = bin_locus_ma_tests[i].arg1; 8487 ma1 = isl_multi_aff_read_from_str(ctx, str); 8488 str = bin_locus_ma_tests[i].arg2; 8489 ma2 = isl_multi_aff_read_from_str(ctx, str); 8490 res = isl_set_read_from_str(ctx, bin_locus_ma_tests[i].res); 8491 set = bin_locus_ma_tests[i].fn(ma1, ma2); 8492 ok = isl_set_is_equal(set, res); 8493 isl_set_free(set); 8494 isl_set_free(res); 8495 if (ok < 0) 8496 return isl_stat_error; 8497 if (!ok) 8498 isl_die(ctx, isl_error_unknown, 8499 "unexpected result", return isl_stat_error); 8500 } 8501 8502 return isl_stat_ok; 8503 } 8504 8505 /* Perform basic locus tests. 8506 */ 8507 static int test_locus(isl_ctx *ctx) 8508 { 8509 if (test_un_locus(ctx) < 0) 8510 return -1; 8511 if (test_bin_locus(ctx) < 0) 8512 return -1; 8513 if (test_bin_locus_ma(ctx) < 0) 8514 return -1; 8515 return 0; 8516 } 8517 8518 /* Test that isl_union_pw_qpolynomial_eval picks up the function 8519 * defined over the correct domain space. 8520 */ 8521 static int test_eval_1(isl_ctx *ctx) 8522 { 8523 const char *str; 8524 isl_point *pnt; 8525 isl_set *set; 8526 isl_union_pw_qpolynomial *upwqp; 8527 isl_val *v; 8528 int cmp; 8529 8530 str = "{ A[x] -> x^2; B[x] -> -x^2 }"; 8531 upwqp = isl_union_pw_qpolynomial_read_from_str(ctx, str); 8532 str = "{ A[6] }"; 8533 set = isl_set_read_from_str(ctx, str); 8534 pnt = isl_set_sample_point(set); 8535 v = isl_union_pw_qpolynomial_eval(upwqp, pnt); 8536 cmp = isl_val_cmp_si(v, 36); 8537 isl_val_free(v); 8538 8539 if (!v) 8540 return -1; 8541 if (cmp != 0) 8542 isl_die(ctx, isl_error_unknown, "unexpected value", return -1); 8543 8544 return 0; 8545 } 8546 8547 /* Check that isl_qpolynomial_eval handles getting called on a void point. 8548 */ 8549 static int test_eval_2(isl_ctx *ctx) 8550 { 8551 const char *str; 8552 isl_point *pnt; 8553 isl_set *set; 8554 isl_qpolynomial *qp; 8555 isl_val *v; 8556 isl_bool ok; 8557 8558 str = "{ A[x] -> [x] }"; 8559 qp = isl_qpolynomial_from_aff(isl_aff_read_from_str(ctx, str)); 8560 str = "{ A[x] : false }"; 8561 set = isl_set_read_from_str(ctx, str); 8562 pnt = isl_set_sample_point(set); 8563 v = isl_qpolynomial_eval(qp, pnt); 8564 ok = isl_val_is_nan(v); 8565 isl_val_free(v); 8566 8567 if (ok < 0) 8568 return -1; 8569 if (!ok) 8570 isl_die(ctx, isl_error_unknown, "expecting NaN", return -1); 8571 8572 return 0; 8573 } 8574 8575 /* Check that a polynomial (without local variables) can be evaluated 8576 * in a rational point. 8577 */ 8578 static isl_stat test_eval_3(isl_ctx *ctx) 8579 { 8580 isl_pw_qpolynomial *pwqp; 8581 isl_point *pnt; 8582 isl_val *v; 8583 isl_stat r; 8584 8585 pwqp = isl_pw_qpolynomial_read_from_str(ctx, "{ [x] -> x^2 }"); 8586 pnt = isl_point_zero(isl_pw_qpolynomial_get_domain_space(pwqp)); 8587 v = isl_val_read_from_str(ctx, "1/2"); 8588 pnt = isl_point_set_coordinate_val(pnt, isl_dim_set, 0, v); 8589 v = isl_pw_qpolynomial_eval(pwqp, pnt); 8590 r = val_check_equal(v, "1/4"); 8591 isl_val_free(v); 8592 8593 return r; 8594 } 8595 8596 /* Inputs for isl_pw_aff_eval test. 8597 * "f" is the affine function. 8598 * "p" is the point where the function should be evaluated. 8599 * "res" is the expected result. 8600 */ 8601 struct { 8602 const char *f; 8603 const char *p; 8604 const char *res; 8605 } aff_eval_tests[] = { 8606 { "{ [i] -> [2 * i] }", "{ [4] }", "8" }, 8607 { "{ [i] -> [2 * i] }", "{ [x] : false }", "NaN" }, 8608 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [0] }", "0" }, 8609 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [1] }", "1" }, 8610 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [2] }", "3" }, 8611 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [3] }", "5" }, 8612 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [4] }", "7" }, 8613 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [0] }", "0" }, 8614 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [1] }", "0" }, 8615 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [2] }", "0" }, 8616 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [3] }", "0" }, 8617 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [4] }", "1" }, 8618 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [6] }", "1" }, 8619 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [8] }", "2" }, 8620 { "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [4] }", "4" }, 8621 { "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [-2] }", "2" }, 8622 { "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [0] }", "NaN" }, 8623 { "[N] -> { [2 * N] }", "[N] -> { : N = 4 }", "8" }, 8624 { "{ [i, j] -> [(i + j)/2] }", "{ [1, 1] }", "1" }, 8625 { "{ [i, j] -> [(i + j)/2] }", "{ [1, 2] }", "3/2" }, 8626 { "{ [i] -> [i] : i mod 2 = 0 }", "{ [4] }", "4" }, 8627 { "{ [i] -> [i] : i mod 2 = 0 }", "{ [3] }", "NaN" }, 8628 { "{ [i] -> [i] : i mod 2 = 0 }", "{ [x] : false }", "NaN" }, 8629 { "[m, n] -> { [2m + 3n] }", "[n=1, m=10] -> { : }", "23" }, 8630 }; 8631 8632 /* Perform basic isl_pw_aff_eval tests. 8633 */ 8634 static int test_eval_aff(isl_ctx *ctx) 8635 { 8636 int i; 8637 8638 for (i = 0; i < ARRAY_SIZE(aff_eval_tests); ++i) { 8639 isl_stat r; 8640 isl_pw_aff *pa; 8641 isl_set *set; 8642 isl_point *pnt; 8643 isl_val *v; 8644 8645 pa = isl_pw_aff_read_from_str(ctx, aff_eval_tests[i].f); 8646 set = isl_set_read_from_str(ctx, aff_eval_tests[i].p); 8647 pnt = isl_set_sample_point(set); 8648 v = isl_pw_aff_eval(pa, pnt); 8649 r = val_check_equal(v, aff_eval_tests[i].res); 8650 isl_val_free(v); 8651 if (r < 0) 8652 return -1; 8653 } 8654 return 0; 8655 } 8656 8657 /* Perform basic evaluation tests. 8658 */ 8659 static int test_eval(isl_ctx *ctx) 8660 { 8661 if (test_eval_1(ctx) < 0) 8662 return -1; 8663 if (test_eval_2(ctx) < 0) 8664 return -1; 8665 if (test_eval_3(ctx) < 0) 8666 return -1; 8667 if (test_eval_aff(ctx) < 0) 8668 return -1; 8669 return 0; 8670 } 8671 8672 /* Descriptions of sets that are tested for reparsing after printing. 8673 */ 8674 const char *output_tests[] = { 8675 "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }", 8676 "{ [x] : 1 = 0 }", 8677 "{ [x] : false }", 8678 "{ [x] : x mod 2 = 0 }", 8679 "{ [x] : x mod 2 = 1 }", 8680 "{ [x, y] : x mod 2 = 0 and 3*floor(y/2) < x }", 8681 "{ [y, x] : x mod 2 = 0 and 3*floor(y/2) < x }", 8682 "{ [x, y] : x mod 2 = 0 and 3*floor(y/2) = x + y }", 8683 "{ [y, x] : x mod 2 = 0 and 3*floor(y/2) = x + y }", 8684 "[n] -> { [y, x] : 2*((x + 2y) mod 3) = n }", 8685 "{ [x, y] : (2*floor(x/3) + 3*floor(y/4)) mod 5 = x }", 8686 }; 8687 8688 /* Check that printing a set and reparsing a set from the printed output 8689 * results in the same set. 8690 */ 8691 static int test_output_set(isl_ctx *ctx) 8692 { 8693 int i; 8694 char *str; 8695 isl_set *set1, *set2; 8696 isl_bool equal; 8697 8698 for (i = 0; i < ARRAY_SIZE(output_tests); ++i) { 8699 set1 = isl_set_read_from_str(ctx, output_tests[i]); 8700 str = isl_set_to_str(set1); 8701 set2 = isl_set_read_from_str(ctx, str); 8702 free(str); 8703 equal = isl_set_is_equal(set1, set2); 8704 isl_set_free(set1); 8705 isl_set_free(set2); 8706 if (equal < 0) 8707 return -1; 8708 if (!equal) 8709 isl_die(ctx, isl_error_unknown, 8710 "parsed output not the same", return -1); 8711 } 8712 8713 return 0; 8714 } 8715 8716 /* Check that an isl_multi_aff is printed using a consistent space. 8717 */ 8718 static isl_stat test_output_ma(isl_ctx *ctx) 8719 { 8720 char *str; 8721 isl_bool equal; 8722 isl_aff *aff; 8723 isl_multi_aff *ma, *ma2; 8724 8725 ma = isl_multi_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }"); 8726 aff = isl_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }"); 8727 ma = isl_multi_aff_set_aff(ma, 0, aff); 8728 str = isl_multi_aff_to_str(ma); 8729 ma2 = isl_multi_aff_read_from_str(ctx, str); 8730 free(str); 8731 equal = isl_multi_aff_plain_is_equal(ma, ma2); 8732 isl_multi_aff_free(ma2); 8733 isl_multi_aff_free(ma); 8734 8735 if (equal < 0) 8736 return isl_stat_error; 8737 if (!equal) 8738 isl_die(ctx, isl_error_unknown, "bad conversion", 8739 return isl_stat_error); 8740 8741 return isl_stat_ok; 8742 } 8743 8744 /* Check that an isl_multi_pw_aff is printed using a consistent space. 8745 */ 8746 static isl_stat test_output_mpa(isl_ctx *ctx) 8747 { 8748 char *str; 8749 isl_bool equal; 8750 isl_pw_aff *pa; 8751 isl_multi_pw_aff *mpa, *mpa2; 8752 8753 mpa = isl_multi_pw_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }"); 8754 pa = isl_pw_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }"); 8755 mpa = isl_multi_pw_aff_set_pw_aff(mpa, 0, pa); 8756 str = isl_multi_pw_aff_to_str(mpa); 8757 mpa2 = isl_multi_pw_aff_read_from_str(ctx, str); 8758 free(str); 8759 equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2); 8760 isl_multi_pw_aff_free(mpa2); 8761 isl_multi_pw_aff_free(mpa); 8762 8763 if (equal < 0) 8764 return isl_stat_error; 8765 if (!equal) 8766 isl_die(ctx, isl_error_unknown, "bad conversion", 8767 return isl_stat_error); 8768 8769 return isl_stat_ok; 8770 } 8771 8772 int test_output(isl_ctx *ctx) 8773 { 8774 char *s; 8775 const char *str; 8776 isl_pw_aff *pa; 8777 isl_printer *p; 8778 int equal; 8779 8780 if (test_output_set(ctx) < 0) 8781 return -1; 8782 if (test_output_ma(ctx) < 0) 8783 return -1; 8784 if (test_output_mpa(ctx) < 0) 8785 return -1; 8786 8787 str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }"; 8788 pa = isl_pw_aff_read_from_str(ctx, str); 8789 8790 p = isl_printer_to_str(ctx); 8791 p = isl_printer_set_output_format(p, ISL_FORMAT_C); 8792 p = isl_printer_print_pw_aff(p, pa); 8793 s = isl_printer_get_str(p); 8794 isl_printer_free(p); 8795 isl_pw_aff_free(pa); 8796 if (!s) 8797 equal = -1; 8798 else 8799 equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2"); 8800 free(s); 8801 if (equal < 0) 8802 return -1; 8803 if (!equal) 8804 isl_die(ctx, isl_error_unknown, "unexpected result", return -1); 8805 8806 return 0; 8807 } 8808 8809 int test_sample(isl_ctx *ctx) 8810 { 8811 const char *str; 8812 isl_basic_set *bset1, *bset2; 8813 int empty, subset; 8814 8815 str = "{ [a, b, c, d, e, f, g, h, i, j, k] : " 8816 "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and " 8817 "3i >= -1 + 3221225466b + c + d - 3221225466e - f and " 8818 "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and " 8819 "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and " 8820 "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and " 8821 "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and " 8822 "3h >= a + 2147483646b + 2c - 2147483646e - 2f and " 8823 "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and " 8824 "f >= 1 - a + 1073741822b + c + d - 1073741822e and " 8825 "3i >= 1 + 2b - 2c + e + 2f + 3g and " 8826 "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +" 8827 "d - 1073741821e and " 8828 "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and " 8829 "3j >= 1 - a + b + 2e and " 8830 "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and " 8831 "3i <= 4 - a + 4b - e and " 8832 "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and " 8833 "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and " 8834 "c <= -1 + a and 3i >= -2 - a + 3e and " 8835 "1073741822e <= 1073741823 - a + 1073741822b + c and " 8836 "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and " 8837 "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and " 8838 "1073741823e >= 1 + 1073741823b - d and " 8839 "3i >= 1073741823b + c - 1073741823e - f and " 8840 "3i >= 1 + 2b + e + 3g }"; 8841 bset1 = isl_basic_set_read_from_str(ctx, str); 8842 bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1)); 8843 empty = isl_basic_set_is_empty(bset2); 8844 subset = isl_basic_set_is_subset(bset2, bset1); 8845 isl_basic_set_free(bset1); 8846 isl_basic_set_free(bset2); 8847 if (empty < 0 || subset < 0) 8848 return -1; 8849 if (empty) 8850 isl_die(ctx, isl_error_unknown, "point not found", return -1); 8851 if (!subset) 8852 isl_die(ctx, isl_error_unknown, "bad point found", return -1); 8853 8854 return 0; 8855 } 8856 8857 /* Perform a projection on a basic set that is known to be empty 8858 * but that has not been assigned a canonical representation. 8859 * Earlier versions of isl would run into a stack overflow 8860 * on this example. 8861 */ 8862 static int test_empty_projection(isl_ctx *ctx) 8863 { 8864 const char *str; 8865 isl_bool empty; 8866 isl_basic_set *bset; 8867 8868 str = "{ [a, b, c, d, e, f, g, h] : 5f = 1 + 4a - b + 5c - d - 2e and " 8869 "3h = 2 + b + c and 14c >= 9 - 3a + 25b and " 8870 "4c <= 50 - 3a + 23b and 6b <= -39 + a and " 8871 "9g >= -6 + 3a + b + c and e < a + b - 2d and " 8872 "7d >= -5 + 2a + 2b and 5g >= -14 + a - 4b + d + 2e and " 8873 "9g <= -28 - 5b - 2c + 3d + 6e }"; 8874 bset = isl_basic_set_read_from_str(ctx, str); 8875 empty = isl_basic_set_is_empty(bset); 8876 bset = isl_basic_set_params(bset); 8877 isl_basic_set_free(bset); 8878 8879 if (empty < 0) 8880 return -1; 8881 8882 return 0; 8883 } 8884 8885 int test_slice(isl_ctx *ctx) 8886 { 8887 const char *str; 8888 isl_map *map; 8889 int equal; 8890 8891 str = "{ [i] -> [j] }"; 8892 map = isl_map_read_from_str(ctx, str); 8893 map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0); 8894 equal = map_check_equal(map, "{ [i] -> [i] }"); 8895 isl_map_free(map); 8896 if (equal < 0) 8897 return -1; 8898 8899 str = "{ [i] -> [j] }"; 8900 map = isl_map_read_from_str(ctx, str); 8901 map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0); 8902 equal = map_check_equal(map, "{ [i] -> [j] }"); 8903 isl_map_free(map); 8904 if (equal < 0) 8905 return -1; 8906 8907 str = "{ [i] -> [j] }"; 8908 map = isl_map_read_from_str(ctx, str); 8909 map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0); 8910 equal = map_check_equal(map, "{ [i] -> [-i] }"); 8911 isl_map_free(map); 8912 if (equal < 0) 8913 return -1; 8914 8915 str = "{ [i] -> [j] }"; 8916 map = isl_map_read_from_str(ctx, str); 8917 map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0); 8918 equal = map_check_equal(map, "{ [0] -> [j] }"); 8919 isl_map_free(map); 8920 if (equal < 0) 8921 return -1; 8922 8923 str = "{ [i] -> [j] }"; 8924 map = isl_map_read_from_str(ctx, str); 8925 map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0); 8926 equal = map_check_equal(map, "{ [i] -> [j] : i > j }"); 8927 isl_map_free(map); 8928 if (equal < 0) 8929 return -1; 8930 8931 str = "{ [i] -> [j] }"; 8932 map = isl_map_read_from_str(ctx, str); 8933 map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0); 8934 equal = map_check_equal(map, "{ [i] -> [j] : false }"); 8935 isl_map_free(map); 8936 if (equal < 0) 8937 return -1; 8938 8939 return 0; 8940 } 8941 8942 int test_eliminate(isl_ctx *ctx) 8943 { 8944 const char *str; 8945 isl_map *map; 8946 int equal; 8947 8948 str = "{ [i] -> [j] : i = 2j }"; 8949 map = isl_map_read_from_str(ctx, str); 8950 map = isl_map_eliminate(map, isl_dim_out, 0, 1); 8951 equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }"); 8952 isl_map_free(map); 8953 if (equal < 0) 8954 return -1; 8955 8956 return 0; 8957 } 8958 8959 /* Check basic functionality of isl_map_deltas_map. 8960 */ 8961 static int test_deltas_map(isl_ctx *ctx) 8962 { 8963 const char *str; 8964 isl_map *map; 8965 int equal; 8966 8967 str = "{ A[i] -> A[i + 1] }"; 8968 map = isl_map_read_from_str(ctx, str); 8969 map = isl_map_deltas_map(map); 8970 equal = map_check_equal(map, "{ [A[i] -> A[i + 1]] -> A[1] }"); 8971 isl_map_free(map); 8972 if (equal < 0) 8973 return -1; 8974 8975 return 0; 8976 } 8977 8978 /* Check that isl_set_dim_residue_class detects that the values of j 8979 * in the set below are all odd and that it does not detect any spurious 8980 * strides. 8981 */ 8982 static int test_residue_class(isl_ctx *ctx) 8983 { 8984 const char *str; 8985 isl_set *set; 8986 isl_int m, r; 8987 isl_stat res; 8988 8989 str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; " 8990 "[i,j] : j = 4 i + 3 and 500 <= i <= 600 }"; 8991 set = isl_set_read_from_str(ctx, str); 8992 isl_int_init(m); 8993 isl_int_init(r); 8994 res = isl_set_dim_residue_class(set, 1, &m, &r); 8995 if (res >= 0 && 8996 (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0)) 8997 isl_die(ctx, isl_error_unknown, "incorrect residue class", 8998 res = isl_stat_error); 8999 isl_int_clear(r); 9000 isl_int_clear(m); 9001 isl_set_free(set); 9002 9003 return res; 9004 } 9005 9006 static int test_align_parameters_1(isl_ctx *ctx) 9007 { 9008 const char *str; 9009 isl_space *space; 9010 isl_multi_aff *ma1, *ma2; 9011 int equal; 9012 9013 str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }"; 9014 ma1 = isl_multi_aff_read_from_str(ctx, str); 9015 9016 space = isl_space_params_alloc(ctx, 1); 9017 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N"); 9018 ma1 = isl_multi_aff_align_params(ma1, space); 9019 9020 str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }"; 9021 ma2 = isl_multi_aff_read_from_str(ctx, str); 9022 9023 equal = isl_multi_aff_plain_is_equal(ma1, ma2); 9024 9025 isl_multi_aff_free(ma1); 9026 isl_multi_aff_free(ma2); 9027 9028 if (equal < 0) 9029 return -1; 9030 if (!equal) 9031 isl_die(ctx, isl_error_unknown, 9032 "result not as expected", return -1); 9033 9034 return 0; 9035 } 9036 9037 /* Check the isl_multi_*_from_*_list operation in case inputs 9038 * have unaligned parameters. 9039 * In particular, older versions of isl would simply fail 9040 * (without printing any error message). 9041 */ 9042 static isl_stat test_align_parameters_2(isl_ctx *ctx) 9043 { 9044 isl_space *space; 9045 isl_map *map; 9046 isl_aff *aff; 9047 isl_multi_aff *ma; 9048 9049 map = isl_map_read_from_str(ctx, "{ A[] -> M[x] }"); 9050 space = isl_map_get_space(map); 9051 isl_map_free(map); 9052 9053 aff = isl_aff_read_from_str(ctx, "[N] -> { A[] -> [N] }"); 9054 ma = isl_multi_aff_from_aff_list(space, isl_aff_list_from_aff(aff)); 9055 isl_multi_aff_free(ma); 9056 9057 if (!ma) 9058 return isl_stat_error; 9059 return isl_stat_ok; 9060 } 9061 9062 /* Perform basic parameter alignment tests. 9063 */ 9064 static int test_align_parameters(isl_ctx *ctx) 9065 { 9066 if (test_align_parameters_1(ctx) < 0) 9067 return -1; 9068 if (test_align_parameters_2(ctx) < 0) 9069 return -1; 9070 9071 return 0; 9072 } 9073 9074 /* Check that isl_*_drop_unused_params actually drops the unused parameters 9075 * by comparing the result using isl_*_plain_is_equal. 9076 * Note that this assumes that isl_*_plain_is_equal does not consider 9077 * objects that only differ by unused parameters to be equal. 9078 */ 9079 int test_drop_unused_parameters(isl_ctx *ctx) 9080 { 9081 const char *str_with, *str_without; 9082 isl_basic_set *bset1, *bset2; 9083 isl_set *set1, *set2; 9084 isl_pw_aff *pwa1, *pwa2; 9085 int equal; 9086 9087 str_with = "[n, m, o] -> { [m] }"; 9088 str_without = "[m] -> { [m] }"; 9089 9090 bset1 = isl_basic_set_read_from_str(ctx, str_with); 9091 bset2 = isl_basic_set_read_from_str(ctx, str_without); 9092 bset1 = isl_basic_set_drop_unused_params(bset1); 9093 equal = isl_basic_set_plain_is_equal(bset1, bset2); 9094 isl_basic_set_free(bset1); 9095 isl_basic_set_free(bset2); 9096 9097 if (equal < 0) 9098 return -1; 9099 if (!equal) 9100 isl_die(ctx, isl_error_unknown, 9101 "result not as expected", return -1); 9102 9103 set1 = isl_set_read_from_str(ctx, str_with); 9104 set2 = isl_set_read_from_str(ctx, str_without); 9105 set1 = isl_set_drop_unused_params(set1); 9106 equal = isl_set_plain_is_equal(set1, set2); 9107 isl_set_free(set1); 9108 isl_set_free(set2); 9109 9110 if (equal < 0) 9111 return -1; 9112 if (!equal) 9113 isl_die(ctx, isl_error_unknown, 9114 "result not as expected", return -1); 9115 9116 pwa1 = isl_pw_aff_read_from_str(ctx, str_with); 9117 pwa2 = isl_pw_aff_read_from_str(ctx, str_without); 9118 pwa1 = isl_pw_aff_drop_unused_params(pwa1); 9119 equal = isl_pw_aff_plain_is_equal(pwa1, pwa2); 9120 isl_pw_aff_free(pwa1); 9121 isl_pw_aff_free(pwa2); 9122 9123 if (equal < 0) 9124 return -1; 9125 if (!equal) 9126 isl_die(ctx, isl_error_unknown, 9127 "result not as expected", return -1); 9128 9129 return 0; 9130 } 9131 9132 static int test_list(isl_ctx *ctx) 9133 { 9134 isl_id *a, *b, *c, *d, *id; 9135 isl_id_list *list; 9136 isl_size n; 9137 int ok; 9138 9139 a = isl_id_alloc(ctx, "a", NULL); 9140 b = isl_id_alloc(ctx, "b", NULL); 9141 c = isl_id_alloc(ctx, "c", NULL); 9142 d = isl_id_alloc(ctx, "d", NULL); 9143 9144 list = isl_id_list_alloc(ctx, 4); 9145 list = isl_id_list_add(list, b); 9146 list = isl_id_list_insert(list, 0, a); 9147 list = isl_id_list_add(list, c); 9148 list = isl_id_list_add(list, d); 9149 list = isl_id_list_drop(list, 1, 1); 9150 9151 n = isl_id_list_n_id(list); 9152 if (n < 0) 9153 return -1; 9154 if (n != 3) { 9155 isl_id_list_free(list); 9156 isl_die(ctx, isl_error_unknown, 9157 "unexpected number of elements in list", return -1); 9158 } 9159 9160 id = isl_id_list_get_id(list, 0); 9161 ok = id == a; 9162 isl_id_free(id); 9163 id = isl_id_list_get_id(list, 1); 9164 ok = ok && id == c; 9165 isl_id_free(id); 9166 id = isl_id_list_get_id(list, 2); 9167 ok = ok && id == d; 9168 isl_id_free(id); 9169 9170 isl_id_list_free(list); 9171 9172 if (!ok) 9173 isl_die(ctx, isl_error_unknown, 9174 "unexpected elements in list", return -1); 9175 9176 return 0; 9177 } 9178 9179 /* Check the conversion from an isl_multi_aff to an isl_basic_set. 9180 */ 9181 static isl_stat test_ma_conversion(isl_ctx *ctx) 9182 { 9183 const char *str; 9184 isl_bool equal; 9185 isl_multi_aff *ma; 9186 isl_basic_set *bset1, *bset2; 9187 9188 str = "[N] -> { A[0, N + 1] }"; 9189 ma = isl_multi_aff_read_from_str(ctx, str); 9190 bset1 = isl_basic_set_read_from_str(ctx, str); 9191 bset2 = isl_basic_set_from_multi_aff(ma); 9192 equal = isl_basic_set_is_equal(bset1, bset2); 9193 isl_basic_set_free(bset1); 9194 isl_basic_set_free(bset2); 9195 if (equal < 0) 9196 return isl_stat_error; 9197 if (!equal) 9198 isl_die(ctx, isl_error_unknown, "bad conversion", 9199 return isl_stat_error); 9200 return isl_stat_ok; 9201 } 9202 9203 const char *set_conversion_tests[] = { 9204 "[N] -> { [i] : N - 1 <= 2 i <= N }", 9205 "[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }", 9206 "[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }", 9207 "[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }", 9208 "[N] -> { [3*floor(N/2) + 5*floor(N/3)] }", 9209 "[a, b] -> { [c, d] : (4*floor((-a + c)/4) = -a + c and " 9210 "32*floor((-b + d)/32) = -b + d and 5 <= c <= 8 and " 9211 "-3 + c <= d <= 28 + c) }", 9212 }; 9213 9214 /* Check that converting from isl_set to isl_pw_multi_aff and back 9215 * to isl_set produces the original isl_set. 9216 */ 9217 static int test_set_conversion(isl_ctx *ctx) 9218 { 9219 int i; 9220 const char *str; 9221 isl_set *set1, *set2; 9222 isl_pw_multi_aff *pma; 9223 int equal; 9224 9225 for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) { 9226 str = set_conversion_tests[i]; 9227 set1 = isl_set_read_from_str(ctx, str); 9228 pma = isl_pw_multi_aff_from_set(isl_set_copy(set1)); 9229 set2 = isl_set_from_pw_multi_aff(pma); 9230 equal = isl_set_is_equal(set1, set2); 9231 isl_set_free(set1); 9232 isl_set_free(set2); 9233 9234 if (equal < 0) 9235 return -1; 9236 if (!equal) 9237 isl_die(ctx, isl_error_unknown, "bad conversion", 9238 return -1); 9239 } 9240 9241 return 0; 9242 } 9243 9244 const char *conversion_tests[] = { 9245 "{ [a, b, c, d] -> s0[a, b, e, f] : " 9246 "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], " 9247 "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and " 9248 "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and " 9249 "9e <= -2 - 2a) }", 9250 "{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): " 9251 "5e0 = -a - b + c and c >= -a and c <= 4 - a) }", 9252 "{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }", 9253 }; 9254 9255 /* Check that converting from isl_map to isl_pw_multi_aff and back 9256 * to isl_map produces the original isl_map. 9257 */ 9258 static int test_map_conversion(isl_ctx *ctx) 9259 { 9260 int i; 9261 isl_map *map1, *map2; 9262 isl_pw_multi_aff *pma; 9263 int equal; 9264 9265 for (i = 0; i < ARRAY_SIZE(conversion_tests); ++i) { 9266 map1 = isl_map_read_from_str(ctx, conversion_tests[i]); 9267 pma = isl_pw_multi_aff_from_map(isl_map_copy(map1)); 9268 map2 = isl_map_from_pw_multi_aff(pma); 9269 equal = isl_map_is_equal(map1, map2); 9270 isl_map_free(map1); 9271 isl_map_free(map2); 9272 9273 if (equal < 0) 9274 return -1; 9275 if (!equal) 9276 isl_die(ctx, isl_error_unknown, "bad conversion", 9277 return -1); 9278 } 9279 9280 return 0; 9281 } 9282 9283 /* Descriptions of isl_pw_multi_aff objects for testing conversion 9284 * to isl_multi_pw_aff and back. 9285 */ 9286 const char *mpa_conversion_tests[] = { 9287 "{ [x] -> A[x] }", 9288 "{ [x] -> A[x] : x >= 0 }", 9289 "{ [x] -> A[x] : x >= 0; [x] -> A[-x] : x < 0 }", 9290 "{ [x] -> A[x, x + 1] }", 9291 "{ [x] -> A[] }", 9292 "{ [x] -> A[] : x >= 0 }", 9293 }; 9294 9295 /* Check that conversion from isl_pw_multi_aff to isl_multi_pw_aff and 9296 * back to isl_pw_multi_aff preserves the original meaning. 9297 */ 9298 static int test_mpa_conversion(isl_ctx *ctx) 9299 { 9300 int i; 9301 isl_pw_multi_aff *pma1, *pma2; 9302 isl_multi_pw_aff *mpa; 9303 int equal; 9304 9305 for (i = 0; i < ARRAY_SIZE(mpa_conversion_tests); ++i) { 9306 const char *str; 9307 str = mpa_conversion_tests[i]; 9308 pma1 = isl_pw_multi_aff_read_from_str(ctx, str); 9309 pma2 = isl_pw_multi_aff_copy(pma1); 9310 mpa = isl_multi_pw_aff_from_pw_multi_aff(pma1); 9311 pma1 = isl_pw_multi_aff_from_multi_pw_aff(mpa); 9312 equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2); 9313 isl_pw_multi_aff_free(pma1); 9314 isl_pw_multi_aff_free(pma2); 9315 9316 if (equal < 0) 9317 return -1; 9318 if (!equal) 9319 isl_die(ctx, isl_error_unknown, "bad conversion", 9320 return -1); 9321 } 9322 9323 return 0; 9324 } 9325 9326 /* Descriptions of union maps that should be convertible 9327 * to an isl_multi_union_pw_aff. 9328 */ 9329 const char *umap_mupa_conversion_tests[] = { 9330 "{ [a, b, c, d] -> s0[a, b, e, f] : " 9331 "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], " 9332 "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and " 9333 "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and " 9334 "9e <= -2 - 2a) }", 9335 "{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): " 9336 "5e0 = -a - b + c and c >= -a and c <= 4 - a) }", 9337 "{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }", 9338 "{ A[] -> B[0]; C[] -> B[1] }", 9339 "{ A[] -> B[]; C[] -> B[] }", 9340 }; 9341 9342 /* Check that converting from isl_union_map to isl_multi_union_pw_aff and back 9343 * to isl_union_map produces the original isl_union_map. 9344 */ 9345 static int test_union_map_mupa_conversion(isl_ctx *ctx) 9346 { 9347 int i; 9348 isl_union_map *umap1, *umap2; 9349 isl_multi_union_pw_aff *mupa; 9350 int equal; 9351 9352 for (i = 0; i < ARRAY_SIZE(umap_mupa_conversion_tests); ++i) { 9353 const char *str; 9354 str = umap_mupa_conversion_tests[i]; 9355 umap1 = isl_union_map_read_from_str(ctx, str); 9356 umap2 = isl_union_map_copy(umap1); 9357 mupa = isl_multi_union_pw_aff_from_union_map(umap2); 9358 umap2 = isl_union_map_from_multi_union_pw_aff(mupa); 9359 equal = isl_union_map_is_equal(umap1, umap2); 9360 isl_union_map_free(umap1); 9361 isl_union_map_free(umap2); 9362 9363 if (equal < 0) 9364 return -1; 9365 if (!equal) 9366 isl_die(ctx, isl_error_unknown, "bad conversion", 9367 return -1); 9368 } 9369 9370 return 0; 9371 } 9372 9373 static int test_conversion(isl_ctx *ctx) 9374 { 9375 if (test_ma_conversion(ctx) < 0) 9376 return -1; 9377 if (test_set_conversion(ctx) < 0) 9378 return -1; 9379 if (test_map_conversion(ctx) < 0) 9380 return -1; 9381 if (test_mpa_conversion(ctx) < 0) 9382 return -1; 9383 if (test_union_map_mupa_conversion(ctx) < 0) 9384 return -1; 9385 return 0; 9386 } 9387 9388 /* Check that isl_basic_map_curry does not modify input. 9389 */ 9390 static int test_curry(isl_ctx *ctx) 9391 { 9392 const char *str; 9393 isl_basic_map *bmap1, *bmap2; 9394 int equal; 9395 9396 str = "{ [A[] -> B[]] -> C[] }"; 9397 bmap1 = isl_basic_map_read_from_str(ctx, str); 9398 bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1)); 9399 equal = isl_basic_map_is_equal(bmap1, bmap2); 9400 isl_basic_map_free(bmap1); 9401 isl_basic_map_free(bmap2); 9402 9403 if (equal < 0) 9404 return -1; 9405 if (equal) 9406 isl_die(ctx, isl_error_unknown, 9407 "curried map should not be equal to original", 9408 return -1); 9409 9410 return 0; 9411 } 9412 9413 struct { 9414 const char *ma1; 9415 const char *ma; 9416 const char *res; 9417 } pullback_tests[] = { 9418 { "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }", 9419 "{ A[a,b] -> C[b + 2a] }" }, 9420 { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" }, 9421 { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" }, 9422 { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }", 9423 "{ A[a] -> C[(a)/6] }" }, 9424 { "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" }, 9425 { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }", 9426 "{ A[a] -> C[(2a)/3] }" }, 9427 { "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"}, 9428 { "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }", 9429 "{ A[i,j] -> C[i + j, i + j] }"}, 9430 { "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" }, 9431 { "[n] -> { B[i,j] -> C[([i/2]) + 2j] }", 9432 "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", }, 9433 { "{ [i, j] -> [floor((i)/4) + floor((2*i+j)/5)] }", 9434 "{ [i, j] -> [floor((i)/3), j] }", 9435 "{ [i, j] -> [(floor((i)/12) + floor((j + 2*floor((i)/3))/5))] }" }, 9436 }; 9437 9438 static int test_pullback(isl_ctx *ctx) 9439 { 9440 int i; 9441 isl_multi_aff *ma1, *ma2; 9442 isl_multi_aff *ma; 9443 int equal; 9444 9445 for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) { 9446 ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1); 9447 ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma); 9448 ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res); 9449 ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma); 9450 equal = isl_multi_aff_plain_is_equal(ma1, ma2); 9451 isl_multi_aff_free(ma1); 9452 isl_multi_aff_free(ma2); 9453 if (equal < 0) 9454 return -1; 9455 if (!equal) 9456 isl_die(ctx, isl_error_unknown, "bad pullback", 9457 return -1); 9458 } 9459 9460 return 0; 9461 } 9462 9463 /* Check that negation is printed correctly and that equal expressions 9464 * are correctly identified. 9465 */ 9466 static int test_ast(isl_ctx *ctx) 9467 { 9468 isl_ast_expr *expr, *expr1, *expr2, *expr3; 9469 char *str; 9470 int ok, equal; 9471 9472 expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL)); 9473 expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL)); 9474 expr = isl_ast_expr_add(expr1, expr2); 9475 expr2 = isl_ast_expr_copy(expr); 9476 expr = isl_ast_expr_neg(expr); 9477 expr2 = isl_ast_expr_neg(expr2); 9478 equal = isl_ast_expr_is_equal(expr, expr2); 9479 str = isl_ast_expr_to_C_str(expr); 9480 ok = str ? !strcmp(str, "-(A + B)") : -1; 9481 free(str); 9482 isl_ast_expr_free(expr); 9483 isl_ast_expr_free(expr2); 9484 9485 if (ok < 0 || equal < 0) 9486 return -1; 9487 if (!equal) 9488 isl_die(ctx, isl_error_unknown, 9489 "equal expressions not considered equal", return -1); 9490 if (!ok) 9491 isl_die(ctx, isl_error_unknown, 9492 "isl_ast_expr printed incorrectly", return -1); 9493 9494 expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL)); 9495 expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL)); 9496 expr = isl_ast_expr_add(expr1, expr2); 9497 expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL)); 9498 expr = isl_ast_expr_sub(expr3, expr); 9499 str = isl_ast_expr_to_C_str(expr); 9500 ok = str ? !strcmp(str, "C - (A + B)") : -1; 9501 free(str); 9502 isl_ast_expr_free(expr); 9503 9504 if (ok < 0) 9505 return -1; 9506 if (!ok) 9507 isl_die(ctx, isl_error_unknown, 9508 "isl_ast_expr printed incorrectly", return -1); 9509 9510 return 0; 9511 } 9512 9513 /* Check that isl_ast_build_expr_from_set returns a valid expression 9514 * for an empty set. Note that isl_ast_build_expr_from_set getting 9515 * called on an empty set probably indicates a bug in the caller. 9516 */ 9517 static int test_ast_build(isl_ctx *ctx) 9518 { 9519 isl_set *set; 9520 isl_ast_build *build; 9521 isl_ast_expr *expr; 9522 9523 set = isl_set_universe(isl_space_params_alloc(ctx, 0)); 9524 build = isl_ast_build_from_context(set); 9525 9526 set = isl_set_empty(isl_space_params_alloc(ctx, 0)); 9527 expr = isl_ast_build_expr_from_set(build, set); 9528 9529 isl_ast_expr_free(expr); 9530 isl_ast_build_free(build); 9531 9532 if (!expr) 9533 return -1; 9534 9535 return 0; 9536 } 9537 9538 /* Internal data structure for before_for and after_for callbacks. 9539 * 9540 * depth is the current depth 9541 * before is the number of times before_for has been called 9542 * after is the number of times after_for has been called 9543 */ 9544 struct isl_test_codegen_data { 9545 int depth; 9546 int before; 9547 int after; 9548 }; 9549 9550 /* This function is called before each for loop in the AST generated 9551 * from test_ast_gen1. 9552 * 9553 * Increment the number of calls and the depth. 9554 * Check that the space returned by isl_ast_build_get_schedule_space 9555 * matches the target space of the schedule returned by 9556 * isl_ast_build_get_schedule. 9557 * Return an isl_id that is checked by the corresponding call 9558 * to after_for. 9559 */ 9560 static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build, 9561 void *user) 9562 { 9563 struct isl_test_codegen_data *data = user; 9564 isl_ctx *ctx; 9565 isl_space *space; 9566 isl_union_map *schedule; 9567 isl_union_set *uset; 9568 isl_set *set; 9569 isl_bool empty; 9570 isl_size n; 9571 char name[] = "d0"; 9572 9573 ctx = isl_ast_build_get_ctx(build); 9574 9575 if (data->before >= 3) 9576 isl_die(ctx, isl_error_unknown, 9577 "unexpected number of for nodes", return NULL); 9578 if (data->depth < 0 || data->depth >= 2) 9579 isl_die(ctx, isl_error_unknown, 9580 "unexpected depth", return NULL); 9581 9582 snprintf(name, sizeof(name), "d%d", data->depth); 9583 data->before++; 9584 data->depth++; 9585 9586 schedule = isl_ast_build_get_schedule(build); 9587 uset = isl_union_map_range(schedule); 9588 n = isl_union_set_n_set(uset); 9589 if (n != 1) { 9590 isl_union_set_free(uset); 9591 if (n < 0) 9592 return NULL; 9593 isl_die(ctx, isl_error_unknown, 9594 "expecting single range space", return NULL); 9595 } 9596 9597 space = isl_ast_build_get_schedule_space(build); 9598 set = isl_union_set_extract_set(uset, space); 9599 isl_union_set_free(uset); 9600 empty = isl_set_is_empty(set); 9601 isl_set_free(set); 9602 9603 if (empty < 0) 9604 return NULL; 9605 if (empty) 9606 isl_die(ctx, isl_error_unknown, 9607 "spaces don't match", return NULL); 9608 9609 return isl_id_alloc(ctx, name, NULL); 9610 } 9611 9612 /* This function is called after each for loop in the AST generated 9613 * from test_ast_gen1. 9614 * 9615 * Increment the number of calls and decrement the depth. 9616 * Check that the annotation attached to the node matches 9617 * the isl_id returned by the corresponding call to before_for. 9618 */ 9619 static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node, 9620 __isl_keep isl_ast_build *build, void *user) 9621 { 9622 struct isl_test_codegen_data *data = user; 9623 isl_id *id; 9624 const char *name; 9625 int valid; 9626 9627 data->after++; 9628 data->depth--; 9629 9630 if (data->after > data->before) 9631 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown, 9632 "mismatch in number of for nodes", 9633 return isl_ast_node_free(node)); 9634 9635 id = isl_ast_node_get_annotation(node); 9636 if (!id) 9637 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown, 9638 "missing annotation", return isl_ast_node_free(node)); 9639 9640 name = isl_id_get_name(id); 9641 valid = name && atoi(name + 1) == data->depth; 9642 isl_id_free(id); 9643 9644 if (!valid) 9645 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown, 9646 "wrong annotation", return isl_ast_node_free(node)); 9647 9648 return node; 9649 } 9650 9651 /* This function is called after node in the AST generated 9652 * from test_ast_gen1. 9653 * 9654 * Increment the count in "user" if this is a for node and 9655 * return true to indicate that descendant should also be visited. 9656 */ 9657 static isl_bool count_for(__isl_keep isl_ast_node *node, void *user) 9658 { 9659 int *count = user; 9660 9661 if (isl_ast_node_get_type(node) == isl_ast_node_for) 9662 ++*count; 9663 9664 return isl_bool_true; 9665 } 9666 9667 /* If "node" is a block node, then replace it by its first child. 9668 */ 9669 static __isl_give isl_ast_node *select_first(__isl_take isl_ast_node *node, 9670 void *user) 9671 { 9672 isl_ast_node_list *children; 9673 isl_ast_node *child; 9674 9675 if (isl_ast_node_get_type(node) != isl_ast_node_block) 9676 return node; 9677 9678 children = isl_ast_node_block_get_children(node); 9679 child = isl_ast_node_list_get_at(children, 0); 9680 isl_ast_node_list_free(children); 9681 isl_ast_node_free(node); 9682 9683 return child; 9684 } 9685 9686 /* Check that the before_each_for and after_each_for callbacks 9687 * are called for each for loop in the generated code, 9688 * that they are called in the right order and that the isl_id 9689 * returned from the before_each_for callback is attached to 9690 * the isl_ast_node passed to the corresponding after_each_for call. 9691 * 9692 * Additionally, check the basic functionality of 9693 * isl_ast_node_foreach_descendant_top_down by counting the number 9694 * of for loops in the resulting AST, 9695 * as well as that of isl_ast_node_map_descendant_bottom_up 9696 * by replacing the block node by its first child and 9697 * counting the number of for loops again. 9698 */ 9699 static isl_stat test_ast_gen1(isl_ctx *ctx) 9700 { 9701 int count = 0; 9702 int modified_count = 0; 9703 const char *str; 9704 isl_set *set; 9705 isl_union_map *schedule; 9706 isl_ast_build *build; 9707 isl_ast_node *tree; 9708 struct isl_test_codegen_data data; 9709 9710 str = "[N] -> { : N >= 10 }"; 9711 set = isl_set_read_from_str(ctx, str); 9712 str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; " 9713 "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }"; 9714 schedule = isl_union_map_read_from_str(ctx, str); 9715 9716 data.before = 0; 9717 data.after = 0; 9718 data.depth = 0; 9719 build = isl_ast_build_from_context(set); 9720 build = isl_ast_build_set_before_each_for(build, 9721 &before_for, &data); 9722 build = isl_ast_build_set_after_each_for(build, 9723 &after_for, &data); 9724 tree = isl_ast_build_node_from_schedule_map(build, schedule); 9725 isl_ast_build_free(build); 9726 9727 if (isl_ast_node_foreach_descendant_top_down(tree, 9728 &count_for, &count) < 0) 9729 tree = isl_ast_node_free(tree); 9730 9731 tree = isl_ast_node_map_descendant_bottom_up(tree, &select_first, NULL); 9732 9733 if (isl_ast_node_foreach_descendant_top_down(tree, &count_for, 9734 &modified_count) < 0) 9735 tree = isl_ast_node_free(tree); 9736 9737 if (!tree) 9738 return isl_stat_error; 9739 9740 isl_ast_node_free(tree); 9741 9742 if (data.before != 3 || data.after != 3 || count != 3) 9743 isl_die(ctx, isl_error_unknown, 9744 "unexpected number of for nodes", 9745 return isl_stat_error); 9746 9747 if (modified_count != 2) 9748 isl_die(ctx, isl_error_unknown, 9749 "unexpected number of for nodes after changes", 9750 return isl_stat_error); 9751 9752 return isl_stat_ok; 9753 } 9754 9755 /* Check that the AST generator handles domains that are integrally disjoint 9756 * but not rationally disjoint. 9757 */ 9758 static int test_ast_gen2(isl_ctx *ctx) 9759 { 9760 const char *str; 9761 isl_set *set; 9762 isl_union_map *schedule; 9763 isl_union_map *options; 9764 isl_ast_build *build; 9765 isl_ast_node *tree; 9766 9767 str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }"; 9768 schedule = isl_union_map_read_from_str(ctx, str); 9769 set = isl_set_universe(isl_space_params_alloc(ctx, 0)); 9770 build = isl_ast_build_from_context(set); 9771 9772 str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }"; 9773 options = isl_union_map_read_from_str(ctx, str); 9774 build = isl_ast_build_set_options(build, options); 9775 tree = isl_ast_build_node_from_schedule_map(build, schedule); 9776 isl_ast_build_free(build); 9777 if (!tree) 9778 return -1; 9779 isl_ast_node_free(tree); 9780 9781 return 0; 9782 } 9783 9784 /* Increment *user on each call. 9785 */ 9786 static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node, 9787 __isl_keep isl_ast_build *build, void *user) 9788 { 9789 int *n = user; 9790 9791 (*n)++; 9792 9793 return node; 9794 } 9795 9796 /* Test that unrolling tries to minimize the number of instances. 9797 * In particular, for the schedule given below, make sure it generates 9798 * 3 nodes (rather than 101). 9799 */ 9800 static int test_ast_gen3(isl_ctx *ctx) 9801 { 9802 const char *str; 9803 isl_set *set; 9804 isl_union_map *schedule; 9805 isl_union_map *options; 9806 isl_ast_build *build; 9807 isl_ast_node *tree; 9808 int n_domain = 0; 9809 9810 str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }"; 9811 schedule = isl_union_map_read_from_str(ctx, str); 9812 set = isl_set_universe(isl_space_params_alloc(ctx, 0)); 9813 9814 str = "{ [i] -> unroll[0] }"; 9815 options = isl_union_map_read_from_str(ctx, str); 9816 9817 build = isl_ast_build_from_context(set); 9818 build = isl_ast_build_set_options(build, options); 9819 build = isl_ast_build_set_at_each_domain(build, 9820 &count_domains, &n_domain); 9821 tree = isl_ast_build_node_from_schedule_map(build, schedule); 9822 isl_ast_build_free(build); 9823 if (!tree) 9824 return -1; 9825 9826 isl_ast_node_free(tree); 9827 9828 if (n_domain != 3) 9829 isl_die(ctx, isl_error_unknown, 9830 "unexpected number of for nodes", return -1); 9831 9832 return 0; 9833 } 9834 9835 /* Check that if the ast_build_exploit_nested_bounds options is set, 9836 * we do not get an outer if node in the generated AST, 9837 * while we do get such an outer if node if the options is not set. 9838 */ 9839 static int test_ast_gen4(isl_ctx *ctx) 9840 { 9841 const char *str; 9842 isl_set *set; 9843 isl_union_map *schedule; 9844 isl_ast_build *build; 9845 isl_ast_node *tree; 9846 enum isl_ast_node_type type; 9847 int enb; 9848 9849 enb = isl_options_get_ast_build_exploit_nested_bounds(ctx); 9850 str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }"; 9851 9852 isl_options_set_ast_build_exploit_nested_bounds(ctx, 1); 9853 9854 schedule = isl_union_map_read_from_str(ctx, str); 9855 set = isl_set_universe(isl_space_params_alloc(ctx, 0)); 9856 build = isl_ast_build_from_context(set); 9857 tree = isl_ast_build_node_from_schedule_map(build, schedule); 9858 isl_ast_build_free(build); 9859 if (!tree) 9860 return -1; 9861 9862 type = isl_ast_node_get_type(tree); 9863 isl_ast_node_free(tree); 9864 9865 if (type == isl_ast_node_if) 9866 isl_die(ctx, isl_error_unknown, 9867 "not expecting if node", return -1); 9868 9869 isl_options_set_ast_build_exploit_nested_bounds(ctx, 0); 9870 9871 schedule = isl_union_map_read_from_str(ctx, str); 9872 set = isl_set_universe(isl_space_params_alloc(ctx, 0)); 9873 build = isl_ast_build_from_context(set); 9874 tree = isl_ast_build_node_from_schedule_map(build, schedule); 9875 isl_ast_build_free(build); 9876 if (!tree) 9877 return -1; 9878 9879 type = isl_ast_node_get_type(tree); 9880 isl_ast_node_free(tree); 9881 9882 if (type != isl_ast_node_if) 9883 isl_die(ctx, isl_error_unknown, 9884 "expecting if node", return -1); 9885 9886 isl_options_set_ast_build_exploit_nested_bounds(ctx, enb); 9887 9888 return 0; 9889 } 9890 9891 /* This function is called for each leaf in the AST generated 9892 * from test_ast_gen5. 9893 * 9894 * We finalize the AST generation by extending the outer schedule 9895 * with a zero-dimensional schedule. If this results in any for loops, 9896 * then this means that we did not pass along enough information 9897 * about the outer schedule to the inner AST generation. 9898 */ 9899 static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build, 9900 void *user) 9901 { 9902 isl_union_map *schedule, *extra; 9903 isl_ast_node *tree; 9904 9905 schedule = isl_ast_build_get_schedule(build); 9906 extra = isl_union_map_copy(schedule); 9907 extra = isl_union_map_from_domain(isl_union_map_domain(extra)); 9908 schedule = isl_union_map_range_product(schedule, extra); 9909 tree = isl_ast_build_node_from_schedule_map(build, schedule); 9910 isl_ast_build_free(build); 9911 9912 if (!tree) 9913 return NULL; 9914 9915 if (isl_ast_node_get_type(tree) == isl_ast_node_for) 9916 isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown, 9917 "code should not contain any for loop", 9918 return isl_ast_node_free(tree)); 9919 9920 return tree; 9921 } 9922 9923 /* Check that we do not lose any information when going back and 9924 * forth between internal and external schedule. 9925 * 9926 * In particular, we create an AST where we unroll the only 9927 * non-constant dimension in the schedule. We therefore do 9928 * not expect any for loops in the AST. However, older versions 9929 * of isl would not pass along enough information about the outer 9930 * schedule when performing an inner code generation from a create_leaf 9931 * callback, resulting in the inner code generation producing a for loop. 9932 */ 9933 static int test_ast_gen5(isl_ctx *ctx) 9934 { 9935 const char *str; 9936 isl_set *set; 9937 isl_union_map *schedule, *options; 9938 isl_ast_build *build; 9939 isl_ast_node *tree; 9940 9941 str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }"; 9942 schedule = isl_union_map_read_from_str(ctx, str); 9943 9944 str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: " 9945 "4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }"; 9946 options = isl_union_map_read_from_str(ctx, str); 9947 9948 set = isl_set_universe(isl_space_params_alloc(ctx, 0)); 9949 build = isl_ast_build_from_context(set); 9950 build = isl_ast_build_set_options(build, options); 9951 build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL); 9952 tree = isl_ast_build_node_from_schedule_map(build, schedule); 9953 isl_ast_build_free(build); 9954 isl_ast_node_free(tree); 9955 if (!tree) 9956 return -1; 9957 9958 return 0; 9959 } 9960 9961 /* Check that the expression 9962 * 9963 * [n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 } 9964 * 9965 * is not combined into 9966 * 9967 * min(n/2, 0) 9968 * 9969 * as this would result in n/2 being evaluated in parts of 9970 * the definition domain where n is not a multiple of 2. 9971 */ 9972 static int test_ast_expr(isl_ctx *ctx) 9973 { 9974 const char *str; 9975 isl_pw_aff *pa; 9976 isl_ast_build *build; 9977 isl_ast_expr *expr; 9978 int min_max; 9979 int is_min; 9980 9981 min_max = isl_options_get_ast_build_detect_min_max(ctx); 9982 isl_options_set_ast_build_detect_min_max(ctx, 1); 9983 9984 str = "[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }"; 9985 pa = isl_pw_aff_read_from_str(ctx, str); 9986 build = isl_ast_build_alloc(ctx); 9987 expr = isl_ast_build_expr_from_pw_aff(build, pa); 9988 is_min = isl_ast_expr_get_type(expr) == isl_ast_expr_op && 9989 isl_ast_expr_get_op_type(expr) == isl_ast_expr_op_min; 9990 isl_ast_build_free(build); 9991 isl_ast_expr_free(expr); 9992 9993 isl_options_set_ast_build_detect_min_max(ctx, min_max); 9994 9995 if (!expr) 9996 return -1; 9997 if (is_min) 9998 isl_die(ctx, isl_error_unknown, 9999 "expressions should not be combined", return -1); 10000 10001 return 0; 10002 } 10003 10004 static int test_ast_gen(isl_ctx *ctx) 10005 { 10006 if (test_ast_gen1(ctx) < 0) 10007 return -1; 10008 if (test_ast_gen2(ctx) < 0) 10009 return -1; 10010 if (test_ast_gen3(ctx) < 0) 10011 return -1; 10012 if (test_ast_gen4(ctx) < 0) 10013 return -1; 10014 if (test_ast_gen5(ctx) < 0) 10015 return -1; 10016 if (test_ast_expr(ctx) < 0) 10017 return -1; 10018 return 0; 10019 } 10020 10021 /* Check if dropping output dimensions from an isl_pw_multi_aff 10022 * works properly. 10023 */ 10024 static int test_pw_multi_aff(isl_ctx *ctx) 10025 { 10026 const char *str; 10027 isl_pw_multi_aff *pma1, *pma2; 10028 int equal; 10029 10030 str = "{ [i,j] -> [i+j, 4i-j] }"; 10031 pma1 = isl_pw_multi_aff_read_from_str(ctx, str); 10032 str = "{ [i,j] -> [4i-j] }"; 10033 pma2 = isl_pw_multi_aff_read_from_str(ctx, str); 10034 10035 pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1); 10036 10037 equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2); 10038 10039 isl_pw_multi_aff_free(pma1); 10040 isl_pw_multi_aff_free(pma2); 10041 if (equal < 0) 10042 return -1; 10043 if (!equal) 10044 isl_die(ctx, isl_error_unknown, 10045 "expressions not equal", return -1); 10046 10047 return 0; 10048 } 10049 10050 /* Check that we can properly parse multi piecewise affine expressions 10051 * where the piecewise affine expressions have different domains. 10052 */ 10053 static int test_multi_pw_aff_1(isl_ctx *ctx) 10054 { 10055 const char *str; 10056 isl_set *dom, *dom2; 10057 isl_multi_pw_aff *mpa1, *mpa2; 10058 isl_pw_aff *pa; 10059 int equal; 10060 int equal_domain; 10061 10062 mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }"); 10063 dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }"); 10064 mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom); 10065 mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }"); 10066 mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2); 10067 str = "{ [i] -> [(i : i > 0), 2i] }"; 10068 mpa1 = isl_multi_pw_aff_read_from_str(ctx, str); 10069 10070 equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2); 10071 10072 pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0); 10073 dom = isl_pw_aff_domain(pa); 10074 pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1); 10075 dom2 = isl_pw_aff_domain(pa); 10076 equal_domain = isl_set_is_equal(dom, dom2); 10077 10078 isl_set_free(dom); 10079 isl_set_free(dom2); 10080 isl_multi_pw_aff_free(mpa1); 10081 isl_multi_pw_aff_free(mpa2); 10082 10083 if (equal < 0) 10084 return -1; 10085 if (!equal) 10086 isl_die(ctx, isl_error_unknown, 10087 "expressions not equal", return -1); 10088 10089 if (equal_domain < 0) 10090 return -1; 10091 if (equal_domain) 10092 isl_die(ctx, isl_error_unknown, 10093 "domains unexpectedly equal", return -1); 10094 10095 return 0; 10096 } 10097 10098 /* Check that the dimensions in the explicit domain 10099 * of a multi piecewise affine expression are properly 10100 * taken into account. 10101 */ 10102 static int test_multi_pw_aff_2(isl_ctx *ctx) 10103 { 10104 const char *str; 10105 isl_bool involves1, involves2, involves3, equal; 10106 isl_multi_pw_aff *mpa, *mpa1, *mpa2; 10107 10108 str = "{ A[x,y] -> B[] : x >= y }"; 10109 mpa = isl_multi_pw_aff_read_from_str(ctx, str); 10110 involves1 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 2); 10111 mpa1 = isl_multi_pw_aff_copy(mpa); 10112 10113 mpa = isl_multi_pw_aff_insert_dims(mpa, isl_dim_in, 0, 1); 10114 involves2 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 1); 10115 involves3 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 1, 2); 10116 str = "{ [a,x,y] -> B[] : x >= y }"; 10117 mpa2 = isl_multi_pw_aff_read_from_str(ctx, str); 10118 equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2); 10119 isl_multi_pw_aff_free(mpa2); 10120 10121 mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_in, 0, 1); 10122 mpa = isl_multi_pw_aff_set_tuple_name(mpa, isl_dim_in, "A"); 10123 if (equal >= 0 && equal) 10124 equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa1); 10125 isl_multi_pw_aff_free(mpa1); 10126 isl_multi_pw_aff_free(mpa); 10127 10128 if (involves1 < 0 || involves2 < 0 || involves3 < 0 || equal < 0) 10129 return -1; 10130 if (!equal) 10131 isl_die(ctx, isl_error_unknown, 10132 "incorrect result of dimension insertion/removal", 10133 return isl_stat_error); 10134 if (!involves1 || involves2 || !involves3) 10135 isl_die(ctx, isl_error_unknown, 10136 "incorrect characterization of involved dimensions", 10137 return isl_stat_error); 10138 10139 return 0; 10140 } 10141 10142 /* Check that isl_multi_union_pw_aff_multi_val_on_domain 10143 * sets the explicit domain of a zero-dimensional result, 10144 * such that it can be converted to an isl_union_map. 10145 */ 10146 static isl_stat test_multi_pw_aff_3(isl_ctx *ctx) 10147 { 10148 isl_space *space; 10149 isl_union_set *dom; 10150 isl_multi_val *mv; 10151 isl_multi_union_pw_aff *mupa; 10152 isl_union_map *umap; 10153 10154 dom = isl_union_set_read_from_str(ctx, "{ A[]; B[] }"); 10155 space = isl_union_set_get_space(dom); 10156 mv = isl_multi_val_zero(isl_space_set_from_params(space)); 10157 mupa = isl_multi_union_pw_aff_multi_val_on_domain(dom, mv); 10158 umap = isl_union_map_from_multi_union_pw_aff(mupa); 10159 isl_union_map_free(umap); 10160 if (!umap) 10161 return isl_stat_error; 10162 10163 return isl_stat_ok; 10164 } 10165 10166 /* String descriptions of boxes that 10167 * are used for reconstructing box maps from their lower and upper bounds. 10168 */ 10169 static const char *multi_pw_aff_box_tests[] = { 10170 "{ A[x, y] -> [] : x + y >= 0 }", 10171 "[N] -> { A[x, y] -> [x] : x + y <= N }", 10172 "[N] -> { A[x, y] -> [x : y] : x + y <= N }", 10173 }; 10174 10175 /* Check that map representations of boxes can be reconstructed 10176 * from their lower and upper bounds. 10177 */ 10178 static isl_stat test_multi_pw_aff_box(isl_ctx *ctx) 10179 { 10180 int i; 10181 10182 for (i = 0; i < ARRAY_SIZE(multi_pw_aff_box_tests); ++i) { 10183 const char *str; 10184 isl_bool equal; 10185 isl_map *map, *box; 10186 isl_multi_pw_aff *min, *max; 10187 10188 str = multi_pw_aff_box_tests[i]; 10189 map = isl_map_read_from_str(ctx, str); 10190 min = isl_map_min_multi_pw_aff(isl_map_copy(map)); 10191 max = isl_map_max_multi_pw_aff(isl_map_copy(map)); 10192 box = isl_map_universe(isl_map_get_space(map)); 10193 box = isl_map_lower_bound_multi_pw_aff(box, min); 10194 box = isl_map_upper_bound_multi_pw_aff(box, max); 10195 equal = isl_map_is_equal(map, box); 10196 isl_map_free(map); 10197 isl_map_free(box); 10198 if (equal < 0) 10199 return isl_stat_error; 10200 if (!equal) 10201 isl_die(ctx, isl_error_unknown, 10202 "unexpected result", return isl_stat_error); 10203 } 10204 10205 return isl_stat_ok; 10206 } 10207 10208 /* Perform some tests on multi piecewise affine expressions. 10209 */ 10210 static int test_multi_pw_aff(isl_ctx *ctx) 10211 { 10212 if (test_multi_pw_aff_1(ctx) < 0) 10213 return -1; 10214 if (test_multi_pw_aff_2(ctx) < 0) 10215 return -1; 10216 if (test_multi_pw_aff_3(ctx) < 0) 10217 return -1; 10218 if (test_multi_pw_aff_box(ctx) < 0) 10219 return -1; 10220 return 0; 10221 } 10222 10223 /* This is a regression test for a bug where isl_basic_map_simplify 10224 * would end up in an infinite loop. In particular, we construct 10225 * an empty basic set that is not obviously empty. 10226 * isl_basic_set_is_empty marks the basic set as empty. 10227 * After projecting out i3, the variable can be dropped completely, 10228 * but isl_basic_map_simplify refrains from doing so if the basic set 10229 * is empty and would end up in an infinite loop if it didn't test 10230 * explicitly for empty basic maps in the outer loop. 10231 */ 10232 static int test_simplify_1(isl_ctx *ctx) 10233 { 10234 const char *str; 10235 isl_basic_set *bset; 10236 int empty; 10237 10238 str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and " 10239 "i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and " 10240 "25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and " 10241 "i3 >= i2 }"; 10242 bset = isl_basic_set_read_from_str(ctx, str); 10243 empty = isl_basic_set_is_empty(bset); 10244 bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1); 10245 isl_basic_set_free(bset); 10246 if (!bset) 10247 return -1; 10248 if (!empty) 10249 isl_die(ctx, isl_error_unknown, 10250 "basic set should be empty", return -1); 10251 10252 return 0; 10253 } 10254 10255 /* Check that the equality in the set description below 10256 * is simplified away. 10257 */ 10258 static int test_simplify_2(isl_ctx *ctx) 10259 { 10260 const char *str; 10261 isl_basic_set *bset; 10262 isl_bool universe; 10263 10264 str = "{ [a] : exists e0, e1: 32e1 = 31 + 31a + 31e0 }"; 10265 bset = isl_basic_set_read_from_str(ctx, str); 10266 universe = isl_basic_set_plain_is_universe(bset); 10267 isl_basic_set_free(bset); 10268 10269 if (universe < 0) 10270 return -1; 10271 if (!universe) 10272 isl_die(ctx, isl_error_unknown, 10273 "equality not simplified away", return -1); 10274 return 0; 10275 } 10276 10277 /* Some simplification tests. 10278 */ 10279 static int test_simplify(isl_ctx *ctx) 10280 { 10281 if (test_simplify_1(ctx) < 0) 10282 return -1; 10283 if (test_simplify_2(ctx) < 0) 10284 return -1; 10285 return 0; 10286 } 10287 10288 /* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt 10289 * with gbr context would fail to disable the use of the shifted tableau 10290 * when transferring equalities for the input to the context, resulting 10291 * in invalid sample values. 10292 */ 10293 static int test_partial_lexmin(isl_ctx *ctx) 10294 { 10295 const char *str; 10296 isl_basic_set *bset; 10297 isl_basic_map *bmap; 10298 isl_map *map; 10299 10300 str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }"; 10301 bmap = isl_basic_map_read_from_str(ctx, str); 10302 str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }"; 10303 bset = isl_basic_set_read_from_str(ctx, str); 10304 map = isl_basic_map_partial_lexmin(bmap, bset, NULL); 10305 isl_map_free(map); 10306 10307 if (!map) 10308 return -1; 10309 10310 return 0; 10311 } 10312 10313 /* Check that the variable compression performed on the existentially 10314 * quantified variables inside isl_basic_set_compute_divs is not confused 10315 * by the implicit equalities among the parameters. 10316 */ 10317 static int test_compute_divs(isl_ctx *ctx) 10318 { 10319 const char *str; 10320 isl_basic_set *bset; 10321 isl_set *set; 10322 10323 str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and " 10324 "b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and " 10325 "2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and " 10326 "32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }"; 10327 bset = isl_basic_set_read_from_str(ctx, str); 10328 set = isl_basic_set_compute_divs(bset); 10329 isl_set_free(set); 10330 if (!set) 10331 return -1; 10332 10333 return 0; 10334 } 10335 10336 /* Check that isl_schedule_get_map is not confused by a schedule tree 10337 * with divergent filter node parameters, as can result from a call 10338 * to isl_schedule_intersect_domain. 10339 */ 10340 static int test_schedule_tree(isl_ctx *ctx) 10341 { 10342 const char *str; 10343 isl_union_set *uset; 10344 isl_schedule *sched1, *sched2; 10345 isl_union_map *umap; 10346 10347 uset = isl_union_set_read_from_str(ctx, "{ A[i] }"); 10348 sched1 = isl_schedule_from_domain(uset); 10349 uset = isl_union_set_read_from_str(ctx, "{ B[] }"); 10350 sched2 = isl_schedule_from_domain(uset); 10351 10352 sched1 = isl_schedule_sequence(sched1, sched2); 10353 str = "[n] -> { A[i] : 0 <= i < n; B[] }"; 10354 uset = isl_union_set_read_from_str(ctx, str); 10355 sched1 = isl_schedule_intersect_domain(sched1, uset); 10356 umap = isl_schedule_get_map(sched1); 10357 isl_schedule_free(sched1); 10358 isl_union_map_free(umap); 10359 if (!umap) 10360 return -1; 10361 10362 return 0; 10363 } 10364 10365 /* Check that a zero-dimensional prefix schedule keeps track 10366 * of the domain and outer filters. 10367 */ 10368 static int test_schedule_tree_prefix(isl_ctx *ctx) 10369 { 10370 const char *str; 10371 isl_bool equal; 10372 isl_union_set *uset; 10373 isl_union_set_list *filters; 10374 isl_multi_union_pw_aff *mupa, *mupa2; 10375 isl_schedule_node *node; 10376 10377 str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }"; 10378 uset = isl_union_set_read_from_str(ctx, str); 10379 node = isl_schedule_node_from_domain(uset); 10380 node = isl_schedule_node_child(node, 0); 10381 10382 str = "{ S1[i,j] : i > j }"; 10383 uset = isl_union_set_read_from_str(ctx, str); 10384 filters = isl_union_set_list_from_union_set(uset); 10385 str = "{ S1[i,j] : i <= j; S2[i,j] }"; 10386 uset = isl_union_set_read_from_str(ctx, str); 10387 filters = isl_union_set_list_add(filters, uset); 10388 node = isl_schedule_node_insert_sequence(node, filters); 10389 10390 node = isl_schedule_node_grandchild(node, 0, 0); 10391 mupa = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(node); 10392 str = "([] : { S1[i,j] : i > j })"; 10393 mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str); 10394 equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2); 10395 isl_multi_union_pw_aff_free(mupa2); 10396 isl_multi_union_pw_aff_free(mupa); 10397 isl_schedule_node_free(node); 10398 10399 if (equal < 0) 10400 return -1; 10401 if (!equal) 10402 isl_die(ctx, isl_error_unknown, "unexpected prefix schedule", 10403 return -1); 10404 10405 return 0; 10406 } 10407 10408 /* Check that the reaching domain elements and the prefix schedule 10409 * at a leaf node are the same before and after grouping. 10410 */ 10411 static int test_schedule_tree_group_1(isl_ctx *ctx) 10412 { 10413 int equal; 10414 const char *str; 10415 isl_id *id; 10416 isl_union_set *uset; 10417 isl_multi_union_pw_aff *mupa; 10418 isl_union_pw_multi_aff *upma1, *upma2; 10419 isl_union_set *domain1, *domain2; 10420 isl_union_map *umap1, *umap2; 10421 isl_schedule_node *node; 10422 10423 str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }"; 10424 uset = isl_union_set_read_from_str(ctx, str); 10425 node = isl_schedule_node_from_domain(uset); 10426 node = isl_schedule_node_child(node, 0); 10427 str = "[{ S1[i,j] -> [i]; S2[i,j] -> [9 - i] }]"; 10428 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str); 10429 node = isl_schedule_node_insert_partial_schedule(node, mupa); 10430 node = isl_schedule_node_child(node, 0); 10431 str = "[{ S1[i,j] -> [j]; S2[i,j] -> [j] }]"; 10432 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str); 10433 node = isl_schedule_node_insert_partial_schedule(node, mupa); 10434 node = isl_schedule_node_child(node, 0); 10435 umap1 = isl_schedule_node_get_prefix_schedule_union_map(node); 10436 upma1 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node); 10437 domain1 = isl_schedule_node_get_domain(node); 10438 id = isl_id_alloc(ctx, "group", NULL); 10439 node = isl_schedule_node_parent(node); 10440 node = isl_schedule_node_group(node, id); 10441 node = isl_schedule_node_child(node, 0); 10442 umap2 = isl_schedule_node_get_prefix_schedule_union_map(node); 10443 upma2 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node); 10444 domain2 = isl_schedule_node_get_domain(node); 10445 equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2); 10446 if (equal >= 0 && equal) 10447 equal = isl_union_set_is_equal(domain1, domain2); 10448 if (equal >= 0 && equal) 10449 equal = isl_union_map_is_equal(umap1, umap2); 10450 isl_union_map_free(umap1); 10451 isl_union_map_free(umap2); 10452 isl_union_set_free(domain1); 10453 isl_union_set_free(domain2); 10454 isl_union_pw_multi_aff_free(upma1); 10455 isl_union_pw_multi_aff_free(upma2); 10456 isl_schedule_node_free(node); 10457 10458 if (equal < 0) 10459 return -1; 10460 if (!equal) 10461 isl_die(ctx, isl_error_unknown, 10462 "expressions not equal", return -1); 10463 10464 return 0; 10465 } 10466 10467 /* Check that we can have nested groupings and that the union map 10468 * schedule representation is the same before and after the grouping. 10469 * Note that after the grouping, the union map representation contains 10470 * the domain constraints from the ranges of the expansion nodes, 10471 * while they are missing from the union map representation of 10472 * the tree without expansion nodes. 10473 * 10474 * Also check that the global expansion is as expected. 10475 */ 10476 static int test_schedule_tree_group_2(isl_ctx *ctx) 10477 { 10478 int equal, equal_expansion; 10479 const char *str; 10480 isl_id *id; 10481 isl_union_set *uset; 10482 isl_union_map *umap1, *umap2; 10483 isl_union_map *expansion1, *expansion2; 10484 isl_union_set_list *filters; 10485 isl_multi_union_pw_aff *mupa; 10486 isl_schedule *schedule; 10487 isl_schedule_node *node; 10488 10489 str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10; " 10490 "S3[i,j] : 0 <= i,j < 10 }"; 10491 uset = isl_union_set_read_from_str(ctx, str); 10492 node = isl_schedule_node_from_domain(uset); 10493 node = isl_schedule_node_child(node, 0); 10494 str = "[{ S1[i,j] -> [i]; S2[i,j] -> [i]; S3[i,j] -> [i] }]"; 10495 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str); 10496 node = isl_schedule_node_insert_partial_schedule(node, mupa); 10497 node = isl_schedule_node_child(node, 0); 10498 str = "{ S1[i,j] }"; 10499 uset = isl_union_set_read_from_str(ctx, str); 10500 filters = isl_union_set_list_from_union_set(uset); 10501 str = "{ S2[i,j]; S3[i,j] }"; 10502 uset = isl_union_set_read_from_str(ctx, str); 10503 filters = isl_union_set_list_add(filters, uset); 10504 node = isl_schedule_node_insert_sequence(node, filters); 10505 node = isl_schedule_node_grandchild(node, 1, 0); 10506 str = "{ S2[i,j] }"; 10507 uset = isl_union_set_read_from_str(ctx, str); 10508 filters = isl_union_set_list_from_union_set(uset); 10509 str = "{ S3[i,j] }"; 10510 uset = isl_union_set_read_from_str(ctx, str); 10511 filters = isl_union_set_list_add(filters, uset); 10512 node = isl_schedule_node_insert_sequence(node, filters); 10513 10514 schedule = isl_schedule_node_get_schedule(node); 10515 umap1 = isl_schedule_get_map(schedule); 10516 uset = isl_schedule_get_domain(schedule); 10517 umap1 = isl_union_map_intersect_domain(umap1, uset); 10518 isl_schedule_free(schedule); 10519 10520 node = isl_schedule_node_grandparent(node); 10521 id = isl_id_alloc(ctx, "group1", NULL); 10522 node = isl_schedule_node_group(node, id); 10523 node = isl_schedule_node_grandchild(node, 1, 0); 10524 id = isl_id_alloc(ctx, "group2", NULL); 10525 node = isl_schedule_node_group(node, id); 10526 10527 schedule = isl_schedule_node_get_schedule(node); 10528 umap2 = isl_schedule_get_map(schedule); 10529 isl_schedule_free(schedule); 10530 10531 node = isl_schedule_node_root(node); 10532 node = isl_schedule_node_child(node, 0); 10533 expansion1 = isl_schedule_node_get_subtree_expansion(node); 10534 isl_schedule_node_free(node); 10535 10536 str = "{ group1[i] -> S1[i,j] : 0 <= i,j < 10; " 10537 "group1[i] -> S2[i,j] : 0 <= i,j < 10; " 10538 "group1[i] -> S3[i,j] : 0 <= i,j < 10 }"; 10539 10540 expansion2 = isl_union_map_read_from_str(ctx, str); 10541 10542 equal = isl_union_map_is_equal(umap1, umap2); 10543 equal_expansion = isl_union_map_is_equal(expansion1, expansion2); 10544 10545 isl_union_map_free(umap1); 10546 isl_union_map_free(umap2); 10547 isl_union_map_free(expansion1); 10548 isl_union_map_free(expansion2); 10549 10550 if (equal < 0 || equal_expansion < 0) 10551 return -1; 10552 if (!equal) 10553 isl_die(ctx, isl_error_unknown, 10554 "expressions not equal", return -1); 10555 if (!equal_expansion) 10556 isl_die(ctx, isl_error_unknown, 10557 "unexpected expansion", return -1); 10558 10559 return 0; 10560 } 10561 10562 /* Some tests for the isl_schedule_node_group function. 10563 */ 10564 static int test_schedule_tree_group(isl_ctx *ctx) 10565 { 10566 if (test_schedule_tree_group_1(ctx) < 0) 10567 return -1; 10568 if (test_schedule_tree_group_2(ctx) < 0) 10569 return -1; 10570 return 0; 10571 } 10572 10573 struct { 10574 const char *set; 10575 const char *dual; 10576 } coef_tests[] = { 10577 { "{ rat: [i] : 0 <= i <= 10 }", 10578 "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" }, 10579 { "{ rat: [i] : FALSE }", 10580 "{ rat: coefficients[[cst] -> [a]] }" }, 10581 { "{ rat: [i] : }", 10582 "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" }, 10583 { "{ [0:,1,2:3] }", 10584 "{ rat: coefficients[[c_cst] -> [a, b, c]] : " 10585 "a >= 0 and 2c >= -c_cst - b and 3c >= -c_cst - b }" }, 10586 { "[M, N] -> { [x = (1 - N):-1, -4x:(M - 4x)] }", 10587 "{ rat: coefficients[[c_cst, c_M = 0:, c_N = 0:] -> [a, b = -c_M:]] :" 10588 "4b >= -c_N + a and 4b >= -c_cst - 2c_N + a }" }, 10589 { "{ rat : [x, y] : 1 <= 2x <= 9 and 2 <= 3y <= 16 }", 10590 "{ rat: coefficients[[c_cst] -> [c_x, c_y]] : " 10591 "4c_y >= -6c_cst - 3c_x and 4c_y >= -6c_cst - 27c_x and " 10592 "32c_y >= -6c_cst - 3c_x and 32c_y >= -6c_cst - 27c_x }" }, 10593 { "{ [x, y, z] : 3y <= 2x - 2 and y >= -2 + 2x and 2y >= 2 - x }", 10594 "{ rat: coefficients[[cst] -> [a, b, c]] }" }, 10595 }; 10596 10597 struct { 10598 const char *set; 10599 const char *dual; 10600 } sol_tests[] = { 10601 { "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }", 10602 "{ rat: [i] : 0 <= i <= 10 }" }, 10603 { "{ rat: coefficients[[cst] -> [a]] : FALSE }", 10604 "{ rat: [i] }" }, 10605 { "{ rat: coefficients[[cst] -> [a]] }", 10606 "{ rat: [i] : FALSE }" }, 10607 }; 10608 10609 /* Test the basic functionality of isl_basic_set_coefficients and 10610 * isl_basic_set_solutions. 10611 */ 10612 static int test_dual(isl_ctx *ctx) 10613 { 10614 int i; 10615 10616 for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) { 10617 int equal; 10618 isl_basic_set *bset1, *bset2; 10619 10620 bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set); 10621 bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual); 10622 bset1 = isl_basic_set_coefficients(bset1); 10623 equal = isl_basic_set_is_equal(bset1, bset2); 10624 isl_basic_set_free(bset1); 10625 isl_basic_set_free(bset2); 10626 if (equal < 0) 10627 return -1; 10628 if (!equal) 10629 isl_die(ctx, isl_error_unknown, 10630 "incorrect dual", return -1); 10631 } 10632 10633 for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) { 10634 int equal; 10635 isl_basic_set *bset1, *bset2; 10636 10637 bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set); 10638 bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual); 10639 bset1 = isl_basic_set_solutions(bset1); 10640 equal = isl_basic_set_is_equal(bset1, bset2); 10641 isl_basic_set_free(bset1); 10642 isl_basic_set_free(bset2); 10643 if (equal < 0) 10644 return -1; 10645 if (!equal) 10646 isl_die(ctx, isl_error_unknown, 10647 "incorrect dual", return -1); 10648 } 10649 10650 return 0; 10651 } 10652 10653 struct { 10654 int scale_tile; 10655 int shift_point; 10656 const char *domain; 10657 const char *schedule; 10658 const char *sizes; 10659 const char *tile; 10660 const char *point; 10661 } tile_tests[] = { 10662 { 0, 0, "[n] -> { S[i,j] : 0 <= i,j < n }", 10663 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]", 10664 "{ [32,32] }", 10665 "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]", 10666 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]", 10667 }, 10668 { 1, 0, "[n] -> { S[i,j] : 0 <= i,j < n }", 10669 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]", 10670 "{ [32,32] }", 10671 "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]", 10672 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]", 10673 }, 10674 { 0, 1, "[n] -> { S[i,j] : 0 <= i,j < n }", 10675 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]", 10676 "{ [32,32] }", 10677 "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]", 10678 "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]", 10679 }, 10680 { 1, 1, "[n] -> { S[i,j] : 0 <= i,j < n }", 10681 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]", 10682 "{ [32,32] }", 10683 "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]", 10684 "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]", 10685 }, 10686 }; 10687 10688 /* Basic tiling tests. Create a schedule tree with a domain and a band node, 10689 * tile the band and then check if the tile and point bands have the 10690 * expected partial schedule. 10691 */ 10692 static int test_tile(isl_ctx *ctx) 10693 { 10694 int i; 10695 int scale; 10696 int shift; 10697 10698 scale = isl_options_get_tile_scale_tile_loops(ctx); 10699 shift = isl_options_get_tile_shift_point_loops(ctx); 10700 10701 for (i = 0; i < ARRAY_SIZE(tile_tests); ++i) { 10702 int opt; 10703 int equal; 10704 const char *str; 10705 isl_union_set *domain; 10706 isl_multi_union_pw_aff *mupa, *mupa2; 10707 isl_schedule_node *node; 10708 isl_multi_val *sizes; 10709 10710 opt = tile_tests[i].scale_tile; 10711 isl_options_set_tile_scale_tile_loops(ctx, opt); 10712 opt = tile_tests[i].shift_point; 10713 isl_options_set_tile_shift_point_loops(ctx, opt); 10714 10715 str = tile_tests[i].domain; 10716 domain = isl_union_set_read_from_str(ctx, str); 10717 node = isl_schedule_node_from_domain(domain); 10718 node = isl_schedule_node_child(node, 0); 10719 str = tile_tests[i].schedule; 10720 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str); 10721 node = isl_schedule_node_insert_partial_schedule(node, mupa); 10722 str = tile_tests[i].sizes; 10723 sizes = isl_multi_val_read_from_str(ctx, str); 10724 node = isl_schedule_node_band_tile(node, sizes); 10725 10726 str = tile_tests[i].tile; 10727 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str); 10728 mupa2 = isl_schedule_node_band_get_partial_schedule(node); 10729 equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2); 10730 isl_multi_union_pw_aff_free(mupa); 10731 isl_multi_union_pw_aff_free(mupa2); 10732 10733 node = isl_schedule_node_child(node, 0); 10734 10735 str = tile_tests[i].point; 10736 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str); 10737 mupa2 = isl_schedule_node_band_get_partial_schedule(node); 10738 if (equal >= 0 && equal) 10739 equal = isl_multi_union_pw_aff_plain_is_equal(mupa, 10740 mupa2); 10741 isl_multi_union_pw_aff_free(mupa); 10742 isl_multi_union_pw_aff_free(mupa2); 10743 10744 isl_schedule_node_free(node); 10745 10746 if (equal < 0) 10747 return -1; 10748 if (!equal) 10749 isl_die(ctx, isl_error_unknown, 10750 "unexpected result", return -1); 10751 } 10752 10753 isl_options_set_tile_scale_tile_loops(ctx, scale); 10754 isl_options_set_tile_shift_point_loops(ctx, shift); 10755 10756 return 0; 10757 } 10758 10759 /* Check that the domain hash of a space is equal to the hash 10760 * of the domain of the space, both ignoring parameters. 10761 */ 10762 static int test_domain_hash(isl_ctx *ctx) 10763 { 10764 isl_map *map; 10765 isl_space *space; 10766 uint32_t hash1, hash2; 10767 10768 map = isl_map_read_from_str(ctx, "[n] -> { A[B[x] -> C[]] -> D[] }"); 10769 space = isl_map_get_space(map); 10770 isl_map_free(map); 10771 hash1 = isl_space_get_tuple_domain_hash(space); 10772 space = isl_space_domain(space); 10773 hash2 = isl_space_get_tuple_hash(space); 10774 isl_space_free(space); 10775 10776 if (!space) 10777 return -1; 10778 if (hash1 != hash2) 10779 isl_die(ctx, isl_error_unknown, 10780 "domain hash not equal to hash of domain", return -1); 10781 10782 return 0; 10783 } 10784 10785 /* Check that a universe basic set that is not obviously equal to the universe 10786 * is still recognized as being equal to the universe. 10787 */ 10788 static int test_universe(isl_ctx *ctx) 10789 { 10790 const char *s; 10791 isl_basic_set *bset; 10792 isl_bool is_univ; 10793 10794 s = "{ [] : exists x, y : 3y <= 2x and y >= -3 + 2x and 2y >= 2 - x }"; 10795 bset = isl_basic_set_read_from_str(ctx, s); 10796 is_univ = isl_basic_set_is_universe(bset); 10797 isl_basic_set_free(bset); 10798 10799 if (is_univ < 0) 10800 return -1; 10801 if (!is_univ) 10802 isl_die(ctx, isl_error_unknown, 10803 "not recognized as universe set", return -1); 10804 10805 return 0; 10806 } 10807 10808 /* Sets for which chambers are computed and checked. 10809 */ 10810 const char *chambers_tests[] = { 10811 "[A, B, C] -> { [x, y, z] : x >= 0 and y >= 0 and y <= A - x and " 10812 "z >= 0 and z <= C - y and z <= B - x - y }", 10813 }; 10814 10815 /* Add the domain of "cell" to "cells". 10816 */ 10817 static isl_stat add_cell(__isl_take isl_cell *cell, void *user) 10818 { 10819 isl_basic_set_list **cells = user; 10820 isl_basic_set *dom; 10821 10822 dom = isl_cell_get_domain(cell); 10823 isl_cell_free(cell); 10824 *cells = isl_basic_set_list_add(*cells, dom); 10825 10826 return *cells ? isl_stat_ok : isl_stat_error; 10827 } 10828 10829 /* Check that the elements of "list" are pairwise disjoint. 10830 */ 10831 static isl_stat check_pairwise_disjoint(__isl_keep isl_basic_set_list *list) 10832 { 10833 int i, j; 10834 isl_size n; 10835 10836 n = isl_basic_set_list_n_basic_set(list); 10837 if (n < 0) 10838 return isl_stat_error; 10839 10840 for (i = 0; i < n; ++i) { 10841 isl_basic_set *bset_i; 10842 10843 bset_i = isl_basic_set_list_get_basic_set(list, i); 10844 for (j = i + 1; j < n; ++j) { 10845 isl_basic_set *bset_j; 10846 isl_bool disjoint; 10847 10848 bset_j = isl_basic_set_list_get_basic_set(list, j); 10849 disjoint = isl_basic_set_is_disjoint(bset_i, bset_j); 10850 isl_basic_set_free(bset_j); 10851 if (!disjoint) 10852 isl_die(isl_basic_set_list_get_ctx(list), 10853 isl_error_unknown, "not disjoint", 10854 break); 10855 if (disjoint < 0 || !disjoint) 10856 break; 10857 } 10858 isl_basic_set_free(bset_i); 10859 if (j < n) 10860 return isl_stat_error; 10861 } 10862 10863 return isl_stat_ok; 10864 } 10865 10866 /* Check that the chambers computed by isl_vertices_foreach_disjoint_cell 10867 * are pairwise disjoint. 10868 */ 10869 static int test_chambers(isl_ctx *ctx) 10870 { 10871 int i; 10872 10873 for (i = 0; i < ARRAY_SIZE(chambers_tests); ++i) { 10874 isl_basic_set *bset; 10875 isl_vertices *vertices; 10876 isl_basic_set_list *cells; 10877 isl_stat ok; 10878 10879 bset = isl_basic_set_read_from_str(ctx, chambers_tests[i]); 10880 vertices = isl_basic_set_compute_vertices(bset); 10881 cells = isl_basic_set_list_alloc(ctx, 0); 10882 if (isl_vertices_foreach_disjoint_cell(vertices, &add_cell, 10883 &cells) < 0) 10884 cells = isl_basic_set_list_free(cells); 10885 ok = check_pairwise_disjoint(cells); 10886 isl_basic_set_list_free(cells); 10887 isl_vertices_free(vertices); 10888 isl_basic_set_free(bset); 10889 10890 if (ok < 0) 10891 return -1; 10892 } 10893 10894 return 0; 10895 } 10896 10897 struct { 10898 const char *name; 10899 int (*fn)(isl_ctx *ctx); 10900 } tests [] = { 10901 { "universe", &test_universe }, 10902 { "domain hash", &test_domain_hash }, 10903 { "dual", &test_dual }, 10904 { "dependence analysis", &test_flow }, 10905 { "val", &test_val }, 10906 { "compute divs", &test_compute_divs }, 10907 { "partial lexmin", &test_partial_lexmin }, 10908 { "simplify", &test_simplify }, 10909 { "curry", &test_curry }, 10910 { "piecewise multi affine expressions", &test_pw_multi_aff }, 10911 { "multi piecewise affine expressions", &test_multi_pw_aff }, 10912 { "conversion", &test_conversion }, 10913 { "list", &test_list }, 10914 { "align parameters", &test_align_parameters }, 10915 { "drop unused parameters", &test_drop_unused_parameters }, 10916 { "pullback", &test_pullback }, 10917 { "AST", &test_ast }, 10918 { "AST build", &test_ast_build }, 10919 { "AST generation", &test_ast_gen }, 10920 { "eliminate", &test_eliminate }, 10921 { "deltas_map", &test_deltas_map }, 10922 { "residue class", &test_residue_class }, 10923 { "div", &test_div }, 10924 { "slice", &test_slice }, 10925 { "sample", &test_sample }, 10926 { "empty projection", &test_empty_projection }, 10927 { "output", &test_output }, 10928 { "vertices", &test_vertices }, 10929 { "chambers", &test_chambers }, 10930 { "fixed", &test_fixed }, 10931 { "equal", &test_equal }, 10932 { "disjoint", &test_disjoint }, 10933 { "product", &test_product }, 10934 { "dim_max", &test_dim_max }, 10935 { "affine", &test_aff }, 10936 { "injective", &test_injective }, 10937 { "schedule (whole component)", &test_schedule_whole }, 10938 { "schedule (incremental)", &test_schedule_incremental }, 10939 { "schedule tree", &test_schedule_tree }, 10940 { "schedule tree prefix", &test_schedule_tree_prefix }, 10941 { "schedule tree grouping", &test_schedule_tree_group }, 10942 { "tile", &test_tile }, 10943 { "union map", &test_union_map }, 10944 { "union_pw", &test_union_pw }, 10945 { "locus", &test_locus }, 10946 { "eval", &test_eval }, 10947 { "parse", &test_parse }, 10948 { "single-valued", &test_sv }, 10949 { "recession cone", &test_recession_cone }, 10950 { "affine hull", &test_affine_hull }, 10951 { "simple_hull", &test_simple_hull }, 10952 { "box hull", &test_box_hull }, 10953 { "coalesce", &test_coalesce }, 10954 { "factorize", &test_factorize }, 10955 { "subset", &test_subset }, 10956 { "subtract", &test_subtract }, 10957 { "intersect", &test_intersect }, 10958 { "lexmin", &test_lexmin }, 10959 { "min", &test_min }, 10960 { "set lower bounds", &test_min_mpa }, 10961 { "gist", &test_gist }, 10962 { "piecewise quasi-polynomials", &test_pwqp }, 10963 { "lift", &test_lift }, 10964 { "bind parameters", &test_bind }, 10965 { "unbind parameters", &test_unbind }, 10966 { "bound", &test_bound }, 10967 { "get lists", &test_get_list }, 10968 { "union", &test_union }, 10969 { "split periods", &test_split_periods }, 10970 { "lexicographic order", &test_lex }, 10971 { "bijectivity", &test_bijective }, 10972 { "dataflow analysis", &test_dep }, 10973 { "reading", &test_read }, 10974 { "bounded", &test_bounded }, 10975 { "construction", &test_construction }, 10976 { "dimension manipulation", &test_dim }, 10977 { "map application", &test_application }, 10978 { "convex hull", &test_convex_hull }, 10979 { "transitive closure", &test_closure }, 10980 { "isl_bool", &test_isl_bool}, 10981 }; 10982 10983 int main(int argc, char **argv) 10984 { 10985 int i; 10986 struct isl_ctx *ctx; 10987 struct isl_options *options; 10988 10989 options = isl_options_new_with_defaults(); 10990 assert(options); 10991 argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL); 10992 10993 ctx = isl_ctx_alloc_with_options(&isl_options_args, options); 10994 for (i = 0; i < ARRAY_SIZE(tests); ++i) { 10995 printf("%s\n", tests[i].name); 10996 if (tests[i].fn(ctx) < 0) 10997 goto error; 10998 } 10999 isl_ctx_free(ctx); 11000 return 0; 11001 error: 11002 isl_ctx_free(ctx); 11003 return -1; 11004 } 11005