11045 lines · c
1/*2 * Copyright 2008-2009 Katholieke Universiteit Leuven3 * Copyright 2010 INRIA Saclay4 * Copyright 2012-2013 Ecole Normale Superieure5 * Copyright 2014 INRIA Rocquencourt6 * Copyright 2022 Cerebras Systems7 *8 * Use of this software is governed by the MIT license9 *10 * Written by Sven Verdoolaege, K.U.Leuven, Departement11 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium12 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,13 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France14 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France15 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,16 * B.P. 105 - 78153 Le Chesnay, France17 * and Cerebras Systems, 1237 E Arques Ave, Sunnyvale, CA, USA18 */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 49static 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 66void 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 75int 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 95void 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 104static 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 */115static 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 expressions126 * that are used for testing printing and parsing.127 */128static 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 BASE145#define BASE multi_pw_aff146 147#include "check_reparse_templ.c"148#include "check_reparse_test_templ.c"149 150/* String descriptions that cannot be parsed151 * as multi piecewise affine expressions.152 */153static 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 expressions161 * that are used for testing printing and parsing.162 */163static 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};172 173#undef BASE174#define BASE pw_multi_aff175 176#include "check_reparse_templ.c"177#include "check_reparse_test_templ.c"178 179/* Test parsing of piecewise multi affine expressions by printing180 * the expressions and checking that parsing the output results181 * in the same expression.182 * Do this for an expression converted from a map with an output183 * dimension name that is equal to an automatically generated name, and184 * a set of expressions parsed from strings.185 */186static isl_stat test_parse_pma(isl_ctx *ctx)187{188 isl_map *map;189 isl_pw_multi_aff *pma;190 191 map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");192 pma = isl_pw_multi_aff_from_map(map);193 if (check_reparse_pw_multi_aff(ctx, pma) < 0)194 return isl_stat_error;195 196 if (check_reparse_pw_multi_aff_tests(ctx) < 0)197 return isl_stat_error;198 199 return isl_stat_ok;200}201 202/* String descriptions that cannot be parsed203 * as union piecewise multi affine expressions.204 */205static const char *parse_union_pw_multi_aff_fail_tests[] = {206 "{ [a] -> [b] : b = a }",207 "{ [a] -> [b = a] : b >= 0 }",208};209 210#undef BASE211#define BASE union_pw_multi_aff212 213#include "check_parse_fail_test_templ.c"214 215/* Test parsing of union piecewise multi affine expressions.216 *217 * In particular, check some cases where parsing is supposed to fail.218 */219static isl_stat test_parse_upma(isl_ctx *ctx)220{221 if (check_parse_union_pw_multi_aff_fail_tests(ctx) < 0)222 return isl_stat_error;223 224 return isl_stat_ok;225}226 227/* Test parsing of multi piecewise affine expressions by printing228 * the expressions and checking that parsing the output results229 * in the same expression.230 * Do this for a couple of manually constructed expressions,231 * an expression converted from a map with an output dimension name232 * that is equal to an automatically generated name, and233 * a set of expressions parsed from strings.234 *235 * Additionally, check some cases where parsing is supposed to fail.236 */237static int test_parse_mpa(isl_ctx *ctx)238{239 isl_space *space;240 isl_set *dom;241 isl_map *map;242 isl_pw_multi_aff *pma;243 isl_multi_pw_aff *mpa;244 isl_stat r;245 246 space = isl_space_set_alloc(ctx, 0, 0);247 space = isl_space_set_tuple_name(space, isl_dim_set, "A");248 mpa = isl_multi_pw_aff_zero(space);249 r = check_reparse_multi_pw_aff(ctx, mpa);250 if (r < 0)251 return -1;252 253 space = isl_space_set_alloc(ctx, 1, 0);254 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");255 space = isl_space_set_tuple_name(space, isl_dim_set, "A");256 dom = isl_set_universe(isl_space_params(isl_space_copy(space)));257 dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);258 mpa = isl_multi_pw_aff_zero(space);259 mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);260 r = check_reparse_multi_pw_aff(ctx, mpa);261 if (r < 0)262 return -1;263 264 map = isl_map_read_from_str(ctx, "{ [a, a] -> [i1 = a + 1] }");265 pma = isl_pw_multi_aff_from_map(map);266 mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);267 if (check_reparse_multi_pw_aff(ctx, mpa) < 0)268 return -1;269 270 if (check_reparse_multi_pw_aff_tests(ctx) < 0)271 return -1;272 if (check_parse_multi_pw_aff_fail_tests(ctx) < 0)273 return -1;274 275 return 0;276}277 278/* String descriptions of multi union piecewise affine expressions279 * that are used for testing printing and parsing.280 */281static const char *reparse_multi_union_pw_aff_tests[] = {282 "[]",283 "A[]",284 "A[B[] -> C[]]",285 "(A[] : { S[x] : x > 0; T[y] : y >= 0 })",286 "(A[] : { })",287 "[N] -> (A[] : { })",288 "[N] -> (A[] : { : N >= 0 })",289 "[N] -> (A[] : { S[x] : x > N; T[y] : y >= 0 })",290 "(A[] : [N] -> { S[x] : x > N; T[y] : y >= 0 })",291 "A[{ S[x] -> [x + 1]; T[x] -> [x] }]",292 "(A[{ S[x] -> [x + 1]; T[x] -> [x] }] : "293 "{ S[x] : x > 0; T[y] : y >= 0 })",294};295 296#undef BASE297#define BASE multi_union_pw_aff298 299#include "check_reparse_templ.c"300#include "check_reparse_test_templ.c"301 302/* Test parsing of multi union piecewise affine expressions by printing303 * the expressions and checking that parsing the output results304 * in the same expression.305 * Do this for a couple of manually constructed expressions and306 * a set of expressions parsed from strings.307 */308static int test_parse_mupa(isl_ctx *ctx)309{310 isl_space *space;311 isl_multi_union_pw_aff *mupa;312 isl_set *dom;313 isl_union_set *uset;314 isl_stat r;315 316 space = isl_space_set_alloc(ctx, 0, 0);317 space = isl_space_set_tuple_name(space, isl_dim_set, "A");318 mupa = isl_multi_union_pw_aff_zero(space);319 r = check_reparse_multi_union_pw_aff(ctx, mupa);320 if (r < 0)321 return -1;322 323 space = isl_space_set_alloc(ctx, 1, 0);324 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");325 space = isl_space_set_tuple_name(space, isl_dim_set, "A");326 dom = isl_set_universe(space);327 dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);328 uset = isl_union_set_from_set(dom);329 space = isl_space_set_alloc(ctx, 1, 0);330 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");331 space = isl_space_set_tuple_name(space, isl_dim_set, "B");332 mupa = isl_multi_union_pw_aff_zero(space);333 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, uset);334 r = check_reparse_multi_union_pw_aff(ctx, mupa);335 if (r < 0)336 return -1;337 338 if (check_reparse_multi_union_pw_aff_tests(ctx) < 0)339 return -1;340 341 return 0;342}343 344/* Test parsing of multi expressions.345 */346static int test_parse_multi(isl_ctx *ctx)347{348 if (test_parse_mpa(ctx) < 0)349 return -1;350 if (test_parse_mupa(ctx) < 0)351 return -1;352 353 return 0;354}355 356/* Pairs of binary relation representations that should represent357 * the same binary relations.358 */359struct {360 const char *map1;361 const char *map2;362} parse_map_equal_tests[] = {363 { "{ [x,y] : [([x/2]+y)/3] >= 1 }",364 "{ [x, y] : 2y >= 6 - x }" },365 { "{ [x,y] : x <= min(y, 2*y+3) }",366 "{ [x,y] : x <= y, 2*y + 3 }" },367 { "{ [x,y] : x >= min(y, 2*y+3) }",368 "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }" },369 { "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }",370 "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }" },371 { "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }",372 "{ [i,j] -> [min(i,j)] }" },373 { "{ [i,j] : i != j }",374 "{ [i,j] : i < j or i > j }" },375 { "{ [i,j] : (i+1)*2 >= j }",376 "{ [i, j] : j <= 2 + 2i }" },377 { "{ [i] -> [i > 0 ? 4 : 5] }",378 "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }" },379 { "[N=2,M] -> { [i=[(M+N)/4]] }",380 "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }" },381 { "{ [x] : x >= 0 }",382 "{ [x] : x-0 >= 0 }" },383 { "{ [i] : ((i > 10)) }",384 "{ [i] : i >= 11 }" },385 { "{ [i] -> [0] }",386 "{ [i] -> [0 * i] }" },387 { "{ [a] -> [b] : (not false) }",388 "{ [a] -> [b] : true }" },389 { "{ [i] : i/2 <= 5 }",390 "{ [i] : i <= 10 }" },391 { "{Sym=[n] [i] : i <= n }",392 "[n] -> { [i] : i <= n }" },393 { "{ [*] }",394 "{ [a] }" },395 { "{ [i] : 2*floor(i/2) = i }",396 "{ [i] : exists a : i = 2 a }" },397 { "{ [a] -> [b] : a = 5 implies b = 5 }",398 "{ [a] -> [b] : a != 5 or b = 5 }" },399 { "{ [a] -> [a - 1 : a > 0] }",400 "{ [a] -> [a - 1] : a > 0 }" },401 { "{ [a] -> [a - 1 : a > 0; a : a <= 0] }",402 "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }" },403 { "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }",404 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },405 { "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }",406 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },407 { "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }",408 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },409 { "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }",410 "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }" },411 { "{ [a,b] -> [i,j] : a,b << i,j }",412 "{ [a,b] -> [i,j] : a < i or (a = i and b < j) }" },413 { "{ [a,b] -> [i,j] : a,b <<= i,j }",414 "{ [a,b] -> [i,j] : a < i or (a = i and b <= j) }" },415 { "{ [a,b] -> [i,j] : a,b >> i,j }",416 "{ [a,b] -> [i,j] : a > i or (a = i and b > j) }" },417 { "{ [a,b] -> [i,j] : a,b >>= i,j }",418 "{ [a,b] -> [i,j] : a > i or (a = i and b >= j) }" },419 { "{ [n] -> [i] : exists (a, b, c: 8b <= i - 32a and "420 "8b >= -7 + i - 32 a and b >= 0 and b <= 3 and "421 "8c < n - 32a and i < n and c >= 0 and "422 "c <= 3 and c >= -4a) }",423 "{ [n] -> [i] : 0 <= i < n }" },424 { "{ [x] -> [] : exists (a, b: 0 <= a <= 1 and 0 <= b <= 3 and "425 "2b <= x - 8a and 2b >= -1 + x - 8a) }",426 "{ [x] -> [] : 0 <= x <= 15 }" },427 { "{ [x] -> [x] : }",428 "{ [x] -> [x] }" },429 { "{ [x=4:5] -> [x + 1] }",430 "{ [x] -> [x + 1] : 4 <= x <= 5 }" },431 { "{ [x=4:5] -> [x + 1 : x + 1] }",432 "{ [x=4:5] -> [x + 1] }" },433 { "{ [x] -> [x - 1 : x + 1] }",434 "{ [x] -> [y] : x - 1 <= y <= x + 1 }" },435 { "{ [x=4:] -> [x + 1] }",436 "{ [x] -> [x + 1] : 4 <= x }" },437 { "{ [x=:5] -> [x + 1] }",438 "{ [x] -> [x + 1] : x <= 5 }" },439 { "{ [x=:] -> [x + 1] }",440 "{ [x] -> [x + 1] }" },441 { "{ [:] -> [:] }",442 "{ [x] -> [y] }" },443 { "{ [x, x//4] }",444 "{ [x, floor(x/4)] }" },445 { "{ [10//4] }",446 "{ [2] }" },447 { "{ [-1//4] }",448 "{ [-1] }" },449 { "{ [0-1//4] }",450 "{ [0] }" },451 { "{ [- 1//4] }",452 "{ [-1] }" },453 { "{ [0 - 1//4] }",454 "{ [0] }" },455 { "{ [0--1//4] }",456 "{ [1] }" },457 { "{ [0 - -1//4] }",458 "{ [1] }" },459 { "{ [-2^2:2^2-1] }",460 "{ [-4:3] }" },461 { "{ [2*-2] }",462 "{ [-4] }" },463 { "{ [i,i*-2] }",464 "{ [i,-2i] }" },465 { "[a, b, c, d] -> { [max(a,b,c,d)] }",466 "[a, b, c, d] -> { [a] : b < a and c < a and d < a; "467 "[b] : b >= a and c < b and d < b; "468 "[c] : c >= a and c >= b and d < c; "469 "[d] : d >= a and d >= b and d >= c }" },470 { "[a, b, c, d] -> { [min(a,b,c,d)] }",471 "[a, b, c, d] -> { [a] : b >= a and c >= a and d >= a; "472 "[b] : b < a and c >= b and d >= b; "473 "[c] : c < b and c < a and d >= c; "474 "[d] : d < c and d < b and d < a }" },475};476 477int test_parse(struct isl_ctx *ctx)478{479 int i;480 isl_map *map, *map2;481 const char *str, *str2;482 483 if (test_parse_multi_val(ctx, "{ A[B[2] -> C[5, 7]] }") < 0)484 return -1;485 if (test_parse_multi_val(ctx, "[n] -> { [2] }") < 0)486 return -1;487 if (test_parse_multi_val(ctx, "{ A[4, infty, NaN, -1/2, 2/3] }") < 0)488 return -1;489 if (test_parse_multi(ctx) < 0)490 return -1;491 if (test_parse_pma(ctx) < 0)492 return -1;493 if (test_parse_upma(ctx) < 0)494 return -1;495 496 str = "{ [i] -> [-i] }";497 map = isl_map_read_from_str(ctx, str);498 assert(map);499 isl_map_free(map);500 501 str = "{ A[i] -> L[([i/3])] }";502 map = isl_map_read_from_str(ctx, str);503 assert(map);504 isl_map_free(map);505 506 test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}");507 test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : "508 "p1 = 1 && (y1 <= y2 || y2 = 0) }");509 510 for (i = 0; i < ARRAY_SIZE(parse_map_equal_tests); ++i) {511 str = parse_map_equal_tests[i].map1;512 str2 = parse_map_equal_tests[i].map2;513 if (test_parse_map_equal(ctx, str, str2) < 0)514 return -1;515 }516 517 str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";518 map = isl_map_read_from_str(ctx, str);519 str = "{ [new, old] -> [o0, o1] : "520 "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: "521 "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and "522 "o0 <= 1 and o1 >= 0 and o1 <= 1) }";523 map2 = isl_map_read_from_str(ctx, str);524 assert(isl_map_is_equal(map, map2));525 isl_map_free(map);526 isl_map_free(map2);527 528 str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";529 map = isl_map_read_from_str(ctx, str);530 str = "{[new,old] -> [(new+1)%2,(old+1)%2]}";531 map2 = isl_map_read_from_str(ctx, str);532 assert(isl_map_is_equal(map, map2));533 isl_map_free(map);534 isl_map_free(map2);535 536 test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }");537 test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }");538 test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }");539 test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }");540 test_parse_pwaff(ctx, "{ [] -> [(100)] }");541 542 return 0;543}544 545static int test_read(isl_ctx *ctx)546{547 char *filename;548 FILE *input;549 isl_basic_set *bset1, *bset2;550 const char *str = "{[y]: Exists ( alpha : 2alpha = y)}";551 int equal;552 553 filename = get_filename(ctx, "set", "omega");554 assert(filename);555 input = fopen(filename, "r");556 assert(input);557 558 bset1 = isl_basic_set_read_from_file(ctx, input);559 bset2 = isl_basic_set_read_from_str(ctx, str);560 561 equal = isl_basic_set_is_equal(bset1, bset2);562 563 isl_basic_set_free(bset1);564 isl_basic_set_free(bset2);565 free(filename);566 567 fclose(input);568 569 if (equal < 0)570 return -1;571 if (!equal)572 isl_die(ctx, isl_error_unknown,573 "read sets not equal", return -1);574 575 return 0;576}577 578static int test_bounded(isl_ctx *ctx)579{580 isl_set *set;581 isl_bool bounded;582 583 set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }");584 bounded = isl_set_is_bounded(set);585 isl_set_free(set);586 587 if (bounded < 0)588 return -1;589 if (!bounded)590 isl_die(ctx, isl_error_unknown,591 "set not considered bounded", return -1);592 593 set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }");594 bounded = isl_set_is_bounded(set);595 assert(!bounded);596 isl_set_free(set);597 598 if (bounded < 0)599 return -1;600 if (bounded)601 isl_die(ctx, isl_error_unknown,602 "set considered bounded", return -1);603 604 set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }");605 bounded = isl_set_is_bounded(set);606 isl_set_free(set);607 608 if (bounded < 0)609 return -1;610 if (bounded)611 isl_die(ctx, isl_error_unknown,612 "set considered bounded", return -1);613 614 return 0;615}616 617/* Construct the basic set { [i] : 5 <= i <= N } */618static int test_construction_1(isl_ctx *ctx)619{620 isl_space *space;621 isl_local_space *ls;622 isl_basic_set *bset;623 isl_constraint *c;624 625 space = isl_space_set_alloc(ctx, 1, 1);626 bset = isl_basic_set_universe(isl_space_copy(space));627 ls = isl_local_space_from_space(space);628 629 c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));630 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);631 c = isl_constraint_set_coefficient_si(c, isl_dim_param, 0, 1);632 bset = isl_basic_set_add_constraint(bset, c);633 634 c = isl_constraint_alloc_inequality(isl_local_space_copy(ls));635 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);636 c = isl_constraint_set_constant_si(c, -5);637 bset = isl_basic_set_add_constraint(bset, c);638 639 isl_local_space_free(ls);640 isl_basic_set_free(bset);641 642 return 0;643}644 645/* Construct the basic set { [x] : -100 <= x <= 100 }646 * using isl_basic_set_{lower,upper}_bound_val and647 * check that it is equal the same basic set parsed from a string.648 */649static int test_construction_2(isl_ctx *ctx)650{651 isl_bool equal;652 isl_val *v;653 isl_space *space;654 isl_basic_set *bset1, *bset2;655 656 v = isl_val_int_from_si(ctx, 100);657 space = isl_space_set_alloc(ctx, 0, 1);658 bset1 = isl_basic_set_universe(space);659 bset1 = isl_basic_set_upper_bound_val(bset1, isl_dim_set, 0,660 isl_val_copy(v));661 bset1 = isl_basic_set_lower_bound_val(bset1, isl_dim_set, 0,662 isl_val_neg(v));663 bset2 = isl_basic_set_read_from_str(ctx, "{ [x] : -100 <= x <= 100 }");664 equal = isl_basic_set_is_equal(bset1, bset2);665 isl_basic_set_free(bset1);666 isl_basic_set_free(bset2);667 668 if (equal < 0)669 return -1;670 if (!equal)671 isl_die(ctx, isl_error_unknown,672 "failed construction", return -1);673 674 return 0;675}676 677/* Basic tests for constructing basic sets.678 */679static int test_construction(isl_ctx *ctx)680{681 if (test_construction_1(ctx) < 0)682 return -1;683 if (test_construction_2(ctx) < 0)684 return -1;685 return 0;686}687 688static int test_dim(isl_ctx *ctx)689{690 const char *str;691 isl_map *map1, *map2;692 int equal;693 694 map1 = isl_map_read_from_str(ctx,695 "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");696 map1 = isl_map_add_dims(map1, isl_dim_in, 1);697 map2 = isl_map_read_from_str(ctx,698 "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");699 equal = isl_map_is_equal(map1, map2);700 isl_map_free(map2);701 702 map1 = isl_map_project_out(map1, isl_dim_in, 0, 1);703 map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }");704 if (equal >= 0 && equal)705 equal = isl_map_is_equal(map1, map2);706 707 isl_map_free(map1);708 isl_map_free(map2);709 710 if (equal < 0)711 return -1;712 if (!equal)713 isl_die(ctx, isl_error_unknown,714 "unexpected result", return -1);715 716 str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }";717 map1 = isl_map_read_from_str(ctx, str);718 str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }";719 map2 = isl_map_read_from_str(ctx, str);720 map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1);721 equal = isl_map_is_equal(map1, map2);722 isl_map_free(map1);723 isl_map_free(map2);724 725 if (equal < 0)726 return -1;727 if (!equal)728 isl_die(ctx, isl_error_unknown,729 "unexpected result", return -1);730 731 return 0;732}733 734#undef BASE735#define BASE multi_val736#include "isl_test_plain_equal_templ.c"737 738#undef BASE739#define BASE multi_aff740#include "isl_test_plain_equal_templ.c"741 742/* Check that "val" is equal to the value described by "str".743 * If "str" is "NaN", then check for a NaN value explicitly.744 */745static isl_stat val_check_equal(__isl_keep isl_val *val, const char *str)746{747 isl_bool ok, is_nan;748 isl_ctx *ctx;749 isl_val *res;750 751 if (!val)752 return isl_stat_error;753 754 ctx = isl_val_get_ctx(val);755 res = isl_val_read_from_str(ctx, str);756 is_nan = isl_val_is_nan(res);757 if (is_nan < 0)758 ok = isl_bool_error;759 else if (is_nan)760 ok = isl_val_is_nan(val);761 else762 ok = isl_val_eq(val, res);763 isl_val_free(res);764 if (ok < 0)765 return isl_stat_error;766 if (!ok)767 isl_die(ctx, isl_error_unknown,768 "unexpected result", return isl_stat_error);769 return isl_stat_ok;770}771 772struct {773 __isl_give isl_val *(*op)(__isl_take isl_val *v);774 const char *arg;775 const char *res;776} val_un_tests[] = {777 { &isl_val_neg, "0", "0" },778 { &isl_val_abs, "0", "0" },779 { &isl_val_pow2, "0", "1" },780 { &isl_val_floor, "0", "0" },781 { &isl_val_ceil, "0", "0" },782 { &isl_val_neg, "1", "-1" },783 { &isl_val_neg, "-1", "1" },784 { &isl_val_neg, "1/2", "-1/2" },785 { &isl_val_neg, "-1/2", "1/2" },786 { &isl_val_neg, "infty", "-infty" },787 { &isl_val_neg, "-infty", "infty" },788 { &isl_val_neg, "NaN", "NaN" },789 { &isl_val_abs, "1", "1" },790 { &isl_val_abs, "-1", "1" },791 { &isl_val_abs, "1/2", "1/2" },792 { &isl_val_abs, "-1/2", "1/2" },793 { &isl_val_abs, "infty", "infty" },794 { &isl_val_abs, "-infty", "infty" },795 { &isl_val_abs, "NaN", "NaN" },796 { &isl_val_floor, "1", "1" },797 { &isl_val_floor, "-1", "-1" },798 { &isl_val_floor, "1/2", "0" },799 { &isl_val_floor, "-1/2", "-1" },800 { &isl_val_floor, "infty", "infty" },801 { &isl_val_floor, "-infty", "-infty" },802 { &isl_val_floor, "NaN", "NaN" },803 { &isl_val_ceil, "1", "1" },804 { &isl_val_ceil, "-1", "-1" },805 { &isl_val_ceil, "1/2", "1" },806 { &isl_val_ceil, "-1/2", "0" },807 { &isl_val_ceil, "infty", "infty" },808 { &isl_val_ceil, "-infty", "-infty" },809 { &isl_val_ceil, "NaN", "NaN" },810 { &isl_val_pow2, "-3", "1/8" },811 { &isl_val_pow2, "-1", "1/2" },812 { &isl_val_pow2, "1", "2" },813 { &isl_val_pow2, "2", "4" },814 { &isl_val_pow2, "3", "8" },815 { &isl_val_inv, "1", "1" },816 { &isl_val_inv, "2", "1/2" },817 { &isl_val_inv, "1/2", "2" },818 { &isl_val_inv, "-2", "-1/2" },819 { &isl_val_inv, "-1/2", "-2" },820 { &isl_val_inv, "0", "NaN" },821 { &isl_val_inv, "NaN", "NaN" },822 { &isl_val_inv, "infty", "0" },823 { &isl_val_inv, "-infty", "0" },824};825 826/* Perform some basic tests of unary operations on isl_val objects.827 */828static int test_un_val(isl_ctx *ctx)829{830 int i;831 isl_val *v;832 __isl_give isl_val *(*fn)(__isl_take isl_val *v);833 834 for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) {835 isl_stat r;836 837 v = isl_val_read_from_str(ctx, val_un_tests[i].arg);838 fn = val_un_tests[i].op;839 v = fn(v);840 r = val_check_equal(v, val_un_tests[i].res);841 isl_val_free(v);842 if (r < 0)843 return -1;844 }845 846 return 0;847}848 849struct {850 __isl_give isl_val *(*fn)(__isl_take isl_val *v1,851 __isl_take isl_val *v2);852} val_bin_op[] = {853 ['+'] = { &isl_val_add },854 ['-'] = { &isl_val_sub },855 ['*'] = { &isl_val_mul },856 ['/'] = { &isl_val_div },857 ['g'] = { &isl_val_gcd },858 ['m'] = { &isl_val_min },859 ['M'] = { &isl_val_max },860};861 862struct {863 const char *arg1;864 unsigned char op;865 const char *arg2;866 const char *res;867} val_bin_tests[] = {868 { "0", '+', "0", "0" },869 { "1", '+', "0", "1" },870 { "1", '+', "1", "2" },871 { "1", '-', "1", "0" },872 { "1", '*', "1", "1" },873 { "1", '/', "1", "1" },874 { "2", '*', "3", "6" },875 { "2", '*', "1/2", "1" },876 { "2", '*', "1/3", "2/3" },877 { "2/3", '*', "3/5", "2/5" },878 { "2/3", '*', "7/5", "14/15" },879 { "2", '/', "1/2", "4" },880 { "-2", '/', "-1/2", "4" },881 { "-2", '/', "1/2", "-4" },882 { "2", '/', "-1/2", "-4" },883 { "2", '/', "2", "1" },884 { "2", '/', "3", "2/3" },885 { "2/3", '/', "5/3", "2/5" },886 { "2/3", '/', "5/7", "14/15" },887 { "0", '/', "0", "NaN" },888 { "42", '/', "0", "NaN" },889 { "-42", '/', "0", "NaN" },890 { "infty", '/', "0", "NaN" },891 { "-infty", '/', "0", "NaN" },892 { "NaN", '/', "0", "NaN" },893 { "0", '/', "NaN", "NaN" },894 { "42", '/', "NaN", "NaN" },895 { "-42", '/', "NaN", "NaN" },896 { "infty", '/', "NaN", "NaN" },897 { "-infty", '/', "NaN", "NaN" },898 { "NaN", '/', "NaN", "NaN" },899 { "0", '/', "infty", "0" },900 { "42", '/', "infty", "0" },901 { "-42", '/', "infty", "0" },902 { "infty", '/', "infty", "NaN" },903 { "-infty", '/', "infty", "NaN" },904 { "NaN", '/', "infty", "NaN" },905 { "0", '/', "-infty", "0" },906 { "42", '/', "-infty", "0" },907 { "-42", '/', "-infty", "0" },908 { "infty", '/', "-infty", "NaN" },909 { "-infty", '/', "-infty", "NaN" },910 { "NaN", '/', "-infty", "NaN" },911 { "1", '-', "1/3", "2/3" },912 { "1/3", '+', "1/2", "5/6" },913 { "1/2", '+', "1/2", "1" },914 { "3/4", '-', "1/4", "1/2" },915 { "1/2", '-', "1/3", "1/6" },916 { "infty", '+', "42", "infty" },917 { "infty", '+', "infty", "infty" },918 { "42", '+', "infty", "infty" },919 { "infty", '-', "infty", "NaN" },920 { "infty", '*', "infty", "infty" },921 { "infty", '*', "-infty", "-infty" },922 { "-infty", '*', "infty", "-infty" },923 { "-infty", '*', "-infty", "infty" },924 { "0", '*', "infty", "NaN" },925 { "1", '*', "infty", "infty" },926 { "infty", '*', "0", "NaN" },927 { "infty", '*', "42", "infty" },928 { "42", '-', "infty", "-infty" },929 { "infty", '+', "-infty", "NaN" },930 { "4", 'g', "6", "2" },931 { "5", 'g', "6", "1" },932 { "42", 'm', "3", "3" },933 { "42", 'M', "3", "42" },934 { "3", 'm', "42", "3" },935 { "3", 'M', "42", "42" },936 { "42", 'm', "infty", "42" },937 { "42", 'M', "infty", "infty" },938 { "42", 'm', "-infty", "-infty" },939 { "42", 'M', "-infty", "42" },940 { "42", 'm', "NaN", "NaN" },941 { "42", 'M', "NaN", "NaN" },942 { "infty", 'm', "-infty", "-infty" },943 { "infty", 'M', "-infty", "infty" },944};945 946/* Perform some basic tests of binary operations on isl_val objects.947 */948static int test_bin_val(isl_ctx *ctx)949{950 int i;951 isl_val *v1, *v2, *res;952 __isl_give isl_val *(*fn)(__isl_take isl_val *v1,953 __isl_take isl_val *v2);954 int ok;955 956 for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) {957 v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1);958 v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2);959 res = isl_val_read_from_str(ctx, val_bin_tests[i].res);960 fn = val_bin_op[val_bin_tests[i].op].fn;961 v1 = fn(v1, v2);962 if (isl_val_is_nan(res))963 ok = isl_val_is_nan(v1);964 else965 ok = isl_val_eq(v1, res);966 isl_val_free(v1);967 isl_val_free(res);968 if (ok < 0)969 return -1;970 if (!ok)971 isl_die(ctx, isl_error_unknown,972 "unexpected result", return -1);973 }974 975 return 0;976}977 978/* Perform some basic tests on isl_val objects.979 */980static int test_val(isl_ctx *ctx)981{982 if (test_un_val(ctx) < 0)983 return -1;984 if (test_bin_val(ctx) < 0)985 return -1;986 return 0;987}988 989/* Sets described using existentially quantified variables that990 * can also be described without.991 */992static const char *elimination_tests[] = {993 "{ [i,j] : 2 * [i/2] + 3 * [j/4] <= 10 and 2 i = j }",994 "{ [m, w] : exists a : w - 2m - 5 <= 3a <= m - 2w }",995 "{ [m, w] : exists a : w >= 0 and a < m and -1 + w <= a <= 2m - w }",996};997 998/* Check that redundant existentially quantified variables are999 * getting removed.1000 */1001static int test_elimination(isl_ctx *ctx)1002{1003 int i;1004 isl_size n;1005 isl_basic_set *bset;1006 1007 for (i = 0; i < ARRAY_SIZE(elimination_tests); ++i) {1008 bset = isl_basic_set_read_from_str(ctx, elimination_tests[i]);1009 n = isl_basic_set_dim(bset, isl_dim_div);1010 isl_basic_set_free(bset);1011 if (n < 0)1012 return -1;1013 if (n != 0)1014 isl_die(ctx, isl_error_unknown,1015 "expecting no existentials", return -1);1016 }1017 1018 return 0;1019}1020 1021static int test_div(isl_ctx *ctx)1022{1023 const char *str;1024 int empty;1025 isl_space *space;1026 isl_set *set;1027 isl_local_space *ls;1028 struct isl_basic_set *bset;1029 struct isl_constraint *c;1030 1031 /* test 1 */1032 space = isl_space_set_alloc(ctx, 0, 3);1033 bset = isl_basic_set_universe(isl_space_copy(space));1034 ls = isl_local_space_from_space(space);1035 1036 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1037 c = isl_constraint_set_constant_si(c, -1);1038 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1039 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);1040 bset = isl_basic_set_add_constraint(bset, c);1041 1042 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1043 c = isl_constraint_set_constant_si(c, 1);1044 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1045 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);1046 bset = isl_basic_set_add_constraint(bset, c);1047 1048 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);1049 1050 assert(bset && bset->n_div == 1);1051 isl_local_space_free(ls);1052 isl_basic_set_free(bset);1053 1054 /* test 2 */1055 space = isl_space_set_alloc(ctx, 0, 3);1056 bset = isl_basic_set_universe(isl_space_copy(space));1057 ls = isl_local_space_from_space(space);1058 1059 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1060 c = isl_constraint_set_constant_si(c, 1);1061 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1062 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);1063 bset = isl_basic_set_add_constraint(bset, c);1064 1065 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1066 c = isl_constraint_set_constant_si(c, -1);1067 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1068 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);1069 bset = isl_basic_set_add_constraint(bset, c);1070 1071 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);1072 1073 assert(bset && bset->n_div == 1);1074 isl_local_space_free(ls);1075 isl_basic_set_free(bset);1076 1077 /* test 3 */1078 space = isl_space_set_alloc(ctx, 0, 3);1079 bset = isl_basic_set_universe(isl_space_copy(space));1080 ls = isl_local_space_from_space(space);1081 1082 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1083 c = isl_constraint_set_constant_si(c, 1);1084 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1085 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);1086 bset = isl_basic_set_add_constraint(bset, c);1087 1088 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1089 c = isl_constraint_set_constant_si(c, -3);1090 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1091 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 4);1092 bset = isl_basic_set_add_constraint(bset, c);1093 1094 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);1095 1096 assert(bset && bset->n_div == 1);1097 isl_local_space_free(ls);1098 isl_basic_set_free(bset);1099 1100 /* test 4 */1101 space = isl_space_set_alloc(ctx, 0, 3);1102 bset = isl_basic_set_universe(isl_space_copy(space));1103 ls = isl_local_space_from_space(space);1104 1105 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1106 c = isl_constraint_set_constant_si(c, 2);1107 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1108 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 3);1109 bset = isl_basic_set_add_constraint(bset, c);1110 1111 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1112 c = isl_constraint_set_constant_si(c, -1);1113 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1114 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);1115 bset = isl_basic_set_add_constraint(bset, c);1116 1117 bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);1118 1119 assert(isl_basic_set_is_empty(bset));1120 isl_local_space_free(ls);1121 isl_basic_set_free(bset);1122 1123 /* test 5 */1124 space = isl_space_set_alloc(ctx, 0, 3);1125 bset = isl_basic_set_universe(isl_space_copy(space));1126 ls = isl_local_space_from_space(space);1127 1128 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1129 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1130 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 3);1131 bset = isl_basic_set_add_constraint(bset, c);1132 1133 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1134 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1135 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);1136 bset = isl_basic_set_add_constraint(bset, c);1137 1138 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);1139 1140 assert(bset && bset->n_div == 0);1141 isl_basic_set_free(bset);1142 isl_local_space_free(ls);1143 1144 /* test 6 */1145 space = isl_space_set_alloc(ctx, 0, 3);1146 bset = isl_basic_set_universe(isl_space_copy(space));1147 ls = isl_local_space_from_space(space);1148 1149 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1150 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1151 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 6);1152 bset = isl_basic_set_add_constraint(bset, c);1153 1154 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1155 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1156 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);1157 bset = isl_basic_set_add_constraint(bset, c);1158 1159 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);1160 1161 assert(bset && bset->n_div == 1);1162 isl_basic_set_free(bset);1163 isl_local_space_free(ls);1164 1165 /* test 7 */1166 /* This test is a bit tricky. We set up an equality1167 * a + 3b + 3c = 6 e01168 * Normalization of divs creates _two_ divs1169 * a = 3 e01170 * c - b - e0 = 2 e11171 * Afterwards e0 is removed again because it has coefficient -11172 * and we end up with the original equality and div again.1173 * Perhaps we can avoid the introduction of this temporary div.1174 */1175 space = isl_space_set_alloc(ctx, 0, 4);1176 bset = isl_basic_set_universe(isl_space_copy(space));1177 ls = isl_local_space_from_space(space);1178 1179 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1180 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1181 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);1182 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -3);1183 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 6);1184 bset = isl_basic_set_add_constraint(bset, c);1185 1186 bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);1187 1188 /* Test disabled for now */1189 /*1190 assert(bset && bset->n_div == 1);1191 */1192 isl_local_space_free(ls);1193 isl_basic_set_free(bset);1194 1195 /* test 8 */1196 space = isl_space_set_alloc(ctx, 0, 5);1197 bset = isl_basic_set_universe(isl_space_copy(space));1198 ls = isl_local_space_from_space(space);1199 1200 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1201 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1202 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -3);1203 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, -3);1204 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 4, 6);1205 bset = isl_basic_set_add_constraint(bset, c);1206 1207 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1208 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1209 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, 1);1210 c = isl_constraint_set_constant_si(c, 1);1211 bset = isl_basic_set_add_constraint(bset, c);1212 1213 bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1);1214 1215 /* Test disabled for now */1216 /*1217 assert(bset && bset->n_div == 1);1218 */1219 isl_local_space_free(ls);1220 isl_basic_set_free(bset);1221 1222 /* test 9 */1223 space = isl_space_set_alloc(ctx, 0, 4);1224 bset = isl_basic_set_universe(isl_space_copy(space));1225 ls = isl_local_space_from_space(space);1226 1227 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1228 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1229 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, -1);1230 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);1231 bset = isl_basic_set_add_constraint(bset, c);1232 1233 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1234 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);1235 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 3, 3);1236 c = isl_constraint_set_constant_si(c, 2);1237 bset = isl_basic_set_add_constraint(bset, c);1238 1239 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2);1240 1241 bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);1242 1243 assert(!isl_basic_set_is_empty(bset));1244 1245 isl_local_space_free(ls);1246 isl_basic_set_free(bset);1247 1248 /* test 10 */1249 space = isl_space_set_alloc(ctx, 0, 3);1250 bset = isl_basic_set_universe(isl_space_copy(space));1251 ls = isl_local_space_from_space(space);1252 1253 c = isl_constraint_alloc_equality(isl_local_space_copy(ls));1254 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);1255 c = isl_constraint_set_coefficient_si(c, isl_dim_set, 2, -2);1256 bset = isl_basic_set_add_constraint(bset, c);1257 1258 bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);1259 1260 bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);1261 1262 isl_local_space_free(ls);1263 isl_basic_set_free(bset);1264 1265 str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "1266 "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }";1267 set = isl_set_read_from_str(ctx, str);1268 set = isl_set_compute_divs(set);1269 isl_set_free(set);1270 if (!set)1271 return -1;1272 1273 if (test_elimination(ctx) < 0)1274 return -1;1275 1276 str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }";1277 set = isl_set_read_from_str(ctx, str);1278 set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2);1279 set = isl_set_fix_si(set, isl_dim_set, 2, -3);1280 empty = isl_set_is_empty(set);1281 isl_set_free(set);1282 if (empty < 0)1283 return -1;1284 if (!empty)1285 isl_die(ctx, isl_error_unknown,1286 "result not as accurate as expected", return -1);1287 1288 return 0;1289}1290 1291void test_application_case(struct isl_ctx *ctx, const char *name)1292{1293 char *filename;1294 FILE *input;1295 struct isl_basic_set *bset1, *bset2;1296 struct isl_basic_map *bmap;1297 1298 filename = get_filename(ctx, name, "omega");1299 assert(filename);1300 input = fopen(filename, "r");1301 assert(input);1302 1303 bset1 = isl_basic_set_read_from_file(ctx, input);1304 bmap = isl_basic_map_read_from_file(ctx, input);1305 1306 bset1 = isl_basic_set_apply(bset1, bmap);1307 1308 bset2 = isl_basic_set_read_from_file(ctx, input);1309 1310 assert(isl_basic_set_is_equal(bset1, bset2) == 1);1311 1312 isl_basic_set_free(bset1);1313 isl_basic_set_free(bset2);1314 free(filename);1315 1316 fclose(input);1317}1318 1319static int test_application(isl_ctx *ctx)1320{1321 test_application_case(ctx, "application");1322 test_application_case(ctx, "application2");1323 1324 return 0;1325}1326 1327void test_affine_hull_case(struct isl_ctx *ctx, const char *name)1328{1329 char *filename;1330 FILE *input;1331 struct isl_basic_set *bset1, *bset2;1332 1333 filename = get_filename(ctx, name, "polylib");1334 assert(filename);1335 input = fopen(filename, "r");1336 assert(input);1337 1338 bset1 = isl_basic_set_read_from_file(ctx, input);1339 bset2 = isl_basic_set_read_from_file(ctx, input);1340 1341 bset1 = isl_basic_set_affine_hull(bset1);1342 1343 assert(isl_basic_set_is_equal(bset1, bset2) == 1);1344 1345 isl_basic_set_free(bset1);1346 isl_basic_set_free(bset2);1347 free(filename);1348 1349 fclose(input);1350}1351 1352/* Pairs of sets and the corresponding expected results of1353 * isl_basic_set_recession_cone.1354 */1355struct {1356 const char *set;1357 const char *cone;1358} recession_cone_tests[] = {1359 { "{ [i] : 0 <= i <= 10 }", "{ [0] }" },1360 { "{ [i] : 0 <= i }", "{ [i] : 0 <= i }" },1361 { "{ [i] : i <= 10 }", "{ [i] : i <= 0 }" },1362 { "{ [i] : false }", "{ [i] : false }" },1363};1364 1365/* Perform some basic isl_basic_set_recession_cone tests.1366 */1367static int test_recession_cone(struct isl_ctx *ctx)1368{1369 int i;1370 1371 for (i = 0; i < ARRAY_SIZE(recession_cone_tests); ++i) {1372 const char *str;1373 isl_basic_set *bset;1374 isl_basic_set *cone, *expected;1375 isl_bool equal;1376 1377 str = recession_cone_tests[i].set;1378 bset = isl_basic_set_read_from_str(ctx, str);1379 str = recession_cone_tests[i].cone;1380 expected = isl_basic_set_read_from_str(ctx, str);1381 cone = isl_basic_set_recession_cone(bset);1382 equal = isl_basic_set_is_equal(cone, expected);1383 isl_basic_set_free(cone);1384 isl_basic_set_free(expected);1385 if (equal < 0)1386 return -1;1387 if (!equal)1388 isl_die(ctx, isl_error_unknown, "unexpected cone",1389 return -1);1390 }1391 1392 return 0;1393}1394 1395int test_affine_hull(struct isl_ctx *ctx)1396{1397 const char *str;1398 isl_set *set;1399 isl_basic_set *bset, *bset2;1400 isl_size n;1401 isl_bool subset;1402 1403 test_affine_hull_case(ctx, "affine2");1404 test_affine_hull_case(ctx, "affine");1405 test_affine_hull_case(ctx, "affine3");1406 1407 str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and "1408 "m >= 3 and 4i0 <= 2 + m and e1 >= i0 and "1409 "e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and "1410 "2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }";1411 set = isl_set_read_from_str(ctx, str);1412 bset = isl_set_affine_hull(set);1413 n = isl_basic_set_dim(bset, isl_dim_div);1414 isl_basic_set_free(bset);1415 if (n < 0)1416 return -1;1417 if (n != 0)1418 isl_die(ctx, isl_error_unknown, "not expecting any divs",1419 return -1);1420 1421 /* Check that isl_map_affine_hull is not confused by1422 * the reordering of divs in isl_map_align_divs.1423 */1424 str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: "1425 "32e0 = b and 32e1 = c); "1426 "[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }";1427 set = isl_set_read_from_str(ctx, str);1428 bset = isl_set_affine_hull(set);1429 isl_basic_set_free(bset);1430 if (!bset)1431 return -1;1432 1433 str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and "1434 "32e2 = 31 + 31e0 }";1435 set = isl_set_read_from_str(ctx, str);1436 bset = isl_set_affine_hull(set);1437 str = "{ [a] : exists e : a = 32 e }";1438 bset2 = isl_basic_set_read_from_str(ctx, str);1439 subset = isl_basic_set_is_subset(bset, bset2);1440 isl_basic_set_free(bset);1441 isl_basic_set_free(bset2);1442 if (subset < 0)1443 return -1;1444 if (!subset)1445 isl_die(ctx, isl_error_unknown, "not as accurate as expected",1446 return -1);1447 1448 return 0;1449}1450 1451/* Test a special case of isl_set_plain_unshifted_simple_hull1452 * where older versions of isl would include a redundant constraint1453 * in the result.1454 * Check that the result does not have any constraints.1455 */1456static isl_stat test_plain_unshifted_simple_hull_special(isl_ctx *ctx)1457{1458 const char *str;1459 isl_bool is_universe;1460 isl_set *set;1461 isl_basic_set *bset;1462 1463 str = "{[x, y] : x = 0 or 2*((x+y)//2) <= y + 2 }";1464 set = isl_set_read_from_str(ctx, str);1465 bset = isl_set_plain_unshifted_simple_hull(set);1466 is_universe = isl_basic_set_plain_is_universe(bset);1467 isl_basic_set_free(bset);1468 1469 if (is_universe < 0)1470 return isl_stat_error;1471 if (!is_universe)1472 isl_die(ctx, isl_error_unknown,1473 "hull should not have any constraints",1474 return isl_stat_error);1475 1476 return isl_stat_ok;1477}1478 1479/* Inputs for simple hull tests, consisting of1480 * the specific simple hull function, the input set and the expected result.1481 */1482struct {1483 __isl_give isl_basic_set *(*fn)(__isl_take isl_set *set);1484 const char *set;1485 const char *hull;1486} simple_hull_tests[] = {1487 { &isl_set_plain_unshifted_simple_hull,1488 "{ [i,j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",1489 "{ [i,j] : i >= 1 }" },1490 { &isl_set_plain_unshifted_simple_hull,1491 "{ [n,i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "1492 "(j mod 4 = 2 and k mod 6 = n) }",1493 "{ [n,i,j,k] : j mod 4 = 2 }" },1494 { &isl_set_unshifted_simple_hull,1495 "{ [0,x,y] : x <= -1; [1,x,y] : x <= y <= -x; [2,x,y] : x <= 1 }",1496 "{ [t,x,y] : 0 <= t <= 2 and x <= 1 }" },1497 { &isl_set_simple_hull,1498 "{ [a, b] : b <= 0 and "1499 "2*floor((-2*floor((b)/2))/5) >= a - floor((b)/2); "1500 "[a, b] : a mod 2 = 0 }",1501 "{ [a, b] }" },1502};1503 1504/* Basic tests for various simple hull functions.1505 */1506static int test_various_simple_hull(isl_ctx *ctx)1507{1508 int i;1509 isl_set *set;1510 isl_basic_set *hull, *expected;1511 isl_bool equal;1512 1513 for (i = 0; i < ARRAY_SIZE(simple_hull_tests); ++i) {1514 const char *str;1515 str = simple_hull_tests[i].set;1516 set = isl_set_read_from_str(ctx, str);1517 str = simple_hull_tests[i].hull;1518 expected = isl_basic_set_read_from_str(ctx, str);1519 hull = simple_hull_tests[i].fn(set);1520 equal = isl_basic_set_is_equal(hull, expected);1521 isl_basic_set_free(hull);1522 isl_basic_set_free(expected);1523 if (equal < 0)1524 return -1;1525 if (!equal)1526 isl_die(ctx, isl_error_unknown, "unexpected hull",1527 return -1);1528 }1529 1530 return 0;1531}1532 1533static int test_simple_hull(struct isl_ctx *ctx)1534{1535 const char *str;1536 isl_set *set;1537 isl_basic_set *bset;1538 isl_bool is_empty;1539 1540 str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"1541 "[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";1542 set = isl_set_read_from_str(ctx, str);1543 bset = isl_set_simple_hull(set);1544 is_empty = isl_basic_set_is_empty(bset);1545 isl_basic_set_free(bset);1546 1547 if (is_empty == isl_bool_error)1548 return -1;1549 1550 if (is_empty == isl_bool_false)1551 isl_die(ctx, isl_error_unknown, "Empty set should be detected",1552 return -1);1553 1554 if (test_plain_unshifted_simple_hull_special(ctx) < 0)1555 return -1;1556 if (test_various_simple_hull(ctx) < 0)1557 return -1;1558 1559 return 0;1560}1561 1562/* Inputs for isl_set_get_simple_fixed_box_hull tests.1563 * "set" is the input set.1564 * "offset" is the expected box offset.1565 * "size" is the expected box size.1566 */1567static struct {1568 const char *set;1569 const char *offset;1570 const char *size;1571} box_hull_tests[] = {1572 { "{ S[x, y] : 0 <= x, y < 10 }", "{ S[0, 0] }", "{ S[10, 10] }" },1573 { "[N] -> { S[x, y] : N <= x, y < N + 10 }",1574 "[N] -> { S[N, N] }", "{ S[10, 10] }" },1575 { "{ S[x, y] : 0 <= x + y, x - y < 10 }",1576 "{ S[0, -4] }", "{ S[10, 9] }" },1577 { "{ [i=0:10] : exists (e0, e1: 3e1 >= 1 + 2e0 and "1578 "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",1579 "{ [3] }", "{ [8] }" },1580 { "[N] -> { [w = 0:17] : exists (e0: w < 2N and "1581 "-1 + w <= e0 <= w and 2e0 >= N + w and w <= 2e0 <= 15 + w) }",1582 "[N] -> { [N] }", "{ [9] }" },1583};1584 1585/* Perform basic isl_set_get_simple_fixed_box_hull tests.1586 */1587static int test_box_hull(struct isl_ctx *ctx)1588{1589 int i;1590 1591 for (i = 0; i < ARRAY_SIZE(box_hull_tests); ++i) {1592 const char *str;1593 isl_stat r;1594 isl_set *set;1595 isl_multi_aff *offset;1596 isl_multi_val *size;1597 isl_fixed_box *box;1598 1599 set = isl_set_read_from_str(ctx, box_hull_tests[i].set);1600 box = isl_set_get_simple_fixed_box_hull(set);1601 offset = isl_fixed_box_get_offset(box);1602 size = isl_fixed_box_get_size(box);1603 str = box_hull_tests[i].offset;1604 r = multi_aff_check_plain_equal(offset, str);1605 str = box_hull_tests[i].size;1606 if (r >= 0)1607 r = multi_val_check_plain_equal(size, str);1608 isl_multi_aff_free(offset);1609 isl_multi_val_free(size);1610 isl_fixed_box_free(box);1611 isl_set_free(set);1612 if (r < 0)1613 return -1;1614 }1615 1616 return 0;1617}1618 1619void test_convex_hull_case(struct isl_ctx *ctx, const char *name)1620{1621 char *filename;1622 FILE *input;1623 struct isl_basic_set *bset1, *bset2;1624 struct isl_set *set;1625 1626 filename = get_filename(ctx, name, "polylib");1627 assert(filename);1628 input = fopen(filename, "r");1629 assert(input);1630 1631 bset1 = isl_basic_set_read_from_file(ctx, input);1632 bset2 = isl_basic_set_read_from_file(ctx, input);1633 1634 set = isl_basic_set_union(bset1, bset2);1635 bset1 = isl_set_convex_hull(set);1636 1637 bset2 = isl_basic_set_read_from_file(ctx, input);1638 1639 assert(isl_basic_set_is_equal(bset1, bset2) == 1);1640 1641 isl_basic_set_free(bset1);1642 isl_basic_set_free(bset2);1643 free(filename);1644 1645 fclose(input);1646}1647 1648struct {1649 const char *set;1650 const char *hull;1651} convex_hull_tests[] = {1652 { "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "1653 "(i0 = 1 and i1 = 0 and i2 = 1) or "1654 "(i0 = 0 and i1 = 0 and i2 = 0) }",1655 "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" },1656 { "[n] -> { [i0, i1, i0] : i0 <= -4 + n; "1657 "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and "1658 "i2 <= 5 and i2 >= 4; "1659 "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }",1660 "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and "1661 "i2 <= 5 + i0 and i2 >= i0 }" },1662 { "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }",1663 "{ [x, y] : 1 = 0 }" },1664 { "{ [x, y, z] : 0 <= x, y, z <= 10; [x, y, 0] : x >= 0 and y > 0; "1665 "[x, y, 0] : x >= 0 and y < 0 }",1666 "{ [x, y, z] : x >= 0 and 0 <= z <= 10 }" },1667 { "{ [a, b, c] : a <= 1 and -a < b <= 1 and 0 <= c <= 2 - a - b and "1668 "c <= a; "1669 "[0, 2, 0]; [3, 1, 0] }",1670 "{ [a, b, c] : b > -a and 2b >= -1 + a and 0 <= c <= a and "1671 "5c <= 6 - a - 3b }" },1672};1673 1674static int test_convex_hull_algo(isl_ctx *ctx, int convex)1675{1676 int i;1677 int orig_convex = ctx->opt->convex;1678 ctx->opt->convex = convex;1679 1680 test_convex_hull_case(ctx, "convex0");1681 test_convex_hull_case(ctx, "convex1");1682 test_convex_hull_case(ctx, "convex2");1683 test_convex_hull_case(ctx, "convex3");1684 test_convex_hull_case(ctx, "convex4");1685 test_convex_hull_case(ctx, "convex5");1686 test_convex_hull_case(ctx, "convex6");1687 test_convex_hull_case(ctx, "convex7");1688 test_convex_hull_case(ctx, "convex8");1689 test_convex_hull_case(ctx, "convex9");1690 test_convex_hull_case(ctx, "convex10");1691 test_convex_hull_case(ctx, "convex11");1692 test_convex_hull_case(ctx, "convex12");1693 test_convex_hull_case(ctx, "convex13");1694 test_convex_hull_case(ctx, "convex14");1695 test_convex_hull_case(ctx, "convex15");1696 1697 for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) {1698 isl_set *set1, *set2;1699 int equal;1700 1701 set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set);1702 set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull);1703 set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));1704 equal = isl_set_is_equal(set1, set2);1705 isl_set_free(set1);1706 isl_set_free(set2);1707 1708 if (equal < 0)1709 return -1;1710 if (!equal)1711 isl_die(ctx, isl_error_unknown,1712 "unexpected convex hull", return -1);1713 }1714 1715 ctx->opt->convex = orig_convex;1716 1717 return 0;1718}1719 1720static int test_convex_hull(isl_ctx *ctx)1721{1722 if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM) < 0)1723 return -1;1724 if (test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP) < 0)1725 return -1;1726 return 0;1727}1728 1729/* Check that computing the gist of "map" with respect to "context"1730 * does not make any copy of "map" get marked empty.1731 * Earlier versions of isl would end up doing that.1732 */1733static isl_stat test_gist_empty_pair(isl_ctx *ctx, const char *map,1734 const char *context)1735{1736 isl_map *m1, *m2, *m3;1737 isl_bool empty_before, empty_after;1738 1739 m1 = isl_map_read_from_str(ctx, map);1740 m2 = isl_map_read_from_str(ctx, context);1741 m3 = isl_map_copy(m1);1742 empty_before = isl_map_is_empty(m3);1743 m1 = isl_map_gist(m1, m2);1744 empty_after = isl_map_is_empty(m3);1745 isl_map_free(m1);1746 isl_map_free(m3);1747 1748 if (empty_before < 0 || empty_after < 0)1749 return isl_stat_error;1750 if (empty_before)1751 isl_die(ctx, isl_error_unknown, "map should not be empty",1752 return isl_stat_error);1753 if (empty_after)1754 isl_die(ctx, isl_error_unknown, "map should still not be empty",1755 return isl_stat_error);1756 1757 return isl_stat_ok;1758}1759 1760/* Check that computing a gist does not make any copy of the input1761 * get marked empty.1762 * Earlier versions of isl would end up doing that on some pairs of inputs.1763 */1764static isl_stat test_gist_empty(isl_ctx *ctx)1765{1766 const char *map, *context;1767 1768 map = "{ [] -> [a, b, c] : 2b = 1 + a }";1769 context = "{ [] -> [a, b, c] : 2c = 2 + a }";1770 if (test_gist_empty_pair(ctx, map, context) < 0)1771 return isl_stat_error;1772 map = "{ [] -> [0, 0] }";1773 context = "{ [] -> [a, b] : a > b }";1774 if (test_gist_empty_pair(ctx, map, context) < 0)1775 return isl_stat_error;1776 1777 return isl_stat_ok;1778}1779 1780/* Inputs to isl_map_plain_gist_basic_map, along with the expected output.1781 */1782struct {1783 const char *map;1784 const char *context;1785 const char *gist;1786} plain_gist_tests[] = {1787 { "{ [i] -> [j] : i >= 1 and j >= 1 or i >= 2 and j <= 10 }",1788 "{ [i] -> [j] : i >= 1 }",1789 "{ [i] -> [j] : j >= 1 or i >= 2 and j <= 10 }" },1790 { "{ [n] -> [i,j,k] : (i mod 3 = 2 and j mod 4 = 2) or "1791 "(j mod 4 = 2 and k mod 6 = n) }",1792 "{ [n] -> [i,j,k] : j mod 4 = 2 }",1793 "{ [n] -> [i,j,k] : (i mod 3 = 2) or (k mod 6 = n) }" },1794 { "{ [i] -> [j] : i > j and (exists a,b : i <= 2a + 5b <= 2) }",1795 "{ [i] -> [j] : i > j }",1796 "{ [i] -> [j] : exists a,b : i <= 2a + 5b <= 2 }" },1797};1798 1799/* Basic tests for isl_map_plain_gist_basic_map.1800 */1801static int test_plain_gist(isl_ctx *ctx)1802{1803 int i;1804 1805 for (i = 0; i < ARRAY_SIZE(plain_gist_tests); ++i) {1806 const char *str;1807 int equal;1808 isl_map *map, *gist;1809 isl_basic_map *context;1810 1811 map = isl_map_read_from_str(ctx, plain_gist_tests[i].map);1812 str = plain_gist_tests[i].context;1813 context = isl_basic_map_read_from_str(ctx, str);1814 map = isl_map_plain_gist_basic_map(map, context);1815 gist = isl_map_read_from_str(ctx, plain_gist_tests[i].gist);1816 equal = isl_map_is_equal(map, gist);1817 isl_map_free(map);1818 isl_map_free(gist);1819 if (equal < 0)1820 return -1;1821 if (!equal)1822 isl_die(ctx, isl_error_unknown,1823 "incorrect gist result", return -1);1824 }1825 1826 return 0;1827}1828 1829/* Inputs for isl_basic_set_gist tests that are expected to fail.1830 */1831struct {1832 const char *set;1833 const char *context;1834} gist_fail_tests[] = {1835 { "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "1836 "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }",1837 "{ [i] : i >= 0 }" },1838};1839 1840/* Check that isl_basic_set_gist fails (gracefully) when expected.1841 * In particular, the user should be able to recover from the failure.1842 */1843static isl_stat test_gist_fail(struct isl_ctx *ctx)1844{1845 int i, n;1846 int on_error;1847 1848 on_error = isl_options_get_on_error(ctx);1849 isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);1850 n = ARRAY_SIZE(gist_fail_tests);1851 for (i = 0; i < n; ++i) {1852 const char *str;1853 isl_basic_set *bset, *context;1854 1855 bset = isl_basic_set_read_from_str(ctx, gist_fail_tests[i].set);1856 str = gist_fail_tests[i].context;1857 context = isl_basic_set_read_from_str(ctx, str);1858 bset = isl_basic_set_gist(bset, context);1859 isl_basic_set_free(bset);1860 if (bset)1861 break;1862 }1863 isl_options_set_on_error(ctx, on_error);1864 if (i < n)1865 isl_die(ctx, isl_error_unknown,1866 "operation not expected to succeed",1867 return isl_stat_error);1868 1869 return isl_stat_ok;1870}1871 1872struct {1873 const char *set;1874 const char *context;1875 const char *gist;1876} gist_tests[] = {1877 { "{ [1, -1, 3] }",1878 "{ [1, b, 2 - b] : -1 <= b <= 2 }",1879 "{ [a, -1, c] }" },1880 { "{ [a, b, c] : a <= 15 and a >= 1 }",1881 "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and "1882 "c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }",1883 "{ [a, b, c] : a <= 15 }" },1884 { "{ : }", "{ : 1 = 0 }", "{ : }" },1885 { "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },1886 { "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",1887 "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },1888 { "{ [m, n, a, b] : a <= 2147 + n }",1889 "{ [m, n, a, b] : (m >= 1 and n >= 1 and a <= 2148 - m and "1890 "b <= 2148 - n and b >= 0 and b >= 2149 - n - a) or "1891 "(n >= 1 and a >= 0 and b <= 2148 - n - a and "1892 "b >= 0) }",1893 "{ [m, n, ku, kl] }" },1894 { "{ [a, a, b] : a >= 10 }",1895 "{ [a, b, c] : c >= a and c <= b and c >= 2 }",1896 "{ [a, a, b] : a >= 10 }" },1897 { "{ [i, j] : i >= 0 and i + j >= 0 }", "{ [i, j] : i <= 0 }",1898 "{ [0, j] : j >= 0 }" },1899 /* Check that no constraints on i6 are introduced in the gist */1900 { "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "1901 "20e0 <= 1530 - 4t1 - 5i4 and 20e0 >= 1511 - 4t1 - 5i4 and "1902 "5e0 <= 381 - t1 and i4 <= 1) }",1903 "[t1] -> { [i4, i6] : exists (e0 = floor((-t1 + i6)/5): "1904 "5e0 = -t1 + i6 and i6 <= 6 and i6 >= 3) }",1905 "[t1] -> { [i4, i6] : exists (e0 = floor((1530 - 4t1 - 5i4)/20): "1906 "i4 <= 1 and 5e0 <= 381 - t1 and 20e0 <= 1530 - 4t1 - 5i4 and "1907 "20e0 >= 1511 - 4t1 - 5i4) }" },1908 /* Check that no constraints on i6 are introduced in the gist */1909 { "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((1 + i4)/2), "1910 "e1 = floor((1530 - 4t1 - 5i4)/20), "1911 "e2 = floor((-4t1 - 5i4 + 10*floor((1 + i4)/2))/20), "1912 "e3 = floor((-1 + i4)/2): t2 = 0 and 2e3 = -1 + i4 and "1913 "20e2 >= -19 - 4t1 - 5i4 + 10e0 and 5e2 <= 1 - t1 and "1914 "2e0 <= 1 + i4 and 2e0 >= i4 and "1915 "20e1 <= 1530 - 4t1 - 5i4 and "1916 "20e1 >= 1511 - 4t1 - 5i4 and i4 <= 1 and "1917 "5e1 <= 381 - t1 and 20e2 <= -4t1 - 5i4 + 10e0) }",1918 "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((-17 + i4)/2), "1919 "e1 = floor((-t1 + i6)/5): 5e1 = -t1 + i6 and "1920 "2e0 <= -17 + i4 and 2e0 >= -18 + i4 and "1921 "10e0 <= -91 + 5i4 + 4i6 and "1922 "10e0 >= -105 + 5i4 + 4i6) }",1923 "[t1, t2] -> { [i4, i5, i6] : exists (e0 = floor((381 - t1)/5), "1924 "e1 = floor((-1 + i4)/2): t2 = 0 and 2e1 = -1 + i4 and "1925 "i4 <= 1 and 5e0 <= 381 - t1 and 20e0 >= 1511 - 4t1 - 5i4) }" },1926 { "{ [0, 0, q, p] : -5 <= q <= 5 and p >= 0 }",1927 "{ [a, b, q, p] : b >= 1 + a }",1928 "{ [a, b, q, p] : false }" },1929 { "[n] -> { [x] : x = n && x mod 32 = 0 }",1930 "[n] -> { [x] : x mod 32 = 0 }",1931 "[n] -> { [x = n] }" },1932 { "{ [x] : x mod 6 = 0 }", "{ [x] : x mod 3 = 0 }",1933 "{ [x] : x mod 2 = 0 }" },1934 { "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10000 = 0 }",1935 "{ [x] : x mod 128 = 0 }" },1936 { "{ [x] : x mod 3200 = 0 }", "{ [x] : x mod 10 = 0 }",1937 "{ [x] : x mod 3200 = 0 }" },1938 { "{ [a, b, c] : a mod 2 = 0 and a = c }",1939 "{ [a, b, c] : b mod 2 = 0 and b = c }",1940 "{ [a, b, c = a] }" },1941 { "{ [a, b, c] : a mod 6 = 0 and a = c }",1942 "{ [a, b, c] : b mod 2 = 0 and b = c }",1943 "{ [a, b, c = a] : a mod 3 = 0 }" },1944 { "{ [x] : 0 <= x <= 4 or 6 <= x <= 9 }",1945 "{ [x] : 1 <= x <= 3 or 7 <= x <= 8 }",1946 "{ [x] }" },1947 { "{ [x,y] : x < 0 and 0 <= y <= 4 or x >= -2 and -x <= y <= 10 + x }",1948 "{ [x,y] : 1 <= y <= 3 }",1949 "{ [x,y] }" },1950};1951 1952/* Check that isl_set_gist behaves as expected.1953 *1954 * For the test cases in gist_tests, besides checking that the result1955 * is as expected, also check that applying the gist operation does1956 * not modify the input set (an earlier version of isl would do that) and1957 * that the test case is consistent, i.e., that the gist has the same1958 * intersection with the context as the input set.1959 */1960static int test_gist(struct isl_ctx *ctx)1961{1962 int i;1963 const char *str;1964 isl_basic_set *bset1, *bset2;1965 isl_map *map1, *map2;1966 isl_bool equal;1967 isl_size n_div;1968 1969 for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {1970 isl_bool equal_input, equal_intersection;1971 isl_set *set1, *set2, *copy, *context;1972 1973 set1 = isl_set_read_from_str(ctx, gist_tests[i].set);1974 context = isl_set_read_from_str(ctx, gist_tests[i].context);1975 copy = isl_set_copy(set1);1976 set1 = isl_set_gist(set1, isl_set_copy(context));1977 set2 = isl_set_read_from_str(ctx, gist_tests[i].gist);1978 equal = isl_set_is_equal(set1, set2);1979 isl_set_free(set1);1980 set1 = isl_set_read_from_str(ctx, gist_tests[i].set);1981 equal_input = isl_set_is_equal(set1, copy);1982 isl_set_free(copy);1983 set1 = isl_set_intersect(set1, isl_set_copy(context));1984 set2 = isl_set_intersect(set2, context);1985 equal_intersection = isl_set_is_equal(set1, set2);1986 isl_set_free(set2);1987 isl_set_free(set1);1988 if (equal < 0 || equal_input < 0 || equal_intersection < 0)1989 return -1;1990 if (!equal)1991 isl_die(ctx, isl_error_unknown,1992 "incorrect gist result", return -1);1993 if (!equal_input)1994 isl_die(ctx, isl_error_unknown,1995 "gist modified input", return -1);1996 if (!equal_input)1997 isl_die(ctx, isl_error_unknown,1998 "inconsistent gist test case", return -1);1999 }2000 2001 if (test_gist_fail(ctx) < 0)2002 return -1;2003 2004 str = "[p0, p2, p3, p5, p6, p10] -> { [] : "2005 "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "2006 "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "2007 "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "2008 "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "2009 "16e0 >= 16 + 16p6 + 15p10 and p2 <= 15 and p3 >= 0 and "2010 "p3 <= 31 and p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "2011 "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "2012 "p10 <= 15 and p10 <= -1 + p0 - p6) }";2013 bset1 = isl_basic_set_read_from_str(ctx, str);2014 str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "2015 "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "2016 "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "2017 "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "2018 "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "2019 "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "2020 "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "2021 "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";2022 bset2 = isl_basic_set_read_from_str(ctx, str);2023 bset1 = isl_basic_set_gist(bset1, bset2);2024 assert(bset1 && bset1->n_div == 0);2025 isl_basic_set_free(bset1);2026 2027 /* Check that the integer divisions of the second disjunct2028 * do not spread to the first disjunct.2029 */2030 str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: "2031 "16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or "2032 "(exists (e0 = [(-1 + t1)/16], "2033 "e1 = [(-16 + t1 - 16e0)/4294967296]: "2034 "4294967296e1 = -16 + t1 - o0 - 16e0 and "2035 "16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and "2036 "o0 <= 4294967295 and t1 <= -1)) }";2037 map1 = isl_map_read_from_str(ctx, str);2038 str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }";2039 map2 = isl_map_read_from_str(ctx, str);2040 map1 = isl_map_gist(map1, map2);2041 if (!map1)2042 return -1;2043 if (map1->n != 1)2044 isl_die(ctx, isl_error_unknown, "expecting single disjunct",2045 isl_map_free(map1); return -1);2046 n_div = isl_basic_map_dim(map1->p[0], isl_dim_div);2047 isl_map_free(map1);2048 if (n_div < 0)2049 return -1;2050 if (n_div != 1)2051 isl_die(ctx, isl_error_unknown, "expecting single div",2052 return -1);2053 2054 if (test_gist_empty(ctx) < 0)2055 return -1;2056 if (test_plain_gist(ctx) < 0)2057 return -1;2058 2059 return 0;2060}2061 2062int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)2063{2064 isl_set *set, *set2;2065 int equal;2066 int one;2067 2068 set = isl_set_read_from_str(ctx, str);2069 set = isl_set_coalesce(set);2070 set2 = isl_set_read_from_str(ctx, str);2071 equal = isl_set_is_equal(set, set2);2072 one = set && set->n == 1;2073 isl_set_free(set);2074 isl_set_free(set2);2075 2076 if (equal < 0)2077 return -1;2078 if (!equal)2079 isl_die(ctx, isl_error_unknown,2080 "coalesced set not equal to input", return -1);2081 if (check_one && !one)2082 isl_die(ctx, isl_error_unknown,2083 "coalesced set should not be a union", return -1);2084 2085 return 0;2086}2087 2088/* Inputs for coalescing tests with unbounded wrapping.2089 * "str" is a string representation of the input set.2090 * "single_disjunct" is set if we expect the result to consist of2091 * a single disjunct.2092 */2093struct {2094 int single_disjunct;2095 const char *str;2096} coalesce_unbounded_tests[] = {2097 { 1, "{ [x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "2098 "-x - y + 1 >= 0 and -3 <= z <= 3;"2099 "[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "2100 "x-z + 20 >= 0 and x+z + 20 >= 0 and "2101 "-10 <= y <= 0}" },2102 { 1, "{ [x,y] : 0 <= x,y <= 10; [5,y]: 4 <= y <= 11 }" },2103 { 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" },2104 { 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" },2105 { 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" },2106 { 0, "{ [x, y, z] : 0 <= x,y,z <= 100 and 0 < z <= 2 + 2x + 2y; "2107 "[x, y, 0] : x,y <= 100 and y <= 9 + 11x and x <= 9 + 11y }" },2108 { 1, "{ [0:1, 0:1]; [0, 2:3] }" },2109 { 1, "{ [0:1, 0:1]; [0, 2:3]; [1, -2:-1] }" },2110 { 1, "{ [0:3, 0:1]; [1:2, 2:5] }" },2111 { 1, "{ [0:3, 0:1]; [0:2, 2:5] }" },2112 { 1, "{ [0:3, 0:1]; [1:3, 2:5] }" },2113 { 0, "{ [0:3, 0:1]; [1:4, 2:5] }" },2114 { 0, "{ [0:3, 0:1]; [1:5, 2:5] }" },2115};2116 2117/* Test the functionality of isl_set_coalesce with the bounded wrapping2118 * option turned off.2119 */2120int test_coalesce_unbounded_wrapping(isl_ctx *ctx)2121{2122 int i;2123 int r = 0;2124 int bounded;2125 2126 bounded = isl_options_get_coalesce_bounded_wrapping(ctx);2127 isl_options_set_coalesce_bounded_wrapping(ctx, 0);2128 2129 for (i = 0; i < ARRAY_SIZE(coalesce_unbounded_tests); ++i) {2130 const char *str = coalesce_unbounded_tests[i].str;2131 int check_one = coalesce_unbounded_tests[i].single_disjunct;2132 if (test_coalesce_set(ctx, str, check_one) >= 0)2133 continue;2134 r = -1;2135 break;2136 }2137 2138 isl_options_set_coalesce_bounded_wrapping(ctx, bounded);2139 2140 return r;2141}2142 2143/* Inputs for coalescing tests.2144 * "str" is a string representation of the input set.2145 * "single_disjunct" is set if we expect the result to consist of2146 * a single disjunct.2147 */2148struct {2149 int single_disjunct;2150 const char *str;2151} coalesce_tests[] = {2152 { 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "2153 "y >= x & x >= 2 & 5 >= y }" },2154 { 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "2155 "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },2156 { 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "2157 "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },2158 { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "2159 "y >= 0 & x >= 6 & x <= 10 & y <= x}" },2160 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "2161 "y >= 0 & x >= 7 & x <= 10 & y <= x}" },2162 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "2163 "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },2164 { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },2165 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },2166 { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },2167 { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },2168 { 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },2169 { 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },2170 { 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },2171 { 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "2172 "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "2173 "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "2174 "4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "2175 "o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "2176 "i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "2177 "4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "2178 "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"2179 "[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "2180 "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "2181 "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "2182 "4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "2183 "2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "2184 "2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "2185 "i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "2186 "4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "2187 "o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "2188 "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },2189 { 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "2190 "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "2191 "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "2192 "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },2193 { 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "2194 "[o0, o1, o2, o3, o4, o5, o6]] : "2195 "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "2196 "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "2197 "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "2198 "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "2199 "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "2200 "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "2201 "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "2202 "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "2203 "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "2204 "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "2205 "o6 >= i3 + i6 - o3 and M >= 0 and "2206 "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "2207 "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },2208 { 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "2209 "(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "2210 "(o0 = 0 and M >= 2 and N >= 3) or "2211 "(M = 0 and o0 = 0 and N >= 3) }" },2212 { 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "2213 "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "2214 "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "2215 "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },2216 { 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },2217 { 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },2218 { 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "2219 "(y = 3 and x = 1) }" },2220 { 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "2221 "i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "2222 "i1 <= M and i3 <= M and i4 <= M) or "2223 "(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "2224 "i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "2225 "i4 <= -1 + M) }" },2226 { 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "2227 "(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },2228 { 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },2229 { 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },2230 { 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },2231 { 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },2232 { 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },2233 { 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },2234 { 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },2235 { 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },2236 { 0, "{ [a, b] : exists e : 2e = a and "2237 "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },2238 { 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "2239 "j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "2240 "j >= 1 and j' <= i + j - i' and i >= 1; "2241 "[1, 1, 1, 1] }" },2242 { 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "2243 "[i,j] : exists a : j = 3a }" },2244 { 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "2245 "c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "2246 "a >= 3) or "2247 "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "2248 "b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },2249 { 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "2250 "c <= 6 + 8a and a >= 3; "2251 "[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "2252 "c <= 7 + 8a and a >= 3 and a <= 4 }" },2253 { 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "2254 "[x,0] : 3 <= x <= 4 }" },2255 { 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "2256 "[x,0] : 4 <= x <= 5 }" },2257 { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "2258 "[x,0] : 3 <= x <= 5 }" },2259 { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "2260 "[x,0] : 3 <= x <= 4 }" },2261 { 1, "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "2262 "i1 <= 0; "2263 "[i0, 0] : i0 >= 123 and i0 <= 124 }" },2264 { 1, "{ [0,0]; [1,1] }" },2265 { 1, "[n] -> { [k] : 16k <= -1 + n and k >= 1; [0] : n >= 2 }" },2266 { 1, "{ [k, ii, k - ii] : ii >= -6 + k and ii <= 6 and ii >= 1 and "2267 "ii <= k;"2268 "[k, 0, k] : k <= 6 and k >= 1 }" },2269 { 1, "{ [i,j] : i = 4 j and 0 <= i <= 100;"2270 "[i,j] : 1 <= i <= 100 and i >= 4j + 1 and i <= 4j + 2 }" },2271 { 1, "{ [x,y] : x % 2 = 0 and y % 2 = 0; [x,x] : x % 2 = 0 }" },2272 { 1, "[n] -> { [1] : n >= 0;"2273 "[x] : exists (e0 = floor((x)/2): x >= 2 and "2274 "2e0 >= -1 + x and 2e0 <= x and 2e0 <= n) }" },2275 { 1, "[n] -> { [x, y] : exists (e0 = floor((x)/2), e1 = floor((y)/3): "2276 "3e1 = y and x >= 2 and 2e0 >= -1 + x and "2277 "2e0 <= x and 2e0 <= n);"2278 "[1, y] : exists (e0 = floor((y)/3): 3e0 = y and "2279 "n >= 0) }" },2280 { 1, "[t1] -> { [i0] : (exists (e0 = floor((63t1)/64): "2281 "128e0 >= -134 + 127t1 and t1 >= 2 and "2282 "64e0 <= 63t1 and 64e0 >= -63 + 63t1)) or "2283 "t1 = 1 }" },2284 { 1, "{ [i, i] : exists (e0 = floor((1 + 2i)/3): 3e0 <= 2i and "2285 "3e0 >= -1 + 2i and i <= 9 and i >= 1);"2286 "[0, 0] }" },2287 { 1, "{ [t1] : exists (e0 = floor((-11 + t1)/2): 2e0 = -11 + t1 and "2288 "t1 >= 13 and t1 <= 16);"2289 "[t1] : t1 <= 15 and t1 >= 12 }" },2290 { 1, "{ [x,y] : x = 3y and 0 <= y <= 2; [-3,-1] }" },2291 { 1, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-2] }" },2292 { 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-2,-2] }" },2293 { 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-1] }" },2294 { 1, "{ [i] : exists j : i = 4 j and 0 <= i <= 100;"2295 "[i] : exists j : 1 <= i <= 100 and i >= 4j + 1 and "2296 "i <= 4j + 2 }" },2297 { 1, "{ [c0] : (exists (e0 : c0 - 1 <= 3e0 <= c0)) or "2298 "(exists (e0 : 3e0 = -2 + c0)) }" },2299 { 0, "[n, b0, t0] -> "2300 "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "2301 "(exists (e0 = floor((-32b0 + i4)/1048576), "2302 "e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "2303 "n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "2304 "32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 >= 8 + n and "2305 "3i4 <= -96 + 3t0 + i0 and 3i4 >= -95 - n + 3t0 + i0 and "2306 "i8 >= -157 + i0 - 4i4 and i8 >= 0 and "2307 "i8 <= -33 + i0 - 4i4 and 3i8 <= -91 + 4n - i0)) or "2308 "(exists (e0 = floor((-32b0 + i4)/1048576), "2309 "e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "2310 "n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "2311 "32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 <= 7 + n and "2312 "4i4 <= -3 + i0 and 3i4 <= -96 + 3t0 + i0 and "2313 "3i4 >= -95 - n + 3t0 + i0 and i8 >= -157 + i0 - 4i4 and "2314 "i8 >= 0 and i8 <= -4 + i0 - 3i4 and i8 <= -41 + i0));"2315 "[i0, i1, i2, i3, 0, i5, i6, i7, i8, i9, i10, i11, i12] : "2316 "(exists (e0 = floor((i8)/32): b0 = 0 and 32e0 = i8 and "2317 "n <= 2147483647 and t0 <= 31 and t0 >= 0 and i0 >= 11 and "2318 "i0 >= 96 - 3t0 and i0 <= 95 + n - 3t0 and i0 <= 7 + n and "2319 "i8 >= -40 + i0 and i8 <= -10 + i0)) }" },2320 { 0, "{ [i0, i1, i2] : "2321 "(exists (e0, e1 = floor((i0)/32), e2 = floor((i1)/32): "2322 "32e1 = i0 and 32e2 = i1 and i1 >= -31 + i0 and "2323 "i1 <= 31 + i0 and i2 >= -30 + i0 and i2 >= -30 + i1 and "2324 "32e0 >= -30 + i0 and 32e0 >= -30 + i1 and "2325 "32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "2326 "32e0 <= 31 + i0)) or "2327 "i0 >= 0 }" },2328 { 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },2329 { 1, "{ [a, a, b, c] : 32*floor((a)/32) = a and 2*floor((b)/2) = b and "2330 "2*floor((c)/2) = c and 0 <= a <= 192;"2331 "[224, 224, b, c] : 2*floor((b)/2) = b and 2*floor((c)/2) = c }"2332 },2333 { 1, "[n] -> { [a,b] : (exists e : 1 <= a <= 7e and 9e <= b <= n) or "2334 "(0 <= a <= b <= n) }" },2335 { 1, "{ [a, b] : 0 <= a <= 2 and b >= 0 and "2336 "((0 < b <= 13) or (2*floor((a + b)/2) >= -5 + a + 2b)) }" },2337 { 1, "{ [a] : (2 <= a <= 5) or (a mod 2 = 1 and 1 <= a <= 5) }" },2338 { 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "2339 "9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "2340 "(exists (e0 = floor((-16 + 2c)/9): a = 4 and "2341 "b = 3 and 9e0 <= -19 + 2c)) }" },2342 { 1, "{ [a, b, c] : (b = -1 + a and 0 < a <= 3 and "2343 "9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "2344 "(a = 4 and b = 3 and "2345 "9*floor((-16 + 2c)/9) <= -19 + 2c) }" },2346 { 0, "{ [a, b, c] : (b <= 2 and b <= -2 + a) or "2347 "(b = -1 + a and 0 < a <= 3 and "2348 "9*floor((-4a + 2c)/9) <= -3 - 4a + 2c) or "2349 "(exists (e0 = floor((-16 + 2c)/9): a = 4 and "2350 "b = 3 and 9e0 <= -19 + 2c)) }" },2351 { 1, "{ [y, x] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"2352 "[1, 0] }" },2353 { 1, "{ [x, y] : (x - y) mod 3 = 2 and 2 <= y <= 200 and 0 <= x <= 2;"2354 "[0, 1] }" },2355 { 1, "{ [1, y] : -1 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },2356 { 1, "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }" },2357 { 1, "{ [x, y] : 0 <= x <= 10 and x - 4*floor(x/4) <= 1 and y <= 0; "2358 "[x, y] : 0 <= x <= 10 and x - 4*floor(x/4) > 1 and y <= 0; "2359 "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) <= 1 and 0 < y; "2360 "[x, y] : 0 <= x <= 10 and x - 5*floor(x/5) > 1 and 0 < y }" },2361 { 1, "{ [x, 0] : 0 <= x <= 10 and x mod 2 = 0; "2362 "[x, 0] : 0 <= x <= 10 and x mod 2 = 1; "2363 "[x, y] : 0 <= x <= 10 and 1 <= y <= 10 }" },2364 { 1, "{ [a] : a <= 8 and "2365 "(a mod 10 = 7 or a mod 10 = 8 or a mod 10 = 9) }" },2366 { 1, "{ [x, y] : 2y = -x and x <= 0 or "2367 "x <= -1 and 2y <= -x - 1 and 2y >= x - 1 }" },2368 { 0, "{ [x, y] : 2y = -x and x <= 0 or "2369 "x <= -2 and 2y <= -x - 1 and 2y >= x - 1 }" },2370 { 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "2371 "(a < 0 and 3*floor((a)/3) < a) }" },2372 { 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "2373 "(a < -1 and 3*floor((a)/3) < a) }" },2374 { 1, "{ [a, b] : a <= 1024 and b >= 0 and "2375 "((-31 - a + b <= 32*floor((-1 - a)/32) <= -33 + b and "2376 "32*floor((-1 - a)/32) <= -16 + b + 16*floor((-1 - a)/16))"2377 "or (2 <= a <= 15 and b < a)) }" },2378 { 1, "{ [a] : a > 0 and ((16*floor((a)/16) < a and "2379 "32*floor((a)/32) < a) or a <= 15) }" },2380 { 1, "{ [a, b, c, d] : (-a + d) mod 64 = 0 and a <= 8 and b <= 1 and "2381 "10 - a <= c <= 3 and d >= 5 and 9 - 64b <= d <= 70;"2382 "[a, b = 1, c, d] : (-a + d) mod 64 = 0 and a <= 8 and c >= 4 and "2383 "10 - a <= c <= 5 and 5 <= d <= 73 - c }" },2384 { 1, "[n, m] -> { S_0[i] : (-n + i) mod 3 = 0 and m >= 3 + n and "2385 "i >= n and 3*floor((2 + n + 2m)/3) <= n + 3m - i; "2386 "S_0[n] : n <= m <= 2 + n }" },2387 { 1, "{ [a, b] : exists (e0: 0 <= a <= 1 and b >= 0 and "2388 "2e0 >= -5 + a + 2b and 2e0 >= -1 + a + b and "2389 "2e0 <= a + b); "2390 "[a, b] : exists (e0: 0 <= a <= 1 and 2e0 >= -5 + a + 2b and "2391 "2e0 >= -1 - a + b and 2e0 <= -a + b and "2392 "2e0 < -a + 2b) }" },2393 { 1, "{ [i, j, i - 8j] : 8 <= i <= 63 and -7 + i <= 8j <= i; "2394 "[i, 0, i] : 0 <= i <= 7 }" },2395 { 1, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [1, 1] }" },2396 { 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [0, 2] }" },2397 { 0, "{ [a, b] : a >= 0 and 0 <= b <= 1 - a; [-1, 3] }" },2398 { 1, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [1, 1] }" },2399 { 0, "{ [a, b] : a, b >= 0 and a + 2b <= 2; [2, 1] }" },2400 { 0, "{ [a, c] : (2 + a) mod 4 = 0 or "2401 "(c = 4 + a and 4 * floor((a)/4) = a and a >= 0 and a <= 4) or "2402 "(c = 3 + a and 4 * floor((-1 + a)/4) = -1 + a and "2403 "a > 0 and a <= 5) }" },2404 { 1, "{ [1, 0, 0]; [a, b, c] : -1 <= -a < b <= 0 and 2c > b }" },2405 { 0, "{ [j, a, l] : a mod 2 = 0 and j <= 29 and a >= 2 and "2406 "2a <= -5 + j and 32j + 2a + 2 <= 4l < 33j; "2407 "[j, 0, l] : 4 <= j <= 29 and -3 + 33j <= 4l <= 33j }" },2408 { 0, "{ [0:1, 0:1]; [0, 2:3] }" },2409 { 1, "{ [a] : (a = 0 or ((1 + a) mod 2 = 0 and 0 < a <= 15) or "2410 "((a) mod 2 = 0 and 0 < a <= 15)) }" },2411 { 1, "{ rat: [0:2]; rat: [1:3] }" },2412};2413 2414/* A specialized coalescing test case that would result2415 * in a segmentation fault or a failed assertion in earlier versions of isl.2416 */2417static int test_coalesce_special(struct isl_ctx *ctx)2418{2419 const char *str;2420 isl_map *map1, *map2;2421 2422 str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "2423 "[[S_L309_IN[] -> T11[]] -> ce_imag2[1, o1]] : "2424 "(y = 201 and o1 <= 239 and o1 >= 212) or "2425 "(exists (e0 = [(y)/3]: 3e0 = y and y <= 198 and y >= 3 and "2426 "o1 <= 239 and o1 >= 212)) or "2427 "(exists (e0 = [(y)/3]: 3e0 = y and y <= 201 and y >= 3 and "2428 "o1 <= 241 and o1 >= 240));"2429 "[S_L220_OUT[] -> T7[]] -> "2430 "[[S_L309_IN[] -> T11[]] -> ce_imag2[0, o1]] : "2431 "(y = 2 and o1 <= 241 and o1 >= 212) or "2432 "(exists (e0 = [(-2 + y)/3]: 3e0 = -2 + y and y <= 200 and "2433 "y >= 5 and o1 <= 241 and o1 >= 212)) }";2434 map1 = isl_map_read_from_str(ctx, str);2435 map1 = isl_map_align_divs_internal(map1);2436 map1 = isl_map_coalesce(map1);2437 str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "2438 "[[S_L309_IN[] -> T11[]] -> ce_imag2[o0, o1]] : "2439 "exists (e0 = [(-1 - y + o0)/3]: 3e0 = -1 - y + o0 and "2440 "y <= 201 and o0 <= 2 and o1 >= 212 and o1 <= 241 and "2441 "o0 >= 3 - y and o0 <= -2 + y and o0 >= 0) }";2442 map2 = isl_map_read_from_str(ctx, str);2443 map2 = isl_map_union(map2, map1);2444 map2 = isl_map_align_divs_internal(map2);2445 map2 = isl_map_coalesce(map2);2446 isl_map_free(map2);2447 if (!map2)2448 return -1;2449 2450 return 0;2451}2452 2453/* Check that the union of the basic sets described by "str1" and "str2"2454 * can be coalesced and that the result is equal to the union.2455 * The explicit call to isl_basic_set_union prevents the implicit2456 * equality constraints in the basic maps from being detected prior2457 * to the call to isl_set_coalesce, at least at the point2458 * where this function was introduced.2459 */2460static isl_stat test_coalesce_union(isl_ctx *ctx, const char *str1,2461 const char *str2)2462{2463 isl_basic_set *bset1, *bset2;2464 isl_set *set, *set2;2465 isl_bool equal;2466 2467 bset1 = isl_basic_set_read_from_str(ctx, str1);2468 bset2 = isl_basic_set_read_from_str(ctx, str2);2469 set = isl_basic_set_union(bset1, bset2);2470 set = isl_set_coalesce(set);2471 2472 bset1 = isl_basic_set_read_from_str(ctx, str1);2473 bset2 = isl_basic_set_read_from_str(ctx, str2);2474 set2 = isl_basic_set_union(bset1, bset2);2475 2476 equal = isl_set_is_equal(set, set2);2477 isl_set_free(set);2478 isl_set_free(set2);2479 2480 if (equal < 0)2481 return isl_stat_error;2482 if (!equal)2483 isl_die(ctx, isl_error_unknown,2484 "coalesced set not equal to input",2485 return isl_stat_error);2486 2487 return isl_stat_non_null(set);2488}2489 2490/* A specialized coalescing test case that would result in an assertion2491 * in an earlier version of isl. Use test_coalesce_union with2492 * an explicit call to isl_basic_set_union to prevent the implicit2493 * equality constraints in the first basic map from being detected prior2494 * to the call to isl_set_coalesce, at least at the point2495 * where this test case was introduced.2496 */2497static isl_stat test_coalesce_special2(struct isl_ctx *ctx)2498{2499 const char *str1;2500 const char *str2;2501 2502 str1 = "{ [x, y] : x, y >= 0 and x + 2y <= 1 and 2x + y <= 1 }";2503 str2 = "{ [x,0] : -1 <= x <= 1 and x mod 2 = 1 }";2504 return test_coalesce_union(ctx, str1, str2);2505}2506 2507/* Check that calling isl_set_coalesce does not leave other sets2508 * that may share some information with the input to isl_set_coalesce2509 * in an inconsistent state.2510 * In particular, older versions of isl would modify all copies2511 * of the basic sets in the isl_set_coalesce input in a way2512 * that could leave them in an inconsistent state.2513 * The result of printing any other set containing one of these2514 * basic sets would then result in an invalid set description.2515 */2516static int test_coalesce_special3(isl_ctx *ctx)2517{2518 const char *str;2519 char *s;2520 isl_set *set1, *set2;2521 isl_printer *p;2522 2523 set1 = isl_set_read_from_str(ctx, "{ [0, 0, 0] }");2524 str = "{ [a, b, a + b] : a >= 0 and b >= 0 and 0 < a + b }";2525 set2 = isl_set_read_from_str(ctx, str);2526 set1 = isl_set_union(set1, isl_set_copy(set2));2527 set1 = isl_set_coalesce(set1);2528 isl_set_free(set1);2529 2530 p = isl_printer_to_str(ctx);2531 p = isl_printer_print_set(p, set2);2532 isl_set_free(set2);2533 s = isl_printer_get_str(p);2534 isl_printer_free(p);2535 set1 = isl_set_read_from_str(ctx, s);2536 free(s);2537 isl_set_free(set1);2538 2539 if (!set1)2540 return -1;2541 2542 return 0;2543}2544 2545/* Check that calling isl_set_coalesce on the intersection of2546 * the sets described by "s1" and "s2" does not leave other sets2547 * that may share some information with the input to isl_set_coalesce2548 * in an inconsistent state.2549 * In particular, when isl_set_coalesce detects equality constraints,2550 * it does not immediately perform Gaussian elimination on them,2551 * but then it needs to ensure that it is performed at some point.2552 * The input set has implicit equality constraints in the first disjunct.2553 * It is constructed as an intersection, because otherwise2554 * those equality constraints would already be detected during parsing.2555 */2556static isl_stat test_coalesce_intersection(isl_ctx *ctx,2557 const char *s1, const char *s2)2558{2559 isl_set *set1, *set2;2560 2561 set1 = isl_set_read_from_str(ctx, s1);2562 set2 = isl_set_read_from_str(ctx, s2);2563 set1 = isl_set_intersect(set1, set2);2564 isl_set_free(isl_set_coalesce(isl_set_copy(set1)));2565 set1 = isl_set_coalesce(set1);2566 isl_set_free(set1);2567 2568 if (!set1)2569 return isl_stat_error;2570 2571 return isl_stat_ok;2572}2573 2574/* Check that calling isl_set_coalesce does not leave other sets2575 * that may share some information with the input to isl_set_coalesce2576 * in an inconsistent state, for the case where one disjunct2577 * is a subset of the other.2578 */2579static isl_stat test_coalesce_special4(isl_ctx *ctx)2580{2581 const char *s1, *s2;2582 2583 s1 = "{ [a, b] : b <= 0 or a <= 1 }";2584 s2 = "{ [a, b] : -1 <= -a < b }";2585 return test_coalesce_intersection(ctx, s1, s2);2586}2587 2588/* Check that calling isl_set_coalesce does not leave other sets2589 * that may share some information with the input to isl_set_coalesce2590 * in an inconsistent state, for the case where two disjuncts2591 * can be fused.2592 */2593static isl_stat test_coalesce_special5(isl_ctx *ctx)2594{2595 const char *s1, *s2;2596 2597 s1 = "{ [a, b, c] : b <= 0 }";2598 s2 = "{ [a, b, c] : -1 <= -a < b and (c >= 0 or c < 0) }";2599 return test_coalesce_intersection(ctx, s1, s2);2600}2601 2602/* Check that calling isl_set_coalesce does not leave other sets2603 * that may share some information with the input to isl_set_coalesce2604 * in an inconsistent state, for the case where two disjuncts2605 * can be fused and where both disjuncts have implicit equality constraints.2606 */2607static isl_stat test_coalesce_special6(isl_ctx *ctx)2608{2609 const char *s1, *s2;2610 2611 s1 = "{ [a, b, c] : c <= 0 }";2612 s2 = "{ [a, b, c] : 0 <= a <= b <= c or (0 <= b <= c and a > 0) }";2613 return test_coalesce_intersection(ctx, s1, s2);2614}2615 2616/* A specialized coalescing test case that would result in an assertion failure2617 * in an earlier version of isl. Use test_coalesce_union with2618 * an explicit call to isl_basic_set_union to prevent the implicit2619 * equality constraints in the basic maps from being detected prior2620 * to the call to isl_set_coalesce, at least at the point2621 * where this test case was introduced.2622 */2623static isl_stat test_coalesce_special7(isl_ctx *ctx)2624{2625 const char *str1;2626 const char *str2;2627 2628 str1 = "{ [a, b, c=0:17] : a <= 7 and 2b <= 11 - a and "2629 "c <= -7 + 2a and 2c >= - 3 + 3a - 2b }";2630 str2 = "{ [a, b, c] : c > -15a and c >= -7 + 2a and c < 0 and "2631 "3c <= -5 + 5a - 3b and 2b >= 11 - a }";2632 return test_coalesce_union(ctx, str1, str2);2633}2634 2635/* A specialized coalescing test case that would result in a disjunct2636 * getting dropped in an earlier version of isl. Use test_coalesce_union with2637 * an explicit call to isl_basic_set_union to prevent the implicit2638 * equality constraints in the basic maps from being detected prior2639 * to the call to isl_set_coalesce, at least at the point2640 * where this test case was introduced.2641 */2642static isl_stat test_coalesce_special8(isl_ctx *ctx)2643{2644 const char *str1;2645 const char *str2;2646 2647 str1 = "{ [a, b, c] : 2c <= -a and b >= -a and b <= 5 and "2648 "6c > -7a and 11c >= -5a - b and a <= 3 }";2649 str2 = "{ [a, b, c] : 6c > -7a and b >= -a and b <= 5 and "2650 "11c >= -5a - b and a >= 4 and 2b <= a and 2c <= -a }";2651 return test_coalesce_union(ctx, str1, str2);2652}2653 2654/* Test the functionality of isl_set_coalesce.2655 * That is, check that the output is always equal to the input2656 * and in some cases that the result consists of a single disjunct.2657 */2658static int test_coalesce(struct isl_ctx *ctx)2659{2660 int i;2661 2662 for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {2663 const char *str = coalesce_tests[i].str;2664 int check_one = coalesce_tests[i].single_disjunct;2665 if (test_coalesce_set(ctx, str, check_one) < 0)2666 return -1;2667 }2668 2669 if (test_coalesce_unbounded_wrapping(ctx) < 0)2670 return -1;2671 if (test_coalesce_special(ctx) < 0)2672 return -1;2673 if (test_coalesce_special2(ctx) < 0)2674 return -1;2675 if (test_coalesce_special3(ctx) < 0)2676 return -1;2677 if (test_coalesce_special4(ctx) < 0)2678 return -1;2679 if (test_coalesce_special5(ctx) < 0)2680 return -1;2681 if (test_coalesce_special6(ctx) < 0)2682 return -1;2683 if (test_coalesce_special7(ctx) < 0)2684 return -1;2685 if (test_coalesce_special8(ctx) < 0)2686 return -1;2687 2688 return 0;2689}2690 2691/* Construct a representation of the graph on the right of Figure 12692 * in "Computing the Transitive Closure of a Union of2693 * Affine Integer Tuple Relations".2694 */2695static __isl_give isl_map *cocoa_fig_1_right_graph(isl_ctx *ctx)2696{2697 isl_set *dom;2698 isl_map *up, *right;2699 2700 dom = isl_set_read_from_str(ctx,2701 "{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "2702 "2 x - 3 y + 3 >= 0 }");2703 right = isl_map_read_from_str(ctx,2704 "{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");2705 up = isl_map_read_from_str(ctx,2706 "{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");2707 right = isl_map_intersect_domain(right, isl_set_copy(dom));2708 right = isl_map_intersect_range(right, isl_set_copy(dom));2709 up = isl_map_intersect_domain(up, isl_set_copy(dom));2710 up = isl_map_intersect_range(up, dom);2711 return isl_map_union(up, right);2712}2713 2714/* Construct a representation of the power of the graph2715 * on the right of Figure 1 in "Computing the Transitive Closure of2716 * a Union of Affine Integer Tuple Relations".2717 */2718static __isl_give isl_map *cocoa_fig_1_right_power(isl_ctx *ctx)2719{2720 return isl_map_read_from_str(ctx,2721 "{ [1] -> [[0,0] -> [0,1]]; [2] -> [[0,0] -> [1,1]]; "2722 " [1] -> [[0,1] -> [1,1]]; [1] -> [[2,2] -> [3,2]]; "2723 " [2] -> [[2,2] -> [3,3]]; [1] -> [[3,2] -> [3,3]] }");2724}2725 2726/* Construct a representation of the transitive closure of the graph2727 * on the right of Figure 1 in "Computing the Transitive Closure of2728 * a Union of Affine Integer Tuple Relations".2729 */2730static __isl_give isl_map *cocoa_fig_1_right_tc(isl_ctx *ctx)2731{2732 return isl_set_unwrap(isl_map_range(cocoa_fig_1_right_power(ctx)));2733}2734 2735static int test_closure(isl_ctx *ctx)2736{2737 const char *str;2738 isl_map *map, *map2;2739 isl_bool exact, equal;2740 2741 /* COCOA example 1 */2742 map = isl_map_read_from_str(ctx,2743 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "2744 "1 <= i and i < n and 1 <= j and j < n or "2745 "i2 = i + 1 and j2 = j - 1 and "2746 "1 <= i and i < n and 2 <= j and j <= n }");2747 map = isl_map_power(map, &exact);2748 assert(exact);2749 isl_map_free(map);2750 2751 /* COCOA example 1 */2752 map = isl_map_read_from_str(ctx,2753 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "2754 "1 <= i and i < n and 1 <= j and j < n or "2755 "i2 = i + 1 and j2 = j - 1 and "2756 "1 <= i and i < n and 2 <= j and j <= n }");2757 map = isl_map_transitive_closure(map, &exact);2758 assert(exact);2759 map2 = isl_map_read_from_str(ctx,2760 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "2761 "1 <= i and i < n and 1 <= j and j <= n and "2762 "2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "2763 "i2 = i + k1 + k2 and j2 = j + k1 - k2 and "2764 "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");2765 assert(isl_map_is_equal(map, map2));2766 isl_map_free(map2);2767 isl_map_free(map);2768 2769 map = isl_map_read_from_str(ctx,2770 "[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "2771 " 0 <= y and y <= n }");2772 map = isl_map_transitive_closure(map, &exact);2773 map2 = isl_map_read_from_str(ctx,2774 "[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "2775 " 0 <= y and y <= n }");2776 assert(isl_map_is_equal(map, map2));2777 isl_map_free(map2);2778 isl_map_free(map);2779 2780 /* COCOA example 2 */2781 map = isl_map_read_from_str(ctx,2782 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "2783 "1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "2784 "i2 = i + 2 and j2 = j - 2 and "2785 "1 <= i and i < n - 1 and 3 <= j and j <= n }");2786 map = isl_map_transitive_closure(map, &exact);2787 assert(exact);2788 map2 = isl_map_read_from_str(ctx,2789 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "2790 "1 <= i and i < n - 1 and 1 <= j and j <= n and "2791 "3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "2792 "i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "2793 "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");2794 assert(isl_map_is_equal(map, map2));2795 isl_map_free(map);2796 isl_map_free(map2);2797 2798 /* COCOA Fig.2 left */2799 map = isl_map_read_from_str(ctx,2800 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "2801 "i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "2802 "j <= n or "2803 "i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "2804 "j <= 2 i - 3 and j <= n - 2 or "2805 "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "2806 "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");2807 map = isl_map_transitive_closure(map, &exact);2808 assert(exact);2809 isl_map_free(map);2810 2811 /* COCOA Fig.2 right */2812 map = isl_map_read_from_str(ctx,2813 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "2814 "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "2815 "j <= n or "2816 "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "2817 "j <= 2 i - 4 and j <= n - 3 or "2818 "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "2819 "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");2820 map = isl_map_power(map, &exact);2821 assert(exact);2822 isl_map_free(map);2823 2824 /* COCOA Fig.2 right */2825 map = isl_map_read_from_str(ctx,2826 "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "2827 "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "2828 "j <= n or "2829 "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "2830 "j <= 2 i - 4 and j <= n - 3 or "2831 "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "2832 "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");2833 map = isl_map_transitive_closure(map, &exact);2834 assert(exact);2835 map2 = isl_map_read_from_str(ctx,2836 "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "2837 "i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "2838 "j <= n and 3 + i + 2 j <= 3 n and "2839 "3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "2840 "i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "2841 "13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "2842 "j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "2843 "k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");2844 assert(isl_map_is_equal(map, map2));2845 isl_map_free(map2);2846 isl_map_free(map);2847 2848 map = cocoa_fig_1_right_graph(ctx);2849 map = isl_map_transitive_closure(map, &exact);2850 assert(exact);2851 map2 = cocoa_fig_1_right_tc(ctx);2852 assert(isl_map_is_equal(map, map2));2853 isl_map_free(map2);2854 isl_map_free(map);2855 2856 map = cocoa_fig_1_right_graph(ctx);2857 map = isl_map_power(map, &exact);2858 map2 = cocoa_fig_1_right_power(ctx);2859 equal = isl_map_is_equal(map, map2);2860 isl_map_free(map2);2861 isl_map_free(map);2862 if (equal < 0)2863 return -1;2864 if (!exact)2865 isl_die(ctx, isl_error_unknown, "power not exact", return -1);2866 if (!equal)2867 isl_die(ctx, isl_error_unknown, "unexpected power", return -1);2868 2869 /* COCOA Theorem 1 counter example */2870 map = isl_map_read_from_str(ctx,2871 "{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "2872 "i2 = 1 and j2 = j or "2873 "i = 0 and j = 0 and i2 = 0 and j2 = 1 }");2874 map = isl_map_transitive_closure(map, &exact);2875 assert(exact);2876 isl_map_free(map);2877 2878 map = isl_map_read_from_str(ctx,2879 "[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "2880 "1 <= i,i2 <= n and 1 <= j,j2 <= m or "2881 "i2 = i + 1 and 3 <= j2 - j <= 4 and "2882 "1 <= i,i2 <= n and 1 <= j,j2 <= m }");2883 map = isl_map_transitive_closure(map, &exact);2884 assert(exact);2885 isl_map_free(map);2886 2887 /* Kelly et al 1996, fig 12 */2888 map = isl_map_read_from_str(ctx,2889 "[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "2890 "1 <= i,j,j+1 <= n or "2891 "j = n and j2 = 1 and i2 = i + 1 and "2892 "1 <= i,i+1 <= n }");2893 map = isl_map_transitive_closure(map, &exact);2894 assert(exact);2895 map2 = isl_map_read_from_str(ctx,2896 "[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "2897 "1 <= i <= n and i = i2 or "2898 "1 <= i < i2 <= n and 1 <= j <= n and "2899 "1 <= j2 <= n }");2900 assert(isl_map_is_equal(map, map2));2901 isl_map_free(map2);2902 isl_map_free(map);2903 2904 /* Omega's closure4 */2905 map = isl_map_read_from_str(ctx,2906 "[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "2907 "1 <= x,y <= 10 or "2908 "x2 = x + 1 and y2 = y and "2909 "1 <= x <= 20 && 5 <= y <= 15 }");2910 map = isl_map_transitive_closure(map, &exact);2911 assert(exact);2912 isl_map_free(map);2913 2914 map = isl_map_read_from_str(ctx,2915 "[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");2916 map = isl_map_transitive_closure(map, &exact);2917 assert(!exact);2918 map2 = isl_map_read_from_str(ctx,2919 "[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");2920 assert(isl_map_is_equal(map, map2));2921 isl_map_free(map);2922 isl_map_free(map2);2923 2924 str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "2925 "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "2926 "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "2927 "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";2928 map = isl_map_read_from_str(ctx, str);2929 map = isl_map_transitive_closure(map, &exact);2930 assert(exact);2931 map2 = isl_map_read_from_str(ctx, str);2932 assert(isl_map_is_equal(map, map2));2933 isl_map_free(map);2934 isl_map_free(map2);2935 2936 str = "{[0] -> [1]; [2] -> [3]}";2937 map = isl_map_read_from_str(ctx, str);2938 map = isl_map_transitive_closure(map, &exact);2939 assert(exact);2940 map2 = isl_map_read_from_str(ctx, str);2941 assert(isl_map_is_equal(map, map2));2942 isl_map_free(map);2943 isl_map_free(map2);2944 2945 str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "2946 "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "2947 "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "2948 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "2949 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "2950 "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "2951 "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "2952 "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "2953 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "2954 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "2955 "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "2956 "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "2957 "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "2958 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "2959 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "2960 "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "2961 "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "2962 "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "2963 "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "2964 "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";2965 map = isl_map_read_from_str(ctx, str);2966 map = isl_map_transitive_closure(map, NULL);2967 assert(map);2968 isl_map_free(map);2969 2970 return 0;2971}2972 2973/* Check that the actual result of a boolean operation is equal2974 * to the expected result.2975 */2976static isl_stat check_bool(isl_ctx *ctx, isl_bool actual, isl_bool expected)2977{2978 if (actual != expected)2979 isl_die(ctx, isl_error_unknown,2980 "incorrect boolean operation", return isl_stat_error);2981 return isl_stat_ok;2982}2983 2984/* Test operations on isl_bool values.2985 *2986 * This tests:2987 *2988 * isl_bool_not2989 * isl_bool_ok2990 */2991static int test_isl_bool(isl_ctx *ctx)2992{2993 if (check_bool(ctx, isl_bool_not(isl_bool_true), isl_bool_false) < 0)2994 return -1;2995 if (check_bool(ctx, isl_bool_not(isl_bool_false), isl_bool_true) < 0)2996 return -1;2997 if (check_bool(ctx, isl_bool_not(isl_bool_error), isl_bool_error) < 0)2998 return -1;2999 if (check_bool(ctx, isl_bool_ok(0), isl_bool_false) < 0)3000 return -1;3001 if (check_bool(ctx, isl_bool_ok(1), isl_bool_true) < 0)3002 return -1;3003 if (check_bool(ctx, isl_bool_ok(-1), isl_bool_true) < 0)3004 return -1;3005 if (check_bool(ctx, isl_bool_ok(2), isl_bool_true) < 0)3006 return -1;3007 if (check_bool(ctx, isl_bool_ok(-2), isl_bool_true) < 0)3008 return -1;3009 3010 return 0;3011}3012 3013static int test_lex(struct isl_ctx *ctx)3014{3015 isl_space *space;3016 isl_map *map;3017 int empty;3018 3019 space = isl_space_set_alloc(ctx, 0, 0);3020 map = isl_map_lex_le(space);3021 empty = isl_map_is_empty(map);3022 isl_map_free(map);3023 3024 if (empty < 0)3025 return -1;3026 if (empty)3027 isl_die(ctx, isl_error_unknown,3028 "expecting non-empty result", return -1);3029 3030 return 0;3031}3032 3033/* Inputs for isl_map_lexmin tests.3034 * "map" is the input and "lexmin" is the expected result.3035 */3036struct {3037 const char *map;3038 const char *lexmin;3039} lexmin_tests [] = {3040 { "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }",3041 "{ [x] -> [5] : 6 <= x <= 8; "3042 "[x] -> [x] : x <= 5 or (9 <= x <= 10) }" },3043 { "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }",3044 "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }" },3045 { "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }",3046 "{ [x] -> [y] : (4y = x and x >= 0) or "3047 "(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "3048 "4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "3049 "(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }" },3050 { "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }",3051 "{ T[a] -> S[b, c] : 2b = a and 2c = a }" },3052 /* Check that empty pieces are properly combined. */3053 { "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "3054 "2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "3055 "b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }",3056 "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "3057 "x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "3058 "x >= 4 }" },3059 { "{ [i, k, j] -> [a, b, c, d] : 8*floor((b)/8) = b and k <= 255 and "3060 "a <= 255 and c <= 255 and d <= 255 - j and "3061 "255 - j <= 7d <= 7 - i and 240d <= 239 + a and "3062 "247d <= 247 + k - j and 247d <= 247 + k - b and "3063 "247d <= 247 + i and 248 - b <= 248d <= c and "3064 "254d >= i - a + b and 254d >= -a + b and "3065 "255d >= -i + a - b and 1792d >= -63736 + 257b }",3066 "{ [i, k, j] -> "3067 "[-127762 + i + 502j, -62992 + 248j, 63240 - 248j, 255 - j] : "3068 "k <= 255 and 7j >= 1778 + i and 246j >= 62738 - k and "3069 "247j >= 62738 - i and 509j <= 129795 + i and "3070 "742j >= 188724 - i; "3071 "[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" },3072 { "{ [a] -> [b] : 0 <= b <= 255 and -509 + a <= 512b < a and "3073 "16*floor((8 + b)/16) <= 7 + b; "3074 "[a] -> [1] }",3075 "{ [a] -> [b = 1] : a >= 510 or a <= 0; "3076 "[a] -> [b = 0] : 0 < a <= 509 }" },3077 { "{ rat: [i] : 1 <= 2i <= 9 }", "{ rat: [i] : 2i = 1 }" },3078 { "{ rat: [i] : 1 <= 2i <= 9 or i >= 10 }", "{ rat: [i] : 2i = 1 }" },3079 { "{ rat: [i] : 21 <= 2i <= 29 or i = 5 }", "{ rat: [5] }" },3080};3081 3082static int test_lexmin(struct isl_ctx *ctx)3083{3084 int i;3085 int equal;3086 const char *str;3087 isl_basic_map *bmap;3088 isl_map *map, *map2;3089 isl_set *set;3090 isl_set *set2;3091 isl_pw_multi_aff *pma;3092 3093 str = "[p0, p1] -> { [] -> [] : "3094 "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "3095 "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "3096 "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "3097 "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "3098 "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "3099 "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "3100 "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "3101 "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "3102 "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "3103 "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "3104 "e2 <= e1 and e3 >= 1 and e4 <= e2) }";3105 map = isl_map_read_from_str(ctx, str);3106 map = isl_map_lexmin(map);3107 isl_map_free(map);3108 if (!map)3109 return -1;3110 3111 str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "3112 "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";3113 set = isl_set_read_from_str(ctx, str);3114 set = isl_set_lexmax(set);3115 str = "[C] -> { [obj,a,b,c] : C = 8 }";3116 set2 = isl_set_read_from_str(ctx, str);3117 set = isl_set_intersect(set, set2);3118 assert(!isl_set_is_empty(set));3119 isl_set_free(set);3120 3121 for (i = 0; i < ARRAY_SIZE(lexmin_tests); ++i) {3122 map = isl_map_read_from_str(ctx, lexmin_tests[i].map);3123 map = isl_map_lexmin(map);3124 map2 = isl_map_read_from_str(ctx, lexmin_tests[i].lexmin);3125 equal = isl_map_is_equal(map, map2);3126 isl_map_free(map);3127 isl_map_free(map2);3128 3129 if (equal < 0)3130 return -1;3131 if (!equal)3132 isl_die(ctx, isl_error_unknown,3133 "unexpected result", return -1);3134 }3135 3136 str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "3137 " 8i' <= i and 8i' >= -7 + i }";3138 bmap = isl_basic_map_read_from_str(ctx, str);3139 pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));3140 map2 = isl_map_from_pw_multi_aff(pma);3141 map = isl_map_from_basic_map(bmap);3142 assert(isl_map_is_equal(map, map2));3143 isl_map_free(map);3144 isl_map_free(map2);3145 3146 str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "3147 " 8i' <= i and 8i' >= -7 + i }";3148 set = isl_set_read_from_str(ctx, str);3149 pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));3150 set2 = isl_set_from_pw_multi_aff(pma);3151 equal = isl_set_is_equal(set, set2);3152 isl_set_free(set);3153 isl_set_free(set2);3154 if (equal < 0)3155 return -1;3156 if (!equal)3157 isl_die(ctx, isl_error_unknown,3158 "unexpected difference between set and "3159 "piecewise affine expression", return -1);3160 3161 return 0;3162}3163 3164/* Inputs for isl_pw_multi_aff_max_multi_val tests.3165 * "pma" is the input.3166 * "res" is the expected result.3167 */3168static struct {3169 const char *pma;3170 const char *res;3171} opt_pw_tests[] = {3172 { "{ [-1] -> [-1]; [1] -> [1] }", "{ [1] }" },3173 { "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] : "3174 "0 <= a, b <= 100 and b mod 2 = 0}", "{ [30] }" },3175 { "[N] -> { [i,j] -> A[i, -i, i + j] : 0 <= i,j <= N <= 10 }",3176 "{ A[10, 0, 20] }" },3177 { "[N] -> {A[N, -N, 2N] : 0 <= N }", "{ A[infty, 0, infty] }" },3178};3179 3180/* Perform basic isl_pw_multi_aff_max_multi_val tests.3181 */3182static isl_stat test_pw_max(struct isl_ctx *ctx)3183{3184 int i;3185 isl_pw_multi_aff *pma;3186 isl_multi_val *mv;3187 isl_stat r;3188 3189 for (i = 0; i < ARRAY_SIZE(opt_pw_tests); ++i) {3190 pma = isl_pw_multi_aff_read_from_str(ctx, opt_pw_tests[i].pma);3191 mv = isl_pw_multi_aff_max_multi_val(pma);3192 r = multi_val_check_plain_equal(mv, opt_pw_tests[i].res);3193 isl_multi_val_free(mv);3194 3195 if (r < 0)3196 return isl_stat_error;3197 }3198 3199 return isl_stat_ok;3200}3201 3202/* A specialized isl_set_min_val test case that would return the wrong result3203 * in earlier versions of isl.3204 * The explicit call to isl_basic_set_union prevents the second basic set3205 * from being determined to be empty prior to the call to isl_set_min_val,3206 * at least at the point where this test case was introduced.3207 */3208static int test_min_special(isl_ctx *ctx)3209{3210 const char *str;3211 isl_basic_set *bset1, *bset2;3212 isl_set *set;3213 isl_aff *obj;3214 isl_val *res;3215 int ok;3216 3217 str = "{ [a, b] : a >= 2 and b >= 0 and 14 - a <= b <= 9 }";3218 bset1 = isl_basic_set_read_from_str(ctx, str);3219 str = "{ [a, b] : 1 <= a, b and a + b <= 1 }";3220 bset2 = isl_basic_set_read_from_str(ctx, str);3221 set = isl_basic_set_union(bset1, bset2);3222 obj = isl_aff_read_from_str(ctx, "{ [a, b] -> [a] }");3223 3224 res = isl_set_min_val(set, obj);3225 ok = isl_val_cmp_si(res, 5) == 0;3226 3227 isl_aff_free(obj);3228 isl_set_free(set);3229 isl_val_free(res);3230 3231 if (!res)3232 return -1;3233 if (!ok)3234 isl_die(ctx, isl_error_unknown, "unexpected minimum",3235 return -1);3236 3237 return 0;3238}3239 3240/* A specialized isl_set_min_val test case that would return an error3241 * in earlier versions of isl.3242 */3243static int test_min_special2(isl_ctx *ctx)3244{3245 const char *str;3246 isl_basic_set *bset;3247 isl_aff *obj;3248 isl_val *res;3249 3250 str = "{ [i, j, k] : 2j = i and 2k = i + 1 and i >= 2 }";3251 bset = isl_basic_set_read_from_str(ctx, str);3252 3253 obj = isl_aff_read_from_str(ctx, "{ [i, j, k] -> [i] }");3254 3255 res = isl_basic_set_max_val(bset, obj);3256 3257 isl_basic_set_free(bset);3258 isl_aff_free(obj);3259 isl_val_free(res);3260 3261 if (!res)3262 return -1;3263 3264 return 0;3265}3266 3267/* Check that the result of isl_set_min_multi_pw_aff3268 * on the union of the sets with string descriptions "s1" and "s2"3269 * consists of a single expression (on a single cell).3270 */3271static isl_stat check_single_expr_min(isl_ctx *ctx, const char *s1,3272 const char *s2)3273{3274 isl_size n;3275 isl_set *set1, *set2;3276 isl_multi_pw_aff *mpa;3277 isl_pw_multi_aff *pma;3278 3279 set1 = isl_set_read_from_str(ctx, s1);3280 set2 = isl_set_read_from_str(ctx, s2);3281 set1 = isl_set_union(set1, set2);3282 mpa = isl_set_min_multi_pw_aff(set1);3283 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);3284 n = isl_pw_multi_aff_n_piece(pma);3285 isl_pw_multi_aff_free(pma);3286 3287 if (n < 0)3288 return isl_stat_error;3289 if (n != 1)3290 isl_die(ctx, isl_error_unknown, "expecting single expression",3291 return isl_stat_error);3292 return isl_stat_ok;3293}3294 3295/* A specialized isl_set_min_multi_pw_aff test that checks3296 * that the minimum of 2N and 3N for N >= 0 is represented3297 * by a single expression, without splitting off the special case N = 0.3298 * Do this for both orderings.3299 */3300static int test_min_mpa(isl_ctx *ctx)3301{3302 const char *s1, *s2;3303 3304 s1 = "[N=0:] -> { [1, 3N:] }";3305 s2 = "[N=0:] -> { [10, 2N:] }";3306 if (check_single_expr_min(ctx, s1, s2) < 0)3307 return -1;3308 if (check_single_expr_min(ctx, s2, s1) < 0)3309 return -1;3310 3311 return 0;3312}3313 3314struct {3315 const char *set;3316 const char *obj;3317 __isl_give isl_val *(*fn)(__isl_keep isl_set *set,3318 __isl_keep isl_aff *obj);3319 const char *res;3320} opt_tests[] = {3321 { "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_min_val, "-1" },3322 { "{ [-1]; [1] }", "{ [x] -> [x] }", &isl_set_max_val, "1" },3323 { "{ [a, b] : 0 <= a, b <= 100 and b mod 2 = 0}",3324 "{ [a, b] -> [floor((b - 2*floor((-a)/4))/5)] }",3325 &isl_set_max_val, "30" },3326 3327};3328 3329/* Perform basic isl_set_min_val and isl_set_max_val tests.3330 * In particular, check the results on non-convex inputs.3331 */3332static int test_min(struct isl_ctx *ctx)3333{3334 int i;3335 isl_set *set;3336 isl_aff *obj;3337 isl_val *val, *res;3338 isl_bool ok;3339 3340 for (i = 0; i < ARRAY_SIZE(opt_tests); ++i) {3341 set = isl_set_read_from_str(ctx, opt_tests[i].set);3342 obj = isl_aff_read_from_str(ctx, opt_tests[i].obj);3343 res = isl_val_read_from_str(ctx, opt_tests[i].res);3344 val = opt_tests[i].fn(set, obj);3345 ok = isl_val_eq(res, val);3346 isl_val_free(res);3347 isl_val_free(val);3348 isl_aff_free(obj);3349 isl_set_free(set);3350 3351 if (ok < 0)3352 return -1;3353 if (!ok)3354 isl_die(ctx, isl_error_unknown,3355 "unexpected optimum", return -1);3356 }3357 3358 if (test_pw_max(ctx) < 0)3359 return -1;3360 if (test_min_special(ctx) < 0)3361 return -1;3362 if (test_min_special2(ctx) < 0)3363 return -1;3364 3365 return 0;3366}3367 3368struct must_may {3369 isl_map *must;3370 isl_map *may;3371};3372 3373static isl_stat collect_must_may(__isl_take isl_map *dep, int must,3374 void *dep_user, void *user)3375{3376 struct must_may *mm = (struct must_may *)user;3377 3378 if (must)3379 mm->must = isl_map_union(mm->must, dep);3380 else3381 mm->may = isl_map_union(mm->may, dep);3382 3383 return isl_stat_ok;3384}3385 3386static int common_space(void *first, void *second)3387{3388 int depth = *(int *)first;3389 return 2 * depth;3390}3391 3392static int map_is_equal(__isl_keep isl_map *map, const char *str)3393{3394 isl_map *map2;3395 int equal;3396 3397 if (!map)3398 return -1;3399 3400 map2 = isl_map_read_from_str(map->ctx, str);3401 equal = isl_map_is_equal(map, map2);3402 isl_map_free(map2);3403 3404 return equal;3405}3406 3407static int map_check_equal(__isl_keep isl_map *map, const char *str)3408{3409 int equal;3410 3411 equal = map_is_equal(map, str);3412 if (equal < 0)3413 return -1;3414 if (!equal)3415 isl_die(isl_map_get_ctx(map), isl_error_unknown,3416 "result not as expected", return -1);3417 return 0;3418}3419 3420/* Is "set" equal to the set described by "str"?3421 */3422static isl_bool set_is_equal(__isl_keep isl_set *set, const char *str)3423{3424 isl_set *set2;3425 isl_bool equal;3426 3427 if (!set)3428 return isl_bool_error;3429 3430 set2 = isl_set_read_from_str(isl_set_get_ctx(set), str);3431 equal = isl_set_is_equal(set, set2);3432 isl_set_free(set2);3433 3434 return equal;3435}3436 3437/* Check that "set" is equal to the set described by "str".3438 */3439static isl_stat set_check_equal(__isl_keep isl_set *set, const char *str)3440{3441 isl_bool equal;3442 3443 equal = set_is_equal(set, str);3444 if (equal < 0)3445 return isl_stat_error;3446 if (!equal)3447 isl_die(isl_set_get_ctx(set), isl_error_unknown,3448 "result not as expected", return isl_stat_error);3449 return isl_stat_ok;3450}3451 3452/* Is "uset" equal to the union set described by "str"?3453 */3454static isl_bool uset_is_equal(__isl_keep isl_union_set *uset, const char *str)3455{3456 isl_union_set *uset2;3457 isl_bool equal;3458 3459 if (!uset)3460 return isl_bool_error;3461 3462 uset2 = isl_union_set_read_from_str(isl_union_set_get_ctx(uset), str);3463 equal = isl_union_set_is_equal(uset, uset2);3464 isl_union_set_free(uset2);3465 3466 return equal;3467}3468 3469/* Check that "uset" is equal to the union set described by "str".3470 */3471static isl_stat uset_check_equal(__isl_keep isl_union_set *uset,3472 const char *str)3473{3474 isl_bool equal;3475 3476 equal = uset_is_equal(uset, str);3477 if (equal < 0)3478 return isl_stat_error;3479 if (!equal)3480 isl_die(isl_union_set_get_ctx(uset), isl_error_unknown,3481 "result not as expected", return isl_stat_error);3482 return isl_stat_ok;3483}3484 3485static int test_dep(struct isl_ctx *ctx)3486{3487 const char *str;3488 isl_space *space;3489 isl_map *map;3490 isl_access_info *ai;3491 isl_flow *flow;3492 int depth;3493 struct must_may mm;3494 3495 depth = 3;3496 3497 str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";3498 map = isl_map_read_from_str(ctx, str);3499 ai = isl_access_info_alloc(map, &depth, &common_space, 2);3500 3501 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3502 map = isl_map_read_from_str(ctx, str);3503 ai = isl_access_info_add_source(ai, map, 1, &depth);3504 3505 str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";3506 map = isl_map_read_from_str(ctx, str);3507 ai = isl_access_info_add_source(ai, map, 1, &depth);3508 3509 flow = isl_access_info_compute_flow(ai);3510 space = isl_space_alloc(ctx, 0, 3, 3);3511 mm.must = isl_map_empty(isl_space_copy(space));3512 mm.may = isl_map_empty(space);3513 3514 isl_flow_foreach(flow, collect_must_may, &mm);3515 3516 str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "3517 " [1,10,0] -> [2,5,0] }";3518 assert(map_is_equal(mm.must, str));3519 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";3520 assert(map_is_equal(mm.may, str));3521 3522 isl_map_free(mm.must);3523 isl_map_free(mm.may);3524 isl_flow_free(flow);3525 3526 3527 str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";3528 map = isl_map_read_from_str(ctx, str);3529 ai = isl_access_info_alloc(map, &depth, &common_space, 2);3530 3531 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3532 map = isl_map_read_from_str(ctx, str);3533 ai = isl_access_info_add_source(ai, map, 1, &depth);3534 3535 str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";3536 map = isl_map_read_from_str(ctx, str);3537 ai = isl_access_info_add_source(ai, map, 0, &depth);3538 3539 flow = isl_access_info_compute_flow(ai);3540 space = isl_space_alloc(ctx, 0, 3, 3);3541 mm.must = isl_map_empty(isl_space_copy(space));3542 mm.may = isl_map_empty(space);3543 3544 isl_flow_foreach(flow, collect_must_may, &mm);3545 3546 str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";3547 assert(map_is_equal(mm.must, str));3548 str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";3549 assert(map_is_equal(mm.may, str));3550 3551 isl_map_free(mm.must);3552 isl_map_free(mm.may);3553 isl_flow_free(flow);3554 3555 3556 str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";3557 map = isl_map_read_from_str(ctx, str);3558 ai = isl_access_info_alloc(map, &depth, &common_space, 2);3559 3560 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3561 map = isl_map_read_from_str(ctx, str);3562 ai = isl_access_info_add_source(ai, map, 0, &depth);3563 3564 str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";3565 map = isl_map_read_from_str(ctx, str);3566 ai = isl_access_info_add_source(ai, map, 0, &depth);3567 3568 flow = isl_access_info_compute_flow(ai);3569 space = isl_space_alloc(ctx, 0, 3, 3);3570 mm.must = isl_map_empty(isl_space_copy(space));3571 mm.may = isl_map_empty(space);3572 3573 isl_flow_foreach(flow, collect_must_may, &mm);3574 3575 str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "3576 " [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";3577 assert(map_is_equal(mm.may, str));3578 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";3579 assert(map_is_equal(mm.must, str));3580 3581 isl_map_free(mm.must);3582 isl_map_free(mm.may);3583 isl_flow_free(flow);3584 3585 3586 str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";3587 map = isl_map_read_from_str(ctx, str);3588 ai = isl_access_info_alloc(map, &depth, &common_space, 2);3589 3590 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3591 map = isl_map_read_from_str(ctx, str);3592 ai = isl_access_info_add_source(ai, map, 0, &depth);3593 3594 str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";3595 map = isl_map_read_from_str(ctx, str);3596 ai = isl_access_info_add_source(ai, map, 0, &depth);3597 3598 flow = isl_access_info_compute_flow(ai);3599 space = isl_space_alloc(ctx, 0, 3, 3);3600 mm.must = isl_map_empty(isl_space_copy(space));3601 mm.may = isl_map_empty(space);3602 3603 isl_flow_foreach(flow, collect_must_may, &mm);3604 3605 str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "3606 " [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";3607 assert(map_is_equal(mm.may, str));3608 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";3609 assert(map_is_equal(mm.must, str));3610 3611 isl_map_free(mm.must);3612 isl_map_free(mm.may);3613 isl_flow_free(flow);3614 3615 3616 str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";3617 map = isl_map_read_from_str(ctx, str);3618 ai = isl_access_info_alloc(map, &depth, &common_space, 2);3619 3620 str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";3621 map = isl_map_read_from_str(ctx, str);3622 ai = isl_access_info_add_source(ai, map, 0, &depth);3623 3624 str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";3625 map = isl_map_read_from_str(ctx, str);3626 ai = isl_access_info_add_source(ai, map, 0, &depth);3627 3628 flow = isl_access_info_compute_flow(ai);3629 space = isl_space_alloc(ctx, 0, 3, 3);3630 mm.must = isl_map_empty(isl_space_copy(space));3631 mm.may = isl_map_empty(space);3632 3633 isl_flow_foreach(flow, collect_must_may, &mm);3634 3635 str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "3636 " [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";3637 assert(map_is_equal(mm.may, str));3638 str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";3639 assert(map_is_equal(mm.must, str));3640 3641 isl_map_free(mm.must);3642 isl_map_free(mm.may);3643 isl_flow_free(flow);3644 3645 3646 depth = 5;3647 3648 str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";3649 map = isl_map_read_from_str(ctx, str);3650 ai = isl_access_info_alloc(map, &depth, &common_space, 1);3651 3652 str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";3653 map = isl_map_read_from_str(ctx, str);3654 ai = isl_access_info_add_source(ai, map, 1, &depth);3655 3656 flow = isl_access_info_compute_flow(ai);3657 space = isl_space_alloc(ctx, 0, 5, 5);3658 mm.must = isl_map_empty(isl_space_copy(space));3659 mm.may = isl_map_empty(space);3660 3661 isl_flow_foreach(flow, collect_must_may, &mm);3662 3663 str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";3664 assert(map_is_equal(mm.must, str));3665 str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";3666 assert(map_is_equal(mm.may, str));3667 3668 isl_map_free(mm.must);3669 isl_map_free(mm.may);3670 isl_flow_free(flow);3671 3672 return 0;3673}3674 3675/* Check that the dependence analysis proceeds without errors.3676 * Earlier versions of isl would break down during the analysis3677 * due to the use of the wrong spaces.3678 */3679static int test_flow(isl_ctx *ctx)3680{3681 const char *str;3682 isl_union_map *access, *schedule;3683 isl_union_map *must_dep, *may_dep;3684 int r;3685 3686 str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }";3687 access = isl_union_map_read_from_str(ctx, str);3688 str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; "3689 "S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; "3690 "S2[] -> [1,0,0,0]; "3691 "S3[] -> [-1,0,0,0] }";3692 schedule = isl_union_map_read_from_str(ctx, str);3693 r = isl_union_map_compute_flow(access, isl_union_map_copy(access),3694 isl_union_map_copy(access), schedule,3695 &must_dep, &may_dep, NULL, NULL);3696 isl_union_map_free(may_dep);3697 isl_union_map_free(must_dep);3698 3699 return r;3700}3701 3702struct {3703 const char *map;3704 int sv;3705} sv_tests[] = {3706 { "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 },3707 { "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 },3708 { "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 },3709 { "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 },3710 { "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 },3711 { "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 },3712 { "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },3713 { "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },3714 { "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 },3715};3716 3717int test_sv(isl_ctx *ctx)3718{3719 isl_union_map *umap;3720 int i;3721 int sv;3722 3723 for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) {3724 umap = isl_union_map_read_from_str(ctx, sv_tests[i].map);3725 sv = isl_union_map_is_single_valued(umap);3726 isl_union_map_free(umap);3727 if (sv < 0)3728 return -1;3729 if (sv_tests[i].sv && !sv)3730 isl_die(ctx, isl_error_internal,3731 "map not detected as single valued", return -1);3732 if (!sv_tests[i].sv && sv)3733 isl_die(ctx, isl_error_internal,3734 "map detected as single valued", return -1);3735 }3736 3737 return 0;3738}3739 3740struct {3741 const char *str;3742 int bijective;3743} bijective_tests[] = {3744 { "[N,M]->{[i,j] -> [i]}", 0 },3745 { "[N,M]->{[i,j] -> [i] : j=i}", 1 },3746 { "[N,M]->{[i,j] -> [i] : j=0}", 1 },3747 { "[N,M]->{[i,j] -> [i] : j=N}", 1 },3748 { "[N,M]->{[i,j] -> [j,i]}", 1 },3749 { "[N,M]->{[i,j] -> [i+j]}", 0 },3750 { "[N,M]->{[i,j] -> []}", 0 },3751 { "[N,M]->{[i,j] -> [i,j,N]}", 1 },3752 { "[N,M]->{[i,j] -> [2i]}", 0 },3753 { "[N,M]->{[i,j] -> [i,i]}", 0 },3754 { "[N,M]->{[i,j] -> [2i,i]}", 0 },3755 { "[N,M]->{[i,j] -> [2i,j]}", 1 },3756 { "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1 },3757};3758 3759static int test_bijective(struct isl_ctx *ctx)3760{3761 isl_map *map;3762 int i;3763 int bijective;3764 3765 for (i = 0; i < ARRAY_SIZE(bijective_tests); ++i) {3766 map = isl_map_read_from_str(ctx, bijective_tests[i].str);3767 bijective = isl_map_is_bijective(map);3768 isl_map_free(map);3769 if (bijective < 0)3770 return -1;3771 if (bijective_tests[i].bijective && !bijective)3772 isl_die(ctx, isl_error_internal,3773 "map not detected as bijective", return -1);3774 if (!bijective_tests[i].bijective && bijective)3775 isl_die(ctx, isl_error_internal,3776 "map detected as bijective", return -1);3777 }3778 3779 return 0;3780}3781 3782/* Inputs for isl_pw_qpolynomial_gist tests.3783 * "pwqp" is the input, "set" is the context and "gist" is the expected result.3784 */3785struct {3786 const char *pwqp;3787 const char *set;3788 const char *gist;3789} pwqp_gist_tests[] = {3790 { "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" },3791 { "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" },3792 { "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }",3793 "{ [i] -> -1/2 + 1/2 * i }" },3794 { "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },3795 { "{ [i] -> i^2 : i > 0; [i] -> i^2 : i < 0 }", "{ [i] : i != 0 }",3796 "{ [i] -> i^2 }" },3797};3798 3799/* Perform some basic isl_pw_qpolynomial_gist tests.3800 */3801static isl_stat test_pwqp_gist(isl_ctx *ctx)3802{3803 int i;3804 const char *str;3805 isl_set *set;3806 isl_pw_qpolynomial *pwqp1, *pwqp2;3807 isl_bool equal;3808 3809 for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {3810 str = pwqp_gist_tests[i].pwqp;3811 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3812 str = pwqp_gist_tests[i].set;3813 set = isl_set_read_from_str(ctx, str);3814 pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);3815 str = pwqp_gist_tests[i].gist;3816 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3817 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3818 equal = isl_pw_qpolynomial_is_zero(pwqp1);3819 isl_pw_qpolynomial_free(pwqp1);3820 3821 if (equal < 0)3822 return isl_stat_error;3823 if (!equal)3824 isl_die(ctx, isl_error_unknown,3825 "unexpected result", return isl_stat_error);3826 }3827 3828 return isl_stat_ok;3829}3830 3831/* Perform a basic isl_pw_qpolynomial_max test.3832 */3833static isl_stat test_pwqp_max(isl_ctx *ctx)3834{3835 const char *str;3836 isl_pw_qpolynomial *pwqp;3837 isl_val *v;3838 int ok;3839 3840 str = "{ [x=2:9, y] -> floor((x + 1)/4)^3 - floor((2x)/3)^2 }";3841 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);3842 v = isl_pw_qpolynomial_max(pwqp);3843 ok = isl_val_cmp_si(v, -1) == 0;3844 isl_val_free(v);3845 3846 if (!v)3847 return isl_stat_error;3848 if (!ok)3849 isl_die(ctx, isl_error_unknown, "unexpected maximum",3850 return isl_stat_error);3851 3852 return isl_stat_ok;3853}3854 3855static int test_pwqp(struct isl_ctx *ctx)3856{3857 const char *str;3858 isl_set *set;3859 isl_pw_qpolynomial *pwqp1, *pwqp2;3860 int equal;3861 3862 str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";3863 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3864 3865 pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,3866 isl_dim_in, 1, 1);3867 3868 str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";3869 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3870 3871 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3872 3873 assert(isl_pw_qpolynomial_is_zero(pwqp1));3874 3875 isl_pw_qpolynomial_free(pwqp1);3876 3877 if (test_pwqp_gist(ctx) < 0)3878 return -1;3879 3880 str = "{ [i] -> ([([i/2] + [i/2])/5]) }";3881 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3882 str = "{ [i] -> ([(2 * [i/2])/5]) }";3883 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3884 3885 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3886 3887 assert(isl_pw_qpolynomial_is_zero(pwqp1));3888 3889 isl_pw_qpolynomial_free(pwqp1);3890 3891 str = "{ [x] -> ([x/2] + [(x+1)/2]) }";3892 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3893 str = "{ [x] -> x }";3894 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3895 3896 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3897 3898 assert(isl_pw_qpolynomial_is_zero(pwqp1));3899 3900 isl_pw_qpolynomial_free(pwqp1);3901 3902 str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";3903 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3904 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3905 pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);3906 pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);3907 assert(isl_pw_qpolynomial_is_zero(pwqp1));3908 isl_pw_qpolynomial_free(pwqp1);3909 3910 str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";3911 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3912 str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";3913 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3914 set = isl_set_read_from_str(ctx, "{ [a,b,a] }");3915 pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);3916 equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);3917 isl_pw_qpolynomial_free(pwqp1);3918 isl_pw_qpolynomial_free(pwqp2);3919 if (equal < 0)3920 return -1;3921 if (!equal)3922 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);3923 3924 str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";3925 pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);3926 str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";3927 pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);3928 pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,3929 isl_val_one(ctx));3930 equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);3931 isl_pw_qpolynomial_free(pwqp1);3932 isl_pw_qpolynomial_free(pwqp2);3933 if (equal < 0)3934 return -1;3935 if (!equal)3936 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);3937 3938 if (test_pwqp_max(ctx) < 0)3939 return -1;3940 3941 return 0;3942}3943 3944static int test_split_periods(isl_ctx *ctx)3945{3946 const char *str;3947 isl_pw_qpolynomial *pwqp;3948 3949 str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "3950 "U + 2V + 3 >= 0 and - U -2V >= 0 and - U + 10 >= 0 and "3951 "U >= 0; [U,V] -> U^2 : U >= 100 }";3952 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);3953 3954 pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);3955 3956 isl_pw_qpolynomial_free(pwqp);3957 3958 if (!pwqp)3959 return -1;3960 3961 return 0;3962}3963 3964static int test_union(isl_ctx *ctx)3965{3966 const char *str;3967 isl_union_set *uset1, *uset2;3968 isl_union_map *umap1, *umap2;3969 int equal;3970 3971 str = "{ [i] : 0 <= i <= 1 }";3972 uset1 = isl_union_set_read_from_str(ctx, str);3973 str = "{ [1] -> [0] }";3974 umap1 = isl_union_map_read_from_str(ctx, str);3975 3976 umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);3977 equal = isl_union_map_is_equal(umap1, umap2);3978 3979 isl_union_map_free(umap1);3980 isl_union_map_free(umap2);3981 3982 if (equal < 0)3983 return -1;3984 if (!equal)3985 isl_die(ctx, isl_error_unknown, "union maps not equal",3986 return -1);3987 3988 str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";3989 umap1 = isl_union_map_read_from_str(ctx, str);3990 str = "{ A[i]; B[i] }";3991 uset1 = isl_union_set_read_from_str(ctx, str);3992 3993 uset2 = isl_union_map_domain(umap1);3994 3995 equal = isl_union_set_is_equal(uset1, uset2);3996 3997 isl_union_set_free(uset1);3998 isl_union_set_free(uset2);3999 4000 if (equal < 0)4001 return -1;4002 if (!equal)4003 isl_die(ctx, isl_error_unknown, "union sets not equal",4004 return -1);4005 4006 return 0;4007}4008 4009/* Inputs for basic isl_pw_qpolynomial_bound tests.4010 * "type" is the type of bound that should be computed.4011 * "poly" is a string representation of the input.4012 * "bound" is a string representation of the expected result.4013 * "tight" is set if the result is expected to be tight.4014 */4015static struct {4016 int tight;4017 enum isl_fold type;4018 const char *poly;4019 const char *bound;4020} bound_tests[] = {4021 /* Check that computing a bound of a non-zero polynomial4022 * over an unbounded domain does not produce a rational value.4023 * In particular, check that the upper bound is infinity.4024 */4025 { 0, isl_fold_max, "{ [m, n] -> -m * n }", "{ max(infty) }" },4026 { 1, isl_fold_max, "{ [[a, b, c, d] -> [e]] -> 0 }",4027 "{ [a, b, c, d] -> max(0) }" },4028 { 1, isl_fold_max, "{ [[x] -> [x]] -> 1 : exists a : x = 2 a }",4029 "{ [x] -> max(1) : x mod 2 = 0 }" },4030 { 1, isl_fold_min, "{ [x=5:10] -> (x + 2)^2 }", "{ min(49) }" },4031 { 1, isl_fold_max, "{ [0:10] -> 1 }", "{ max(1) }" },4032 { 1, isl_fold_max, "{ [[m] -> [0:m]] -> m^2 }",4033 "{ [m] -> max(m^2) : m >= 0 }" },4034};4035 4036/* Check that the bound computation can handle differences4037 * in domain dimension names of the input polynomial and its domain.4038 */4039static isl_stat test_bound_space(isl_ctx *ctx)4040{4041 const char *str;4042 isl_set *set;4043 isl_pw_qpolynomial *pwqp;4044 isl_pw_qpolynomial_fold *pwf;4045 4046 str = "{ [[c] -> [c]] }";4047 set = isl_set_read_from_str(ctx, str);4048 str = "{ [[a] -> [b]] -> 1 }";4049 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);4050 pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);4051 pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);4052 isl_pw_qpolynomial_fold_free(pwf);4053 4054 return isl_stat_non_null(pwf);4055}4056 4057/* Perform basic isl_pw_qpolynomial_bound tests.4058 */4059static int test_bound(isl_ctx *ctx)4060{4061 int i;4062 4063 if (test_bound_space(ctx) < 0)4064 return -1;4065 4066 for (i = 0; i < ARRAY_SIZE(bound_tests); ++i) {4067 const char *str;4068 enum isl_fold type;4069 isl_bool equal, tight;4070 isl_pw_qpolynomial *pwqp;4071 isl_pw_qpolynomial_fold *pwf1, *pwf2;4072 4073 str = bound_tests[i].poly;4074 pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);4075 type = bound_tests[i].type;4076 pwf1 = isl_pw_qpolynomial_bound(pwqp, type, &tight);4077 str = bound_tests[i].bound;4078 pwf2 = isl_pw_qpolynomial_fold_read_from_str(ctx, str);4079 equal = isl_pw_qpolynomial_fold_plain_is_equal(pwf1, pwf2);4080 isl_pw_qpolynomial_fold_free(pwf2);4081 isl_pw_qpolynomial_fold_free(pwf1);4082 if (equal < 0)4083 return -1;4084 if (!equal)4085 isl_die(ctx, isl_error_unknown,4086 "incorrect bound result", return -1);4087 if (bound_tests[i].tight && !tight)4088 isl_die(ctx, isl_error_unknown,4089 "bound unexpectedly not tight", return -1);4090 }4091 4092 return 0;4093}4094 4095/* isl_set is defined to isl_map internally, so the corresponding elements4096 * are isl_basic_map objects.4097 */4098#undef EL_BASE4099#undef SET_BASE4100#define EL_BASE basic_map4101#define SET_BASE set4102#include "isl_test_list_templ.c"4103 4104#undef EL_BASE4105#undef SET_BASE4106#define EL_BASE basic_set4107#define SET_BASE union_set4108#include "isl_test_list_templ.c"4109 4110#undef EL_BASE4111#undef SET_BASE4112#define EL_BASE set4113#define SET_BASE union_set4114#include "isl_test_list_templ.c"4115 4116#undef EL_BASE4117#undef SET_BASE4118#define EL_BASE basic_map4119#define SET_BASE map4120#include "isl_test_list_templ.c"4121 4122#undef EL_BASE4123#undef SET_BASE4124#define EL_BASE map4125#define SET_BASE union_map4126#include "isl_test_list_templ.c"4127 4128/* Check that the conversion from isl objects to lists works as expected.4129 */4130static int test_get_list(isl_ctx *ctx)4131{4132 if (test_get_list_basic_map_from_set(ctx, "{ [0]; [2]; [3] }"))4133 return -1;4134 if (test_get_list_basic_set_from_union_set(ctx, "{ A[0]; B[2]; B[3] }"))4135 return -1;4136 if (test_get_list_set_from_union_set(ctx, "{ A[0]; A[2]; B[3] }"))4137 return -1;4138 if (test_get_list_basic_map_from_map(ctx,4139 "{ [0] -> [0]; [2] -> [0]; [3] -> [0] }"))4140 return -1;4141 if (test_get_list_map_from_union_map(ctx,4142 "{ A[0] -> [0]; A[2] -> [0]; B[3] -> [0] }"))4143 return -1;4144 4145 return 0;4146}4147 4148static int test_lift(isl_ctx *ctx)4149{4150 const char *str;4151 isl_basic_map *bmap;4152 isl_basic_set *bset;4153 4154 str = "{ [i0] : exists e0 : i0 = 4e0 }";4155 bset = isl_basic_set_read_from_str(ctx, str);4156 bset = isl_basic_set_lift(bset);4157 bmap = isl_basic_map_from_range(bset);4158 bset = isl_basic_map_domain(bmap);4159 isl_basic_set_free(bset);4160 4161 return 0;4162}4163 4164/* Check that isl_set_is_subset is not confused by identical4165 * integer divisions.4166 * The call to isl_set_normalize ensures that the equality constraints4167 * a = b = 0 are discovered, turning e0 and e1 into identical4168 * integer divisions. Any further simplification would remove4169 * the duplicate integer divisions.4170 */4171static isl_stat test_subset_duplicate_integer_divisions(isl_ctx *ctx)4172{4173 const char *str;4174 isl_bool is_subset;4175 isl_set *set1, *set2;4176 4177 str = "{ [a, b, c, d] : "4178 "exists (e0 = floor((a + d)/4), e1 = floor((d)/4), "4179 "e2 = floor((-a - d + 4 *floor((a + d)/4))/10), "4180 "e3 = floor((-d + 4*floor((d)/4))/10): "4181 "10e2 = -a - 2c - d + 4e0 and 10e3 = -2c - d + 4e1 and "4182 "b >= 0 and a <= 0 and b <= a) }";4183 set1 = isl_set_read_from_str(ctx, str);4184 set2 = isl_set_read_from_str(ctx, str);4185 set2 = isl_set_normalize(set2);4186 4187 is_subset = isl_set_is_subset(set1, set2);4188 4189 isl_set_free(set1);4190 isl_set_free(set2);4191 4192 if (is_subset < 0)4193 return isl_stat_error;4194 if (!is_subset)4195 isl_die(ctx, isl_error_unknown,4196 "set is not considered to be a subset of itself",4197 return isl_stat_error);4198 4199 return isl_stat_ok;4200}4201 4202struct {4203 const char *set1;4204 const char *set2;4205 int subset;4206} subset_tests[] = {4207 { "{ [112, 0] }",4208 "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "4209 "16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "4210 "16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },4211 { "{ [65] }",4212 "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "4213 "e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "4214 "e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "4215 "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "4216 "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "4217 "256e0 <= 255i and 256e0 >= -255 + 255i and "4218 "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "4219 "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "4220 "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },4221 { "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },4222 { "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },4223 { "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },4224 { "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },4225 { "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and "4226 "4e0 >= -1 + t and i >= 57 and i <= 62 and "4227 "4e0 <= 62 + t - i and 4e0 >= -61 + t + i and "4228 "t >= 0 and t <= 511 and 4e0 <= -57 + t + i and "4229 "4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }",4230 "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and "4231 "4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and "4232 "4e0 <= -57 + i0 + i1)) or "4233 "(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and "4234 "4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and "4235 "4e0 >= -61 + i0 + i1)) or "4236 "(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 },4237 { "[a, b] -> { : a = 0 and b = -1 }", "[b, a] -> { : b >= -10 }", 1 },4238};4239 4240static int test_subset(isl_ctx *ctx)4241{4242 int i;4243 isl_set *set1, *set2;4244 int subset;4245 4246 if (test_subset_duplicate_integer_divisions(ctx) < 0)4247 return -1;4248 4249 for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {4250 set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);4251 set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);4252 subset = isl_set_is_subset(set1, set2);4253 isl_set_free(set1);4254 isl_set_free(set2);4255 if (subset < 0)4256 return -1;4257 if (subset != subset_tests[i].subset)4258 isl_die(ctx, isl_error_unknown,4259 "incorrect subset result", return -1);4260 }4261 4262 return 0;4263}4264 4265/* Perform a set subtraction with a set that has a non-obviously empty disjunct.4266 * Older versions of isl would fail on such cases.4267 */4268static isl_stat test_subtract_empty(isl_ctx *ctx)4269{4270 const char *str;4271 isl_set *s1, *s2;4272 4273 s1 = isl_set_read_from_str(ctx, "{ [0] }");4274 str = "{ [a] : (exists (e0, e1, e2: 1056e1 <= 32 + a - 33e0 and "4275 "1089e1 >= a - 33e0 and 1089e1 <= 1 + a - 33e0 and "4276 "33e2 >= -a + 33e0 + 1056e1 and "4277 "33e2 < -2a + 66e0 + 2112e1)) or a = 0 }";4278 s2 = isl_set_read_from_str(ctx, str);4279 s1 = isl_set_subtract(s1, s2);4280 isl_set_free(s1);4281 4282 return isl_stat_non_null(s1);4283}4284 4285struct {4286 const char *minuend;4287 const char *subtrahend;4288 const char *difference;4289} subtract_domain_tests[] = {4290 { "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },4291 { "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },4292 { "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },4293};4294 4295static int test_subtract(isl_ctx *ctx)4296{4297 int i;4298 isl_union_map *umap1, *umap2;4299 isl_union_pw_multi_aff *upma1, *upma2;4300 isl_union_set *uset;4301 int equal;4302 4303 if (test_subtract_empty(ctx) < 0)4304 return -1;4305 4306 for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {4307 umap1 = isl_union_map_read_from_str(ctx,4308 subtract_domain_tests[i].minuend);4309 uset = isl_union_set_read_from_str(ctx,4310 subtract_domain_tests[i].subtrahend);4311 umap2 = isl_union_map_read_from_str(ctx,4312 subtract_domain_tests[i].difference);4313 umap1 = isl_union_map_subtract_domain(umap1, uset);4314 equal = isl_union_map_is_equal(umap1, umap2);4315 isl_union_map_free(umap1);4316 isl_union_map_free(umap2);4317 if (equal < 0)4318 return -1;4319 if (!equal)4320 isl_die(ctx, isl_error_unknown,4321 "incorrect subtract domain result", return -1);4322 }4323 4324 for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {4325 upma1 = isl_union_pw_multi_aff_read_from_str(ctx,4326 subtract_domain_tests[i].minuend);4327 uset = isl_union_set_read_from_str(ctx,4328 subtract_domain_tests[i].subtrahend);4329 upma2 = isl_union_pw_multi_aff_read_from_str(ctx,4330 subtract_domain_tests[i].difference);4331 upma1 = isl_union_pw_multi_aff_subtract_domain(upma1, uset);4332 equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);4333 isl_union_pw_multi_aff_free(upma1);4334 isl_union_pw_multi_aff_free(upma2);4335 if (equal < 0)4336 return -1;4337 if (!equal)4338 isl_die(ctx, isl_error_unknown,4339 "incorrect subtract domain result", return -1);4340 }4341 4342 return 0;4343}4344 4345/* Check that intersecting the empty basic set with another basic set4346 * does not increase the number of constraints. In particular,4347 * the empty basic set should maintain its canonical representation.4348 */4349static int test_intersect_1(isl_ctx *ctx)4350{4351 isl_size n1, n2;4352 isl_basic_set *bset1, *bset2;4353 4354 bset1 = isl_basic_set_read_from_str(ctx, "{ [a,b,c] : 1 = 0 }");4355 bset2 = isl_basic_set_read_from_str(ctx, "{ [1,2,3] }");4356 n1 = isl_basic_set_n_constraint(bset1);4357 bset1 = isl_basic_set_intersect(bset1, bset2);4358 n2 = isl_basic_set_n_constraint(bset1);4359 isl_basic_set_free(bset1);4360 if (n1 < 0 || n2 < 0)4361 return -1;4362 if (n1 != n2)4363 isl_die(ctx, isl_error_unknown,4364 "number of constraints of empty set changed",4365 return -1);4366 4367 return 0;4368}4369 4370/* Check that intersecting a set with itself does not cause4371 * an explosion in the number of disjuncts.4372 */4373static isl_stat test_intersect_2(isl_ctx *ctx)4374{4375 int i;4376 isl_set *set;4377 4378 set = isl_set_read_from_str(ctx, "{ [x,y] : x >= 0 or y >= 0 }");4379 for (i = 0; i < 100; ++i)4380 set = isl_set_intersect(set, isl_set_copy(set));4381 isl_set_free(set);4382 if (!set)4383 return isl_stat_error;4384 return isl_stat_ok;4385}4386 4387/* Perform some intersection tests.4388 */4389static int test_intersect(isl_ctx *ctx)4390{4391 if (test_intersect_1(ctx) < 0)4392 return -1;4393 if (test_intersect_2(ctx) < 0)4394 return -1;4395 4396 return 0;4397}4398 4399int test_factorize(isl_ctx *ctx)4400{4401 const char *str;4402 isl_basic_set *bset;4403 isl_factorizer *f;4404 4405 str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "4406 "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "4407 "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "4408 "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "4409 "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "4410 "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "4411 "3i5 >= -2i0 - i2 + 3i4 }";4412 bset = isl_basic_set_read_from_str(ctx, str);4413 f = isl_basic_set_factorizer(bset);4414 isl_basic_set_free(bset);4415 isl_factorizer_free(f);4416 if (!f)4417 isl_die(ctx, isl_error_unknown,4418 "failed to construct factorizer", return -1);4419 4420 str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "4421 "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "4422 "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "4423 "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "4424 "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "4425 "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "4426 "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "4427 "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "4428 "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "4429 "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";4430 bset = isl_basic_set_read_from_str(ctx, str);4431 f = isl_basic_set_factorizer(bset);4432 isl_basic_set_free(bset);4433 isl_factorizer_free(f);4434 if (!f)4435 isl_die(ctx, isl_error_unknown,4436 "failed to construct factorizer", return -1);4437 4438 return 0;4439}4440 4441static isl_stat check_injective(__isl_take isl_map *map, void *user)4442{4443 int *injective = user;4444 4445 *injective = isl_map_is_injective(map);4446 isl_map_free(map);4447 4448 if (*injective < 0 || !*injective)4449 return isl_stat_error;4450 4451 return isl_stat_ok;4452}4453 4454int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,4455 const char *r, const char *s, int tilable, int parallel)4456{4457 int i;4458 isl_union_set *D;4459 isl_union_map *W, *R, *S;4460 isl_union_map *empty;4461 isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;4462 isl_union_map *validity, *proximity, *coincidence;4463 isl_union_map *schedule;4464 isl_union_map *test;4465 isl_union_set *delta;4466 isl_union_set *domain;4467 isl_set *delta_set;4468 isl_set *slice;4469 isl_set *origin;4470 isl_schedule_constraints *sc;4471 isl_schedule *sched;4472 int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;4473 isl_size n;4474 4475 D = isl_union_set_read_from_str(ctx, d);4476 W = isl_union_map_read_from_str(ctx, w);4477 R = isl_union_map_read_from_str(ctx, r);4478 S = isl_union_map_read_from_str(ctx, s);4479 4480 W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));4481 R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));4482 4483 empty = isl_union_map_empty(isl_union_map_get_space(S));4484 isl_union_map_compute_flow(isl_union_map_copy(R),4485 isl_union_map_copy(W), empty,4486 isl_union_map_copy(S),4487 &dep_raw, NULL, NULL, NULL);4488 isl_union_map_compute_flow(isl_union_map_copy(W),4489 isl_union_map_copy(W),4490 isl_union_map_copy(R),4491 isl_union_map_copy(S),4492 &dep_waw, &dep_war, NULL, NULL);4493 4494 dep = isl_union_map_union(dep_waw, dep_war);4495 dep = isl_union_map_union(dep, dep_raw);4496 validity = isl_union_map_copy(dep);4497 coincidence = isl_union_map_copy(dep);4498 proximity = isl_union_map_copy(dep);4499 4500 sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D));4501 sc = isl_schedule_constraints_set_validity(sc, validity);4502 sc = isl_schedule_constraints_set_coincidence(sc, coincidence);4503 sc = isl_schedule_constraints_set_proximity(sc, proximity);4504 sched = isl_schedule_constraints_compute_schedule(sc);4505 schedule = isl_schedule_get_map(sched);4506 isl_schedule_free(sched);4507 isl_union_map_free(W);4508 isl_union_map_free(R);4509 isl_union_map_free(S);4510 4511 is_injection = 1;4512 isl_union_map_foreach_map(schedule, &check_injective, &is_injection);4513 4514 domain = isl_union_map_domain(isl_union_map_copy(schedule));4515 is_complete = isl_union_set_is_subset(D, domain);4516 isl_union_set_free(D);4517 isl_union_set_free(domain);4518 4519 test = isl_union_map_reverse(isl_union_map_copy(schedule));4520 test = isl_union_map_apply_range(test, dep);4521 test = isl_union_map_apply_range(test, schedule);4522 4523 delta = isl_union_map_deltas(test);4524 n = isl_union_set_n_set(delta);4525 if (n < 0) {4526 isl_union_set_free(delta);4527 return -1;4528 }4529 if (n == 0) {4530 is_tilable = 1;4531 is_parallel = 1;4532 is_nonneg = 1;4533 isl_union_set_free(delta);4534 } else {4535 isl_size dim;4536 4537 delta_set = isl_set_from_union_set(delta);4538 4539 slice = isl_set_universe(isl_set_get_space(delta_set));4540 for (i = 0; i < tilable; ++i)4541 slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);4542 is_tilable = isl_set_is_subset(delta_set, slice);4543 isl_set_free(slice);4544 4545 slice = isl_set_universe(isl_set_get_space(delta_set));4546 for (i = 0; i < parallel; ++i)4547 slice = isl_set_fix_si(slice, isl_dim_set, i, 0);4548 is_parallel = isl_set_is_subset(delta_set, slice);4549 isl_set_free(slice);4550 4551 origin = isl_set_universe(isl_set_get_space(delta_set));4552 dim = isl_set_dim(origin, isl_dim_set);4553 if (dim < 0)4554 origin = isl_set_free(origin);4555 for (i = 0; i < dim; ++i)4556 origin = isl_set_fix_si(origin, isl_dim_set, i, 0);4557 4558 delta_set = isl_set_union(delta_set, isl_set_copy(origin));4559 delta_set = isl_set_lexmin(delta_set);4560 4561 is_nonneg = isl_set_is_equal(delta_set, origin);4562 4563 isl_set_free(origin);4564 isl_set_free(delta_set);4565 }4566 4567 if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||4568 is_injection < 0 || is_complete < 0)4569 return -1;4570 if (!is_complete)4571 isl_die(ctx, isl_error_unknown,4572 "generated schedule incomplete", return -1);4573 if (!is_injection)4574 isl_die(ctx, isl_error_unknown,4575 "generated schedule not injective on each statement",4576 return -1);4577 if (!is_nonneg)4578 isl_die(ctx, isl_error_unknown,4579 "negative dependences in generated schedule",4580 return -1);4581 if (!is_tilable)4582 isl_die(ctx, isl_error_unknown,4583 "generated schedule not as tilable as expected",4584 return -1);4585 if (!is_parallel)4586 isl_die(ctx, isl_error_unknown,4587 "generated schedule not as parallel as expected",4588 return -1);4589 4590 return 0;4591}4592 4593/* Compute a schedule for the given instance set, validity constraints,4594 * proximity constraints and context and return a corresponding union map4595 * representation.4596 */4597static __isl_give isl_union_map *compute_schedule_with_context(isl_ctx *ctx,4598 const char *domain, const char *validity, const char *proximity,4599 const char *context)4600{4601 isl_set *con;4602 isl_union_set *dom;4603 isl_union_map *dep;4604 isl_union_map *prox;4605 isl_schedule_constraints *sc;4606 isl_schedule *schedule;4607 isl_union_map *sched;4608 4609 con = isl_set_read_from_str(ctx, context);4610 dom = isl_union_set_read_from_str(ctx, domain);4611 dep = isl_union_map_read_from_str(ctx, validity);4612 prox = isl_union_map_read_from_str(ctx, proximity);4613 sc = isl_schedule_constraints_on_domain(dom);4614 sc = isl_schedule_constraints_set_context(sc, con);4615 sc = isl_schedule_constraints_set_validity(sc, dep);4616 sc = isl_schedule_constraints_set_proximity(sc, prox);4617 schedule = isl_schedule_constraints_compute_schedule(sc);4618 sched = isl_schedule_get_map(schedule);4619 isl_schedule_free(schedule);4620 4621 return sched;4622}4623 4624/* Compute a schedule for the given instance set, validity constraints and4625 * proximity constraints and return a corresponding union map representation.4626 */4627static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,4628 const char *domain, const char *validity, const char *proximity)4629{4630 return compute_schedule_with_context(ctx, domain, validity, proximity,4631 "{ : }");4632}4633 4634/* Check that a schedule can be constructed on the given domain4635 * with the given validity and proximity constraints.4636 */4637static int test_has_schedule(isl_ctx *ctx, const char *domain,4638 const char *validity, const char *proximity)4639{4640 isl_union_map *sched;4641 4642 sched = compute_schedule(ctx, domain, validity, proximity);4643 if (!sched)4644 return -1;4645 4646 isl_union_map_free(sched);4647 return 0;4648}4649 4650int test_special_schedule(isl_ctx *ctx, const char *domain,4651 const char *validity, const char *proximity, const char *expected_sched)4652{4653 isl_union_map *sched1, *sched2;4654 int equal;4655 4656 sched1 = compute_schedule(ctx, domain, validity, proximity);4657 sched2 = isl_union_map_read_from_str(ctx, expected_sched);4658 4659 equal = isl_union_map_is_equal(sched1, sched2);4660 isl_union_map_free(sched1);4661 isl_union_map_free(sched2);4662 4663 if (equal < 0)4664 return -1;4665 if (!equal)4666 isl_die(ctx, isl_error_unknown, "unexpected schedule",4667 return -1);4668 4669 return 0;4670}4671 4672/* Check that the schedule map is properly padded, i.e., that the range4673 * lives in a single space.4674 */4675static int test_padded_schedule(isl_ctx *ctx)4676{4677 const char *str;4678 isl_union_set *D;4679 isl_union_map *validity, *proximity;4680 isl_schedule_constraints *sc;4681 isl_schedule *sched;4682 isl_union_map *umap;4683 isl_union_set *range;4684 isl_set *set;4685 4686 str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";4687 D = isl_union_set_read_from_str(ctx, str);4688 validity = isl_union_map_empty(isl_union_set_get_space(D));4689 proximity = isl_union_map_copy(validity);4690 sc = isl_schedule_constraints_on_domain(D);4691 sc = isl_schedule_constraints_set_validity(sc, validity);4692 sc = isl_schedule_constraints_set_proximity(sc, proximity);4693 sched = isl_schedule_constraints_compute_schedule(sc);4694 umap = isl_schedule_get_map(sched);4695 isl_schedule_free(sched);4696 range = isl_union_map_range(umap);4697 set = isl_set_from_union_set(range);4698 isl_set_free(set);4699 4700 if (!set)4701 return -1;4702 4703 return 0;4704}4705 4706/* Check that conditional validity constraints are also taken into4707 * account across bands.4708 * In particular, try to make sure that live ranges D[1,0]->C[2,1] and4709 * D[2,0]->C[3,0] are not local in the outer band of the generated schedule4710 * and then check that the adjacent order constraint C[2,1]->D[2,0]4711 * is enforced by the rest of the schedule.4712 */4713static int test_special_conditional_schedule_constraints(isl_ctx *ctx)4714{4715 const char *str;4716 isl_union_set *domain;4717 isl_union_map *validity, *proximity, *condition;4718 isl_union_map *sink, *source, *dep;4719 isl_schedule_constraints *sc;4720 isl_schedule *schedule;4721 isl_union_access_info *access;4722 isl_union_flow *flow;4723 int empty;4724 4725 str = "[n] -> { C[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "4726 "A[k] : k >= 1 and k <= -1 + n; "4727 "B[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k; "4728 "D[k, i] : k <= -1 + n and i >= 0 and i <= -1 + k }";4729 domain = isl_union_set_read_from_str(ctx, str);4730 sc = isl_schedule_constraints_on_domain(domain);4731 str = "[n] -> { D[k, i] -> C[1 + k, k - i] : "4732 "k <= -2 + n and i >= 1 and i <= -1 + k; "4733 "D[k, i] -> C[1 + k, i] : "4734 "k <= -2 + n and i >= 1 and i <= -1 + k; "4735 "D[k, 0] -> C[1 + k, k] : k >= 1 and k <= -2 + n; "4736 "D[k, 0] -> C[1 + k, 0] : k >= 1 and k <= -2 + n }";4737 validity = isl_union_map_read_from_str(ctx, str);4738 sc = isl_schedule_constraints_set_validity(sc, validity);4739 str = "[n] -> { C[k, i] -> D[k, i] : "4740 "0 <= i <= -1 + k and k <= -1 + n }";4741 proximity = isl_union_map_read_from_str(ctx, str);4742 sc = isl_schedule_constraints_set_proximity(sc, proximity);4743 str = "[n] -> { [D[k, i] -> a[]] -> [C[1 + k, k - i] -> b[]] : "4744 "i <= -1 + k and i >= 1 and k <= -2 + n; "4745 "[B[k, i] -> c[]] -> [B[k, 1 + i] -> c[]] : "4746 "k <= -1 + n and i >= 0 and i <= -2 + k }";4747 condition = isl_union_map_read_from_str(ctx, str);4748 str = "[n] -> { [B[k, i] -> e[]] -> [D[k, i] -> a[]] : "4749 "i >= 0 and i <= -1 + k and k <= -1 + n; "4750 "[C[k, i] -> b[]] -> [D[k', -1 + k - i] -> a[]] : "4751 "i >= 0 and i <= -1 + k and k <= -1 + n and "4752 "k' <= -1 + n and k' >= k - i and k' >= 1 + k; "4753 "[C[k, i] -> b[]] -> [D[k, -1 + k - i] -> a[]] : "4754 "i >= 0 and i <= -1 + k and k <= -1 + n; "4755 "[B[k, i] -> c[]] -> [A[k'] -> d[]] : "4756 "k <= -1 + n and i >= 0 and i <= -1 + k and "4757 "k' >= 1 and k' <= -1 + n and k' >= 1 + k }";4758 validity = isl_union_map_read_from_str(ctx, str);4759 sc = isl_schedule_constraints_set_conditional_validity(sc, condition,4760 validity);4761 schedule = isl_schedule_constraints_compute_schedule(sc);4762 str = "{ D[2,0] -> [] }";4763 sink = isl_union_map_read_from_str(ctx, str);4764 access = isl_union_access_info_from_sink(sink);4765 str = "{ C[2,1] -> [] }";4766 source = isl_union_map_read_from_str(ctx, str);4767 access = isl_union_access_info_set_must_source(access, source);4768 access = isl_union_access_info_set_schedule(access, schedule);4769 flow = isl_union_access_info_compute_flow(access);4770 dep = isl_union_flow_get_must_dependence(flow);4771 isl_union_flow_free(flow);4772 empty = isl_union_map_is_empty(dep);4773 isl_union_map_free(dep);4774 4775 if (empty < 0)4776 return -1;4777 if (empty)4778 isl_die(ctx, isl_error_unknown,4779 "conditional validity not respected", return -1);4780 4781 return 0;4782}4783 4784/* Check that the test for violated conditional validity constraints4785 * is not confused by domain compression.4786 * In particular, earlier versions of isl would apply4787 * a schedule on the compressed domains to the original domains,4788 * resulting in a failure to detect that the default schedule4789 * violates the conditional validity constraints.4790 */4791static int test_special_conditional_schedule_constraints_2(isl_ctx *ctx)4792{4793 const char *str;4794 isl_bool empty;4795 isl_union_set *domain;4796 isl_union_map *validity, *condition;4797 isl_schedule_constraints *sc;4798 isl_schedule *schedule;4799 isl_union_map *umap;4800 isl_map *map, *ge;4801 4802 str = "{ A[0, i] : 0 <= i <= 10; B[1, i] : 0 <= i <= 10 }";4803 domain = isl_union_set_read_from_str(ctx, str);4804 sc = isl_schedule_constraints_on_domain(domain);4805 str = "{ B[1, i] -> A[0, i + 1] }";4806 condition = isl_union_map_read_from_str(ctx, str);4807 str = "{ A[0, i] -> B[1, i - 1] }";4808 validity = isl_union_map_read_from_str(ctx, str);4809 sc = isl_schedule_constraints_set_conditional_validity(sc, condition,4810 isl_union_map_copy(validity));4811 schedule = isl_schedule_constraints_compute_schedule(sc);4812 umap = isl_schedule_get_map(schedule);4813 isl_schedule_free(schedule);4814 validity = isl_union_map_apply_domain(validity,4815 isl_union_map_copy(umap));4816 validity = isl_union_map_apply_range(validity, umap);4817 map = isl_map_from_union_map(validity);4818 ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));4819 map = isl_map_intersect(map, ge);4820 empty = isl_map_is_empty(map);4821 isl_map_free(map);4822 4823 if (empty < 0)4824 return -1;4825 if (!empty)4826 isl_die(ctx, isl_error_unknown,4827 "conditional validity constraints not satisfied",4828 return -1);4829 4830 return 0;4831}4832 4833/* Input for testing of schedule construction based on4834 * conditional constraints.4835 *4836 * domain is the iteration domain4837 * flow are the flow dependences, which determine the validity and4838 * proximity constraints4839 * condition are the conditions on the conditional validity constraints4840 * conditional_validity are the conditional validity constraints4841 * outer_band_n is the expected number of members in the outer band4842 */4843struct {4844 const char *domain;4845 const char *flow;4846 const char *condition;4847 const char *conditional_validity;4848 int outer_band_n;4849} live_range_tests[] = {4850 /* Contrived example that illustrates that we need to keep4851 * track of tagged condition dependences and4852 * tagged conditional validity dependences4853 * in isl_sched_edge separately.4854 * In particular, the conditional validity constraints on A4855 * cannot be satisfied,4856 * but they can be ignored because there are no corresponding4857 * condition constraints. However, we do have an additional4858 * conditional validity constraint that maps to the same4859 * dependence relation4860 * as the condition constraint on B. If we did not make a distinction4861 * between tagged condition and tagged conditional validity4862 * dependences, then we4863 * could end up treating this shared dependence as an condition4864 * constraint on A, forcing a localization of the conditions,4865 * which is impossible.4866 */4867 { "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }",4868 "{ S[i] -> S[i+1] : 0 <= i < 99 }",4869 "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }",4870 "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';"4871 "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';"4872 "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }",4873 14874 },4875 /* TACO 2013 Fig. 7 */4876 { "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",4877 "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"4878 "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",4879 "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;"4880 "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : "4881 "0 <= i < n and 0 <= j < n - 1 }",4882 "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : "4883 "0 <= i < n and 0 <= j < j' < n;"4884 "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : "4885 "0 <= i < i' < n and 0 <= j,j' < n;"4886 "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : "4887 "0 <= i,j,j' < n and j < j' }",4888 24889 },4890 /* TACO 2013 Fig. 7, without tags */4891 { "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",4892 "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"4893 "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",4894 "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"4895 "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",4896 "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;"4897 "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;"4898 "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }",4899 14900 },4901 /* TACO 2013 Fig. 12 */4902 { "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;"4903 "S3[i,3] : 0 <= i <= 1 }",4904 "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;"4905 "S2[i,1] -> S2[i,2] : 0 <= i <= 1;"4906 "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }",4907 "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;"4908 "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"4909 "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }",4910 "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"4911 "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;"4912 "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;"4913 "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;"4914 "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }",4915 14916 }4917};4918 4919/* Test schedule construction based on conditional constraints.4920 * In particular, check the number of members in the outer band node4921 * as an indication of whether tiling is possible or not.4922 */4923static int test_conditional_schedule_constraints(isl_ctx *ctx)4924{4925 int i;4926 isl_union_set *domain;4927 isl_union_map *condition;4928 isl_union_map *flow;4929 isl_union_map *validity;4930 isl_schedule_constraints *sc;4931 isl_schedule *schedule;4932 isl_schedule_node *node;4933 isl_size n_member;4934 4935 if (test_special_conditional_schedule_constraints(ctx) < 0)4936 return -1;4937 if (test_special_conditional_schedule_constraints_2(ctx) < 0)4938 return -1;4939 4940 for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {4941 domain = isl_union_set_read_from_str(ctx,4942 live_range_tests[i].domain);4943 flow = isl_union_map_read_from_str(ctx,4944 live_range_tests[i].flow);4945 condition = isl_union_map_read_from_str(ctx,4946 live_range_tests[i].condition);4947 validity = isl_union_map_read_from_str(ctx,4948 live_range_tests[i].conditional_validity);4949 sc = isl_schedule_constraints_on_domain(domain);4950 sc = isl_schedule_constraints_set_validity(sc,4951 isl_union_map_copy(flow));4952 sc = isl_schedule_constraints_set_proximity(sc, flow);4953 sc = isl_schedule_constraints_set_conditional_validity(sc,4954 condition, validity);4955 schedule = isl_schedule_constraints_compute_schedule(sc);4956 node = isl_schedule_get_root(schedule);4957 while (node &&4958 isl_schedule_node_get_type(node) != isl_schedule_node_band)4959 node = isl_schedule_node_first_child(node);4960 n_member = isl_schedule_node_band_n_member(node);4961 isl_schedule_node_free(node);4962 isl_schedule_free(schedule);4963 4964 if (!schedule || n_member < 0)4965 return -1;4966 if (n_member != live_range_tests[i].outer_band_n)4967 isl_die(ctx, isl_error_unknown,4968 "unexpected number of members in outer band",4969 return -1);4970 }4971 return 0;4972}4973 4974/* Check that the schedule computed for the given instance set and4975 * dependence relation strongly satisfies the dependences.4976 * In particular, check that no instance is scheduled before4977 * or together with an instance on which it depends.4978 * Earlier versions of isl would produce a schedule that4979 * only weakly satisfies the dependences.4980 */4981static int test_strongly_satisfying_schedule(isl_ctx *ctx)4982{4983 const char *domain, *dep;4984 isl_union_map *D, *schedule;4985 isl_map *map, *ge;4986 int empty;4987 4988 domain = "{ B[i0, i1] : 0 <= i0 <= 1 and 0 <= i1 <= 11; "4989 "A[i0] : 0 <= i0 <= 1 }";4990 dep = "{ B[i0, i1] -> B[i0, 1 + i1] : 0 <= i0 <= 1 and 0 <= i1 <= 10; "4991 "B[0, 11] -> A[1]; A[i0] -> B[i0, 0] : 0 <= i0 <= 1 }";4992 schedule = compute_schedule(ctx, domain, dep, dep);4993 D = isl_union_map_read_from_str(ctx, dep);4994 D = isl_union_map_apply_domain(D, isl_union_map_copy(schedule));4995 D = isl_union_map_apply_range(D, schedule);4996 map = isl_map_from_union_map(D);4997 ge = isl_map_lex_ge(isl_space_domain(isl_map_get_space(map)));4998 map = isl_map_intersect(map, ge);4999 empty = isl_map_is_empty(map);5000 isl_map_free(map);5001 5002 if (empty < 0)5003 return -1;5004 if (!empty)5005 isl_die(ctx, isl_error_unknown,5006 "dependences not strongly satisfied", return -1);5007 5008 return 0;5009}5010 5011/* Compute a schedule for input where the instance set constraints5012 * conflict with the context constraints.5013 * Earlier versions of isl did not properly handle this situation.5014 */5015static int test_conflicting_context_schedule(isl_ctx *ctx)5016{5017 isl_union_map *schedule;5018 const char *domain, *context;5019 5020 domain = "[n] -> { A[] : n >= 0 }";5021 context = "[n] -> { : n < 0 }";5022 schedule = compute_schedule_with_context(ctx,5023 domain, "{}", "{}", context);5024 isl_union_map_free(schedule);5025 5026 if (!schedule)5027 return -1;5028 5029 return 0;5030}5031 5032/* Check that a set of schedule constraints that only allow for5033 * a coalescing schedule still produces a schedule even if the user5034 * request a non-coalescing schedule. Earlier versions of isl5035 * would not handle this case correctly.5036 */5037static int test_coalescing_schedule(isl_ctx *ctx)5038{5039 const char *domain, *dep;5040 isl_union_set *I;5041 isl_union_map *D;5042 isl_schedule_constraints *sc;5043 isl_schedule *schedule;5044 int treat_coalescing;5045 5046 domain = "{ S[a, b] : 0 <= a <= 1 and 0 <= b <= 1 }";5047 dep = "{ S[a, b] -> S[a + b, 1 - b] }";5048 I = isl_union_set_read_from_str(ctx, domain);5049 D = isl_union_map_read_from_str(ctx, dep);5050 sc = isl_schedule_constraints_on_domain(I);5051 sc = isl_schedule_constraints_set_validity(sc, D);5052 treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);5053 isl_options_set_schedule_treat_coalescing(ctx, 1);5054 schedule = isl_schedule_constraints_compute_schedule(sc);5055 isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);5056 isl_schedule_free(schedule);5057 if (!schedule)5058 return -1;5059 return 0;5060}5061 5062/* Check that the scheduler does not perform any needless5063 * compound skewing. Earlier versions of isl would compute5064 * schedules in terms of transformed schedule coefficients and5065 * would not accurately keep track of the sum of the original5066 * schedule coefficients. It could then produce the schedule5067 * S[t,i,j,k] -> [t, 2t + i, 2t + i + j, 2t + i + j + k]5068 * for the input below instead of the schedule below.5069 */5070static int test_skewing_schedule(isl_ctx *ctx)5071{5072 const char *D, *V, *P, *S;5073 5074 D = "[n] -> { S[t,i,j,k] : 0 <= t,i,j,k < n }";5075 V = "[n] -> { S[t,i,j,k] -> S[t+1,a,b,c] : 0 <= t,i,j,k,a,b,c < n and "5076 "-2 <= a-i <= 2 and -1 <= a-i + b-j <= 1 and "5077 "-1 <= a-i + b-j + c-k <= 1 }";5078 P = "{ }";5079 S = "{ S[t,i,j,k] -> [t, 2t + i, t + i + j, 2t + k] }";5080 5081 return test_special_schedule(ctx, D, V, P, S);5082}5083 5084int test_schedule(isl_ctx *ctx)5085{5086 const char *D, *W, *R, *V, *P, *S;5087 int max_coincidence;5088 int treat_coalescing;5089 5090 /* Handle resulting schedule with zero bands. */5091 if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)5092 return -1;5093 5094 /* Jacobi */5095 D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";5096 W = "{ S1[t,i] -> a[t,i] }";5097 R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "5098 "S1[t,i] -> a[t-1,i+1] }";5099 S = "{ S1[t,i] -> [t,i] }";5100 if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)5101 return -1;5102 5103 /* Fig. 5 of CC2008 */5104 D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "5105 "j <= -1 + N }";5106 W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "5107 "j >= 2 and j <= -1 + N }";5108 R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "5109 "j >= 2 and j <= -1 + N; "5110 "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "5111 "j >= 2 and j <= -1 + N }";5112 S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";5113 if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)5114 return -1;5115 5116 D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";5117 W = "{ S1[i] -> a[i] }";5118 R = "{ S2[i] -> a[i+1] }";5119 S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";5120 if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)5121 return -1;5122 5123 D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";5124 W = "{ S1[i] -> a[i] }";5125 R = "{ S2[i] -> a[9-i] }";5126 S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";5127 if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)5128 return -1;5129 5130 D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";5131 W = "{ S1[i] -> a[i] }";5132 R = "[N] -> { S2[i] -> a[N-1-i] }";5133 S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";5134 if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)5135 return -1;5136 5137 D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";5138 W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";5139 R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";5140 S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";5141 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5142 return -1;5143 5144 D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";5145 W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";5146 R = "{ S2[i,j] -> a[i-1,j] }";5147 S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";5148 if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)5149 return -1;5150 5151 D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";5152 W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";5153 R = "{ S2[i,j] -> a[i,j-1] }";5154 S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";5155 if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)5156 return -1;5157 5158 D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";5159 W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "5160 "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";5161 R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";5162 S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "5163 "S_0[] -> [0, 0, 0] }";5164 if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)5165 return -1;5166 ctx->opt->schedule_parametric = 0;5167 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5168 return -1;5169 ctx->opt->schedule_parametric = 1;5170 5171 D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "5172 "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";5173 W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";5174 R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "5175 "S4[i] -> a[i,N] }";5176 S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "5177 "S4[i] -> [4,i,0] }";5178 max_coincidence = isl_options_get_schedule_maximize_coincidence(ctx);5179 isl_options_set_schedule_maximize_coincidence(ctx, 0);5180 if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)5181 return -1;5182 isl_options_set_schedule_maximize_coincidence(ctx, max_coincidence);5183 5184 D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";5185 W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "5186 "j <= N }";5187 R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "5188 "j <= N; "5189 "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "5190 "j <= N }";5191 S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";5192 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5193 return -1;5194 5195 D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "5196 " S_2[t] : t >= 0 and t <= -1 + N; "5197 " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "5198 "i <= -1 + N }";5199 W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "5200 " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "5201 " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "5202 "i >= 0 and i <= -1 + N }";5203 R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "5204 "i >= 0 and i <= -1 + N; "5205 " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";5206 S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "5207 " S_0[t] -> [0, t, 0] }";5208 5209 if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)5210 return -1;5211 ctx->opt->schedule_parametric = 0;5212 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5213 return -1;5214 ctx->opt->schedule_parametric = 1;5215 5216 D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";5217 S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";5218 if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)5219 return -1;5220 5221 D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "5222 "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";5223 W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "5224 "j >= 0 and j <= -1 + N; "5225 "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";5226 R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "5227 "j >= 0 and j <= -1 + N; "5228 "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";5229 S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";5230 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5231 return -1;5232 5233 D = "{ S_0[i] : i >= 0 }";5234 W = "{ S_0[i] -> a[i] : i >= 0 }";5235 R = "{ S_0[i] -> a[0] : i >= 0 }";5236 S = "{ S_0[i] -> [0, i, 0] }";5237 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5238 return -1;5239 5240 D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";5241 W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";5242 R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";5243 S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";5244 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5245 return -1;5246 5247 D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "5248 "k <= -1 + n and k >= 0 }";5249 W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and " "k <= -1 + n and k >= 0 }";5250 R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "5251 "k <= -1 + n and k >= 0; "5252 "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "5253 "k <= -1 + n and k >= 0; "5254 "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "5255 "k <= -1 + n and k >= 0 }";5256 S = "[n] -> { S_0[j, k] -> [2, j, k] }";5257 ctx->opt->schedule_outer_coincidence = 1;5258 if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)5259 return -1;5260 ctx->opt->schedule_outer_coincidence = 0;5261 5262 D = "{Stmt_for_body24[i0, i1, i2, i3]:"5263 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "5264 "i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"5265 "Stmt_for_body24[i0, i1, 1, 0]:"5266 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"5267 "Stmt_for_body7[i0, i1, i2]:"5268 "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "5269 "i2 <= 7 }";5270 5271 V = "{Stmt_for_body24[0, i1, i2, i3] -> "5272 "Stmt_for_body24[1, i1, i2, i3]:"5273 "i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "5274 "i2 >= 1;"5275 "Stmt_for_body24[0, i1, i2, i3] -> "5276 "Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"5277 "i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "5278 "i3 >= 0;"5279 "Stmt_for_body24[0, i1, i2, i3] ->"5280 "Stmt_for_body7[1, i1, 1 + i1 + i3]:"5281 "i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"5282 "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"5283 "(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "5284 "(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "5285 "(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"5286 "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"5287 "i1 <= 6 and i1 >= 0;"5288 "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"5289 "Stmt_for_body7[i0, i1, i2] -> "5290 "Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"5291 "i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "5292 "o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"5293 "Stmt_for_body7[i0, i1, i2] -> "5294 "Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"5295 "i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "5296 "o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";5297 P = V;5298 5299 treat_coalescing = isl_options_get_schedule_treat_coalescing(ctx);5300 isl_options_set_schedule_treat_coalescing(ctx, 0);5301 if (test_has_schedule(ctx, D, V, P) < 0)5302 return -1;5303 isl_options_set_schedule_treat_coalescing(ctx, treat_coalescing);5304 5305 D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";5306 V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "5307 "j >= 1 and j <= 7;"5308 "S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "5309 "j >= 1 and j <= 8 }";5310 P = "{ }";5311 S = "{ S_0[i, j] -> [i + j, i] }";5312 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5313 if (test_special_schedule(ctx, D, V, P, S) < 0)5314 return -1;5315 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5316 5317 /* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */5318 D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "5319 "j >= 0 and j <= -1 + i }";5320 V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "5321 "i <= -1 + N and j >= 0;"5322 "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "5323 "i <= -2 + N }";5324 P = "{ }";5325 S = "{ S_0[i, j] -> [i, j] }";5326 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5327 if (test_special_schedule(ctx, D, V, P, S) < 0)5328 return -1;5329 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5330 5331 /* Test both algorithms on a case with only proximity dependences. */5332 D = "{ S[i,j] : 0 <= i <= 10 }";5333 V = "{ }";5334 P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";5335 S = "{ S[i, j] -> [j, i] }";5336 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5337 if (test_special_schedule(ctx, D, V, P, S) < 0)5338 return -1;5339 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5340 if (test_special_schedule(ctx, D, V, P, S) < 0)5341 return -1;5342 5343 D = "{ A[a]; B[] }";5344 V = "{}";5345 P = "{ A[a] -> B[] }";5346 if (test_has_schedule(ctx, D, V, P) < 0)5347 return -1;5348 5349 if (test_padded_schedule(ctx) < 0)5350 return -1;5351 5352 /* Check that check for progress is not confused by rational5353 * solution.5354 */5355 D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";5356 V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "5357 "i0 <= -2 + N; "5358 "S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "5359 "i0 <= N and i1 >= 0 and i1 <= -1 + N }";5360 P = "{}";5361 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5362 if (test_has_schedule(ctx, D, V, P) < 0)5363 return -1;5364 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5365 5366 /* Check that we allow schedule rows that are only non-trivial5367 * on some full-dimensional domains.5368 */5369 D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }";5370 V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];"5371 "S1[j] -> S2[1] : 0 <= j <= 1 }";5372 P = "{}";5373 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;5374 if (test_has_schedule(ctx, D, V, P) < 0)5375 return -1;5376 ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;5377 5378 if (test_conditional_schedule_constraints(ctx) < 0)5379 return -1;5380 5381 if (test_strongly_satisfying_schedule(ctx) < 0)5382 return -1;5383 5384 if (test_conflicting_context_schedule(ctx) < 0)5385 return -1;5386 5387 if (test_coalescing_schedule(ctx) < 0)5388 return -1;5389 if (test_skewing_schedule(ctx) < 0)5390 return -1;5391 5392 return 0;5393}5394 5395/* Perform scheduling tests using the whole component scheduler.5396 */5397static int test_schedule_whole(isl_ctx *ctx)5398{5399 int whole;5400 int r;5401 5402 whole = isl_options_get_schedule_whole_component(ctx);5403 isl_options_set_schedule_whole_component(ctx, 1);5404 r = test_schedule(ctx);5405 isl_options_set_schedule_whole_component(ctx, whole);5406 5407 return r;5408}5409 5410/* Perform scheduling tests using the incremental scheduler.5411 */5412static int test_schedule_incremental(isl_ctx *ctx)5413{5414 int whole;5415 int r;5416 5417 whole = isl_options_get_schedule_whole_component(ctx);5418 isl_options_set_schedule_whole_component(ctx, 0);5419 r = test_schedule(ctx);5420 isl_options_set_schedule_whole_component(ctx, whole);5421 5422 return r;5423}5424 5425int test_plain_injective(isl_ctx *ctx, const char *str, int injective)5426{5427 isl_union_map *umap;5428 int test;5429 5430 umap = isl_union_map_read_from_str(ctx, str);5431 test = isl_union_map_plain_is_injective(umap);5432 isl_union_map_free(umap);5433 if (test < 0)5434 return -1;5435 if (test == injective)5436 return 0;5437 if (injective)5438 isl_die(ctx, isl_error_unknown,5439 "map not detected as injective", return -1);5440 else5441 isl_die(ctx, isl_error_unknown,5442 "map detected as injective", return -1);5443}5444 5445int test_injective(isl_ctx *ctx)5446{5447 const char *str;5448 5449 if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))5450 return -1;5451 if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))5452 return -1;5453 if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))5454 return -1;5455 if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))5456 return -1;5457 if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))5458 return -1;5459 if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))5460 return -1;5461 if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))5462 return -1;5463 if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))5464 return -1;5465 5466 str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";5467 if (test_plain_injective(ctx, str, 1))5468 return -1;5469 str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";5470 if (test_plain_injective(ctx, str, 0))5471 return -1;5472 5473 return 0;5474}5475 5476#undef BASE5477#define BASE aff5478#include "isl_test_plain_equal_templ.c"5479 5480#undef BASE5481#define BASE pw_multi_aff5482#include "isl_test_plain_equal_templ.c"5483 5484#undef BASE5485#define BASE union_pw_aff5486#include "isl_test_plain_equal_templ.c"5487 5488/* Basic tests on isl_union_pw_aff.5489 *5490 * In particular, check that isl_union_pw_aff_aff_on_domain5491 * aligns the parameters of the input objects and5492 * that isl_union_pw_aff_param_on_domain_id properly5493 * introduces the parameter.5494 */5495static int test_upa(isl_ctx *ctx)5496{5497 const char *str;5498 isl_id *id;5499 isl_aff *aff;5500 isl_union_set *domain;5501 isl_union_pw_aff *upa;5502 isl_stat ok;5503 5504 aff = isl_aff_read_from_str(ctx, "[N] -> { [N] }");5505 str = "[M] -> { A[i] : 0 <= i < M; B[] }";5506 domain = isl_union_set_read_from_str(ctx, str);5507 upa = isl_union_pw_aff_aff_on_domain(domain, aff);5508 str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";5509 ok = union_pw_aff_check_plain_equal(upa, str);5510 isl_union_pw_aff_free(upa);5511 if (ok < 0)5512 return -1;5513 5514 id = isl_id_alloc(ctx, "N", NULL);5515 str = "[M] -> { A[i] : 0 <= i < M; B[] }";5516 domain = isl_union_set_read_from_str(ctx, str);5517 upa = isl_union_pw_aff_param_on_domain_id(domain, id);5518 str = "[N, M] -> { A[i] -> [N] : 0 <= i < M; B[] -> [N] }";5519 ok = union_pw_aff_check_plain_equal(upa, str);5520 isl_union_pw_aff_free(upa);5521 if (ok < 0)5522 return -1;5523 5524 return 0;5525}5526 5527struct {5528 __isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,5529 __isl_take isl_aff *aff2);5530} aff_bin_op[] = {5531 ['+'] = { &isl_aff_add },5532 ['-'] = { &isl_aff_sub },5533 ['*'] = { &isl_aff_mul },5534 ['/'] = { &isl_aff_div },5535};5536 5537struct {5538 const char *arg1;5539 unsigned char op;5540 const char *arg2;5541 const char *res;5542} aff_bin_tests[] = {5543 { "{ [i] -> [i] }", '+', "{ [i] -> [i] }",5544 "{ [i] -> [2i] }" },5545 { "{ [i] -> [i] }", '-', "{ [i] -> [i] }",5546 "{ [i] -> [0] }" },5547 { "{ [i] -> [i] }", '*', "{ [i] -> [2] }",5548 "{ [i] -> [2i] }" },5549 { "{ [i] -> [2] }", '*', "{ [i] -> [i] }",5550 "{ [i] -> [2i] }" },5551 { "{ [i] -> [i] }", '/', "{ [i] -> [2] }",5552 "{ [i] -> [i/2] }" },5553 { "{ [i] -> [2i] }", '/', "{ [i] -> [2] }",5554 "{ [i] -> [i] }" },5555 { "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }",5556 "{ [i] -> [NaN] }" },5557 { "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }",5558 "{ [i] -> [NaN] }" },5559 { "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }",5560 "{ [i] -> [NaN] }" },5561 { "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }",5562 "{ [i] -> [NaN] }" },5563 { "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }",5564 "{ [i] -> [NaN] }" },5565 { "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }",5566 "{ [i] -> [NaN] }" },5567 { "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }",5568 "{ [i] -> [NaN] }" },5569 { "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }",5570 "{ [i] -> [NaN] }" },5571 { "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }",5572 "{ [i] -> [NaN] }" },5573 { "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }",5574 "{ [i] -> [NaN] }" },5575 { "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }",5576 "{ [i] -> [NaN] }" },5577 { "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }",5578 "{ [i] -> [NaN] }" },5579 { "{ [i] -> [i] }", '/', "{ [i] -> [0] }",5580 "{ [i] -> [NaN] }" },5581};5582 5583/* Perform some basic tests of binary operations on isl_aff objects.5584 */5585static int test_bin_aff(isl_ctx *ctx)5586{5587 int i;5588 isl_aff *aff1, *aff2, *res;5589 __isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,5590 __isl_take isl_aff *aff2);5591 int ok;5592 5593 for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) {5594 aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1);5595 aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2);5596 res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res);5597 fn = aff_bin_op[aff_bin_tests[i].op].fn;5598 aff1 = fn(aff1, aff2);5599 if (isl_aff_is_nan(res))5600 ok = isl_aff_is_nan(aff1);5601 else5602 ok = isl_aff_plain_is_equal(aff1, res);5603 isl_aff_free(aff1);5604 isl_aff_free(res);5605 if (ok < 0)5606 return -1;5607 if (!ok)5608 isl_die(ctx, isl_error_unknown,5609 "unexpected result", return -1);5610 }5611 5612 return 0;5613}5614 5615struct {5616 __isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pa1,5617 __isl_take isl_pw_aff *pa2);5618} pw_aff_bin_op[] = {5619 ['m'] = { &isl_pw_aff_min },5620 ['M'] = { &isl_pw_aff_max },5621};5622 5623/* Inputs for binary isl_pw_aff operation tests.5624 * "arg1" and "arg2" are the two arguments, "op" identifies the operation5625 * defined by pw_aff_bin_op, and "res" is the expected result.5626 */5627struct {5628 const char *arg1;5629 unsigned char op;5630 const char *arg2;5631 const char *res;5632} pw_aff_bin_tests[] = {5633 { "{ [i] -> [i] }", 'm', "{ [i] -> [i] }",5634 "{ [i] -> [i] }" },5635 { "{ [i] -> [i] }", 'M', "{ [i] -> [i] }",5636 "{ [i] -> [i] }" },5637 { "{ [i] -> [i] }", 'm', "{ [i] -> [0] }",5638 "{ [i] -> [i] : i <= 0; [i] -> [0] : i > 0 }" },5639 { "{ [i] -> [i] }", 'M', "{ [i] -> [0] }",5640 "{ [i] -> [i] : i >= 0; [i] -> [0] : i < 0 }" },5641 { "{ [i] -> [i] }", 'm', "{ [i] -> [NaN] }",5642 "{ [i] -> [NaN] }" },5643 { "{ [i] -> [NaN] }", 'm', "{ [i] -> [i] }",5644 "{ [i] -> [NaN] }" },5645};5646 5647/* Perform some basic tests of binary operations on isl_pw_aff objects.5648 */5649static int test_bin_pw_aff(isl_ctx *ctx)5650{5651 int i;5652 isl_bool ok;5653 isl_pw_aff *pa1, *pa2, *res;5654 5655 for (i = 0; i < ARRAY_SIZE(pw_aff_bin_tests); ++i) {5656 pa1 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg1);5657 pa2 = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].arg2);5658 res = isl_pw_aff_read_from_str(ctx, pw_aff_bin_tests[i].res);5659 pa1 = pw_aff_bin_op[pw_aff_bin_tests[i].op].fn(pa1, pa2);5660 if (isl_pw_aff_involves_nan(res))5661 ok = isl_pw_aff_involves_nan(pa1);5662 else5663 ok = isl_pw_aff_plain_is_equal(pa1, res);5664 isl_pw_aff_free(pa1);5665 isl_pw_aff_free(res);5666 if (ok < 0)5667 return -1;5668 if (!ok)5669 isl_die(ctx, isl_error_unknown,5670 "unexpected result", return -1);5671 }5672 5673 return 0;5674}5675 5676/* Inputs for basic tests of test operations on5677 * isl_union_pw_multi_aff objects.5678 * "fn" is the function that is being tested.5679 * "arg" is a string description of the input.5680 * "res" is the expected result.5681 */5682static struct {5683 isl_bool (*fn)(__isl_keep isl_union_pw_multi_aff *upma1);5684 const char *arg;5685 isl_bool res;5686} upma_test_tests[] = {5687 { &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [1] }",5688 isl_bool_false },5689 { &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [NaN]; B[0] -> [1] }",5690 isl_bool_true },5691 { &isl_union_pw_multi_aff_involves_nan, "{ A[] -> [0]; B[0] -> [NaN] }",5692 isl_bool_true },5693 { &isl_union_pw_multi_aff_involves_nan,5694 "{ A[] -> [0]; B[0] -> [1, NaN, 5] }",5695 isl_bool_true },5696 { &isl_union_pw_multi_aff_involves_locals,5697 "{ A[] -> [0]; B[0] -> [1] }",5698 isl_bool_false },5699 { &isl_union_pw_multi_aff_involves_locals,5700 "{ A[] -> [0]; B[x] -> [1] : x mod 2 = 0 }",5701 isl_bool_true },5702 { &isl_union_pw_multi_aff_involves_locals,5703 "{ A[] -> [0]; B[x] -> [x // 2] }",5704 isl_bool_true },5705 { &isl_union_pw_multi_aff_involves_locals,5706 "{ A[i] -> [i // 2]; B[0] -> [1] }",5707 isl_bool_true },5708};5709 5710/* Perform some basic tests of test operations on5711 * isl_union_pw_multi_aff objects.5712 */5713static isl_stat test_upma_test(isl_ctx *ctx)5714{5715 int i;5716 isl_union_pw_multi_aff *upma;5717 isl_bool res;5718 5719 for (i = 0; i < ARRAY_SIZE(upma_test_tests); ++i) {5720 const char *str;5721 5722 str = upma_test_tests[i].arg;5723 upma = isl_union_pw_multi_aff_read_from_str(ctx, str);5724 res = upma_test_tests[i].fn(upma);5725 isl_union_pw_multi_aff_free(upma);5726 if (res < 0)5727 return isl_stat_error;5728 if (res != upma_test_tests[i].res)5729 isl_die(ctx, isl_error_unknown,5730 "unexpected result", return isl_stat_error);5731 }5732 5733 return isl_stat_ok;5734}5735 5736struct {5737 __isl_give isl_union_pw_multi_aff *(*fn)(5738 __isl_take isl_union_pw_multi_aff *upma1,5739 __isl_take isl_union_pw_multi_aff *upma2);5740 const char *arg1;5741 const char *arg2;5742 const char *res;5743} upma_bin_tests[] = {5744 { &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }",5745 "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" },5746 { &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",5747 "{ B[x] -> [2] : x >= 0 }",5748 "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },5749 { &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,5750 "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",5751 "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",5752 "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "5753 "D[i] -> B[2] : i >= 5 }" },5754 { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",5755 "{ B[x] -> C[2] : x > 0 }",5756 "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },5757 { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",5758 "{ B[x] -> A[2] : x >= 0 }",5759 "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },5760 {5761 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,5762 "{ B[x] -> C[x + 2] }",5763 "{ D[y] -> B[2y] }",5764 "{ }" },5765 {5766 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,5767 "{ [A[x] -> B[x + 1]] -> C[x + 2] }",5768 "{ D[y] -> B[2y] }",5769 "{ }" },5770 {5771 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,5772 "{ [A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",5773 "{ D[y] -> A[2y] }",5774 "{ [D[y] -> B[2y + 1]] -> C[2y + 2] }" },5775 {5776 &isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff,5777 "{ T[A[x] -> B[x + 1]] -> C[x + 2]; B[x] -> C[x + 2] }",5778 "{ D[y] -> A[2y] }",5779 "{ T[D[y] -> B[2y + 1]] -> C[2y + 2] }" },5780};5781 5782/* Perform some basic tests of binary operations on5783 * isl_union_pw_multi_aff objects.5784 */5785static int test_bin_upma(isl_ctx *ctx)5786{5787 int i;5788 isl_union_pw_multi_aff *upma1, *upma2, *res;5789 int ok;5790 5791 for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) {5792 upma1 = isl_union_pw_multi_aff_read_from_str(ctx,5793 upma_bin_tests[i].arg1);5794 upma2 = isl_union_pw_multi_aff_read_from_str(ctx,5795 upma_bin_tests[i].arg2);5796 res = isl_union_pw_multi_aff_read_from_str(ctx,5797 upma_bin_tests[i].res);5798 upma1 = upma_bin_tests[i].fn(upma1, upma2);5799 ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res);5800 isl_union_pw_multi_aff_free(upma1);5801 isl_union_pw_multi_aff_free(res);5802 if (ok < 0)5803 return -1;5804 if (!ok)5805 isl_die(ctx, isl_error_unknown,5806 "unexpected result", return -1);5807 }5808 5809 return 0;5810}5811 5812struct {5813 __isl_give isl_union_pw_multi_aff *(*fn)(5814 __isl_take isl_union_pw_multi_aff *upma1,5815 __isl_take isl_union_pw_multi_aff *upma2);5816 const char *arg1;5817 const char *arg2;5818} upma_bin_fail_tests[] = {5819 { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",5820 "{ B[x] -> C[2] : x >= 0 }" },5821};5822 5823/* Perform some basic tests of binary operations on5824 * isl_union_pw_multi_aff objects that are expected to fail.5825 */5826static int test_bin_upma_fail(isl_ctx *ctx)5827{5828 int i, n;5829 isl_union_pw_multi_aff *upma1, *upma2;5830 int on_error;5831 5832 on_error = isl_options_get_on_error(ctx);5833 isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);5834 n = ARRAY_SIZE(upma_bin_fail_tests);5835 for (i = 0; i < n; ++i) {5836 upma1 = isl_union_pw_multi_aff_read_from_str(ctx,5837 upma_bin_fail_tests[i].arg1);5838 upma2 = isl_union_pw_multi_aff_read_from_str(ctx,5839 upma_bin_fail_tests[i].arg2);5840 upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);5841 isl_union_pw_multi_aff_free(upma1);5842 if (upma1)5843 break;5844 }5845 isl_options_set_on_error(ctx, on_error);5846 if (i < n)5847 isl_die(ctx, isl_error_unknown,5848 "operation not expected to succeed", return -1);5849 5850 return 0;5851}5852 5853/* Inputs for basic tests of binary operations on5854 * pairs of isl_union_pw_multi_aff and isl_union_set objects.5855 * "fn" is the function that is being tested.5856 * "arg1" and "arg2" are string descriptions of the inputs.5857 * "res" is a string description of the expected result.5858 */5859struct {5860 __isl_give isl_union_pw_multi_aff *(*fn)(5861 __isl_take isl_union_pw_multi_aff *upma,5862 __isl_take isl_union_set *uset);5863 const char *arg1;5864 const char *arg2;5865 const char *res;5866} upma_uset_tests[] = {5867 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5868 "{ A[i] -> B[i] }", "{ B[0] }",5869 "{ }" },5870 { &isl_union_pw_multi_aff_intersect_domain_wrapped_domain,5871 "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",5872 "{ [A[1] -> B[1]] -> C[2] }" },5873 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5874 "{ [A[i] -> B[i]] -> C[i + 1] }", "{ A[1]; B[0] }",5875 "{ [A[0] -> B[0]] -> C[1] }" },5876 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5877 "{ [A[i] -> B[i]] -> C[i + 1] }", "[N] -> { B[N] }",5878 "[N] -> { [A[N] -> B[N]] -> C[N + 1] }" },5879 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5880 "[M] -> { [A[M] -> B[M]] -> C[M + 1] }", "[N] -> { B[N] }",5881 "[N, M] -> { [A[N] -> B[N]] -> C[N + 1] : N = M }" },5882 { &isl_union_pw_multi_aff_intersect_domain_wrapped_range,5883 "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[]; [B[] -> A[]] -> E[] }",5884 "{ B[] }",5885 "{ [A[] -> B[]] -> C[]; N[A[] -> B[]] -> D[] }" },5886};5887 5888/* Perform some basic tests of binary operations on5889 * pairs of isl_union_pw_multi_aff and isl_union_set objects.5890 */5891static isl_stat test_upma_uset(isl_ctx *ctx)5892{5893 int i;5894 isl_bool ok;5895 isl_union_pw_multi_aff *upma, *res;5896 isl_union_set *uset;5897 5898 for (i = 0; i < ARRAY_SIZE(upma_uset_tests); ++i) {5899 upma = isl_union_pw_multi_aff_read_from_str(ctx,5900 upma_uset_tests[i].arg1);5901 uset = isl_union_set_read_from_str(ctx,5902 upma_uset_tests[i].arg2);5903 res = isl_union_pw_multi_aff_read_from_str(ctx,5904 upma_uset_tests[i].res);5905 upma = upma_uset_tests[i].fn(upma, uset);5906 ok = isl_union_pw_multi_aff_plain_is_equal(upma, res);5907 isl_union_pw_multi_aff_free(upma);5908 isl_union_pw_multi_aff_free(res);5909 if (ok < 0)5910 return isl_stat_error;5911 if (!ok)5912 isl_die(ctx, isl_error_unknown,5913 "unexpected result", return isl_stat_error);5914 }5915 5916 return isl_stat_ok;5917}5918 5919/* Inputs for basic tests of unary operations on isl_multi_pw_aff objects.5920 * "fn" is the function that is tested.5921 * "arg" is a string description of the input.5922 * "res" is a string description of the expected result.5923 */5924struct {5925 __isl_give isl_multi_pw_aff *(*fn)(__isl_take isl_multi_pw_aff *mpa);5926 const char *arg;5927 const char *res;5928} mpa_un_tests[] = {5929 { &isl_multi_pw_aff_range_factor_domain,5930 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",5931 "{ A[x] -> B[(1 : x >= 5)] }" },5932 { &isl_multi_pw_aff_range_factor_range,5933 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }",5934 "{ A[y] -> C[(2 : y <= 10)] }" },5935 { &isl_multi_pw_aff_range_factor_domain,5936 "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",5937 "{ A[x] -> B[(1 : x >= 5)] }" },5938 { &isl_multi_pw_aff_range_factor_range,5939 "{ A[x] -> [B[(1 : x >= 5)] -> C[]] }",5940 "{ A[y] -> C[] }" },5941 { &isl_multi_pw_aff_range_factor_domain,5942 "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",5943 "{ A[x] -> B[] }" },5944 { &isl_multi_pw_aff_range_factor_range,5945 "{ A[x] -> [B[] -> C[(2 : x <= 10)]] }",5946 "{ A[y] -> C[(2 : y <= 10)] }" },5947 { &isl_multi_pw_aff_range_factor_domain,5948 "{ A[x] -> [B[] -> C[]] }",5949 "{ A[x] -> B[] }" },5950 { &isl_multi_pw_aff_range_factor_range,5951 "{ A[x] -> [B[] -> C[]] }",5952 "{ A[y] -> C[] }" },5953 { &isl_multi_pw_aff_factor_range,5954 "{ [B[] -> C[]] }",5955 "{ C[] }" },5956 { &isl_multi_pw_aff_range_factor_domain,5957 "{ A[x] -> [B[] -> C[]] : x >= 0 }",5958 "{ A[x] -> B[] : x >= 0 }" },5959 { &isl_multi_pw_aff_range_factor_range,5960 "{ A[x] -> [B[] -> C[]] : x >= 0 }",5961 "{ A[y] -> C[] : y >= 0 }" },5962 { &isl_multi_pw_aff_factor_range,5963 "[N] -> { [B[] -> C[]] : N >= 0 }",5964 "[N] -> { C[] : N >= 0 }" },5965};5966 5967/* Perform some basic tests of unary operations on isl_multi_pw_aff objects.5968 */5969static int test_un_mpa(isl_ctx *ctx)5970{5971 int i;5972 isl_bool ok;5973 isl_multi_pw_aff *mpa, *res;5974 5975 for (i = 0; i < ARRAY_SIZE(mpa_un_tests); ++i) {5976 mpa = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].arg);5977 res = isl_multi_pw_aff_read_from_str(ctx, mpa_un_tests[i].res);5978 mpa = mpa_un_tests[i].fn(mpa);5979 ok = isl_multi_pw_aff_plain_is_equal(mpa, res);5980 isl_multi_pw_aff_free(mpa);5981 isl_multi_pw_aff_free(res);5982 if (ok < 0)5983 return -1;5984 if (!ok)5985 isl_die(ctx, isl_error_unknown,5986 "unexpected result", return -1);5987 }5988 5989 return 0;5990}5991 5992/* Inputs for basic tests of binary operations on isl_multi_pw_aff objects.5993 * "fn" is the function that is tested.5994 * "arg1" and "arg2" are string descriptions of the inputs.5995 * "res" is a string description of the expected result.5996 */5997struct {5998 __isl_give isl_multi_pw_aff *(*fn)(5999 __isl_take isl_multi_pw_aff *mpa1,6000 __isl_take isl_multi_pw_aff *mpa2);6001 const char *arg1;6002 const char *arg2;6003 const char *res;6004} mpa_bin_tests[] = {6005 { &isl_multi_pw_aff_add, "{ A[] -> [1] }", "{ A[] -> [2] }",6006 "{ A[] -> [3] }" },6007 { &isl_multi_pw_aff_add, "{ A[x] -> [(1 : x >= 5)] }",6008 "{ A[x] -> [(x : x <= 10)] }",6009 "{ A[x] -> [(1 + x : 5 <= x <= 10)] }" },6010 { &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",6011 "{ A[x] -> [] : x <= 10 }",6012 "{ A[x] -> [] : 5 <= x <= 10 }" },6013 { &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",6014 "[N] -> { A[x] -> [] : x <= N }",6015 "[N] -> { A[x] -> [] : 5 <= x <= N }" },6016 { &isl_multi_pw_aff_add,6017 "[N] -> { A[x] -> [] : x <= N }",6018 "{ A[x] -> [] : x >= 5 }",6019 "[N] -> { A[x] -> [] : 5 <= x <= N }" },6020 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",6021 "{ A[y] -> C[(2 : y <= 10)] }",6022 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },6023 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",6024 "{ A[y] -> C[2] : y <= 10 }",6025 "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },6026 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",6027 "[N] -> { A[y] -> C[2] : y <= N }",6028 "[N] -> { A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= N)]] }" },6029 { &isl_multi_pw_aff_range_product, "[N] -> { A[x] -> B[1] : x >= N }",6030 "{ A[y] -> C[2] : y <= 10 }",6031 "[N] -> { A[x] -> [B[(1 : x >= N)] -> C[(2 : x <= 10)]] }" },6032 { &isl_multi_pw_aff_range_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",6033 "{ A[] -> [B[1] -> C[2]] }" },6034 { &isl_multi_pw_aff_range_product, "{ A[] -> B[] }", "{ A[] -> C[] }",6035 "{ A[] -> [B[] -> C[]] }" },6036 { &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",6037 "{ A[y] -> C[] : y <= 10 }",6038 "{ A[x] -> [B[(1 : x >= 5)] -> C[]] : x <= 10 }" },6039 { &isl_multi_pw_aff_range_product, "{ A[y] -> C[] : y <= 10 }",6040 "{ A[x] -> B[(1 : x >= 5)] }",6041 "{ A[x] -> [C[] -> B[(1 : x >= 5)]] : x <= 10 }" },6042 { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",6043 "{ A[y] -> C[(2 : y <= 10)] }",6044 "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[(2 : y <= 10)]] }" },6045 { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",6046 "{ A[y] -> C[] : y <= 10 }",6047 "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= 10 }" },6048 { &isl_multi_pw_aff_product, "{ A[y] -> C[] : y <= 10 }",6049 "{ A[x] -> B[(1 : x >= 5)] }",6050 "{ [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= 10 }" },6051 { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",6052 "[N] -> { A[y] -> C[] : y <= N }",6053 "[N] -> { [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= N }" },6054 { &isl_multi_pw_aff_product, "[N] -> { A[y] -> C[] : y <= N }",6055 "{ A[x] -> B[(1 : x >= 5)] }",6056 "[N] -> { [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= N }" },6057 { &isl_multi_pw_aff_product, "{ A[x] -> B[] : x >= 5 }",6058 "{ A[y] -> C[] : y <= 10 }",6059 "{ [A[x] -> A[y]] -> [B[] -> C[]] : x >= 5 and y <= 10 }" },6060 { &isl_multi_pw_aff_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",6061 "{ [A[] -> A[]] -> [B[1] -> C[2]] }" },6062 { &isl_multi_pw_aff_product, "{ A[] -> B[] }", "{ A[] -> C[] }",6063 "{ [A[] -> A[]] -> [B[] -> C[]] }" },6064 { &isl_multi_pw_aff_pullback_multi_pw_aff,6065 "{ B[i,j] -> C[i + 2j] }", "{ A[a,b] -> B[b,a] }",6066 "{ A[a,b] -> C[b + 2a] }" },6067 { &isl_multi_pw_aff_pullback_multi_pw_aff,6068 "{ B[i,j] -> C[i + 2j] }",6069 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6070 "{ A[a,b] -> C[(b + 2a : b > a)] }" },6071 { &isl_multi_pw_aff_pullback_multi_pw_aff,6072 "{ B[i,j] -> C[(i + 2j : j > 4)] }",6073 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6074 "{ A[a,b] -> C[(b + 2a : b > a > 4)] }" },6075 { &isl_multi_pw_aff_pullback_multi_pw_aff,6076 "{ B[i,j] -> C[] }",6077 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6078 "{ A[a,b] -> C[] }" },6079 { &isl_multi_pw_aff_pullback_multi_pw_aff,6080 "{ B[i,j] -> C[] : i > j }",6081 "{ A[a,b] -> B[b,a] }",6082 "{ A[a,b] -> C[] : b > a }" },6083 { &isl_multi_pw_aff_pullback_multi_pw_aff,6084 "{ B[i,j] -> C[] : j > 5 }",6085 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6086 "{ A[a,b] -> C[] : b > a > 5 }" },6087 { &isl_multi_pw_aff_pullback_multi_pw_aff,6088 "[N] -> { B[i,j] -> C[] : j > N }",6089 "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",6090 "[N] -> { A[a,b] -> C[] : b > a > N }" },6091 { &isl_multi_pw_aff_pullback_multi_pw_aff,6092 "[M,N] -> { B[] -> C[] : N > 5 }",6093 "[M,N] -> { A[] -> B[] : M > N }",6094 "[M,N] -> { A[] -> C[] : M > N > 5 }" },6095};6096 6097/* Perform some basic tests of binary operations on isl_multi_pw_aff objects.6098 */6099static int test_bin_mpa(isl_ctx *ctx)6100{6101 int i;6102 isl_bool ok;6103 isl_multi_pw_aff *mpa1, *mpa2, *res;6104 6105 for (i = 0; i < ARRAY_SIZE(mpa_bin_tests); ++i) {6106 mpa1 = isl_multi_pw_aff_read_from_str(ctx,6107 mpa_bin_tests[i].arg1);6108 mpa2 = isl_multi_pw_aff_read_from_str(ctx,6109 mpa_bin_tests[i].arg2);6110 res = isl_multi_pw_aff_read_from_str(ctx,6111 mpa_bin_tests[i].res);6112 mpa1 = mpa_bin_tests[i].fn(mpa1, mpa2);6113 ok = isl_multi_pw_aff_plain_is_equal(mpa1, res);6114 isl_multi_pw_aff_free(mpa1);6115 isl_multi_pw_aff_free(res);6116 if (ok < 0)6117 return -1;6118 if (!ok)6119 isl_die(ctx, isl_error_unknown,6120 "unexpected result", return -1);6121 }6122 6123 return 0;6124}6125 6126/* Inputs for basic tests of unary operations on6127 * isl_multi_union_pw_aff objects.6128 * "fn" is the function that is tested.6129 * "arg" is a string description of the input.6130 * "res" is a string description of the expected result.6131 */6132struct {6133 __isl_give isl_multi_union_pw_aff *(*fn)(6134 __isl_take isl_multi_union_pw_aff *mupa);6135 const char *arg;6136 const char *res;6137} mupa_un_tests[] = {6138 { &isl_multi_union_pw_aff_factor_range,6139 "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]",6140 "C[{ A[] -> [2] }]" },6141 { &isl_multi_union_pw_aff_factor_range,6142 "[B[] -> C[{ A[] -> [2] }]]",6143 "C[{ A[] -> [2] }]" },6144 { &isl_multi_union_pw_aff_factor_range,6145 "[B[{ A[] -> [1] }] -> C[]]",6146 "C[]" },6147 { &isl_multi_union_pw_aff_factor_range,6148 "[B[] -> C[]]",6149 "C[]" },6150 { &isl_multi_union_pw_aff_factor_range,6151 "([B[] -> C[]] : { A[x] : x >= 0 })",6152 "(C[] : { A[x] : x >= 0 })" },6153 { &isl_multi_union_pw_aff_factor_range,6154 "[N] -> ([B[] -> C[]] : { A[x] : x <= N })",6155 "[N] -> (C[] : { A[x] : x <= N })" },6156 { &isl_multi_union_pw_aff_factor_range,6157 "[N] -> ([B[] -> C[]] : { : N >= 0 })",6158 "[N] -> (C[] : { : N >= 0 })" },6159};6160 6161/* Perform some basic tests of unary operations on6162 * isl_multi_union_pw_aff objects.6163 */6164static int test_un_mupa(isl_ctx *ctx)6165{6166 int i;6167 isl_bool ok;6168 isl_multi_union_pw_aff *mupa, *res;6169 6170 for (i = 0; i < ARRAY_SIZE(mupa_un_tests); ++i) {6171 mupa = isl_multi_union_pw_aff_read_from_str(ctx,6172 mupa_un_tests[i].arg);6173 res = isl_multi_union_pw_aff_read_from_str(ctx,6174 mupa_un_tests[i].res);6175 mupa = mupa_un_tests[i].fn(mupa);6176 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6177 isl_multi_union_pw_aff_free(mupa);6178 isl_multi_union_pw_aff_free(res);6179 if (ok < 0)6180 return -1;6181 if (!ok)6182 isl_die(ctx, isl_error_unknown,6183 "unexpected result", return -1);6184 }6185 6186 return 0;6187}6188 6189/* Inputs for basic tests of binary operations on6190 * isl_multi_union_pw_aff objects.6191 * "fn" is the function that is tested.6192 * "arg1" and "arg2" are string descriptions of the inputs.6193 * "res" is a string description of the expected result.6194 */6195struct {6196 __isl_give isl_multi_union_pw_aff *(*fn)(6197 __isl_take isl_multi_union_pw_aff *mupa1,6198 __isl_take isl_multi_union_pw_aff *mupa2);6199 const char *arg1;6200 const char *arg2;6201 const char *res;6202} mupa_bin_tests[] = {6203 { &isl_multi_union_pw_aff_add, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",6204 "[{ A[] -> [3] }]" },6205 { &isl_multi_union_pw_aff_sub, "[{ A[] -> [1] }]", "[{ A[] -> [2] }]",6206 "[{ A[] -> [-1] }]" },6207 { &isl_multi_union_pw_aff_add,6208 "[{ A[] -> [1]; B[] -> [4] }]",6209 "[{ A[] -> [2]; C[] -> [5] }]",6210 "[{ A[] -> [3] }]" },6211 { &isl_multi_union_pw_aff_union_add,6212 "[{ A[] -> [1]; B[] -> [4] }]",6213 "[{ A[] -> [2]; C[] -> [5] }]",6214 "[{ A[] -> [3]; B[] -> [4]; C[] -> [5] }]" },6215 { &isl_multi_union_pw_aff_add, "[{ A[x] -> [(1)] : x >= 5 }]",6216 "[{ A[x] -> [(x)] : x <= 10 }]",6217 "[{ A[x] -> [(1 + x)] : 5 <= x <= 10 }]" },6218 { &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",6219 "([] : { A[x] : x <= 10 })",6220 "([] : { A[x] : 5 <= x <= 10 })" },6221 { &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",6222 "[N] -> ([] : { A[x] : x <= N })",6223 "[N] -> ([] : { A[x] : 5 <= x <= N })" },6224 { &isl_multi_union_pw_aff_add, "[N] -> ([] : { A[x] : x >= N })",6225 "([] : { A[x] : x <= 10 })",6226 "[N] -> ([] : { A[x] : N <= x <= 10 })" },6227 { &isl_multi_union_pw_aff_union_add, "[{ A[x] -> [(1)] : x >= 5 }]",6228 "[{ A[x] -> [(x)] : x <= 10 }]",6229 "[{ A[x] -> [(1 + x)] : 5 <= x <= 10; "6230 "A[x] -> [(1)] : x > 10; A[x] -> [(x)] : x < 5 }]" },6231 { &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 5 })",6232 "([] : { A[x] : x <= 10 })",6233 "([] : { A[x] })" },6234 { &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 0 })",6235 "[N] -> ([] : { A[x] : x >= N })",6236 "[N] -> ([] : { A[x] : x >= 0 or x >= N })" },6237 { &isl_multi_union_pw_aff_union_add,6238 "[N] -> ([] : { A[] : N >= 0})",6239 "[N] -> ([] : { A[] : N <= 0})",6240 "[N] -> ([] : { A[] })" },6241 { &isl_multi_union_pw_aff_union_add,6242 "[N] -> ([] : { A[] })",6243 "[N] -> ([] : { : })",6244 "[N] -> ([] : { : })" },6245 { &isl_multi_union_pw_aff_union_add,6246 "[N] -> ([] : { : })",6247 "[N] -> ([] : { A[] })",6248 "[N] -> ([] : { : })" },6249 { &isl_multi_union_pw_aff_union_add,6250 "[N] -> ([] : { : N >= 0})",6251 "[N] -> ([] : { : N <= 0})",6252 "[N] -> ([] : { : })" },6253 { &isl_multi_union_pw_aff_range_product,6254 "B[{ A[] -> [1] }]",6255 "C[{ A[] -> [2] }]",6256 "[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]" },6257 { &isl_multi_union_pw_aff_range_product,6258 "(B[] : { A[x] : x >= 5 })",6259 "(C[] : { A[x] : x <= 10 })",6260 "([B[] -> C[]] : { A[x] : 5 <= x <= 10 })" },6261 { &isl_multi_union_pw_aff_range_product,6262 "B[{ A[x] -> [x + 1] : x >= 5 }]",6263 "(C[] : { A[x] : x <= 10 })",6264 "[B[{ A[x] -> [x + 1] : 5 <= x <= 10 }] -> C[]]" },6265 { &isl_multi_union_pw_aff_range_product,6266 "(C[] : { A[x] : x <= 10 })",6267 "B[{ A[x] -> [x + 1] : x >= 5 }]",6268 "[C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= 10 }]]" },6269 { &isl_multi_union_pw_aff_range_product,6270 "B[{ A[x] -> [x + 1] : x >= 5 }]",6271 "[N] -> (C[] : { A[x] : x <= N })",6272 "[N] -> [B[{ A[x] -> [x + 1] : 5 <= x <= N }] -> C[]]" },6273 { &isl_multi_union_pw_aff_range_product,6274 "[N] -> (C[] : { A[x] : x <= N })",6275 "B[{ A[x] -> [x + 1] : x >= 5 }]",6276 "[N] -> [C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= N }]]" },6277 { &isl_multi_union_pw_aff_range_product,6278 "B[{ A[] -> [1]; D[] -> [3] }]",6279 "C[{ A[] -> [2] }]",6280 "[B[{ A[] -> [1]; D[] -> [3] }] -> C[{ A[] -> [2] }]]" },6281 { &isl_multi_union_pw_aff_range_product,6282 "B[] }]",6283 "(C[] : { A[x] })",6284 "([B[] -> C[]] : { A[x] })" },6285 { &isl_multi_union_pw_aff_range_product,6286 "(B[] : { A[x] })",6287 "C[] }]",6288 "([B[] -> C[]] : { A[x] })" },6289};6290 6291/* Perform some basic tests of binary operations on6292 * isl_multi_union_pw_aff objects.6293 */6294static int test_bin_mupa(isl_ctx *ctx)6295{6296 int i;6297 isl_bool ok;6298 isl_multi_union_pw_aff *mupa1, *mupa2, *res;6299 6300 for (i = 0; i < ARRAY_SIZE(mupa_bin_tests); ++i) {6301 mupa1 = isl_multi_union_pw_aff_read_from_str(ctx,6302 mupa_bin_tests[i].arg1);6303 mupa2 = isl_multi_union_pw_aff_read_from_str(ctx,6304 mupa_bin_tests[i].arg2);6305 res = isl_multi_union_pw_aff_read_from_str(ctx,6306 mupa_bin_tests[i].res);6307 mupa1 = mupa_bin_tests[i].fn(mupa1, mupa2);6308 ok = isl_multi_union_pw_aff_plain_is_equal(mupa1, res);6309 isl_multi_union_pw_aff_free(mupa1);6310 isl_multi_union_pw_aff_free(res);6311 if (ok < 0)6312 return -1;6313 if (!ok)6314 isl_die(ctx, isl_error_unknown,6315 "unexpected result", return -1);6316 }6317 6318 return 0;6319}6320 6321/* Inputs for basic tests of binary operations on6322 * pairs of isl_multi_union_pw_aff and isl_set objects.6323 * "fn" is the function that is tested.6324 * "arg1" and "arg2" are string descriptions of the inputs.6325 * "res" is a string description of the expected result.6326 */6327struct {6328 __isl_give isl_multi_union_pw_aff *(*fn)(6329 __isl_take isl_multi_union_pw_aff *mupa,6330 __isl_take isl_set *set);6331 const char *arg1;6332 const char *arg2;6333 const char *res;6334} mupa_set_tests[] = {6335 { &isl_multi_union_pw_aff_intersect_range,6336 "C[{ B[i,j] -> [i + 2j] }]", "{ C[1] }",6337 "C[{ B[i,j] -> [i + 2j] : i + 2j = 1 }]" },6338 { &isl_multi_union_pw_aff_intersect_range,6339 "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[N] }",6340 "[N] -> C[{ B[i,j] -> [i + 2j] : i + 2j = N }]" },6341 { &isl_multi_union_pw_aff_intersect_range,6342 "[N] -> C[{ B[i,j] -> [i + 2j + N] }]", "{ C[1] }",6343 "[N] -> C[{ B[i,j] -> [i + 2j + N] : i + 2j + N = 1 }]" },6344 { &isl_multi_union_pw_aff_intersect_range,6345 "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[x] : N >= 0 }",6346 "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0 }]" },6347 { &isl_multi_union_pw_aff_intersect_range,6348 "C[]", "{ C[] }", "C[]" },6349 { &isl_multi_union_pw_aff_intersect_range,6350 "[N] -> (C[] : { : N >= 0 })",6351 "{ C[] }",6352 "[N] -> (C[] : { : N >= 0 })" },6353 { &isl_multi_union_pw_aff_intersect_range,6354 "(C[] : { A[a,b] })",6355 "{ C[] }",6356 "(C[] : { A[a,b] })" },6357 { &isl_multi_union_pw_aff_intersect_range,6358 "[N] -> (C[] : { A[a,b] : a,b <= N })",6359 "{ C[] }",6360 "[N] -> (C[] : { A[a,b] : a,b <= N })" },6361 { &isl_multi_union_pw_aff_intersect_range,6362 "C[]",6363 "[N] -> { C[] : N >= 0 }",6364 "[N] -> (C[] : { : N >= 0 })" },6365 { &isl_multi_union_pw_aff_intersect_range,6366 "(C[] : { A[a,b] })",6367 "[N] -> { C[] : N >= 0 }",6368 "[N] -> (C[] : { A[a,b] : N >= 0 })" },6369 { &isl_multi_union_pw_aff_intersect_range,6370 "[N] -> (C[] : { : N >= 0 })",6371 "[N] -> { C[] : N < 1024 }",6372 "[N] -> (C[] : { : 0 <= N < 1024 })" },6373 { &isl_multi_union_pw_aff_intersect_params,6374 "C[{ B[i,j] -> [i + 2j] }]", "[N] -> { : N >= 0 }",6375 "[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0}]" },6376 { &isl_multi_union_pw_aff_intersect_params,6377 "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "[N] -> { : N >= 0 }",6378 "[N] -> C[{ B[i,j] -> [i + 2j] : 0 <= N <= 256 }]" },6379 { &isl_multi_union_pw_aff_intersect_params,6380 "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "{ : }",6381 "[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]" },6382 { &isl_multi_union_pw_aff_intersect_params,6383 "C[]", "[N] -> { : N >= 0 }",6384 "[N] -> (C[] : { : N >= 0 })" },6385 { &isl_multi_union_pw_aff_intersect_params,6386 "(C[] : { A[a,b] })", "[N] -> { : N >= 0 }",6387 "[N] -> (C[] : { A[a,b] : N >= 0 })" },6388 { &isl_multi_union_pw_aff_intersect_params,6389 "[N] -> (C[] : { A[a,N] })", "{ : }",6390 "[N] -> (C[] : { A[a,N] })" },6391 { &isl_multi_union_pw_aff_intersect_params,6392 "[N] -> (C[] : { A[a,b] : N <= 256 })", "[N] -> { : N >= 0 }",6393 "[N] -> (C[] : { A[a,b] : 0 <= N <= 256 })" },6394};6395 6396/* Perform some basic tests of binary operations on6397 * pairs of isl_multi_union_pw_aff and isl_set objects.6398 */6399static int test_mupa_set(isl_ctx *ctx)6400{6401 int i;6402 isl_bool ok;6403 isl_multi_union_pw_aff *mupa, *res;6404 isl_set *set;6405 6406 for (i = 0; i < ARRAY_SIZE(mupa_set_tests); ++i) {6407 mupa = isl_multi_union_pw_aff_read_from_str(ctx,6408 mupa_set_tests[i].arg1);6409 set = isl_set_read_from_str(ctx, mupa_set_tests[i].arg2);6410 res = isl_multi_union_pw_aff_read_from_str(ctx,6411 mupa_set_tests[i].res);6412 mupa = mupa_set_tests[i].fn(mupa, set);6413 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6414 isl_multi_union_pw_aff_free(mupa);6415 isl_multi_union_pw_aff_free(res);6416 if (ok < 0)6417 return -1;6418 if (!ok)6419 isl_die(ctx, isl_error_unknown,6420 "unexpected result", return -1);6421 }6422 6423 return 0;6424}6425 6426/* Inputs for basic tests of binary operations on6427 * pairs of isl_multi_union_pw_aff and isl_union_set objects.6428 * "fn" is the function that is tested.6429 * "arg1" and "arg2" are string descriptions of the inputs.6430 * "res" is a string description of the expected result.6431 */6432struct {6433 __isl_give isl_multi_union_pw_aff *(*fn)(6434 __isl_take isl_multi_union_pw_aff *mupa,6435 __isl_take isl_union_set *uset);6436 const char *arg1;6437 const char *arg2;6438 const char *res;6439} mupa_uset_tests[] = {6440 { &isl_multi_union_pw_aff_intersect_domain,6441 "C[{ B[i,j] -> [i + 2j] }]", "{ B[i,i] }",6442 "C[{ B[i,i] -> [3i] }]" },6443 { &isl_multi_union_pw_aff_intersect_domain,6444 "(C[] : { B[i,j] })", "{ B[i,i] }",6445 "(C[] : { B[i,i] })" },6446 { &isl_multi_union_pw_aff_intersect_domain,6447 "(C[] : { B[i,j] })", "[N] -> { B[N,N] }",6448 "[N] -> (C[] : { B[N,N] })" },6449 { &isl_multi_union_pw_aff_intersect_domain,6450 "C[]", "{ B[i,i] }",6451 "(C[] : { B[i,i] })" },6452 { &isl_multi_union_pw_aff_intersect_domain,6453 "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }",6454 "[N] -> (C[] : { B[i,i] : N >= 0 })" },6455};6456 6457/* Perform some basic tests of binary operations on6458 * pairs of isl_multi_union_pw_aff and isl_union_set objects.6459 */6460static int test_mupa_uset(isl_ctx *ctx)6461{6462 int i;6463 isl_bool ok;6464 isl_multi_union_pw_aff *mupa, *res;6465 isl_union_set *uset;6466 6467 for (i = 0; i < ARRAY_SIZE(mupa_uset_tests); ++i) {6468 mupa = isl_multi_union_pw_aff_read_from_str(ctx,6469 mupa_uset_tests[i].arg1);6470 uset = isl_union_set_read_from_str(ctx,6471 mupa_uset_tests[i].arg2);6472 res = isl_multi_union_pw_aff_read_from_str(ctx,6473 mupa_uset_tests[i].res);6474 mupa = mupa_uset_tests[i].fn(mupa, uset);6475 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6476 isl_multi_union_pw_aff_free(mupa);6477 isl_multi_union_pw_aff_free(res);6478 if (ok < 0)6479 return -1;6480 if (!ok)6481 isl_die(ctx, isl_error_unknown,6482 "unexpected result", return -1);6483 }6484 6485 return 0;6486}6487 6488/* Inputs for basic tests of binary operations on6489 * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.6490 * "fn" is the function that is tested.6491 * "arg1" and "arg2" are string descriptions of the inputs.6492 * "res" is a string description of the expected result.6493 */6494struct {6495 __isl_give isl_multi_union_pw_aff *(*fn)(6496 __isl_take isl_multi_union_pw_aff *mupa,6497 __isl_take isl_multi_aff *ma);6498 const char *arg1;6499 const char *arg2;6500 const char *res;6501} mupa_ma_tests[] = {6502 { &isl_multi_union_pw_aff_apply_multi_aff,6503 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "6504 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6505 "{ C[a,b] -> D[b,a] }",6506 "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "6507 "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },6508 { &isl_multi_union_pw_aff_apply_multi_aff,6509 "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "6510 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6511 "{ C[a,b] -> D[b,a] }",6512 "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "6513 "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },6514 { &isl_multi_union_pw_aff_apply_multi_aff,6515 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6516 "[N] -> { C[a] -> D[a + N] }",6517 "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }] " },6518 { &isl_multi_union_pw_aff_apply_multi_aff,6519 "C[]",6520 "{ C[] -> D[] }",6521 "D[]" },6522 { &isl_multi_union_pw_aff_apply_multi_aff,6523 "[N] -> (C[] : { : N >= 0 })",6524 "{ C[] -> D[] }",6525 "[N] -> (D[] : { : N >= 0 })" },6526 { &isl_multi_union_pw_aff_apply_multi_aff,6527 "C[]",6528 "[N] -> { C[] -> D[N] }",6529 "[N] -> D[{ [N] }]" },6530 { &isl_multi_union_pw_aff_apply_multi_aff,6531 "(C[] : { A[i,j] : i >= j })",6532 "{ C[] -> D[] }",6533 "(D[] : { A[i,j] : i >= j })" },6534 { &isl_multi_union_pw_aff_apply_multi_aff,6535 "[N] -> (C[] : { A[i,j] : N >= 0 })",6536 "{ C[] -> D[] }",6537 "[N] -> (D[] : { A[i,j] : N >= 0 })" },6538 { &isl_multi_union_pw_aff_apply_multi_aff,6539 "(C[] : { A[i,j] : i >= j })",6540 "[N] -> { C[] -> D[N] }",6541 "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },6542};6543 6544/* Perform some basic tests of binary operations on6545 * pairs of isl_multi_union_pw_aff and isl_multi_aff objects.6546 */6547static int test_mupa_ma(isl_ctx *ctx)6548{6549 int i;6550 isl_bool ok;6551 isl_multi_union_pw_aff *mupa, *res;6552 isl_multi_aff *ma;6553 6554 for (i = 0; i < ARRAY_SIZE(mupa_ma_tests); ++i) {6555 mupa = isl_multi_union_pw_aff_read_from_str(ctx,6556 mupa_ma_tests[i].arg1);6557 ma = isl_multi_aff_read_from_str(ctx, mupa_ma_tests[i].arg2);6558 res = isl_multi_union_pw_aff_read_from_str(ctx,6559 mupa_ma_tests[i].res);6560 mupa = mupa_ma_tests[i].fn(mupa, ma);6561 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6562 isl_multi_union_pw_aff_free(mupa);6563 isl_multi_union_pw_aff_free(res);6564 if (ok < 0)6565 return -1;6566 if (!ok)6567 isl_die(ctx, isl_error_unknown,6568 "unexpected result", return -1);6569 }6570 6571 return 0;6572}6573 6574/* Inputs for basic tests of binary operations on6575 * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.6576 * "fn" is the function that is tested.6577 * "arg1" and "arg2" are string descriptions of the inputs.6578 * "res" is a string description of the expected result.6579 */6580struct {6581 __isl_give isl_union_pw_aff *(*fn)(6582 __isl_take isl_multi_union_pw_aff *mupa,6583 __isl_take isl_pw_aff *pa);6584 const char *arg1;6585 const char *arg2;6586 const char *res;6587} mupa_pa_tests[] = {6588 { &isl_multi_union_pw_aff_apply_pw_aff,6589 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6590 "[N] -> { C[a] -> [a + N] }",6591 "[N] -> { A[i,j] -> [i + N]; B[i,j] -> [j + N] }" },6592 { &isl_multi_union_pw_aff_apply_pw_aff,6593 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6594 "{ C[a] -> [a] : a >= 0; C[a] -> [-a] : a < 0 }",6595 "{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "6596 "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }" },6597 { &isl_multi_union_pw_aff_apply_pw_aff,6598 "C[]",6599 "[N] -> { C[] -> [N] }",6600 "[N] -> { [N] }" },6601 { &isl_multi_union_pw_aff_apply_pw_aff,6602 "C[]",6603 "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",6604 "[N] -> { [N] : N >= 0; [-N] : N < 0 }" },6605 { &isl_multi_union_pw_aff_apply_pw_aff,6606 "[N] -> (C[] : { : N >= 0 })",6607 "[N] -> { C[] -> [N] }",6608 "[N] -> { [N] : N >= 0 }" },6609 { &isl_multi_union_pw_aff_apply_pw_aff,6610 "[N] -> (C[] : { : N >= 0 })",6611 "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",6612 "[N] -> { [N] : N >= 0 }" },6613 { &isl_multi_union_pw_aff_apply_pw_aff,6614 "[N] -> (C[] : { : N >= 0 })",6615 "{ C[] -> [0] }",6616 "[N] -> { [0] : N >= 0 }" },6617 { &isl_multi_union_pw_aff_apply_pw_aff,6618 "(C[] : { A[i,j] : i >= j })",6619 "[N] -> { C[] -> [N] }",6620 "[N] -> { A[i,j] -> [N] : i >= j }" },6621 { &isl_multi_union_pw_aff_apply_pw_aff,6622 "(C[] : { A[i,j] : i >= j })",6623 "[N] -> { C[] -> [N] : N >= 0 }",6624 "[N] -> { A[i,j] -> [N] : i >= j and N >= 0 }" },6625};6626 6627/* Perform some basic tests of binary operations on6628 * pairs of isl_multi_union_pw_aff and isl_pw_aff objects.6629 */6630static int test_mupa_pa(isl_ctx *ctx)6631{6632 int i;6633 isl_bool ok;6634 isl_multi_union_pw_aff *mupa;6635 isl_union_pw_aff *upa, *res;6636 isl_pw_aff *pa;6637 6638 for (i = 0; i < ARRAY_SIZE(mupa_pa_tests); ++i) {6639 mupa = isl_multi_union_pw_aff_read_from_str(ctx,6640 mupa_pa_tests[i].arg1);6641 pa = isl_pw_aff_read_from_str(ctx, mupa_pa_tests[i].arg2);6642 res = isl_union_pw_aff_read_from_str(ctx,6643 mupa_pa_tests[i].res);6644 upa = mupa_pa_tests[i].fn(mupa, pa);6645 ok = isl_union_pw_aff_plain_is_equal(upa, res);6646 isl_union_pw_aff_free(upa);6647 isl_union_pw_aff_free(res);6648 if (ok < 0)6649 return -1;6650 if (!ok)6651 isl_die(ctx, isl_error_unknown,6652 "unexpected result", return -1);6653 }6654 6655 return 0;6656}6657 6658/* Inputs for basic tests of binary operations on6659 * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.6660 * "fn" is the function that is tested.6661 * "arg1" and "arg2" are string descriptions of the inputs.6662 * "res" is a string description of the expected result.6663 */6664struct {6665 __isl_give isl_multi_union_pw_aff *(*fn)(6666 __isl_take isl_multi_union_pw_aff *mupa,6667 __isl_take isl_pw_multi_aff *pma);6668 const char *arg1;6669 const char *arg2;6670 const char *res;6671} mupa_pma_tests[] = {6672 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6673 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "6674 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6675 "{ C[a,b] -> D[b,a] }",6676 "D[{ A[i,j] -> [j]; B[i,j] -> [i] }, "6677 "{ A[i,j] -> [i]; B[i,j] -> [j] }]" },6678 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6679 "C[{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }, "6680 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6681 "{ C[a,b] -> D[b,a] }",6682 "D[{ A[i,j] -> [j] : i >= 0; B[i,j] -> [i] }, "6683 "{ A[i,j] -> [i] : i >= 0; B[i,j] -> [j] }]" },6684 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6685 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6686 "[N] -> { C[a] -> D[a + N] }",6687 "[N] -> D[{ A[i,j] -> [i + N]; B[i,j] -> [j + N] }]" },6688 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6689 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }]",6690 "{ C[a] -> D[a] : a >= 0; C[a] -> D[-a] : a < 0 }",6691 "D[{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "6692 "B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }]" },6693 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6694 "C[{ A[i,j] -> [i]; B[i,j] -> [j] }, "6695 "{ A[i,j] -> [j]; B[i,j] -> [i] }]",6696 "{ C[a,b] -> D[a,b] : a >= b; C[a,b] -> D[b,a] : a < b }",6697 "D[{ A[i,j] -> [i] : i >= j; A[i,j] -> [j] : i < j; "6698 "B[i,j] -> [j] : i <= j; B[i,j] -> [i] : i > j }, "6699 "{ A[i,j] -> [j] : i >= j; A[i,j] -> [i] : i < j; "6700 "B[i,j] -> [i] : i <= j; B[i,j] -> [j] : i > j }]" },6701 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6702 "C[]",6703 "{ C[] -> D[] }",6704 "D[]" },6705 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6706 "[N] -> (C[] : { : N >= 0 })",6707 "{ C[] -> D[] }",6708 "[N] -> (D[] : { : N >= 0 })" },6709 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6710 "C[]",6711 "[N] -> { C[] -> D[N] }",6712 "[N] -> D[{ [N] }]" },6713 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6714 "(C[] : { A[i,j] : i >= j })",6715 "{ C[] -> D[] }",6716 "(D[] : { A[i,j] : i >= j })" },6717 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6718 "[N] -> (C[] : { A[i,j] : N >= 0 })",6719 "{ C[] -> D[] }",6720 "[N] -> (D[] : { A[i,j] : N >= 0 })" },6721 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6722 "(C[] : { A[i,j] : i >= j })",6723 "[N] -> { C[] -> D[N] }",6724 "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },6725 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6726 "C[]",6727 "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",6728 "[N] -> D[{ [N] : N >= 0; [-N] : N < 0 }]" },6729 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6730 "[N] -> (C[] : { : N >= 0 })",6731 "[N] -> { C[] -> D[N] }",6732 "[N] -> D[{ [N] : N >= 0 }]" },6733 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6734 "[N] -> (C[] : { : N >= 0 })",6735 "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",6736 "[N] -> D[{ [N] : N >= 0 }]" },6737 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6738 "[N] -> (C[] : { : N >= 0 })",6739 "{ C[] -> D[0] }",6740 "[N] -> D[{ [0] : N >= 0 }]" },6741 { &isl_multi_union_pw_aff_apply_pw_multi_aff,6742 "(C[] : { A[i,j] : i >= j })",6743 "[N] -> { C[] -> D[N] : N >= 0 }",6744 "[N] -> D[{ A[i,j] -> [N] : i >= j and N >= 0 }]" },6745};6746 6747/* Perform some basic tests of binary operations on6748 * pairs of isl_multi_union_pw_aff and isl_pw_multi_aff objects.6749 */6750static int test_mupa_pma(isl_ctx *ctx)6751{6752 int i;6753 isl_bool ok;6754 isl_multi_union_pw_aff *mupa, *res;6755 isl_pw_multi_aff *pma;6756 6757 for (i = 0; i < ARRAY_SIZE(mupa_pma_tests); ++i) {6758 mupa = isl_multi_union_pw_aff_read_from_str(ctx,6759 mupa_pma_tests[i].arg1);6760 pma = isl_pw_multi_aff_read_from_str(ctx,6761 mupa_pma_tests[i].arg2);6762 res = isl_multi_union_pw_aff_read_from_str(ctx,6763 mupa_pma_tests[i].res);6764 mupa = mupa_pma_tests[i].fn(mupa, pma);6765 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6766 isl_multi_union_pw_aff_free(mupa);6767 isl_multi_union_pw_aff_free(res);6768 if (ok < 0)6769 return -1;6770 if (!ok)6771 isl_die(ctx, isl_error_unknown,6772 "unexpected result", return -1);6773 }6774 6775 return 0;6776}6777 6778/* Inputs for basic tests of binary operations on6779 * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.6780 * "fn" is the function that is tested.6781 * "arg1" and "arg2" are string descriptions of the inputs.6782 * "res" is a string description of the expected result.6783 */6784struct {6785 __isl_give isl_multi_union_pw_aff *(*fn)(6786 __isl_take isl_multi_union_pw_aff *mupa,6787 __isl_take isl_union_pw_multi_aff *upma);6788 const char *arg1;6789 const char *arg2;6790 const char *res;6791} mupa_upma_tests[] = {6792 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6793 "C[{ B[i,j] -> [i + 2j] }]", "{ A[a,b] -> B[b,a] }",6794 "C[{ A[a,b] -> [b + 2a] }]" },6795 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6796 "C[{ B[i,j] -> [i + 2j] }]",6797 "{ A[a,b] -> B[b,a] : b > a }",6798 "C[{ A[a,b] -> [b + 2a] : b > a }]" },6799 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6800 "C[{ B[i,j] -> [i + 2j] : j > 4 }]",6801 "{ A[a,b] -> B[b,a] : b > a }",6802 "C[{ A[a,b] -> [b + 2a] : b > a > 4 }]" },6803 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6804 "C[{ B[i,j] -> [i + 2j] }]",6805 "{ A[a,b] -> B[b,a] : a > b; A[a,b] -> B[a,b] : a <= b }",6806 "C[{ A[a,b] -> [b + 2a] : a > b; A[a,b] -> [a + 2b] : a <= b }]" },6807 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6808 "(C[] : { B[a,b] })",6809 "{ A[a,b] -> B[b,a] }",6810 "(C[] : { A[a,b] })" },6811 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6812 "(C[] : { B[a,b] })",6813 "{ B[a,b] -> A[b,a] }",6814 "(C[] : { })" },6815 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6816 "(C[] : { B[a,b] })",6817 "{ A[a,b] -> B[b,a] : a > b }",6818 "(C[] : { A[a,b] : a > b })" },6819 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6820 "(C[] : { B[a,b] : a > b })",6821 "{ A[a,b] -> B[b,a] }",6822 "(C[] : { A[a,b] : b > a })" },6823 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6824 "[N] -> (C[] : { B[a,b] : a > N })",6825 "{ A[a,b] -> B[b,a] : a > b }",6826 "[N] -> (C[] : { A[a,b] : a > b > N })" },6827 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6828 "(C[] : { B[a,b] : a > b })",6829 "[N] -> { A[a,b] -> B[b,a] : a > N }",6830 "[N] -> (C[] : { A[a,b] : b > a > N })" },6831 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6832 "C[]",6833 "{ A[a,b] -> B[b,a] }",6834 "C[]" },6835 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6836 "[N] -> (C[] : { : N >= 0 })",6837 "{ A[a,b] -> B[b,a] }",6838 "[N] -> (C[] : { : N >= 0 })" },6839 { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,6840 "C[]",6841 "[N] -> { A[a,b] -> B[b,a] : N >= 0 }",6842 "[N] -> (C[] : { : N >= 0 })" },6843};6844 6845/* Perform some basic tests of binary operations on6846 * pairs of isl_multi_union_pw_aff and isl_union_pw_multi_aff objects.6847 */6848static int test_mupa_upma(isl_ctx *ctx)6849{6850 int i;6851 isl_bool ok;6852 isl_multi_union_pw_aff *mupa, *res;6853 isl_union_pw_multi_aff *upma;6854 6855 for (i = 0; i < ARRAY_SIZE(mupa_upma_tests); ++i) {6856 mupa = isl_multi_union_pw_aff_read_from_str(ctx,6857 mupa_upma_tests[i].arg1);6858 upma = isl_union_pw_multi_aff_read_from_str(ctx,6859 mupa_upma_tests[i].arg2);6860 res = isl_multi_union_pw_aff_read_from_str(ctx,6861 mupa_upma_tests[i].res);6862 mupa = mupa_upma_tests[i].fn(mupa, upma);6863 ok = isl_multi_union_pw_aff_plain_is_equal(mupa, res);6864 isl_multi_union_pw_aff_free(mupa);6865 isl_multi_union_pw_aff_free(res);6866 if (ok < 0)6867 return -1;6868 if (!ok)6869 isl_die(ctx, isl_error_unknown,6870 "unexpected result", return -1);6871 }6872 6873 return 0;6874}6875 6876/* Check that the input tuple of an isl_aff can be set properly.6877 */6878static isl_stat test_aff_set_tuple_id(isl_ctx *ctx)6879{6880 isl_id *id;6881 isl_aff *aff;6882 isl_stat equal;6883 6884 aff = isl_aff_read_from_str(ctx, "{ [x] -> [x + 1] }");6885 id = isl_id_alloc(ctx, "A", NULL);6886 aff = isl_aff_set_tuple_id(aff, isl_dim_in, id);6887 equal = aff_check_plain_equal(aff, "{ A[x] -> [x + 1] }");6888 isl_aff_free(aff);6889 if (equal < 0)6890 return isl_stat_error;6891 6892 return isl_stat_ok;6893}6894 6895/* Check that affine expressions get normalized on addition/subtraction.6896 * In particular, check that (final) unused integer divisions get removed6897 * such that an expression derived from expressions with integer divisions6898 * is found to be obviously equal to one that is created directly.6899 */6900static isl_stat test_aff_normalize(isl_ctx *ctx)6901{6902 isl_aff *aff, *aff2;6903 isl_stat ok;6904 6905 aff = isl_aff_read_from_str(ctx, "{ [x] -> [x//2] }");6906 aff2 = isl_aff_read_from_str(ctx, "{ [x] -> [1 + x//2] }");6907 aff = isl_aff_sub(aff2, aff);6908 ok = aff_check_plain_equal(aff, "{ [x] -> [1] }");6909 isl_aff_free(aff);6910 6911 return ok;6912}6913 6914int test_aff(isl_ctx *ctx)6915{6916 const char *str;6917 isl_set *set;6918 isl_space *space;6919 isl_local_space *ls;6920 isl_aff *aff;6921 int zero;6922 isl_stat equal;6923 6924 if (test_upa(ctx) < 0)6925 return -1;6926 if (test_bin_aff(ctx) < 0)6927 return -1;6928 if (test_bin_pw_aff(ctx) < 0)6929 return -1;6930 if (test_upma_test(ctx) < 0)6931 return -1;6932 if (test_bin_upma(ctx) < 0)6933 return -1;6934 if (test_bin_upma_fail(ctx) < 0)6935 return -1;6936 if (test_upma_uset(ctx) < 0)6937 return -1;6938 if (test_un_mpa(ctx) < 0)6939 return -1;6940 if (test_bin_mpa(ctx) < 0)6941 return -1;6942 if (test_un_mupa(ctx) < 0)6943 return -1;6944 if (test_bin_mupa(ctx) < 0)6945 return -1;6946 if (test_mupa_set(ctx) < 0)6947 return -1;6948 if (test_mupa_uset(ctx) < 0)6949 return -1;6950 if (test_mupa_ma(ctx) < 0)6951 return -1;6952 if (test_mupa_pa(ctx) < 0)6953 return -1;6954 if (test_mupa_pma(ctx) < 0)6955 return -1;6956 if (test_mupa_upma(ctx) < 0)6957 return -1;6958 6959 space = isl_space_set_alloc(ctx, 0, 1);6960 ls = isl_local_space_from_space(space);6961 aff = isl_aff_zero_on_domain(ls);6962 6963 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);6964 aff = isl_aff_scale_down_ui(aff, 3);6965 aff = isl_aff_floor(aff);6966 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);6967 aff = isl_aff_scale_down_ui(aff, 2);6968 aff = isl_aff_floor(aff);6969 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);6970 6971 str = "{ [10] }";6972 set = isl_set_read_from_str(ctx, str);6973 aff = isl_aff_gist(aff, set);6974 6975 aff = isl_aff_add_constant_si(aff, -16);6976 zero = isl_aff_plain_is_zero(aff);6977 isl_aff_free(aff);6978 6979 if (zero < 0)6980 return -1;6981 if (!zero)6982 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);6983 6984 aff = isl_aff_read_from_str(ctx, "{ [-1] }");6985 aff = isl_aff_scale_down_ui(aff, 64);6986 aff = isl_aff_floor(aff);6987 equal = aff_check_plain_equal(aff, "{ [-1] }");6988 isl_aff_free(aff);6989 if (equal < 0)6990 return -1;6991 6992 if (test_aff_set_tuple_id(ctx) < 0)6993 return -1;6994 if (test_aff_normalize(ctx) < 0)6995 return -1;6996 6997 return 0;6998}6999 7000/* Inputs for isl_set_bind tests.7001 * "set" is the input set.7002 * "tuple" is the binding tuple.7003 * "res" is the expected result.7004 */7005static7006struct {7007 const char *set;7008 const char *tuple;7009 const char *res;7010} bind_set_tests[] = {7011 { "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",7012 "{ A[M, N] }",7013 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },7014 { "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }",7015 "{ B[N, M] }",7016 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },7017 { "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }",7018 "{ C[N] }",7019 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }" },7020 { "[M] -> { D[x, N] : x mod 2 = 0 and N mod 8 = 3 and M >= 0 }",7021 "{ D[M, N] }",7022 "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 and M >= 0 }" },7023};7024 7025/* Perform basic isl_set_bind tests.7026 */7027static isl_stat test_bind_set(isl_ctx *ctx)7028{7029 int i;7030 7031 for (i = 0; i < ARRAY_SIZE(bind_set_tests); ++i) {7032 const char *str;7033 isl_set *set;7034 isl_multi_id *tuple;7035 isl_stat r;7036 7037 set = isl_set_read_from_str(ctx, bind_set_tests[i].set);7038 str = bind_set_tests[i].tuple;7039 tuple = isl_multi_id_read_from_str(ctx, str);7040 set = isl_set_bind(set, tuple);7041 r = set_check_equal(set, bind_set_tests[i].res);7042 isl_set_free(set);7043 if (r < 0)7044 return isl_stat_error;7045 }7046 7047 return isl_stat_ok;7048}7049 7050/* Inputs for isl_map_bind_domain tests.7051 * "map" is the input map.7052 * "tuple" is the binding tuple.7053 * "res" is the expected result.7054 */7055struct {7056 const char *map;7057 const char *tuple;7058 const char *res;7059} bind_map_domain_tests[] = {7060 { "{ A[M, N] -> [M + floor(N/2)] }",7061 "{ A[M, N] }",7062 "[M, N] -> { [M + floor(N/2)] }" },7063 { "{ B[N, M] -> [M + floor(N/2)] }",7064 "{ B[N, M] }",7065 "[N, M] -> { [M + floor(N/2)] }" },7066 { "[M] -> { C[N] -> [M + floor(N/2)] }",7067 "{ C[N] }",7068 "[M, N] -> { [M + floor(N/2)] }" },7069 { "[M] -> { C[x, N] -> [x + floor(N/2)] }",7070 "{ C[M, N] }",7071 "[M, N] -> { [M + floor(N/2)] }" },7072 { "[M] -> { C[x, N] -> [M + floor(N/2)] }",7073 "{ C[M, N] }",7074 "[M, N] -> { [M + floor(N/2)] }" },7075 { "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",7076 "{ C[N, M] }",7077 "[A, N, M] -> { [M + floor(N/2)] }" },7078};7079 7080/* Perform basic isl_map_bind_domain tests.7081 */7082static isl_stat test_bind_map_domain(isl_ctx *ctx)7083{7084 int i;7085 7086 for (i = 0; i < ARRAY_SIZE(bind_map_domain_tests); ++i) {7087 const char *str;7088 isl_map *map;7089 isl_set *set;7090 isl_multi_id *tuple;7091 isl_stat r;7092 7093 str = bind_map_domain_tests[i].map;7094 map = isl_map_read_from_str(ctx, str);7095 str = bind_map_domain_tests[i].tuple;7096 tuple = isl_multi_id_read_from_str(ctx, str);7097 set = isl_map_bind_domain(map, tuple);7098 str = bind_map_domain_tests[i].res;7099 r = set_check_equal(set, str);7100 isl_set_free(set);7101 if (r < 0)7102 return isl_stat_error;7103 }7104 7105 return isl_stat_ok;7106}7107 7108/* Inputs for isl_union_map_bind_range tests.7109 * "map" is the input union map.7110 * "tuple" is the binding tuple.7111 * "res" is the expected result.7112 */7113struct {7114 const char *map;7115 const char *tuple;7116 const char *res;7117} bind_umap_range_tests[] = {7118 { "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",7119 "{ A[M, N] }",7120 "[M, N] -> { B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },7121 { "{ B[N, M] -> A[M, N] : M mod 2 = 0 and N mod 8 = 3 }",7122 "{ B[M, N] }",7123 "{ }" },7124 { "{ A[] -> B[]; C[] -> D[]; E[] -> B[] }",7125 "{ B[] }",7126 "{ A[]; E[] }" },7127};7128 7129/* Perform basic isl_union_map_bind_range tests.7130 */7131static isl_stat test_bind_umap_range(isl_ctx *ctx)7132{7133 int i;7134 7135 for (i = 0; i < ARRAY_SIZE(bind_umap_range_tests); ++i) {7136 const char *str;7137 isl_union_map *umap;7138 isl_union_set *uset;7139 isl_multi_id *tuple;7140 isl_stat r;7141 7142 str = bind_umap_range_tests[i].map;7143 umap = isl_union_map_read_from_str(ctx, str);7144 str = bind_umap_range_tests[i].tuple;7145 tuple = isl_multi_id_read_from_str(ctx, str);7146 uset = isl_union_map_bind_range(umap, tuple);7147 str = bind_umap_range_tests[i].res;7148 r = uset_check_equal(uset, str);7149 isl_union_set_free(uset);7150 if (r < 0)7151 return isl_stat_error;7152 }7153 7154 return isl_stat_ok;7155}7156 7157/* Inputs for isl_pw_multi_aff_bind_domain tests.7158 * "pma" is the input expression.7159 * "tuple" is the binding tuple.7160 * "res" is the expected result.7161 */7162struct {7163 const char *pma;7164 const char *tuple;7165 const char *res;7166} bind_pma_domain_tests[] = {7167 { "{ A[M, N] -> [M + floor(N/2)] }",7168 "{ A[M, N] }",7169 "[M, N] -> { [M + floor(N/2)] }" },7170 { "{ B[N, M] -> [M + floor(N/2)] }",7171 "{ B[N, M] }",7172 "[N, M] -> { [M + floor(N/2)] }" },7173 { "[M] -> { C[N] -> [M + floor(N/2)] }",7174 "{ C[N] }",7175 "[M, N] -> { [M + floor(N/2)] }" },7176 { "[M] -> { C[x, N] -> [x + floor(N/2)] }",7177 "{ C[M, N] }",7178 "[M, N] -> { [M + floor(N/2)] }" },7179 { "[M] -> { C[x, N] -> [M + floor(N/2)] }",7180 "{ C[M, N] }",7181 "[M, N] -> { [M + floor(N/2)] }" },7182 { "[A, M] -> { C[N, x] -> [x + floor(N/2)] }",7183 "{ C[N, M] }",7184 "[A, N, M] -> { [M + floor(N/2)] }" },7185};7186 7187/* Perform basic isl_pw_multi_aff_bind_domain tests.7188 */7189static isl_stat test_bind_pma_domain(isl_ctx *ctx)7190{7191 int i;7192 7193 for (i = 0; i < ARRAY_SIZE(bind_pma_domain_tests); ++i) {7194 const char *str;7195 isl_pw_multi_aff *pma;7196 isl_multi_id *tuple;7197 isl_stat r;7198 7199 str = bind_pma_domain_tests[i].pma;7200 pma = isl_pw_multi_aff_read_from_str(ctx, str);7201 str = bind_pma_domain_tests[i].tuple;7202 tuple = isl_multi_id_read_from_str(ctx, str);7203 pma = isl_pw_multi_aff_bind_domain(pma, tuple);7204 str = bind_pma_domain_tests[i].res;7205 r = pw_multi_aff_check_plain_equal(pma, str);7206 isl_pw_multi_aff_free(pma);7207 if (r < 0)7208 return isl_stat_error;7209 }7210 7211 return isl_stat_ok;7212}7213 7214/* Inputs for isl_pw_multi_aff_bind_domain_wrapped_domain tests.7215 * "pma" is the input expression.7216 * "tuple" is the binding tuple.7217 * "res" is the expected result.7218 */7219struct {7220 const char *pma;7221 const char *tuple;7222 const char *res;7223} bind_pma_domain_wrapped_tests[] = {7224 { "{ [A[M, N] -> B[]] -> [M + floor(N/2)] }",7225 "{ A[M, N] }",7226 "[M, N] -> { B[] -> [M + floor(N/2)] }" },7227 { "{ [B[N, M] -> D[]] -> [M + floor(N/2)] }",7228 "{ B[N, M] }",7229 "[N, M] -> { D[] -> [M + floor(N/2)] }" },7230 { "[M] -> { [C[N] -> B[x]] -> [x + M + floor(N/2)] }",7231 "{ C[N] }",7232 "[M, N] -> { B[x] -> [x + M + floor(N/2)] }" },7233 { "[M] -> { [C[x, N] -> B[]] -> [x + floor(N/2)] }",7234 "{ C[M, N] }",7235 "[M, N] -> { B[] -> [M + floor(N/2)] }" },7236 { "[M] -> { [C[x, N] -> B[]] -> [M + floor(N/2)] }",7237 "{ C[M, N] }",7238 "[M, N] -> { B[] -> [M + floor(N/2)] }" },7239 { "[A, M] -> { [C[N, x] -> B[]] -> [x + floor(N/2)] }",7240 "{ C[N, M] }",7241 "[A, N, M] -> { B[] -> [M + floor(N/2)] }" },7242};7243 7244/* Perform basic isl_pw_multi_aff_bind_domain_wrapped_domain tests.7245 */7246static isl_stat test_bind_pma_domain_wrapped(isl_ctx *ctx)7247{7248 int i;7249 7250 for (i = 0; i < ARRAY_SIZE(bind_pma_domain_wrapped_tests); ++i) {7251 const char *str;7252 isl_pw_multi_aff *pma;7253 isl_multi_id *tuple;7254 isl_stat r;7255 7256 str = bind_pma_domain_wrapped_tests[i].pma;7257 pma = isl_pw_multi_aff_read_from_str(ctx, str);7258 str = bind_pma_domain_wrapped_tests[i].tuple;7259 tuple = isl_multi_id_read_from_str(ctx, str);7260 pma = isl_pw_multi_aff_bind_domain_wrapped_domain(pma, tuple);7261 str = bind_pma_domain_wrapped_tests[i].res;7262 r = pw_multi_aff_check_plain_equal(pma, str);7263 isl_pw_multi_aff_free(pma);7264 if (r < 0)7265 return isl_stat_error;7266 }7267 7268 return isl_stat_ok;7269}7270 7271/* Inputs for isl_aff_bind_id tests.7272 * "aff" is the input expression.7273 * "id" is the binding id.7274 * "res" is the expected result.7275 */7276static7277struct {7278 const char *aff;7279 const char *id;7280 const char *res;7281} bind_aff_tests[] = {7282 { "{ [4] }", "M", "[M = 4] -> { : }" },7283 { "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },7284 { "[M] -> { [4] }", "M", "[M = 4] -> { : }" },7285 { "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },7286 { "{ [NaN] }", "M", "{ : false }" },7287 { "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },7288};7289 7290/* Perform basic isl_aff_bind_id tests.7291 */7292static isl_stat test_bind_aff(isl_ctx *ctx)7293{7294 int i;7295 7296 for (i = 0; i < ARRAY_SIZE(bind_aff_tests); ++i) {7297 isl_aff *aff;7298 isl_set *res;7299 isl_id *id;7300 isl_stat r;7301 7302 aff = isl_aff_read_from_str(ctx, bind_aff_tests[i].aff);7303 id = isl_id_read_from_str(ctx, bind_aff_tests[i].id);7304 res = isl_set_from_basic_set(isl_aff_bind_id(aff, id));7305 r = set_check_equal(res, bind_aff_tests[i].res);7306 isl_set_free(res);7307 if (r < 0)7308 return isl_stat_error;7309 }7310 7311 return isl_stat_ok;7312}7313 7314/* Inputs for isl_pw_aff_bind_id tests.7315 * "pa" is the input expression.7316 * "id" is the binding id.7317 * "res" is the expected result.7318 */7319static7320struct {7321 const char *pa;7322 const char *id;7323 const char *res;7324} bind_pa_tests[] = {7325 { "{ [4] }", "M", "[M = 4] -> { : }" },7326 { "{ B[x] -> [floor(x/2)] }", "M", "[M] -> { B[x] : M = floor(x/2) }" },7327 { "[M] -> { [4] }", "M", "[M = 4] -> { : }" },7328 { "[M] -> { [floor(M/2)] }", "M", "[M] -> { : floor(M/2) = M }" },7329 { "[M] -> { [M] : M >= 0; [-M] : M < 0 }", "M", "[M] -> { : M >= 0 }" },7330 { "{ [NaN] }", "M", "{ : false }" },7331 { "{ A[x] -> [NaN] }", "M", "{ A[x] : false }" },7332};7333 7334/* Perform basic isl_pw_aff_bind_id tests.7335 */7336static isl_stat test_bind_pa(isl_ctx *ctx)7337{7338 int i;7339 7340 for (i = 0; i < ARRAY_SIZE(bind_pa_tests); ++i) {7341 isl_pw_aff *pa;7342 isl_set *res;7343 isl_id *id;7344 isl_stat r;7345 7346 pa = isl_pw_aff_read_from_str(ctx, bind_pa_tests[i].pa);7347 id = isl_id_read_from_str(ctx, bind_pa_tests[i].id);7348 res = isl_pw_aff_bind_id(pa, id);7349 r = set_check_equal(res, bind_pa_tests[i].res);7350 isl_set_free(res);7351 if (r < 0)7352 return isl_stat_error;7353 }7354 7355 return isl_stat_ok;7356}7357 7358/* Inputs for isl_multi_union_pw_aff_bind tests.7359 * "mupa" is the input expression.7360 * "tuple" is the binding tuple.7361 * "res" is the expected result.7362 */7363static7364struct {7365 const char *mupa;7366 const char *tuple;7367 const char *res;7368} bind_mupa_tests[] = {7369 { "A[{ [4] }, { [5] }]",7370 "{ A[M, N] }",7371 "[M = 4, N = 5] -> { : }" },7372 { "A[{ B[x] -> [floor(x/2)] }, { B[y] -> [y + 5] }]",7373 "{ A[M, N] }",7374 "[M, N] -> { B[x] : M = floor(x/2) and N = x + 5 }" },7375 { "[M] -> A[{ [4] }, { [M + 1] }]",7376 "{ A[M, N] }",7377 "[M = 4, N = 5] -> { : }" },7378};7379 7380/* Perform basic isl_multi_union_pw_aff_bind tests.7381 */7382static isl_stat test_bind_mupa(isl_ctx *ctx)7383{7384 int i;7385 7386 for (i = 0; i < ARRAY_SIZE(bind_mupa_tests); ++i) {7387 const char *str;7388 isl_multi_union_pw_aff *mupa;7389 isl_union_set *res;7390 isl_multi_id *tuple;7391 isl_stat r;7392 7393 str = bind_mupa_tests[i].mupa;7394 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);7395 str = bind_mupa_tests[i].tuple;7396 tuple = isl_multi_id_read_from_str(ctx, str);7397 res = isl_multi_union_pw_aff_bind(mupa, tuple);7398 r = uset_check_equal(res, bind_mupa_tests[i].res);7399 isl_union_set_free(res);7400 if (r < 0)7401 return isl_stat_error;7402 }7403 7404 return isl_stat_ok;7405}7406 7407/* Perform tests that reinterpret dimensions as parameters.7408 */7409static int test_bind(isl_ctx *ctx)7410{7411 if (test_bind_set(ctx) < 0)7412 return -1;7413 if (test_bind_map_domain(ctx) < 0)7414 return -1;7415 if (test_bind_umap_range(ctx) < 0)7416 return -1;7417 if (test_bind_pma_domain(ctx) < 0)7418 return -1;7419 if (test_bind_pma_domain_wrapped(ctx) < 0)7420 return -1;7421 if (test_bind_aff(ctx) < 0)7422 return -1;7423 if (test_bind_pa(ctx) < 0)7424 return -1;7425 if (test_bind_mupa(ctx) < 0)7426 return -1;7427 7428 return 0;7429}7430 7431/* Inputs for isl_set_unbind_params tests.7432 * "set" is the input parameter domain.7433 * "tuple" is the tuple of the constructed set.7434 * "res" is the expected result.7435 */7436struct {7437 const char *set;7438 const char *tuple;7439 const char *res;7440} unbind_set_tests[] = {7441 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",7442 "{ A[M, N] }",7443 "{ A[M, N] : M mod 2 = 0 and N mod 8 = 3 }" },7444 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",7445 "{ B[N, M] }",7446 "{ B[N, M] : M mod 2 = 0 and N mod 8 = 3 }" },7447 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",7448 "{ C[N] }",7449 "[M] -> { C[N] : M mod 2 = 0 and N mod 8 = 3 }" },7450 { "[M, N] -> { : M mod 2 = 0 and N mod 8 = 3 }",7451 "{ D[T, N] }",7452 "[M] -> { D[x, N] : M mod 2 = 0 and N mod 8 = 3 }" },7453};7454 7455/* Perform basic isl_set_unbind_params tests.7456 */7457static isl_stat test_unbind_set(isl_ctx *ctx)7458{7459 int i;7460 7461 for (i = 0; i < ARRAY_SIZE(unbind_set_tests); ++i) {7462 const char *str;7463 isl_set *set;7464 isl_multi_id *tuple;7465 isl_stat r;7466 7467 set = isl_set_read_from_str(ctx, unbind_set_tests[i].set);7468 str = unbind_set_tests[i].tuple;7469 tuple = isl_multi_id_read_from_str(ctx, str);7470 set = isl_set_unbind_params(set, tuple);7471 r = set_check_equal(set, unbind_set_tests[i].res);7472 isl_set_free(set);7473 if (r < 0)7474 return isl_stat_error;7475 }7476 7477 return isl_stat_ok;7478}7479 7480/* Inputs for isl_aff_unbind_params_insert_domain tests.7481 * "aff" is the input affine expression defined over a parameter domain.7482 * "tuple" is the tuple of the domain that gets introduced.7483 * "res" is the expected result.7484 */7485struct {7486 const char *aff;7487 const char *tuple;7488 const char *res;7489} unbind_aff_tests[] = {7490 { "[M, N] -> { [M + floor(N/2)] }",7491 "{ A[M, N] }",7492 "{ A[M, N] -> [M + floor(N/2)] }" },7493 { "[M, N] -> { [M + floor(N/2)] }",7494 "{ B[N, M] }",7495 "{ B[N, M] -> [M + floor(N/2)] }" },7496 { "[M, N] -> { [M + floor(N/2)] }",7497 "{ C[N] }",7498 "[M] -> { C[N] -> [M + floor(N/2)] }" },7499 { "[M, N] -> { [M + floor(N/2)] }",7500 "{ D[A, B, C, N, Z] }",7501 "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },7502};7503 7504/* Perform basic isl_aff_unbind_params_insert_domain tests.7505 */7506static isl_stat test_unbind_aff(isl_ctx *ctx)7507{7508 int i;7509 7510 for (i = 0; i < ARRAY_SIZE(unbind_aff_tests); ++i) {7511 const char *str;7512 isl_aff *aff;7513 isl_multi_id *tuple;7514 isl_stat r;7515 7516 aff = isl_aff_read_from_str(ctx, unbind_aff_tests[i].aff);7517 str = unbind_aff_tests[i].tuple;7518 tuple = isl_multi_id_read_from_str(ctx, str);7519 aff = isl_aff_unbind_params_insert_domain(aff, tuple);7520 r = aff_check_plain_equal(aff, unbind_aff_tests[i].res);7521 isl_aff_free(aff);7522 if (r < 0)7523 return isl_stat_error;7524 }7525 7526 return isl_stat_ok;7527}7528 7529/* Inputs for isl_multi_aff_unbind_params_insert_domain tests.7530 * "ma" is the input multi affine expression defined over a parameter domain.7531 * "tuple" is the tuple of the domain that gets introduced.7532 * "res" is the expected result.7533 */7534static struct {7535 const char *ma;7536 const char *tuple;7537 const char *res;7538} unbind_multi_aff_tests[] = {7539 { "[M, N] -> { T[M + floor(N/2)] }",7540 "{ A[M, N] }",7541 "{ A[M, N] -> T[M + floor(N/2)] }" },7542 { "[M, N] -> { [M + floor(N/2)] }",7543 "{ B[N, M] }",7544 "{ B[N, M] -> [M + floor(N/2)] }" },7545 { "[M, N] -> { [M + floor(N/2)] }",7546 "{ C[N] }",7547 "[M] -> { C[N] -> [M + floor(N/2)] }" },7548 { "[M, N] -> { [M + floor(N/2)] }",7549 "{ D[A, B, C, N, Z] }",7550 "[M] -> { D[A, B, C, N, Z] -> [M + floor(N/2)] }" },7551 { "[M, N] -> { T[M + floor(N/2), N + floor(M/3)] }",7552 "{ A[M, N] }",7553 "{ A[M, N] -> T[M + floor(N/2), N + floor(M/3)] }" },7554};7555 7556/* Perform basic isl_multi_aff_unbind_params_insert_domain tests.7557 */7558static isl_stat test_unbind_multi_aff(isl_ctx *ctx)7559{7560 int i;7561 7562 for (i = 0; i < ARRAY_SIZE(unbind_multi_aff_tests); ++i) {7563 const char *str;7564 isl_multi_aff *ma;7565 isl_multi_id *tuple;7566 isl_stat r;7567 7568 str = unbind_multi_aff_tests[i].ma;7569 ma = isl_multi_aff_read_from_str(ctx, str);7570 str = unbind_multi_aff_tests[i].tuple;7571 tuple = isl_multi_id_read_from_str(ctx, str);7572 ma = isl_multi_aff_unbind_params_insert_domain(ma, tuple);7573 str = unbind_multi_aff_tests[i].res;7574 r = multi_aff_check_plain_equal(ma, str);7575 isl_multi_aff_free(ma);7576 if (r < 0)7577 return isl_stat_error;7578 }7579 7580 return isl_stat_ok;7581}7582 7583/* Perform tests that reinterpret parameters.7584 */7585static int test_unbind(isl_ctx *ctx)7586{7587 if (test_unbind_set(ctx) < 0)7588 return -1;7589 if (test_unbind_aff(ctx) < 0)7590 return -1;7591 if (test_unbind_multi_aff(ctx) < 0)7592 return -1;7593 7594 return 0;7595}7596 7597/* Check that "pa" consists of a single expression.7598 */7599static int check_single_piece(isl_ctx *ctx, __isl_take isl_pw_aff *pa)7600{7601 isl_size n;7602 7603 n = isl_pw_aff_n_piece(pa);7604 isl_pw_aff_free(pa);7605 7606 if (n < 0)7607 return -1;7608 if (n != 1)7609 isl_die(ctx, isl_error_unknown, "expecting single expression",7610 return -1);7611 7612 return 0;7613}7614 7615/* Check that the computation below results in a single expression.7616 * One or two expressions may result depending on which constraint7617 * ends up being considered as redundant with respect to the other7618 * constraints after the projection that is performed internally7619 * by isl_set_dim_min.7620 */7621static int test_dim_max_1(isl_ctx *ctx)7622{7623 const char *str;7624 isl_set *set;7625 isl_pw_aff *pa;7626 7627 str = "[n] -> { [a, b] : n >= 0 and 4a >= -4 + n and b >= 0 and "7628 "-4a <= b <= 3 and b < n - 4a }";7629 set = isl_set_read_from_str(ctx, str);7630 pa = isl_set_dim_min(set, 0);7631 return check_single_piece(ctx, pa);7632}7633 7634/* Check that the computation below results in a single expression.7635 * The PIP problem corresponding to these constraints has a row7636 * that causes a split of the solution domain. The solver should7637 * first pick rows that split off empty parts such that the actual7638 * solution domain does not get split.7639 * Note that the description contains some redundant constraints.7640 * If these constraints get removed first, then the row mentioned7641 * above does not appear in the PIP problem.7642 */7643static int test_dim_max_2(isl_ctx *ctx)7644{7645 const char *str;7646 isl_set *set;7647 isl_pw_aff *pa;7648 7649 str = "[P, N] -> { [a] : a < N and a >= 0 and N > P and a <= P and "7650 "N > 0 and P >= 0 }";7651 set = isl_set_read_from_str(ctx, str);7652 pa = isl_set_dim_max(set, 0);7653 return check_single_piece(ctx, pa);7654}7655 7656int test_dim_max(isl_ctx *ctx)7657{7658 int equal;7659 const char *str;7660 isl_set *set1, *set2;7661 isl_set *set;7662 isl_map *map;7663 isl_pw_aff *pwaff;7664 7665 if (test_dim_max_1(ctx) < 0)7666 return -1;7667 if (test_dim_max_2(ctx) < 0)7668 return -1;7669 7670 str = "[N] -> { [i] : 0 <= i <= min(N,10) }";7671 set = isl_set_read_from_str(ctx, str);7672 pwaff = isl_set_dim_max(set, 0);7673 set1 = isl_set_from_pw_aff(pwaff);7674 str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";7675 set2 = isl_set_read_from_str(ctx, str);7676 equal = isl_set_is_equal(set1, set2);7677 isl_set_free(set1);7678 isl_set_free(set2);7679 if (equal < 0)7680 return -1;7681 if (!equal)7682 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7683 7684 str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";7685 set = isl_set_read_from_str(ctx, str);7686 pwaff = isl_set_dim_max(set, 0);7687 set1 = isl_set_from_pw_aff(pwaff);7688 str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";7689 set2 = isl_set_read_from_str(ctx, str);7690 equal = isl_set_is_equal(set1, set2);7691 isl_set_free(set1);7692 isl_set_free(set2);7693 if (equal < 0)7694 return -1;7695 if (!equal)7696 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7697 7698 str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";7699 set = isl_set_read_from_str(ctx, str);7700 pwaff = isl_set_dim_max(set, 0);7701 set1 = isl_set_from_pw_aff(pwaff);7702 str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";7703 set2 = isl_set_read_from_str(ctx, str);7704 equal = isl_set_is_equal(set1, set2);7705 isl_set_free(set1);7706 isl_set_free(set2);7707 if (equal < 0)7708 return -1;7709 if (!equal)7710 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7711 7712 str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "7713 "0 <= i < N and 0 <= j < M }";7714 map = isl_map_read_from_str(ctx, str);7715 set = isl_map_range(map);7716 7717 pwaff = isl_set_dim_max(isl_set_copy(set), 0);7718 set1 = isl_set_from_pw_aff(pwaff);7719 str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";7720 set2 = isl_set_read_from_str(ctx, str);7721 equal = isl_set_is_equal(set1, set2);7722 isl_set_free(set1);7723 isl_set_free(set2);7724 7725 pwaff = isl_set_dim_max(isl_set_copy(set), 3);7726 set1 = isl_set_from_pw_aff(pwaff);7727 str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";7728 set2 = isl_set_read_from_str(ctx, str);7729 if (equal >= 0 && equal)7730 equal = isl_set_is_equal(set1, set2);7731 isl_set_free(set1);7732 isl_set_free(set2);7733 7734 isl_set_free(set);7735 7736 if (equal < 0)7737 return -1;7738 if (!equal)7739 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7740 7741 /* Check that solutions are properly merged. */7742 str = "[n] -> { [a, b, c] : c >= -4a - 2b and "7743 "c <= -1 + n - 4a - 2b and c >= -2b and "7744 "4a >= -4 + n and c >= 0 }";7745 set = isl_set_read_from_str(ctx, str);7746 pwaff = isl_set_dim_min(set, 2);7747 set1 = isl_set_from_pw_aff(pwaff);7748 str = "[n] -> { [(0)] : n >= 1 }";7749 set2 = isl_set_read_from_str(ctx, str);7750 equal = isl_set_is_equal(set1, set2);7751 isl_set_free(set1);7752 isl_set_free(set2);7753 7754 if (equal < 0)7755 return -1;7756 if (!equal)7757 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7758 7759 /* Check that empty solution lie in the right space. */7760 str = "[n] -> { [t,a] : 1 = 0 }";7761 set = isl_set_read_from_str(ctx, str);7762 pwaff = isl_set_dim_max(set, 0);7763 set1 = isl_set_from_pw_aff(pwaff);7764 str = "[n] -> { [t] : 1 = 0 }";7765 set2 = isl_set_read_from_str(ctx, str);7766 equal = isl_set_is_equal(set1, set2);7767 isl_set_free(set1);7768 isl_set_free(set2);7769 7770 if (equal < 0)7771 return -1;7772 if (!equal)7773 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7774 7775 return 0;7776}7777 7778/* Basic test for isl_pw_multi_aff_product.7779 *7780 * Check that multiple pieces are properly handled.7781 */7782static int test_product_pma(isl_ctx *ctx)7783{7784 isl_stat equal;7785 const char *str;7786 isl_pw_multi_aff *pma1, *pma2;7787 7788 str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }";7789 pma1 = isl_pw_multi_aff_read_from_str(ctx, str);7790 str = "{ C[] -> D[] }";7791 pma2 = isl_pw_multi_aff_read_from_str(ctx, str);7792 pma1 = isl_pw_multi_aff_product(pma1, pma2);7793 str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;"7794 "[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }";7795 equal = pw_multi_aff_check_plain_equal(pma1, str);7796 isl_pw_multi_aff_free(pma1);7797 if (equal < 0)7798 return -1;7799 7800 return 0;7801}7802 7803int test_product(isl_ctx *ctx)7804{7805 const char *str;7806 isl_set *set;7807 isl_union_set *uset1, *uset2;7808 int ok;7809 7810 str = "{ A[i] }";7811 set = isl_set_read_from_str(ctx, str);7812 set = isl_set_product(set, isl_set_copy(set));7813 ok = isl_set_is_wrapping(set);7814 isl_set_free(set);7815 if (ok < 0)7816 return -1;7817 if (!ok)7818 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7819 7820 str = "{ [] }";7821 uset1 = isl_union_set_read_from_str(ctx, str);7822 uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));7823 str = "{ [[] -> []] }";7824 uset2 = isl_union_set_read_from_str(ctx, str);7825 ok = isl_union_set_is_equal(uset1, uset2);7826 isl_union_set_free(uset1);7827 isl_union_set_free(uset2);7828 if (ok < 0)7829 return -1;7830 if (!ok)7831 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7832 7833 if (test_product_pma(ctx) < 0)7834 return -1;7835 7836 return 0;7837}7838 7839/* Check that two sets are not considered disjoint just because7840 * they have a different set of (named) parameters.7841 */7842static int test_disjoint(isl_ctx *ctx)7843{7844 const char *str;7845 isl_set *set, *set2;7846 int disjoint;7847 7848 str = "[n] -> { [[]->[]] }";7849 set = isl_set_read_from_str(ctx, str);7850 str = "{ [[]->[]] }";7851 set2 = isl_set_read_from_str(ctx, str);7852 disjoint = isl_set_is_disjoint(set, set2);7853 isl_set_free(set);7854 isl_set_free(set2);7855 if (disjoint < 0)7856 return -1;7857 if (disjoint)7858 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7859 7860 return 0;7861}7862 7863/* Inputs for isl_pw_multi_aff_is_equal tests.7864 * "f1" and "f2" are the two function that need to be compared.7865 * "equal" is the expected result.7866 */7867struct {7868 int equal;7869 const char *f1;7870 const char *f2;7871} pma_equal_tests[] = {7872 { 1, "[N] -> { [floor(N/2)] : 0 <= N <= 1 }",7873 "[N] -> { [0] : 0 <= N <= 1 }" },7874 { 1, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",7875 "[N] -> { [0] : 0 <= N <= 1; [1] : N = 2 }" },7876 { 0, "[N] -> { [floor(N/2)] : 0 <= N <= 2 }",7877 "[N] -> { [0] : 0 <= N <= 1 }" },7878 { 0, "{ [NaN] }", "{ [NaN] }" },7879};7880 7881int test_equal(isl_ctx *ctx)7882{7883 int i;7884 const char *str;7885 isl_set *set, *set2;7886 int equal;7887 7888 str = "{ S_6[i] }";7889 set = isl_set_read_from_str(ctx, str);7890 str = "{ S_7[i] }";7891 set2 = isl_set_read_from_str(ctx, str);7892 equal = isl_set_is_equal(set, set2);7893 isl_set_free(set);7894 isl_set_free(set2);7895 if (equal < 0)7896 return -1;7897 if (equal)7898 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);7899 7900 for (i = 0; i < ARRAY_SIZE(pma_equal_tests); ++i) {7901 int expected = pma_equal_tests[i].equal;7902 isl_pw_multi_aff *f1, *f2;7903 7904 f1 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f1);7905 f2 = isl_pw_multi_aff_read_from_str(ctx, pma_equal_tests[i].f2);7906 equal = isl_pw_multi_aff_is_equal(f1, f2);7907 isl_pw_multi_aff_free(f1);7908 isl_pw_multi_aff_free(f2);7909 if (equal < 0)7910 return -1;7911 if (equal != expected)7912 isl_die(ctx, isl_error_unknown,7913 "unexpected equality result", return -1);7914 }7915 7916 return 0;7917}7918 7919static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,7920 enum isl_dim_type type, unsigned pos, int fixed)7921{7922 isl_bool test;7923 7924 test = isl_map_plain_is_fixed(map, type, pos, NULL);7925 isl_map_free(map);7926 if (test < 0)7927 return -1;7928 if (test == fixed)7929 return 0;7930 if (fixed)7931 isl_die(ctx, isl_error_unknown,7932 "map not detected as fixed", return -1);7933 else7934 isl_die(ctx, isl_error_unknown,7935 "map detected as fixed", return -1);7936}7937 7938int test_fixed(isl_ctx *ctx)7939{7940 const char *str;7941 isl_map *map;7942 7943 str = "{ [i] -> [i] }";7944 map = isl_map_read_from_str(ctx, str);7945 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))7946 return -1;7947 str = "{ [i] -> [1] }";7948 map = isl_map_read_from_str(ctx, str);7949 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))7950 return -1;7951 str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";7952 map = isl_map_read_from_str(ctx, str);7953 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))7954 return -1;7955 map = isl_map_read_from_str(ctx, str);7956 map = isl_map_neg(map);7957 if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))7958 return -1;7959 7960 return 0;7961}7962 7963struct isl_vertices_test_data {7964 const char *set;7965 int n;7966 const char *vertex[6];7967} vertices_tests[] = {7968 { "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }",7969 2, { "{ A[12, 4] }", "{ A[12, 12] }" } },7970 { "{ A[t, i] : t = 14 and i = 1 }",7971 1, { "{ A[14, 1] }" } },7972 { "[n, m] -> { [a, b, c] : b <= a and a <= n and b > 0 and c >= b and "7973 "c <= m and m <= n and m > 0 }",7974 6, {7975 "[n, m] -> { [n, m, m] : 0 < m <= n }",7976 "[n, m] -> { [n, 1, m] : 0 < m <= n }",7977 "[n, m] -> { [n, 1, 1] : 0 < m <= n }",7978 "[n, m] -> { [m, m, m] : 0 < m <= n }",7979 "[n, m] -> { [1, 1, m] : 0 < m <= n }",7980 "[n, m] -> { [1, 1, 1] : 0 < m <= n }"7981 } },7982 /* An input with implicit equality constraints among the parameters. */7983 { "[N, M] -> { [a, b] : M >= 3 and 9 + 3M <= a <= 29 + 2N + 11M and "7984 "2b >= M + a and 5 - 2N - M + a <= 2b <= 3 + a and "7985 "3b >= 15 + a }",7986 2, {7987 "[N, M] -> { [(21), (12)] : M = 3 and N >= 0 }",7988 "[N, M] -> { [(61 + 2N), (32 + N)] : M = 3 and N >= 0 }",7989 }7990 },7991};7992 7993/* Check that "vertex" corresponds to one of the vertices in data->vertex.7994 */7995static isl_stat find_vertex(__isl_take isl_vertex *vertex, void *user)7996{7997 struct isl_vertices_test_data *data = user;7998 isl_ctx *ctx;7999 isl_multi_aff *ma;8000 isl_basic_set *bset;8001 isl_pw_multi_aff *pma;8002 int i;8003 isl_bool equal;8004 8005 ctx = isl_vertex_get_ctx(vertex);8006 bset = isl_vertex_get_domain(vertex);8007 ma = isl_vertex_get_expr(vertex);8008 pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma);8009 8010 for (i = 0; i < data->n; ++i) {8011 isl_pw_multi_aff *pma_i;8012 8013 pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]);8014 equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i);8015 isl_pw_multi_aff_free(pma_i);8016 8017 if (equal < 0 || equal)8018 break;8019 }8020 8021 isl_pw_multi_aff_free(pma);8022 isl_vertex_free(vertex);8023 8024 if (equal < 0)8025 return isl_stat_error;8026 8027 return equal ? isl_stat_ok : isl_stat_error;8028}8029 8030int test_vertices(isl_ctx *ctx)8031{8032 int i;8033 8034 for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) {8035 isl_basic_set *bset;8036 isl_vertices *vertices;8037 int ok = 1;8038 isl_size n;8039 8040 bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);8041 vertices = isl_basic_set_compute_vertices(bset);8042 n = isl_vertices_get_n_vertices(vertices);8043 if (vertices_tests[i].n != n)8044 ok = 0;8045 if (isl_vertices_foreach_vertex(vertices, &find_vertex,8046 &vertices_tests[i]) < 0)8047 ok = 0;8048 isl_vertices_free(vertices);8049 isl_basic_set_free(bset);8050 8051 if (n < 0)8052 return -1;8053 if (!ok)8054 isl_die(ctx, isl_error_unknown, "unexpected vertices",8055 return -1);8056 }8057 8058 return 0;8059}8060 8061/* Inputs for basic tests of unary operations on isl_union_map.8062 * "fn" is the function that is being tested.8063 * "arg" is a string description of the input.8064 * "res" is a string description of the expected result.8065 */8066static struct {8067 __isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap);8068 const char *arg;8069 const char *res;8070} umap_un_tests[] = {8071 { &isl_union_map_range_reverse,8072 "{ A[] -> [B[] -> C[]]; A[] -> B[]; A[0] -> N[B[1] -> B[2]] }",8073 "{ A[] -> [C[] -> B[]]; A[0] -> N[B[2] -> B[1]] }" },8074 { &isl_union_map_range_reverse,8075 "{ A[] -> N[B[] -> C[]] }",8076 "{ A[] -> [C[] -> B[]] }" },8077 { &isl_union_map_range_reverse,8078 "{ A[] -> N[B[x] -> B[y]] }",8079 "{ A[] -> N[B[*] -> B[*]] }" },8080};8081 8082/* Perform basic tests of unary operations on isl_union_map.8083 */8084static isl_stat test_un_union_map(isl_ctx *ctx)8085{8086 int i;8087 8088 for (i = 0; i < ARRAY_SIZE(umap_un_tests); ++i) {8089 const char *str;8090 isl_union_map *umap, *res;8091 isl_bool equal;8092 8093 str = umap_un_tests[i].arg;8094 umap = isl_union_map_read_from_str(ctx, str);8095 str = umap_un_tests[i].res;8096 res = isl_union_map_read_from_str(ctx, str);8097 umap = umap_un_tests[i].fn(umap);8098 equal = isl_union_map_is_equal(umap, res);8099 isl_union_map_free(umap);8100 isl_union_map_free(res);8101 if (equal < 0)8102 return isl_stat_error;8103 if (!equal)8104 isl_die(ctx, isl_error_unknown,8105 "unexpected result", return isl_stat_error);8106 }8107 8108 return isl_stat_ok;8109}8110 8111/* Inputs for basic tests of binary operations on isl_union_map.8112 * "fn" is the function that is being tested.8113 * "arg1" and "arg2" are string descriptions of the inputs.8114 * "res" is a string description of the expected result.8115 */8116static struct {8117 __isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap1,8118 __isl_take isl_union_map *umap2);8119 const char *arg1;8120 const char *arg2;8121 const char *res;8122} umap_bin_tests[] = {8123 { &isl_union_map_intersect,8124 "[n] -> { A[i] -> [] : 0 <= i <= n; B[] -> [] }",8125 "[m] -> { A[i] -> [] : 0 <= i <= m; C[] -> [] }",8126 "[m, n] -> { A[i] -> [] : 0 <= i <= n and i <= m }" },8127 { &isl_union_map_intersect_domain_factor_domain,8128 "{ [A[i] -> B[i + 1]] -> C[i + 2] }",8129 "[N] -> { B[i] -> C[N] }",8130 "{ }" },8131 { &isl_union_map_intersect_domain_factor_domain,8132 "{ [A[i] -> B[i + 1]] -> C[i + 2] }",8133 "[N] -> { A[i] -> C[N] }",8134 "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },8135 { &isl_union_map_intersect_domain_factor_domain,8136 "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",8137 "[N] -> { A[i] -> C[N] }",8138 "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },8139 { &isl_union_map_intersect_domain_factor_range,8140 "{ [A[i] -> B[i + 1]] -> C[i + 2] }",8141 "[N] -> { B[i] -> C[N] }",8142 "[N] -> { [A[N - 2] -> B[N - 1]] -> C[N] }" },8143 { &isl_union_map_intersect_domain_factor_range,8144 "{ T[A[i] -> B[i + 1]] -> C[i + 2] }",8145 "[N] -> { B[i] -> C[N] }",8146 "[N] -> { T[A[N - 2] -> B[N - 1]] -> C[N] }" },8147 { &isl_union_map_intersect_domain_factor_range,8148 "{ [A[i] -> B[i + 1]] -> C[i + 2] }",8149 "[N] -> { A[i] -> C[N] }",8150 "{ }" },8151 { &isl_union_map_intersect_range_factor_domain,8152 "{ A[i] -> [B[i + 1] -> C[i + 2]] }",8153 "[N] -> { A[i] -> B[N] }",8154 "[N] -> { A[N - 1] -> [B[N] -> C[N + 1]] }" },8155 { &isl_union_map_intersect_range_factor_domain,8156 "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",8157 "[N] -> { A[i] -> B[N] }",8158 "[N] -> { A[N - 1] -> T[B[N] -> C[N + 1]] }" },8159 { &isl_union_map_intersect_range_factor_domain,8160 "{ A[i] -> [B[i + 1] -> C[i + 2]] }",8161 "[N] -> { A[i] -> C[N] }",8162 "{ }" },8163 { &isl_union_map_intersect_range_factor_range,8164 "{ A[i] -> [B[i + 1] -> C[i + 2]] }",8165 "[N] -> { A[i] -> C[N] }",8166 "[N] -> { A[N - 2] -> [B[N - 1] -> C[N]] }" },8167 { &isl_union_map_intersect_range_factor_range,8168 "{ A[i] -> T[B[i + 1] -> C[i + 2]] }",8169 "[N] -> { A[i] -> C[N] }",8170 "[N] -> { A[N - 2] -> T[B[N - 1] -> C[N]] }" },8171 { &isl_union_map_intersect_range_factor_range,8172 "{ A[i] -> [B[i + 1] -> C[i + 2]] }",8173 "[N] -> { A[i] -> B[N] }",8174 "{ }" },8175};8176 8177/* Perform basic tests of binary operations on isl_union_map.8178 */8179static isl_stat test_bin_union_map(isl_ctx *ctx)8180{8181 int i;8182 8183 for (i = 0; i < ARRAY_SIZE(umap_bin_tests); ++i) {8184 const char *str;8185 isl_union_map *umap1, *umap2, *res;8186 isl_bool equal;8187 8188 str = umap_bin_tests[i].arg1;8189 umap1 = isl_union_map_read_from_str(ctx, str);8190 str = umap_bin_tests[i].arg2;8191 umap2 = isl_union_map_read_from_str(ctx, str);8192 str = umap_bin_tests[i].res;8193 res = isl_union_map_read_from_str(ctx, str);8194 umap1 = umap_bin_tests[i].fn(umap1, umap2);8195 equal = isl_union_map_is_equal(umap1, res);8196 isl_union_map_free(umap1);8197 isl_union_map_free(res);8198 if (equal < 0)8199 return isl_stat_error;8200 if (!equal)8201 isl_die(ctx, isl_error_unknown,8202 "unexpected result", return isl_stat_error);8203 }8204 8205 return isl_stat_ok;8206}8207 8208/* Check that isl_union_set_contains finds space independently8209 * of the parameters.8210 */8211static isl_stat test_union_set_contains(isl_ctx *ctx)8212{8213 const char *str;8214 isl_bool ok;8215 isl_space *space;8216 isl_id *id;8217 isl_union_set *uset;8218 8219 str = "[N] -> { A[0:N]; B[*,*] }";8220 uset = isl_union_set_read_from_str(ctx, str);8221 space = isl_space_unit(ctx);8222 id = isl_id_alloc(ctx, "A", NULL);8223 space = isl_space_add_named_tuple_id_ui(space, id, 1);8224 ok = isl_union_set_contains(uset, space);8225 isl_space_free(space);8226 isl_union_set_free(uset);8227 8228 if (ok < 0)8229 return isl_stat_error;8230 if (!ok)8231 isl_die(ctx, isl_error_unknown,8232 "unexpected result", return isl_stat_error);8233 8234 return isl_stat_ok;8235}8236 8237/* Perform basic tests of operations on isl_union_map or isl_union_set.8238 */8239static int test_union_map(isl_ctx *ctx)8240{8241 if (test_un_union_map(ctx) < 0)8242 return -1;8243 if (test_bin_union_map(ctx) < 0)8244 return -1;8245 if (test_union_set_contains(ctx) < 0)8246 return -1;8247 return 0;8248}8249 8250#undef BASE8251#define BASE union_pw_qpolynomial8252#include "isl_test_plain_equal_templ.c"8253 8254/* Check that the result of applying "fn" to "a" and "b"8255 * in (obviously) equal to "res".8256 */8257static isl_stat test_union_pw_op(isl_ctx *ctx, const char *a, const char *b,8258 __isl_give isl_union_pw_qpolynomial *(*fn)(8259 __isl_take isl_union_pw_qpolynomial *upwqp1,8260 __isl_take isl_union_pw_qpolynomial *upwqp2),8261 const char *res)8262{8263 isl_stat r;8264 isl_union_pw_qpolynomial *upwqp1, *upwqp2;8265 8266 upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, a);8267 upwqp2 = isl_union_pw_qpolynomial_read_from_str(ctx, b);8268 upwqp1 = fn(upwqp1, upwqp2);8269 r = union_pw_qpolynomial_check_plain_equal(upwqp1, res);8270 isl_union_pw_qpolynomial_free(upwqp1);8271 8272 return r;8273}8274 8275int test_union_pw(isl_ctx *ctx)8276{8277 int equal;8278 const char *str;8279 isl_union_set *uset;8280 isl_union_pw_qpolynomial *upwqp1, *upwqp2;8281 const char *a, *b;8282 8283 str = "{ [x] -> x^2 }";8284 upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);8285 upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);8286 uset = isl_union_pw_qpolynomial_domain(upwqp1);8287 upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);8288 upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);8289 equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);8290 isl_union_pw_qpolynomial_free(upwqp1);8291 isl_union_pw_qpolynomial_free(upwqp2);8292 if (equal < 0)8293 return -1;8294 if (!equal)8295 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);8296 8297 a = "{ A[x] -> x^2 : x >= 0; B[x] -> x }";8298 b = "{ A[x] -> x }";8299 str = "{ A[x] -> x^2 + x : x >= 0; A[x] -> x : x < 0; B[x] -> x }";8300 if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_add, str) < 0)8301 return -1;8302 str = "{ A[x] -> x^2 - x : x >= 0; A[x] -> -x : x < 0; B[x] -> x }";8303 if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_sub, str) < 0)8304 return -1;8305 8306 str = "{ A[x] -> 0 }";8307 a = "{ A[x] -> 1 }";8308 b = "{ A[x] -> -1 }";8309 if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_add, str) < 0)8310 return -1;8311 a = "{ A[x] -> 1 }";8312 b = "{ A[x] -> 1 }";8313 if (test_union_pw_op(ctx, a, b, &isl_union_pw_qpolynomial_sub, str) < 0)8314 return -1;8315 8316 return 0;8317}8318 8319/* Inputs for basic tests of functions that select8320 * subparts of the domain of an isl_multi_union_pw_aff.8321 * "fn" is the function that is tested.8322 * "arg" is a string description of the input.8323 * "res" is a string description of the expected result.8324 */8325struct {8326 __isl_give isl_union_set *(*fn)(8327 __isl_take isl_multi_union_pw_aff *mupa);8328 const char *arg;8329 const char *res;8330} un_locus_tests[] = {8331 { &isl_multi_union_pw_aff_zero_union_set,8332 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",8333 "{ A[0,j]; B[0,j] }" },8334 { &isl_multi_union_pw_aff_zero_union_set,8335 "F[{ A[i,j] -> [i-j]; B[i,j] -> [i-j] : i >= 0 }]",8336 "{ A[i,i]; B[i,i] : i >= 0 }" },8337 { &isl_multi_union_pw_aff_zero_union_set,8338 "(F[] : { A[i,j]; B[i,i] : i >= 0 })",8339 "{ A[i,j]; B[i,i] : i >= 0 }" },8340};8341 8342/* Perform some basic tests of functions that select8343 * subparts of the domain of an isl_multi_union_pw_aff.8344 */8345static int test_un_locus(isl_ctx *ctx)8346{8347 int i;8348 isl_bool ok;8349 isl_union_set *uset, *res;8350 isl_multi_union_pw_aff *mupa;8351 8352 for (i = 0; i < ARRAY_SIZE(un_locus_tests); ++i) {8353 mupa = isl_multi_union_pw_aff_read_from_str(ctx,8354 un_locus_tests[i].arg);8355 res = isl_union_set_read_from_str(ctx, un_locus_tests[i].res);8356 uset = un_locus_tests[i].fn(mupa);8357 ok = isl_union_set_is_equal(uset, res);8358 isl_union_set_free(uset);8359 isl_union_set_free(res);8360 if (ok < 0)8361 return -1;8362 if (!ok)8363 isl_die(ctx, isl_error_unknown,8364 "unexpected result", return -1);8365 }8366 8367 return 0;8368}8369 8370/* Inputs for basic tests of functions that select8371 * subparts of an isl_union_map based on a relation8372 * specified by an isl_multi_union_pw_aff.8373 * "fn" is the function that is tested.8374 * "arg1" and "arg2" are string descriptions of the inputs.8375 * "res" is a string description of the expected result.8376 */8377struct {8378 __isl_give isl_union_map *(*fn)(8379 __isl_take isl_union_map *umap,8380 __isl_take isl_multi_union_pw_aff *mupa);8381 const char *arg1;8382 const char *arg2;8383 const char *res;8384} bin_locus_tests[] = {8385 { &isl_union_map_eq_at_multi_union_pw_aff,8386 "{ A[i,j] -> B[i',j'] }",8387 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",8388 "{ A[i,j] -> B[i,j'] }" },8389 { &isl_union_map_eq_at_multi_union_pw_aff,8390 "{ A[i,j] -> B[i',j'] }",8391 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8392 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8393 "{ A[i,j] -> B[i,j] }" },8394 { &isl_union_map_eq_at_multi_union_pw_aff,8395 "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",8396 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }]",8397 "{ A[i,j] -> B[i,j'] }" },8398 { &isl_union_map_eq_at_multi_union_pw_aff,8399 "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",8400 "F[{ A[i,j] -> [i]; B[i,j] -> [i]; C[i,j] -> [0] }]",8401 "{ A[i,j] -> B[i,j']; A[0,j] -> C[i',j'] }" },8402 { &isl_union_map_eq_at_multi_union_pw_aff,8403 "{ A[i,j] -> B[i',j'] }",8404 "F[{ A[i,j] -> [i] : i > j; B[i,j] -> [i] }]",8405 "{ A[i,j] -> B[i,j'] : i > j }" },8406 { &isl_union_map_lex_le_at_multi_union_pw_aff,8407 "{ A[i,j] -> B[i',j'] }",8408 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8409 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8410 "{ A[i,j] -> B[i',j'] : i,j <<= i',j' }" },8411 { &isl_union_map_lex_lt_at_multi_union_pw_aff,8412 "{ A[i,j] -> B[i',j'] }",8413 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8414 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8415 "{ A[i,j] -> B[i',j'] : i,j << i',j' }" },8416 { &isl_union_map_lex_ge_at_multi_union_pw_aff,8417 "{ A[i,j] -> B[i',j'] }",8418 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8419 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8420 "{ A[i,j] -> B[i',j'] : i,j >>= i',j' }" },8421 { &isl_union_map_lex_gt_at_multi_union_pw_aff,8422 "{ A[i,j] -> B[i',j'] }",8423 "F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "8424 "{ A[i,j] -> [j]; B[i,j] -> [j] }]",8425 "{ A[i,j] -> B[i',j'] : i,j >> i',j' }" },8426 { &isl_union_map_eq_at_multi_union_pw_aff,8427 "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",8428 "(F[] : { A[i,j]; B[i,j] })",8429 "{ A[i,j] -> B[i',j'] }" },8430 { &isl_union_map_eq_at_multi_union_pw_aff,8431 "{ A[i,j] -> B[i',j'] }",8432 "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",8433 "{ A[i,j] -> B[i',j'] : i > j and i' < j' }" },8434 { &isl_union_map_eq_at_multi_union_pw_aff,8435 "[N] -> { A[i,j] -> B[i',j'] : i,i' <= N }",8436 "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",8437 "[N] -> { A[i,j] -> B[i',j'] : i > j and i' < j' and i,i' <= N }" },8438 { &isl_union_map_eq_at_multi_union_pw_aff,8439 "{ A[i,j] -> B[i',j'] }",8440 "[N] -> (F[] : { A[i,j] : i < N; B[i,j] : i < N })",8441 "[N] -> { A[i,j] -> B[i',j'] : i,i' < N }" },8442 { &isl_union_map_eq_at_multi_union_pw_aff,8443 "{ A[i,j] -> B[i',j'] }",8444 "[N] -> (F[] : { : N >= 0 })",8445 "[N] -> { A[i,j] -> B[i',j'] : N >= 0 }" },8446};8447 8448/* Perform some basic tests of functions that select8449 * subparts of an isl_union_map based on a relation8450 * specified by an isl_multi_union_pw_aff.8451 */8452static int test_bin_locus(isl_ctx *ctx)8453{8454 int i;8455 isl_bool ok;8456 isl_union_map *umap, *res;8457 isl_multi_union_pw_aff *mupa;8458 8459 for (i = 0; i < ARRAY_SIZE(bin_locus_tests); ++i) {8460 umap = isl_union_map_read_from_str(ctx,8461 bin_locus_tests[i].arg1);8462 mupa = isl_multi_union_pw_aff_read_from_str(ctx,8463 bin_locus_tests[i].arg2);8464 res = isl_union_map_read_from_str(ctx, bin_locus_tests[i].res);8465 umap = bin_locus_tests[i].fn(umap, mupa);8466 ok = isl_union_map_is_equal(umap, res);8467 isl_union_map_free(umap);8468 isl_union_map_free(res);8469 if (ok < 0)8470 return -1;8471 if (!ok)8472 isl_die(ctx, isl_error_unknown,8473 "unexpected result", return -1);8474 }8475 8476 return 0;8477}8478 8479/* Inputs for basic tests of functions that determine8480 * the part of the domain where two isl_multi_aff objects8481 * related to each other in a specific way.8482 * "fn" is the function that is being tested.8483 * "arg1" and "arg2" are string descriptions of the inputs.8484 * "res" is a string description of the expected result.8485 */8486static struct {8487 __isl_give isl_set *(*fn)(__isl_take isl_multi_aff *ma1,8488 __isl_take isl_multi_aff *ma2);8489 const char *arg1;8490 const char *arg2;8491 const char *res;8492} bin_locus_ma_tests[] = {8493 { &isl_multi_aff_lex_le_set, "{ [] }", "{ [] }", "{ : }" },8494 { &isl_multi_aff_lex_lt_set, "{ [] }", "{ [] }", "{ : false }" },8495 { &isl_multi_aff_lex_le_set,8496 "{ A[i] -> [i] }", "{ A[i] -> [0] }",8497 "{ A[i] : i <= 0 }" },8498 { &isl_multi_aff_lex_lt_set,8499 "{ A[i] -> [i] }", "{ A[i] -> [0] }",8500 "{ A[i] : i < 0 }" },8501 { &isl_multi_aff_lex_le_set,8502 "{ A[i] -> [i, i] }", "{ A[i] -> [0, 0] }",8503 "{ A[i] : i <= 0 }" },8504 { &isl_multi_aff_lex_le_set,8505 "{ A[i] -> [i, 0] }", "{ A[i] -> [0, 0] }",8506 "{ A[i] : i <= 0 }" },8507 { &isl_multi_aff_lex_le_set,8508 "{ A[i] -> [i, 1] }", "{ A[i] -> [0, 0] }",8509 "{ A[i] : i < 0 }" },8510};8511 8512/* Perform some basic tests of functions that determine8513 * the part of the domain where two isl_multi_aff objects8514 * related to each other in a specific way.8515 */8516static isl_stat test_bin_locus_ma(isl_ctx *ctx)8517{8518 int i;8519 8520 for (i = 0; i < ARRAY_SIZE(bin_locus_ma_tests); ++i) {8521 const char *str;8522 isl_bool ok;8523 isl_multi_aff *ma1, *ma2;8524 isl_set *set, *res;8525 8526 str = bin_locus_ma_tests[i].arg1;8527 ma1 = isl_multi_aff_read_from_str(ctx, str);8528 str = bin_locus_ma_tests[i].arg2;8529 ma2 = isl_multi_aff_read_from_str(ctx, str);8530 res = isl_set_read_from_str(ctx, bin_locus_ma_tests[i].res);8531 set = bin_locus_ma_tests[i].fn(ma1, ma2);8532 ok = isl_set_is_equal(set, res);8533 isl_set_free(set);8534 isl_set_free(res);8535 if (ok < 0)8536 return isl_stat_error;8537 if (!ok)8538 isl_die(ctx, isl_error_unknown,8539 "unexpected result", return isl_stat_error);8540 }8541 8542 return isl_stat_ok;8543}8544 8545/* Perform basic locus tests.8546 */8547static int test_locus(isl_ctx *ctx)8548{8549 if (test_un_locus(ctx) < 0)8550 return -1;8551 if (test_bin_locus(ctx) < 0)8552 return -1;8553 if (test_bin_locus_ma(ctx) < 0)8554 return -1;8555 return 0;8556}8557 8558/* Test that isl_union_pw_qpolynomial_eval picks up the function8559 * defined over the correct domain space.8560 */8561static int test_eval_1(isl_ctx *ctx)8562{8563 const char *str;8564 isl_point *pnt;8565 isl_set *set;8566 isl_union_pw_qpolynomial *upwqp;8567 isl_val *v;8568 int cmp;8569 8570 str = "{ A[x] -> x^2; B[x] -> -x^2 }";8571 upwqp = isl_union_pw_qpolynomial_read_from_str(ctx, str);8572 str = "{ A[6] }";8573 set = isl_set_read_from_str(ctx, str);8574 pnt = isl_set_sample_point(set);8575 v = isl_union_pw_qpolynomial_eval(upwqp, pnt);8576 cmp = isl_val_cmp_si(v, 36);8577 isl_val_free(v);8578 8579 if (!v)8580 return -1;8581 if (cmp != 0)8582 isl_die(ctx, isl_error_unknown, "unexpected value", return -1);8583 8584 return 0;8585}8586 8587/* Check that isl_qpolynomial_eval handles getting called on a void point.8588 */8589static int test_eval_2(isl_ctx *ctx)8590{8591 const char *str;8592 isl_point *pnt;8593 isl_set *set;8594 isl_qpolynomial *qp;8595 isl_val *v;8596 isl_bool ok;8597 8598 str = "{ A[x] -> [x] }";8599 qp = isl_qpolynomial_from_aff(isl_aff_read_from_str(ctx, str));8600 str = "{ A[x] : false }";8601 set = isl_set_read_from_str(ctx, str);8602 pnt = isl_set_sample_point(set);8603 v = isl_qpolynomial_eval(qp, pnt);8604 ok = isl_val_is_nan(v);8605 isl_val_free(v);8606 8607 if (ok < 0)8608 return -1;8609 if (!ok)8610 isl_die(ctx, isl_error_unknown, "expecting NaN", return -1);8611 8612 return 0;8613}8614 8615/* Check that a polynomial (without local variables) can be evaluated8616 * in a rational point.8617 */8618static isl_stat test_eval_3(isl_ctx *ctx)8619{8620 isl_pw_qpolynomial *pwqp;8621 isl_point *pnt;8622 isl_val *v;8623 isl_stat r;8624 8625 pwqp = isl_pw_qpolynomial_read_from_str(ctx, "{ [x] -> x^2 }");8626 pnt = isl_point_zero(isl_pw_qpolynomial_get_domain_space(pwqp));8627 v = isl_val_read_from_str(ctx, "1/2");8628 pnt = isl_point_set_coordinate_val(pnt, isl_dim_set, 0, v);8629 v = isl_pw_qpolynomial_eval(pwqp, pnt);8630 r = val_check_equal(v, "1/4");8631 isl_val_free(v);8632 8633 return r;8634}8635 8636/* Inputs for isl_pw_aff_eval test.8637 * "f" is the affine function.8638 * "p" is the point where the function should be evaluated.8639 * "res" is the expected result.8640 */8641struct {8642 const char *f;8643 const char *p;8644 const char *res;8645} aff_eval_tests[] = {8646 { "{ [i] -> [2 * i] }", "{ [4] }", "8" },8647 { "{ [i] -> [2 * i] }", "{ [x] : false }", "NaN" },8648 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [0] }", "0" },8649 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [1] }", "1" },8650 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [2] }", "3" },8651 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [3] }", "5" },8652 { "{ [i] -> [i + floor(i/2) + floor(i/3)] }", "{ [4] }", "7" },8653 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [0] }", "0" },8654 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [1] }", "0" },8655 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [2] }", "0" },8656 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [3] }", "0" },8657 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [4] }", "1" },8658 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [6] }", "1" },8659 { "{ [i] -> [floor((3 * floor(i/2))/5)] }", "{ [8] }", "2" },8660 { "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [4] }", "4" },8661 { "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [-2] }", "2" },8662 { "{ [i] -> [i] : i > 0; [i] -> [-i] : i < 0 }", "{ [0] }", "NaN" },8663 { "[N] -> { [2 * N] }", "[N] -> { : N = 4 }", "8" },8664 { "{ [i, j] -> [(i + j)/2] }", "{ [1, 1] }", "1" },8665 { "{ [i, j] -> [(i + j)/2] }", "{ [1, 2] }", "3/2" },8666 { "{ [i] -> [i] : i mod 2 = 0 }", "{ [4] }", "4" },8667 { "{ [i] -> [i] : i mod 2 = 0 }", "{ [3] }", "NaN" },8668 { "{ [i] -> [i] : i mod 2 = 0 }", "{ [x] : false }", "NaN" },8669 { "[m, n] -> { [2m + 3n] }", "[n=1, m=10] -> { : }", "23" },8670};8671 8672/* Perform basic isl_pw_aff_eval tests.8673 */8674static int test_eval_aff(isl_ctx *ctx)8675{8676 int i;8677 8678 for (i = 0; i < ARRAY_SIZE(aff_eval_tests); ++i) {8679 isl_stat r;8680 isl_pw_aff *pa;8681 isl_set *set;8682 isl_point *pnt;8683 isl_val *v;8684 8685 pa = isl_pw_aff_read_from_str(ctx, aff_eval_tests[i].f);8686 set = isl_set_read_from_str(ctx, aff_eval_tests[i].p);8687 pnt = isl_set_sample_point(set);8688 v = isl_pw_aff_eval(pa, pnt);8689 r = val_check_equal(v, aff_eval_tests[i].res);8690 isl_val_free(v);8691 if (r < 0)8692 return -1;8693 }8694 return 0;8695}8696 8697/* Perform basic evaluation tests.8698 */8699static int test_eval(isl_ctx *ctx)8700{8701 if (test_eval_1(ctx) < 0)8702 return -1;8703 if (test_eval_2(ctx) < 0)8704 return -1;8705 if (test_eval_3(ctx) < 0)8706 return -1;8707 if (test_eval_aff(ctx) < 0)8708 return -1;8709 return 0;8710}8711 8712/* Descriptions of sets that are tested for reparsing after printing.8713 */8714const char *output_tests[] = {8715 "{ [1, y] : 0 <= y <= 1; [x, -x] : 0 <= x <= 1 }",8716 "{ [x] : 1 = 0 }",8717 "{ [x] : false }",8718 "{ [x] : x mod 2 = 0 }",8719 "{ [x] : x mod 2 = 1 }",8720 "{ [x, y] : x mod 2 = 0 and 3*floor(y/2) < x }",8721 "{ [y, x] : x mod 2 = 0 and 3*floor(y/2) < x }",8722 "{ [x, y] : x mod 2 = 0 and 3*floor(y/2) = x + y }",8723 "{ [y, x] : x mod 2 = 0 and 3*floor(y/2) = x + y }",8724 "[n] -> { [y, x] : 2*((x + 2y) mod 3) = n }",8725 "{ [x, y] : (2*floor(x/3) + 3*floor(y/4)) mod 5 = x }",8726};8727 8728/* Check that printing a set and reparsing a set from the printed output8729 * results in the same set.8730 */8731static int test_output_set(isl_ctx *ctx)8732{8733 int i;8734 char *str;8735 isl_set *set1, *set2;8736 isl_bool equal;8737 8738 for (i = 0; i < ARRAY_SIZE(output_tests); ++i) {8739 set1 = isl_set_read_from_str(ctx, output_tests[i]);8740 str = isl_set_to_str(set1);8741 set2 = isl_set_read_from_str(ctx, str);8742 free(str);8743 equal = isl_set_is_equal(set1, set2);8744 isl_set_free(set1);8745 isl_set_free(set2);8746 if (equal < 0)8747 return -1;8748 if (!equal)8749 isl_die(ctx, isl_error_unknown,8750 "parsed output not the same", return -1);8751 }8752 8753 return 0;8754}8755 8756/* Check that an isl_multi_aff is printed using a consistent space.8757 */8758static isl_stat test_output_ma(isl_ctx *ctx)8759{8760 char *str;8761 isl_bool equal;8762 isl_aff *aff;8763 isl_multi_aff *ma, *ma2;8764 8765 ma = isl_multi_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");8766 aff = isl_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");8767 ma = isl_multi_aff_set_aff(ma, 0, aff);8768 str = isl_multi_aff_to_str(ma);8769 ma2 = isl_multi_aff_read_from_str(ctx, str);8770 free(str);8771 equal = isl_multi_aff_plain_is_equal(ma, ma2);8772 isl_multi_aff_free(ma2);8773 isl_multi_aff_free(ma);8774 8775 if (equal < 0)8776 return isl_stat_error;8777 if (!equal)8778 isl_die(ctx, isl_error_unknown, "bad conversion",8779 return isl_stat_error);8780 8781 return isl_stat_ok;8782}8783 8784/* Check that an isl_multi_pw_aff is printed using a consistent space.8785 */8786static isl_stat test_output_mpa(isl_ctx *ctx)8787{8788 char *str;8789 isl_bool equal;8790 isl_pw_aff *pa;8791 isl_multi_pw_aff *mpa, *mpa2;8792 8793 mpa = isl_multi_pw_aff_read_from_str(ctx, "{ [a, b] -> [a + b] }");8794 pa = isl_pw_aff_read_from_str(ctx, "{ [c, d] -> [c + d] }");8795 mpa = isl_multi_pw_aff_set_pw_aff(mpa, 0, pa);8796 str = isl_multi_pw_aff_to_str(mpa);8797 mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);8798 free(str);8799 equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);8800 isl_multi_pw_aff_free(mpa2);8801 isl_multi_pw_aff_free(mpa);8802 8803 if (equal < 0)8804 return isl_stat_error;8805 if (!equal)8806 isl_die(ctx, isl_error_unknown, "bad conversion",8807 return isl_stat_error);8808 8809 return isl_stat_ok;8810}8811 8812int test_output(isl_ctx *ctx)8813{8814 char *s;8815 const char *str;8816 isl_pw_aff *pa;8817 isl_printer *p;8818 int equal;8819 8820 if (test_output_set(ctx) < 0)8821 return -1;8822 if (test_output_ma(ctx) < 0)8823 return -1;8824 if (test_output_mpa(ctx) < 0)8825 return -1;8826 8827 str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";8828 pa = isl_pw_aff_read_from_str(ctx, str);8829 8830 p = isl_printer_to_str(ctx);8831 p = isl_printer_set_output_format(p, ISL_FORMAT_C);8832 p = isl_printer_print_pw_aff(p, pa);8833 s = isl_printer_get_str(p);8834 isl_printer_free(p);8835 isl_pw_aff_free(pa);8836 if (!s)8837 equal = -1;8838 else8839 equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2");8840 free(s);8841 if (equal < 0)8842 return -1;8843 if (!equal)8844 isl_die(ctx, isl_error_unknown, "unexpected result", return -1);8845 8846 return 0;8847}8848 8849int test_sample(isl_ctx *ctx)8850{8851 const char *str;8852 isl_basic_set *bset1, *bset2;8853 int empty, subset;8854 8855 str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "8856 "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "8857 "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "8858 "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "8859 "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "8860 "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "8861 "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "8862 "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "8863 "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "8864 "f >= 1 - a + 1073741822b + c + d - 1073741822e and "8865 "3i >= 1 + 2b - 2c + e + 2f + 3g and "8866 "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"8867 "d - 1073741821e and "8868 "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "8869 "3j >= 1 - a + b + 2e and "8870 "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "8871 "3i <= 4 - a + 4b - e and "8872 "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "8873 "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "8874 "c <= -1 + a and 3i >= -2 - a + 3e and "8875 "1073741822e <= 1073741823 - a + 1073741822b + c and "8876 "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "8877 "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "8878 "1073741823e >= 1 + 1073741823b - d and "8879 "3i >= 1073741823b + c - 1073741823e - f and "8880 "3i >= 1 + 2b + e + 3g }";8881 bset1 = isl_basic_set_read_from_str(ctx, str);8882 bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));8883 empty = isl_basic_set_is_empty(bset2);8884 subset = isl_basic_set_is_subset(bset2, bset1);8885 isl_basic_set_free(bset1);8886 isl_basic_set_free(bset2);8887 if (empty < 0 || subset < 0)8888 return -1;8889 if (empty)8890 isl_die(ctx, isl_error_unknown, "point not found", return -1);8891 if (!subset)8892 isl_die(ctx, isl_error_unknown, "bad point found", return -1);8893 8894 return 0;8895}8896 8897/* Perform a projection on a basic set that is known to be empty8898 * but that has not been assigned a canonical representation.8899 * Earlier versions of isl would run into a stack overflow8900 * on this example.8901 */8902static int test_empty_projection(isl_ctx *ctx)8903{8904 const char *str;8905 isl_bool empty;8906 isl_basic_set *bset;8907 8908 str = "{ [a, b, c, d, e, f, g, h] : 5f = 1 + 4a - b + 5c - d - 2e and "8909 "3h = 2 + b + c and 14c >= 9 - 3a + 25b and "8910 "4c <= 50 - 3a + 23b and 6b <= -39 + a and "8911 "9g >= -6 + 3a + b + c and e < a + b - 2d and "8912 "7d >= -5 + 2a + 2b and 5g >= -14 + a - 4b + d + 2e and "8913 "9g <= -28 - 5b - 2c + 3d + 6e }";8914 bset = isl_basic_set_read_from_str(ctx, str);8915 empty = isl_basic_set_is_empty(bset);8916 bset = isl_basic_set_params(bset);8917 isl_basic_set_free(bset);8918 8919 if (empty < 0)8920 return -1;8921 8922 return 0;8923}8924 8925int test_slice(isl_ctx *ctx)8926{8927 const char *str;8928 isl_map *map;8929 int equal;8930 8931 str = "{ [i] -> [j] }";8932 map = isl_map_read_from_str(ctx, str);8933 map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);8934 equal = map_check_equal(map, "{ [i] -> [i] }");8935 isl_map_free(map);8936 if (equal < 0)8937 return -1;8938 8939 str = "{ [i] -> [j] }";8940 map = isl_map_read_from_str(ctx, str);8941 map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);8942 equal = map_check_equal(map, "{ [i] -> [j] }");8943 isl_map_free(map);8944 if (equal < 0)8945 return -1;8946 8947 str = "{ [i] -> [j] }";8948 map = isl_map_read_from_str(ctx, str);8949 map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);8950 equal = map_check_equal(map, "{ [i] -> [-i] }");8951 isl_map_free(map);8952 if (equal < 0)8953 return -1;8954 8955 str = "{ [i] -> [j] }";8956 map = isl_map_read_from_str(ctx, str);8957 map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);8958 equal = map_check_equal(map, "{ [0] -> [j] }");8959 isl_map_free(map);8960 if (equal < 0)8961 return -1;8962 8963 str = "{ [i] -> [j] }";8964 map = isl_map_read_from_str(ctx, str);8965 map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);8966 equal = map_check_equal(map, "{ [i] -> [j] : i > j }");8967 isl_map_free(map);8968 if (equal < 0)8969 return -1;8970 8971 str = "{ [i] -> [j] }";8972 map = isl_map_read_from_str(ctx, str);8973 map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);8974 equal = map_check_equal(map, "{ [i] -> [j] : false }");8975 isl_map_free(map);8976 if (equal < 0)8977 return -1;8978 8979 return 0;8980}8981 8982int test_eliminate(isl_ctx *ctx)8983{8984 const char *str;8985 isl_map *map;8986 int equal;8987 8988 str = "{ [i] -> [j] : i = 2j }";8989 map = isl_map_read_from_str(ctx, str);8990 map = isl_map_eliminate(map, isl_dim_out, 0, 1);8991 equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");8992 isl_map_free(map);8993 if (equal < 0)8994 return -1;8995 8996 return 0;8997}8998 8999/* Check basic functionality of isl_map_deltas_map.9000 */9001static int test_deltas_map(isl_ctx *ctx)9002{9003 const char *str;9004 isl_map *map;9005 int equal;9006 9007 str = "{ A[i] -> A[i + 1] }";9008 map = isl_map_read_from_str(ctx, str);9009 map = isl_map_deltas_map(map);9010 equal = map_check_equal(map, "{ [A[i] -> A[i + 1]] -> A[1] }");9011 isl_map_free(map);9012 if (equal < 0)9013 return -1;9014 9015 return 0;9016}9017 9018/* Check that isl_set_dim_residue_class detects that the values of j9019 * in the set below are all odd and that it does not detect any spurious9020 * strides.9021 */9022static int test_residue_class(isl_ctx *ctx)9023{9024 const char *str;9025 isl_set *set;9026 isl_int m, r;9027 isl_stat res;9028 9029 str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "9030 "[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";9031 set = isl_set_read_from_str(ctx, str);9032 isl_int_init(m);9033 isl_int_init(r);9034 res = isl_set_dim_residue_class(set, 1, &m, &r);9035 if (res >= 0 &&9036 (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))9037 isl_die(ctx, isl_error_unknown, "incorrect residue class",9038 res = isl_stat_error);9039 isl_int_clear(r);9040 isl_int_clear(m);9041 isl_set_free(set);9042 9043 return res;9044}9045 9046static int test_align_parameters_1(isl_ctx *ctx)9047{9048 const char *str;9049 isl_space *space;9050 isl_multi_aff *ma1, *ma2;9051 int equal;9052 9053 str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";9054 ma1 = isl_multi_aff_read_from_str(ctx, str);9055 9056 space = isl_space_params_alloc(ctx, 1);9057 space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");9058 ma1 = isl_multi_aff_align_params(ma1, space);9059 9060 str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";9061 ma2 = isl_multi_aff_read_from_str(ctx, str);9062 9063 equal = isl_multi_aff_plain_is_equal(ma1, ma2);9064 9065 isl_multi_aff_free(ma1);9066 isl_multi_aff_free(ma2);9067 9068 if (equal < 0)9069 return -1;9070 if (!equal)9071 isl_die(ctx, isl_error_unknown,9072 "result not as expected", return -1);9073 9074 return 0;9075}9076 9077/* Check the isl_multi_*_from_*_list operation in case inputs9078 * have unaligned parameters.9079 * In particular, older versions of isl would simply fail9080 * (without printing any error message).9081 */9082static isl_stat test_align_parameters_2(isl_ctx *ctx)9083{9084 isl_space *space;9085 isl_map *map;9086 isl_aff *aff;9087 isl_multi_aff *ma;9088 9089 map = isl_map_read_from_str(ctx, "{ A[] -> M[x] }");9090 space = isl_map_get_space(map);9091 isl_map_free(map);9092 9093 aff = isl_aff_read_from_str(ctx, "[N] -> { A[] -> [N] }");9094 ma = isl_multi_aff_from_aff_list(space, isl_aff_list_from_aff(aff));9095 isl_multi_aff_free(ma);9096 9097 if (!ma)9098 return isl_stat_error;9099 return isl_stat_ok;9100}9101 9102/* Perform basic parameter alignment tests.9103 */9104static int test_align_parameters(isl_ctx *ctx)9105{9106 if (test_align_parameters_1(ctx) < 0)9107 return -1;9108 if (test_align_parameters_2(ctx) < 0)9109 return -1;9110 9111 return 0;9112}9113 9114/* Check that isl_*_drop_unused_params actually drops the unused parameters9115 * by comparing the result using isl_*_plain_is_equal.9116 * Note that this assumes that isl_*_plain_is_equal does not consider9117 * objects that only differ by unused parameters to be equal.9118 */9119int test_drop_unused_parameters(isl_ctx *ctx)9120{9121 const char *str_with, *str_without;9122 isl_basic_set *bset1, *bset2;9123 isl_set *set1, *set2;9124 isl_pw_aff *pwa1, *pwa2;9125 int equal;9126 9127 str_with = "[n, m, o] -> { [m] }";9128 str_without = "[m] -> { [m] }";9129 9130 bset1 = isl_basic_set_read_from_str(ctx, str_with);9131 bset2 = isl_basic_set_read_from_str(ctx, str_without);9132 bset1 = isl_basic_set_drop_unused_params(bset1);9133 equal = isl_basic_set_plain_is_equal(bset1, bset2);9134 isl_basic_set_free(bset1);9135 isl_basic_set_free(bset2);9136 9137 if (equal < 0)9138 return -1;9139 if (!equal)9140 isl_die(ctx, isl_error_unknown,9141 "result not as expected", return -1);9142 9143 set1 = isl_set_read_from_str(ctx, str_with);9144 set2 = isl_set_read_from_str(ctx, str_without);9145 set1 = isl_set_drop_unused_params(set1);9146 equal = isl_set_plain_is_equal(set1, set2);9147 isl_set_free(set1);9148 isl_set_free(set2);9149 9150 if (equal < 0)9151 return -1;9152 if (!equal)9153 isl_die(ctx, isl_error_unknown,9154 "result not as expected", return -1);9155 9156 pwa1 = isl_pw_aff_read_from_str(ctx, str_with);9157 pwa2 = isl_pw_aff_read_from_str(ctx, str_without);9158 pwa1 = isl_pw_aff_drop_unused_params(pwa1);9159 equal = isl_pw_aff_plain_is_equal(pwa1, pwa2);9160 isl_pw_aff_free(pwa1);9161 isl_pw_aff_free(pwa2);9162 9163 if (equal < 0)9164 return -1;9165 if (!equal)9166 isl_die(ctx, isl_error_unknown,9167 "result not as expected", return -1);9168 9169 return 0;9170}9171 9172static int test_list(isl_ctx *ctx)9173{9174 isl_id *a, *b, *c, *d, *id;9175 isl_id_list *list;9176 isl_size n;9177 int ok;9178 9179 a = isl_id_alloc(ctx, "a", NULL);9180 b = isl_id_alloc(ctx, "b", NULL);9181 c = isl_id_alloc(ctx, "c", NULL);9182 d = isl_id_alloc(ctx, "d", NULL);9183 9184 list = isl_id_list_alloc(ctx, 4);9185 list = isl_id_list_add(list, b);9186 list = isl_id_list_insert(list, 0, a);9187 list = isl_id_list_add(list, c);9188 list = isl_id_list_add(list, d);9189 list = isl_id_list_drop(list, 1, 1);9190 9191 n = isl_id_list_n_id(list);9192 if (n < 0)9193 return -1;9194 if (n != 3) {9195 isl_id_list_free(list);9196 isl_die(ctx, isl_error_unknown,9197 "unexpected number of elements in list", return -1);9198 }9199 9200 id = isl_id_list_get_id(list, 0);9201 ok = id == a;9202 isl_id_free(id);9203 id = isl_id_list_get_id(list, 1);9204 ok = ok && id == c;9205 isl_id_free(id);9206 id = isl_id_list_get_id(list, 2);9207 ok = ok && id == d;9208 isl_id_free(id);9209 9210 isl_id_list_free(list);9211 9212 if (!ok)9213 isl_die(ctx, isl_error_unknown,9214 "unexpected elements in list", return -1);9215 9216 return 0;9217}9218 9219/* Check the conversion from an isl_multi_aff to an isl_basic_set.9220 */9221static isl_stat test_ma_conversion(isl_ctx *ctx)9222{9223 const char *str;9224 isl_bool equal;9225 isl_multi_aff *ma;9226 isl_basic_set *bset1, *bset2;9227 9228 str = "[N] -> { A[0, N + 1] }";9229 ma = isl_multi_aff_read_from_str(ctx, str);9230 bset1 = isl_basic_set_read_from_str(ctx, str);9231 bset2 = isl_basic_set_from_multi_aff(ma);9232 equal = isl_basic_set_is_equal(bset1, bset2);9233 isl_basic_set_free(bset1);9234 isl_basic_set_free(bset2);9235 if (equal < 0)9236 return isl_stat_error;9237 if (!equal)9238 isl_die(ctx, isl_error_unknown, "bad conversion",9239 return isl_stat_error);9240 return isl_stat_ok;9241}9242 9243const char *set_conversion_tests[] = {9244 "[N] -> { [i] : N - 1 <= 2 i <= N }",9245 "[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",9246 "[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",9247 "[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",9248 "[N] -> { [3*floor(N/2) + 5*floor(N/3)] }",9249 "[a, b] -> { [c, d] : (4*floor((-a + c)/4) = -a + c and "9250 "32*floor((-b + d)/32) = -b + d and 5 <= c <= 8 and "9251 "-3 + c <= d <= 28 + c) }",9252};9253 9254/* Check that converting from isl_set to isl_pw_multi_aff and back9255 * to isl_set produces the original isl_set.9256 */9257static int test_set_conversion(isl_ctx *ctx)9258{9259 int i;9260 const char *str;9261 isl_set *set1, *set2;9262 isl_pw_multi_aff *pma;9263 int equal;9264 9265 for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {9266 str = set_conversion_tests[i];9267 set1 = isl_set_read_from_str(ctx, str);9268 pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));9269 set2 = isl_set_from_pw_multi_aff(pma);9270 equal = isl_set_is_equal(set1, set2);9271 isl_set_free(set1);9272 isl_set_free(set2);9273 9274 if (equal < 0)9275 return -1;9276 if (!equal)9277 isl_die(ctx, isl_error_unknown, "bad conversion",9278 return -1);9279 }9280 9281 return 0;9282}9283 9284const char *conversion_tests[] = {9285 "{ [a, b, c, d] -> s0[a, b, e, f] : "9286 "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "9287 "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "9288 "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "9289 "9e <= -2 - 2a) }",9290 "{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "9291 "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",9292 "{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",9293};9294 9295/* Check that converting from isl_map to isl_pw_multi_aff and back9296 * to isl_map produces the original isl_map.9297 */9298static int test_map_conversion(isl_ctx *ctx)9299{9300 int i;9301 isl_map *map1, *map2;9302 isl_pw_multi_aff *pma;9303 int equal;9304 9305 for (i = 0; i < ARRAY_SIZE(conversion_tests); ++i) {9306 map1 = isl_map_read_from_str(ctx, conversion_tests[i]);9307 pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));9308 map2 = isl_map_from_pw_multi_aff(pma);9309 equal = isl_map_is_equal(map1, map2);9310 isl_map_free(map1);9311 isl_map_free(map2);9312 9313 if (equal < 0)9314 return -1;9315 if (!equal)9316 isl_die(ctx, isl_error_unknown, "bad conversion",9317 return -1);9318 }9319 9320 return 0;9321}9322 9323/* Descriptions of isl_pw_multi_aff objects for testing conversion9324 * to isl_multi_pw_aff and back.9325 */9326const char *mpa_conversion_tests[] = {9327 "{ [x] -> A[x] }",9328 "{ [x] -> A[x] : x >= 0 }",9329 "{ [x] -> A[x] : x >= 0; [x] -> A[-x] : x < 0 }",9330 "{ [x] -> A[x, x + 1] }",9331 "{ [x] -> A[] }",9332 "{ [x] -> A[] : x >= 0 }",9333};9334 9335/* Check that conversion from isl_pw_multi_aff to isl_multi_pw_aff and9336 * back to isl_pw_multi_aff preserves the original meaning.9337 */9338static int test_mpa_conversion(isl_ctx *ctx)9339{9340 int i;9341 isl_pw_multi_aff *pma1, *pma2;9342 isl_multi_pw_aff *mpa;9343 int equal;9344 9345 for (i = 0; i < ARRAY_SIZE(mpa_conversion_tests); ++i) {9346 const char *str;9347 str = mpa_conversion_tests[i];9348 pma1 = isl_pw_multi_aff_read_from_str(ctx, str);9349 pma2 = isl_pw_multi_aff_copy(pma1);9350 mpa = isl_multi_pw_aff_from_pw_multi_aff(pma1);9351 pma1 = isl_pw_multi_aff_from_multi_pw_aff(mpa);9352 equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);9353 isl_pw_multi_aff_free(pma1);9354 isl_pw_multi_aff_free(pma2);9355 9356 if (equal < 0)9357 return -1;9358 if (!equal)9359 isl_die(ctx, isl_error_unknown, "bad conversion",9360 return -1);9361 }9362 9363 return 0;9364}9365 9366/* Descriptions of union maps that should be convertible9367 * to an isl_multi_union_pw_aff.9368 */9369const char *umap_mupa_conversion_tests[] = {9370 "{ [a, b, c, d] -> s0[a, b, e, f] : "9371 "exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "9372 "e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "9373 "9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "9374 "9e <= -2 - 2a) }",9375 "{ [a, b] -> [c] : exists (e0 = floor((-a - b + c)/5): "9376 "5e0 = -a - b + c and c >= -a and c <= 4 - a) }",9377 "{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",9378 "{ A[] -> B[0]; C[] -> B[1] }",9379 "{ A[] -> B[]; C[] -> B[] }",9380};9381 9382/* Check that converting from isl_union_map to isl_multi_union_pw_aff and back9383 * to isl_union_map produces the original isl_union_map.9384 */9385static int test_union_map_mupa_conversion(isl_ctx *ctx)9386{9387 int i;9388 isl_union_map *umap1, *umap2;9389 isl_multi_union_pw_aff *mupa;9390 int equal;9391 9392 for (i = 0; i < ARRAY_SIZE(umap_mupa_conversion_tests); ++i) {9393 const char *str;9394 str = umap_mupa_conversion_tests[i];9395 umap1 = isl_union_map_read_from_str(ctx, str);9396 umap2 = isl_union_map_copy(umap1);9397 mupa = isl_multi_union_pw_aff_from_union_map(umap2);9398 umap2 = isl_union_map_from_multi_union_pw_aff(mupa);9399 equal = isl_union_map_is_equal(umap1, umap2);9400 isl_union_map_free(umap1);9401 isl_union_map_free(umap2);9402 9403 if (equal < 0)9404 return -1;9405 if (!equal)9406 isl_die(ctx, isl_error_unknown, "bad conversion",9407 return -1);9408 }9409 9410 return 0;9411}9412 9413static int test_conversion(isl_ctx *ctx)9414{9415 if (test_ma_conversion(ctx) < 0)9416 return -1;9417 if (test_set_conversion(ctx) < 0)9418 return -1;9419 if (test_map_conversion(ctx) < 0)9420 return -1;9421 if (test_mpa_conversion(ctx) < 0)9422 return -1;9423 if (test_union_map_mupa_conversion(ctx) < 0)9424 return -1;9425 return 0;9426}9427 9428/* Check that isl_basic_map_curry does not modify input.9429 */9430static int test_curry(isl_ctx *ctx)9431{9432 const char *str;9433 isl_basic_map *bmap1, *bmap2;9434 int equal;9435 9436 str = "{ [A[] -> B[]] -> C[] }";9437 bmap1 = isl_basic_map_read_from_str(ctx, str);9438 bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));9439 equal = isl_basic_map_is_equal(bmap1, bmap2);9440 isl_basic_map_free(bmap1);9441 isl_basic_map_free(bmap2);9442 9443 if (equal < 0)9444 return -1;9445 if (equal)9446 isl_die(ctx, isl_error_unknown,9447 "curried map should not be equal to original",9448 return -1);9449 9450 return 0;9451}9452 9453struct {9454 const char *ma1;9455 const char *ma;9456 const char *res;9457} pullback_tests[] = {9458 { "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",9459 "{ A[a,b] -> C[b + 2a] }" },9460 { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },9461 { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },9462 { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",9463 "{ A[a] -> C[(a)/6] }" },9464 { "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },9465 { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",9466 "{ A[a] -> C[(2a)/3] }" },9467 { "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},9468 { "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",9469 "{ A[i,j] -> C[i + j, i + j] }"},9470 { "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },9471 { "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",9472 "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },9473 { "{ [i, j] -> [floor((i)/4) + floor((2*i+j)/5)] }",9474 "{ [i, j] -> [floor((i)/3), j] }",9475 "{ [i, j] -> [(floor((i)/12) + floor((j + 2*floor((i)/3))/5))] }" },9476};9477 9478static int test_pullback(isl_ctx *ctx)9479{9480 int i;9481 isl_multi_aff *ma1, *ma2;9482 isl_multi_aff *ma;9483 int equal;9484 9485 for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {9486 ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);9487 ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);9488 ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);9489 ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);9490 equal = isl_multi_aff_plain_is_equal(ma1, ma2);9491 isl_multi_aff_free(ma1);9492 isl_multi_aff_free(ma2);9493 if (equal < 0)9494 return -1;9495 if (!equal)9496 isl_die(ctx, isl_error_unknown, "bad pullback",9497 return -1);9498 }9499 9500 return 0;9501}9502 9503/* Check that negation is printed correctly and that equal expressions9504 * are correctly identified.9505 */9506static int test_ast(isl_ctx *ctx)9507{9508 isl_ast_expr *expr, *expr1, *expr2, *expr3;9509 char *str;9510 int ok, equal;9511 9512 expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));9513 expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));9514 expr = isl_ast_expr_add(expr1, expr2);9515 expr2 = isl_ast_expr_copy(expr);9516 expr = isl_ast_expr_neg(expr);9517 expr2 = isl_ast_expr_neg(expr2);9518 equal = isl_ast_expr_is_equal(expr, expr2);9519 str = isl_ast_expr_to_C_str(expr);9520 ok = str ? !strcmp(str, "-(A + B)") : -1;9521 free(str);9522 isl_ast_expr_free(expr);9523 isl_ast_expr_free(expr2);9524 9525 if (ok < 0 || equal < 0)9526 return -1;9527 if (!equal)9528 isl_die(ctx, isl_error_unknown,9529 "equal expressions not considered equal", return -1);9530 if (!ok)9531 isl_die(ctx, isl_error_unknown,9532 "isl_ast_expr printed incorrectly", return -1);9533 9534 expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));9535 expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));9536 expr = isl_ast_expr_add(expr1, expr2);9537 expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));9538 expr = isl_ast_expr_sub(expr3, expr);9539 str = isl_ast_expr_to_C_str(expr);9540 ok = str ? !strcmp(str, "C - (A + B)") : -1;9541 free(str);9542 isl_ast_expr_free(expr);9543 9544 if (ok < 0)9545 return -1;9546 if (!ok)9547 isl_die(ctx, isl_error_unknown,9548 "isl_ast_expr printed incorrectly", return -1);9549 9550 return 0;9551}9552 9553/* Check that isl_ast_build_expr_from_set returns a valid expression9554 * for an empty set. Note that isl_ast_build_expr_from_set getting9555 * called on an empty set probably indicates a bug in the caller.9556 */9557static int test_ast_build(isl_ctx *ctx)9558{9559 isl_set *set;9560 isl_ast_build *build;9561 isl_ast_expr *expr;9562 9563 set = isl_set_universe(isl_space_params_alloc(ctx, 0));9564 build = isl_ast_build_from_context(set);9565 9566 set = isl_set_empty(isl_space_params_alloc(ctx, 0));9567 expr = isl_ast_build_expr_from_set(build, set);9568 9569 isl_ast_expr_free(expr);9570 isl_ast_build_free(build);9571 9572 if (!expr)9573 return -1;9574 9575 return 0;9576}9577 9578/* Internal data structure for before_for and after_for callbacks.9579 *9580 * depth is the current depth9581 * before is the number of times before_for has been called9582 * after is the number of times after_for has been called9583 */9584struct isl_test_codegen_data {9585 int depth;9586 int before;9587 int after;9588};9589 9590/* This function is called before each for loop in the AST generated9591 * from test_ast_gen1.9592 *9593 * Increment the number of calls and the depth.9594 * Check that the space returned by isl_ast_build_get_schedule_space9595 * matches the target space of the schedule returned by9596 * isl_ast_build_get_schedule.9597 * Return an isl_id that is checked by the corresponding call9598 * to after_for.9599 */9600static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,9601 void *user)9602{9603 struct isl_test_codegen_data *data = user;9604 isl_ctx *ctx;9605 isl_space *space;9606 isl_union_map *schedule;9607 isl_union_set *uset;9608 isl_set *set;9609 isl_bool empty;9610 isl_size n;9611 char name[] = "d0";9612 9613 ctx = isl_ast_build_get_ctx(build);9614 9615 if (data->before >= 3)9616 isl_die(ctx, isl_error_unknown,9617 "unexpected number of for nodes", return NULL);9618 if (data->depth < 0 || data->depth >= 2)9619 isl_die(ctx, isl_error_unknown,9620 "unexpected depth", return NULL);9621 9622 snprintf(name, sizeof(name), "d%d", data->depth);9623 data->before++;9624 data->depth++;9625 9626 schedule = isl_ast_build_get_schedule(build);9627 uset = isl_union_map_range(schedule);9628 n = isl_union_set_n_set(uset);9629 if (n != 1) {9630 isl_union_set_free(uset);9631 if (n < 0)9632 return NULL;9633 isl_die(ctx, isl_error_unknown,9634 "expecting single range space", return NULL);9635 }9636 9637 space = isl_ast_build_get_schedule_space(build);9638 set = isl_union_set_extract_set(uset, space);9639 isl_union_set_free(uset);9640 empty = isl_set_is_empty(set);9641 isl_set_free(set);9642 9643 if (empty < 0)9644 return NULL;9645 if (empty)9646 isl_die(ctx, isl_error_unknown,9647 "spaces don't match", return NULL);9648 9649 return isl_id_alloc(ctx, name, NULL);9650}9651 9652/* This function is called after each for loop in the AST generated9653 * from test_ast_gen1.9654 *9655 * Increment the number of calls and decrement the depth.9656 * Check that the annotation attached to the node matches9657 * the isl_id returned by the corresponding call to before_for.9658 */9659static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,9660 __isl_keep isl_ast_build *build, void *user)9661{9662 struct isl_test_codegen_data *data = user;9663 isl_id *id;9664 const char *name;9665 int valid;9666 9667 data->after++;9668 data->depth--;9669 9670 if (data->after > data->before)9671 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,9672 "mismatch in number of for nodes",9673 return isl_ast_node_free(node));9674 9675 id = isl_ast_node_get_annotation(node);9676 if (!id)9677 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,9678 "missing annotation", return isl_ast_node_free(node));9679 9680 name = isl_id_get_name(id);9681 valid = name && atoi(name + 1) == data->depth;9682 isl_id_free(id);9683 9684 if (!valid)9685 isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,9686 "wrong annotation", return isl_ast_node_free(node));9687 9688 return node;9689}9690 9691/* This function is called after node in the AST generated9692 * from test_ast_gen1.9693 *9694 * Increment the count in "user" if this is a for node and9695 * return true to indicate that descendant should also be visited.9696 */9697static isl_bool count_for(__isl_keep isl_ast_node *node, void *user)9698{9699 int *count = user;9700 9701 if (isl_ast_node_get_type(node) == isl_ast_node_for)9702 ++*count;9703 9704 return isl_bool_true;9705}9706 9707/* If "node" is a block node, then replace it by its first child.9708 */9709static __isl_give isl_ast_node *select_first(__isl_take isl_ast_node *node,9710 void *user)9711{9712 isl_ast_node_list *children;9713 isl_ast_node *child;9714 9715 if (isl_ast_node_get_type(node) != isl_ast_node_block)9716 return node;9717 9718 children = isl_ast_node_block_get_children(node);9719 child = isl_ast_node_list_get_at(children, 0);9720 isl_ast_node_list_free(children);9721 isl_ast_node_free(node);9722 9723 return child;9724}9725 9726/* Check that the before_each_for and after_each_for callbacks9727 * are called for each for loop in the generated code,9728 * that they are called in the right order and that the isl_id9729 * returned from the before_each_for callback is attached to9730 * the isl_ast_node passed to the corresponding after_each_for call.9731 *9732 * Additionally, check the basic functionality of9733 * isl_ast_node_foreach_descendant_top_down by counting the number9734 * of for loops in the resulting AST,9735 * as well as that of isl_ast_node_map_descendant_bottom_up9736 * by replacing the block node by its first child and9737 * counting the number of for loops again.9738 */9739static isl_stat test_ast_gen1(isl_ctx *ctx)9740{9741 int count = 0;9742 int modified_count = 0;9743 const char *str;9744 isl_set *set;9745 isl_union_map *schedule;9746 isl_ast_build *build;9747 isl_ast_node *tree;9748 struct isl_test_codegen_data data;9749 9750 str = "[N] -> { : N >= 10 }";9751 set = isl_set_read_from_str(ctx, str);9752 str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "9753 "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";9754 schedule = isl_union_map_read_from_str(ctx, str);9755 9756 data.before = 0;9757 data.after = 0;9758 data.depth = 0;9759 build = isl_ast_build_from_context(set);9760 build = isl_ast_build_set_before_each_for(build,9761 &before_for, &data);9762 build = isl_ast_build_set_after_each_for(build,9763 &after_for, &data);9764 tree = isl_ast_build_node_from_schedule_map(build, schedule);9765 isl_ast_build_free(build);9766 9767 if (isl_ast_node_foreach_descendant_top_down(tree,9768 &count_for, &count) < 0)9769 tree = isl_ast_node_free(tree);9770 9771 tree = isl_ast_node_map_descendant_bottom_up(tree, &select_first, NULL);9772 9773 if (isl_ast_node_foreach_descendant_top_down(tree, &count_for,9774 &modified_count) < 0)9775 tree = isl_ast_node_free(tree);9776 9777 if (!tree)9778 return isl_stat_error;9779 9780 isl_ast_node_free(tree);9781 9782 if (data.before != 3 || data.after != 3 || count != 3)9783 isl_die(ctx, isl_error_unknown,9784 "unexpected number of for nodes",9785 return isl_stat_error);9786 9787 if (modified_count != 2)9788 isl_die(ctx, isl_error_unknown,9789 "unexpected number of for nodes after changes",9790 return isl_stat_error);9791 9792 return isl_stat_ok;9793}9794 9795/* Check that the AST generator handles domains that are integrally disjoint9796 * but not rationally disjoint.9797 */9798static int test_ast_gen2(isl_ctx *ctx)9799{9800 const char *str;9801 isl_set *set;9802 isl_union_map *schedule;9803 isl_union_map *options;9804 isl_ast_build *build;9805 isl_ast_node *tree;9806 9807 str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";9808 schedule = isl_union_map_read_from_str(ctx, str);9809 set = isl_set_universe(isl_space_params_alloc(ctx, 0));9810 build = isl_ast_build_from_context(set);9811 9812 str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";9813 options = isl_union_map_read_from_str(ctx, str);9814 build = isl_ast_build_set_options(build, options);9815 tree = isl_ast_build_node_from_schedule_map(build, schedule);9816 isl_ast_build_free(build);9817 if (!tree)9818 return -1;9819 isl_ast_node_free(tree);9820 9821 return 0;9822}9823 9824/* Increment *user on each call.9825 */9826static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,9827 __isl_keep isl_ast_build *build, void *user)9828{9829 int *n = user;9830 9831 (*n)++;9832 9833 return node;9834}9835 9836/* Test that unrolling tries to minimize the number of instances.9837 * In particular, for the schedule given below, make sure it generates9838 * 3 nodes (rather than 101).9839 */9840static int test_ast_gen3(isl_ctx *ctx)9841{9842 const char *str;9843 isl_set *set;9844 isl_union_map *schedule;9845 isl_union_map *options;9846 isl_ast_build *build;9847 isl_ast_node *tree;9848 int n_domain = 0;9849 9850 str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";9851 schedule = isl_union_map_read_from_str(ctx, str);9852 set = isl_set_universe(isl_space_params_alloc(ctx, 0));9853 9854 str = "{ [i] -> unroll[0] }";9855 options = isl_union_map_read_from_str(ctx, str);9856 9857 build = isl_ast_build_from_context(set);9858 build = isl_ast_build_set_options(build, options);9859 build = isl_ast_build_set_at_each_domain(build,9860 &count_domains, &n_domain);9861 tree = isl_ast_build_node_from_schedule_map(build, schedule);9862 isl_ast_build_free(build);9863 if (!tree)9864 return -1;9865 9866 isl_ast_node_free(tree);9867 9868 if (n_domain != 3)9869 isl_die(ctx, isl_error_unknown,9870 "unexpected number of for nodes", return -1);9871 9872 return 0;9873}9874 9875/* Check that if the ast_build_exploit_nested_bounds options is set,9876 * we do not get an outer if node in the generated AST,9877 * while we do get such an outer if node if the options is not set.9878 */9879static int test_ast_gen4(isl_ctx *ctx)9880{9881 const char *str;9882 isl_set *set;9883 isl_union_map *schedule;9884 isl_ast_build *build;9885 isl_ast_node *tree;9886 enum isl_ast_node_type type;9887 int enb;9888 9889 enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);9890 str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";9891 9892 isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);9893 9894 schedule = isl_union_map_read_from_str(ctx, str);9895 set = isl_set_universe(isl_space_params_alloc(ctx, 0));9896 build = isl_ast_build_from_context(set);9897 tree = isl_ast_build_node_from_schedule_map(build, schedule);9898 isl_ast_build_free(build);9899 if (!tree)9900 return -1;9901 9902 type = isl_ast_node_get_type(tree);9903 isl_ast_node_free(tree);9904 9905 if (type == isl_ast_node_if)9906 isl_die(ctx, isl_error_unknown,9907 "not expecting if node", return -1);9908 9909 isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);9910 9911 schedule = isl_union_map_read_from_str(ctx, str);9912 set = isl_set_universe(isl_space_params_alloc(ctx, 0));9913 build = isl_ast_build_from_context(set);9914 tree = isl_ast_build_node_from_schedule_map(build, schedule);9915 isl_ast_build_free(build);9916 if (!tree)9917 return -1;9918 9919 type = isl_ast_node_get_type(tree);9920 isl_ast_node_free(tree);9921 9922 if (type != isl_ast_node_if)9923 isl_die(ctx, isl_error_unknown,9924 "expecting if node", return -1);9925 9926 isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);9927 9928 return 0;9929}9930 9931/* This function is called for each leaf in the AST generated9932 * from test_ast_gen5.9933 *9934 * We finalize the AST generation by extending the outer schedule9935 * with a zero-dimensional schedule. If this results in any for loops,9936 * then this means that we did not pass along enough information9937 * about the outer schedule to the inner AST generation.9938 */9939static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,9940 void *user)9941{9942 isl_union_map *schedule, *extra;9943 isl_ast_node *tree;9944 9945 schedule = isl_ast_build_get_schedule(build);9946 extra = isl_union_map_copy(schedule);9947 extra = isl_union_map_from_domain(isl_union_map_domain(extra));9948 schedule = isl_union_map_range_product(schedule, extra);9949 tree = isl_ast_build_node_from_schedule_map(build, schedule);9950 isl_ast_build_free(build);9951 9952 if (!tree)9953 return NULL;9954 9955 if (isl_ast_node_get_type(tree) == isl_ast_node_for)9956 isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,9957 "code should not contain any for loop",9958 return isl_ast_node_free(tree));9959 9960 return tree;9961}9962 9963/* Check that we do not lose any information when going back and9964 * forth between internal and external schedule.9965 *9966 * In particular, we create an AST where we unroll the only9967 * non-constant dimension in the schedule. We therefore do9968 * not expect any for loops in the AST. However, older versions9969 * of isl would not pass along enough information about the outer9970 * schedule when performing an inner code generation from a create_leaf9971 * callback, resulting in the inner code generation producing a for loop.9972 */9973static int test_ast_gen5(isl_ctx *ctx)9974{9975 const char *str;9976 isl_set *set;9977 isl_union_map *schedule, *options;9978 isl_ast_build *build;9979 isl_ast_node *tree;9980 9981 str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";9982 schedule = isl_union_map_read_from_str(ctx, str);9983 9984 str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "9985 "4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";9986 options = isl_union_map_read_from_str(ctx, str);9987 9988 set = isl_set_universe(isl_space_params_alloc(ctx, 0));9989 build = isl_ast_build_from_context(set);9990 build = isl_ast_build_set_options(build, options);9991 build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);9992 tree = isl_ast_build_node_from_schedule_map(build, schedule);9993 isl_ast_build_free(build);9994 isl_ast_node_free(tree);9995 if (!tree)9996 return -1;9997 9998 return 0;9999}10000 10001/* Check that the expression10002 *10003 * [n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }10004 *10005 * is not combined into10006 *10007 * min(n/2, 0)10008 *10009 * as this would result in n/2 being evaluated in parts of10010 * the definition domain where n is not a multiple of 2.10011 */10012static int test_ast_expr(isl_ctx *ctx)10013{10014 const char *str;10015 isl_pw_aff *pa;10016 isl_ast_build *build;10017 isl_ast_expr *expr;10018 int min_max;10019 int is_min;10020 10021 min_max = isl_options_get_ast_build_detect_min_max(ctx);10022 isl_options_set_ast_build_detect_min_max(ctx, 1);10023 10024 str = "[n] -> { [n/2] : n <= 0 and n % 2 = 0; [0] : n > 0 }";10025 pa = isl_pw_aff_read_from_str(ctx, str);10026 build = isl_ast_build_alloc(ctx);10027 expr = isl_ast_build_expr_from_pw_aff(build, pa);10028 is_min = isl_ast_expr_get_type(expr) == isl_ast_expr_op &&10029 isl_ast_expr_get_op_type(expr) == isl_ast_expr_op_min;10030 isl_ast_build_free(build);10031 isl_ast_expr_free(expr);10032 10033 isl_options_set_ast_build_detect_min_max(ctx, min_max);10034 10035 if (!expr)10036 return -1;10037 if (is_min)10038 isl_die(ctx, isl_error_unknown,10039 "expressions should not be combined", return -1);10040 10041 return 0;10042}10043 10044static int test_ast_gen(isl_ctx *ctx)10045{10046 if (test_ast_gen1(ctx) < 0)10047 return -1;10048 if (test_ast_gen2(ctx) < 0)10049 return -1;10050 if (test_ast_gen3(ctx) < 0)10051 return -1;10052 if (test_ast_gen4(ctx) < 0)10053 return -1;10054 if (test_ast_gen5(ctx) < 0)10055 return -1;10056 if (test_ast_expr(ctx) < 0)10057 return -1;10058 return 0;10059}10060 10061/* Check if dropping output dimensions from an isl_pw_multi_aff10062 * works properly.10063 */10064static int test_pw_multi_aff(isl_ctx *ctx)10065{10066 const char *str;10067 isl_pw_multi_aff *pma1, *pma2;10068 int equal;10069 10070 str = "{ [i,j] -> [i+j, 4i-j] }";10071 pma1 = isl_pw_multi_aff_read_from_str(ctx, str);10072 str = "{ [i,j] -> [4i-j] }";10073 pma2 = isl_pw_multi_aff_read_from_str(ctx, str);10074 10075 pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);10076 10077 equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);10078 10079 isl_pw_multi_aff_free(pma1);10080 isl_pw_multi_aff_free(pma2);10081 if (equal < 0)10082 return -1;10083 if (!equal)10084 isl_die(ctx, isl_error_unknown,10085 "expressions not equal", return -1);10086 10087 return 0;10088}10089 10090/* Check that we can properly parse multi piecewise affine expressions10091 * where the piecewise affine expressions have different domains.10092 */10093static int test_multi_pw_aff_1(isl_ctx *ctx)10094{10095 const char *str;10096 isl_set *dom, *dom2;10097 isl_multi_pw_aff *mpa1, *mpa2;10098 isl_pw_aff *pa;10099 int equal;10100 int equal_domain;10101 10102 mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }");10103 dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }");10104 mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom);10105 mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }");10106 mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2);10107 str = "{ [i] -> [(i : i > 0), 2i] }";10108 mpa1 = isl_multi_pw_aff_read_from_str(ctx, str);10109 10110 equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2);10111 10112 pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0);10113 dom = isl_pw_aff_domain(pa);10114 pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1);10115 dom2 = isl_pw_aff_domain(pa);10116 equal_domain = isl_set_is_equal(dom, dom2);10117 10118 isl_set_free(dom);10119 isl_set_free(dom2);10120 isl_multi_pw_aff_free(mpa1);10121 isl_multi_pw_aff_free(mpa2);10122 10123 if (equal < 0)10124 return -1;10125 if (!equal)10126 isl_die(ctx, isl_error_unknown,10127 "expressions not equal", return -1);10128 10129 if (equal_domain < 0)10130 return -1;10131 if (equal_domain)10132 isl_die(ctx, isl_error_unknown,10133 "domains unexpectedly equal", return -1);10134 10135 return 0;10136}10137 10138/* Check that the dimensions in the explicit domain10139 * of a multi piecewise affine expression are properly10140 * taken into account.10141 */10142static int test_multi_pw_aff_2(isl_ctx *ctx)10143{10144 const char *str;10145 isl_bool involves1, involves2, involves3, equal;10146 isl_multi_pw_aff *mpa, *mpa1, *mpa2;10147 10148 str = "{ A[x,y] -> B[] : x >= y }";10149 mpa = isl_multi_pw_aff_read_from_str(ctx, str);10150 involves1 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 2);10151 mpa1 = isl_multi_pw_aff_copy(mpa);10152 10153 mpa = isl_multi_pw_aff_insert_dims(mpa, isl_dim_in, 0, 1);10154 involves2 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 1);10155 involves3 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 1, 2);10156 str = "{ [a,x,y] -> B[] : x >= y }";10157 mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);10158 equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);10159 isl_multi_pw_aff_free(mpa2);10160 10161 mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_in, 0, 1);10162 mpa = isl_multi_pw_aff_set_tuple_name(mpa, isl_dim_in, "A");10163 if (equal >= 0 && equal)10164 equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa1);10165 isl_multi_pw_aff_free(mpa1);10166 isl_multi_pw_aff_free(mpa);10167 10168 if (involves1 < 0 || involves2 < 0 || involves3 < 0 || equal < 0)10169 return -1;10170 if (!equal)10171 isl_die(ctx, isl_error_unknown,10172 "incorrect result of dimension insertion/removal",10173 return isl_stat_error);10174 if (!involves1 || involves2 || !involves3)10175 isl_die(ctx, isl_error_unknown,10176 "incorrect characterization of involved dimensions",10177 return isl_stat_error);10178 10179 return 0;10180}10181 10182/* Check that isl_multi_union_pw_aff_multi_val_on_domain10183 * sets the explicit domain of a zero-dimensional result,10184 * such that it can be converted to an isl_union_map.10185 */10186static isl_stat test_multi_pw_aff_3(isl_ctx *ctx)10187{10188 isl_space *space;10189 isl_union_set *dom;10190 isl_multi_val *mv;10191 isl_multi_union_pw_aff *mupa;10192 isl_union_map *umap;10193 10194 dom = isl_union_set_read_from_str(ctx, "{ A[]; B[] }");10195 space = isl_union_set_get_space(dom);10196 mv = isl_multi_val_zero(isl_space_set_from_params(space));10197 mupa = isl_multi_union_pw_aff_multi_val_on_domain(dom, mv);10198 umap = isl_union_map_from_multi_union_pw_aff(mupa);10199 isl_union_map_free(umap);10200 if (!umap)10201 return isl_stat_error;10202 10203 return isl_stat_ok;10204}10205 10206/* String descriptions of boxes that10207 * are used for reconstructing box maps from their lower and upper bounds.10208 */10209static const char *multi_pw_aff_box_tests[] = {10210 "{ A[x, y] -> [] : x + y >= 0 }",10211 "[N] -> { A[x, y] -> [x] : x + y <= N }",10212 "[N] -> { A[x, y] -> [x : y] : x + y <= N }",10213};10214 10215/* Check that map representations of boxes can be reconstructed10216 * from their lower and upper bounds.10217 */10218static isl_stat test_multi_pw_aff_box(isl_ctx *ctx)10219{10220 int i;10221 10222 for (i = 0; i < ARRAY_SIZE(multi_pw_aff_box_tests); ++i) {10223 const char *str;10224 isl_bool equal;10225 isl_map *map, *box;10226 isl_multi_pw_aff *min, *max;10227 10228 str = multi_pw_aff_box_tests[i];10229 map = isl_map_read_from_str(ctx, str);10230 min = isl_map_min_multi_pw_aff(isl_map_copy(map));10231 max = isl_map_max_multi_pw_aff(isl_map_copy(map));10232 box = isl_map_universe(isl_map_get_space(map));10233 box = isl_map_lower_bound_multi_pw_aff(box, min);10234 box = isl_map_upper_bound_multi_pw_aff(box, max);10235 equal = isl_map_is_equal(map, box);10236 isl_map_free(map);10237 isl_map_free(box);10238 if (equal < 0)10239 return isl_stat_error;10240 if (!equal)10241 isl_die(ctx, isl_error_unknown,10242 "unexpected result", return isl_stat_error);10243 }10244 10245 return isl_stat_ok;10246}10247 10248/* Perform some tests on multi piecewise affine expressions.10249 */10250static int test_multi_pw_aff(isl_ctx *ctx)10251{10252 if (test_multi_pw_aff_1(ctx) < 0)10253 return -1;10254 if (test_multi_pw_aff_2(ctx) < 0)10255 return -1;10256 if (test_multi_pw_aff_3(ctx) < 0)10257 return -1;10258 if (test_multi_pw_aff_box(ctx) < 0)10259 return -1;10260 return 0;10261}10262 10263/* This is a regression test for a bug where isl_basic_map_simplify10264 * would end up in an infinite loop. In particular, we construct10265 * an empty basic set that is not obviously empty.10266 * isl_basic_set_is_empty marks the basic set as empty.10267 * After projecting out i3, the variable can be dropped completely,10268 * but isl_basic_map_simplify refrains from doing so if the basic set10269 * is empty and would end up in an infinite loop if it didn't test10270 * explicitly for empty basic maps in the outer loop.10271 */10272static int test_simplify_1(isl_ctx *ctx)10273{10274 const char *str;10275 isl_basic_set *bset;10276 int empty;10277 10278 str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "10279 "i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "10280 "25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "10281 "i3 >= i2 }";10282 bset = isl_basic_set_read_from_str(ctx, str);10283 empty = isl_basic_set_is_empty(bset);10284 bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);10285 isl_basic_set_free(bset);10286 if (!bset)10287 return -1;10288 if (!empty)10289 isl_die(ctx, isl_error_unknown,10290 "basic set should be empty", return -1);10291 10292 return 0;10293}10294 10295/* Check that the equality in the set description below10296 * is simplified away.10297 */10298static int test_simplify_2(isl_ctx *ctx)10299{10300 const char *str;10301 isl_basic_set *bset;10302 isl_bool universe;10303 10304 str = "{ [a] : exists e0, e1: 32e1 = 31 + 31a + 31e0 }";10305 bset = isl_basic_set_read_from_str(ctx, str);10306 universe = isl_basic_set_plain_is_universe(bset);10307 isl_basic_set_free(bset);10308 10309 if (universe < 0)10310 return -1;10311 if (!universe)10312 isl_die(ctx, isl_error_unknown,10313 "equality not simplified away", return -1);10314 return 0;10315}10316 10317/* Some simplification tests.10318 */10319static int test_simplify(isl_ctx *ctx)10320{10321 if (test_simplify_1(ctx) < 0)10322 return -1;10323 if (test_simplify_2(ctx) < 0)10324 return -1;10325 return 0;10326}10327 10328/* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt10329 * with gbr context would fail to disable the use of the shifted tableau10330 * when transferring equalities for the input to the context, resulting10331 * in invalid sample values.10332 */10333static int test_partial_lexmin(isl_ctx *ctx)10334{10335 const char *str;10336 isl_basic_set *bset;10337 isl_basic_map *bmap;10338 isl_map *map;10339 10340 str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";10341 bmap = isl_basic_map_read_from_str(ctx, str);10342 str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";10343 bset = isl_basic_set_read_from_str(ctx, str);10344 map = isl_basic_map_partial_lexmin(bmap, bset, NULL);10345 isl_map_free(map);10346 10347 if (!map)10348 return -1;10349 10350 return 0;10351}10352 10353/* Check that the variable compression performed on the existentially10354 * quantified variables inside isl_basic_set_compute_divs is not confused10355 * by the implicit equalities among the parameters.10356 */10357static int test_compute_divs(isl_ctx *ctx)10358{10359 const char *str;10360 isl_basic_set *bset;10361 isl_set *set;10362 10363 str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "10364 "b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "10365 "2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "10366 "32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";10367 bset = isl_basic_set_read_from_str(ctx, str);10368 set = isl_basic_set_compute_divs(bset);10369 isl_set_free(set);10370 if (!set)10371 return -1;10372 10373 return 0;10374}10375 10376/* Check that isl_schedule_get_map is not confused by a schedule tree10377 * with divergent filter node parameters, as can result from a call10378 * to isl_schedule_intersect_domain.10379 */10380static int test_schedule_tree(isl_ctx *ctx)10381{10382 const char *str;10383 isl_union_set *uset;10384 isl_schedule *sched1, *sched2;10385 isl_union_map *umap;10386 10387 uset = isl_union_set_read_from_str(ctx, "{ A[i] }");10388 sched1 = isl_schedule_from_domain(uset);10389 uset = isl_union_set_read_from_str(ctx, "{ B[] }");10390 sched2 = isl_schedule_from_domain(uset);10391 10392 sched1 = isl_schedule_sequence(sched1, sched2);10393 str = "[n] -> { A[i] : 0 <= i < n; B[] }";10394 uset = isl_union_set_read_from_str(ctx, str);10395 sched1 = isl_schedule_intersect_domain(sched1, uset);10396 umap = isl_schedule_get_map(sched1);10397 isl_schedule_free(sched1);10398 isl_union_map_free(umap);10399 if (!umap)10400 return -1;10401 10402 return 0;10403}10404 10405/* Check that a zero-dimensional prefix schedule keeps track10406 * of the domain and outer filters.10407 */10408static int test_schedule_tree_prefix(isl_ctx *ctx)10409{10410 const char *str;10411 isl_bool equal;10412 isl_union_set *uset;10413 isl_union_set_list *filters;10414 isl_multi_union_pw_aff *mupa, *mupa2;10415 isl_schedule_node *node;10416 10417 str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";10418 uset = isl_union_set_read_from_str(ctx, str);10419 node = isl_schedule_node_from_domain(uset);10420 node = isl_schedule_node_child(node, 0);10421 10422 str = "{ S1[i,j] : i > j }";10423 uset = isl_union_set_read_from_str(ctx, str);10424 filters = isl_union_set_list_from_union_set(uset);10425 str = "{ S1[i,j] : i <= j; S2[i,j] }";10426 uset = isl_union_set_read_from_str(ctx, str);10427 filters = isl_union_set_list_add(filters, uset);10428 node = isl_schedule_node_insert_sequence(node, filters);10429 10430 node = isl_schedule_node_grandchild(node, 0, 0);10431 mupa = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(node);10432 str = "([] : { S1[i,j] : i > j })";10433 mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);10434 equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);10435 isl_multi_union_pw_aff_free(mupa2);10436 isl_multi_union_pw_aff_free(mupa);10437 isl_schedule_node_free(node);10438 10439 if (equal < 0)10440 return -1;10441 if (!equal)10442 isl_die(ctx, isl_error_unknown, "unexpected prefix schedule",10443 return -1);10444 10445 return 0;10446}10447 10448/* Check that the reaching domain elements and the prefix schedule10449 * at a leaf node are the same before and after grouping.10450 */10451static int test_schedule_tree_group_1(isl_ctx *ctx)10452{10453 int equal;10454 const char *str;10455 isl_id *id;10456 isl_union_set *uset;10457 isl_multi_union_pw_aff *mupa;10458 isl_union_pw_multi_aff *upma1, *upma2;10459 isl_union_set *domain1, *domain2;10460 isl_union_map *umap1, *umap2;10461 isl_schedule_node *node;10462 10463 str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";10464 uset = isl_union_set_read_from_str(ctx, str);10465 node = isl_schedule_node_from_domain(uset);10466 node = isl_schedule_node_child(node, 0);10467 str = "[{ S1[i,j] -> [i]; S2[i,j] -> [9 - i] }]";10468 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10469 node = isl_schedule_node_insert_partial_schedule(node, mupa);10470 node = isl_schedule_node_child(node, 0);10471 str = "[{ S1[i,j] -> [j]; S2[i,j] -> [j] }]";10472 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10473 node = isl_schedule_node_insert_partial_schedule(node, mupa);10474 node = isl_schedule_node_child(node, 0);10475 umap1 = isl_schedule_node_get_prefix_schedule_union_map(node);10476 upma1 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);10477 domain1 = isl_schedule_node_get_domain(node);10478 id = isl_id_alloc(ctx, "group", NULL);10479 node = isl_schedule_node_parent(node);10480 node = isl_schedule_node_group(node, id);10481 node = isl_schedule_node_child(node, 0);10482 umap2 = isl_schedule_node_get_prefix_schedule_union_map(node);10483 upma2 = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);10484 domain2 = isl_schedule_node_get_domain(node);10485 equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);10486 if (equal >= 0 && equal)10487 equal = isl_union_set_is_equal(domain1, domain2);10488 if (equal >= 0 && equal)10489 equal = isl_union_map_is_equal(umap1, umap2);10490 isl_union_map_free(umap1);10491 isl_union_map_free(umap2);10492 isl_union_set_free(domain1);10493 isl_union_set_free(domain2);10494 isl_union_pw_multi_aff_free(upma1);10495 isl_union_pw_multi_aff_free(upma2);10496 isl_schedule_node_free(node);10497 10498 if (equal < 0)10499 return -1;10500 if (!equal)10501 isl_die(ctx, isl_error_unknown,10502 "expressions not equal", return -1);10503 10504 return 0;10505}10506 10507/* Check that we can have nested groupings and that the union map10508 * schedule representation is the same before and after the grouping.10509 * Note that after the grouping, the union map representation contains10510 * the domain constraints from the ranges of the expansion nodes,10511 * while they are missing from the union map representation of10512 * the tree without expansion nodes.10513 *10514 * Also check that the global expansion is as expected.10515 */10516static int test_schedule_tree_group_2(isl_ctx *ctx)10517{10518 int equal, equal_expansion;10519 const char *str;10520 isl_id *id;10521 isl_union_set *uset;10522 isl_union_map *umap1, *umap2;10523 isl_union_map *expansion1, *expansion2;10524 isl_union_set_list *filters;10525 isl_multi_union_pw_aff *mupa;10526 isl_schedule *schedule;10527 isl_schedule_node *node;10528 10529 str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10; "10530 "S3[i,j] : 0 <= i,j < 10 }";10531 uset = isl_union_set_read_from_str(ctx, str);10532 node = isl_schedule_node_from_domain(uset);10533 node = isl_schedule_node_child(node, 0);10534 str = "[{ S1[i,j] -> [i]; S2[i,j] -> [i]; S3[i,j] -> [i] }]";10535 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10536 node = isl_schedule_node_insert_partial_schedule(node, mupa);10537 node = isl_schedule_node_child(node, 0);10538 str = "{ S1[i,j] }";10539 uset = isl_union_set_read_from_str(ctx, str);10540 filters = isl_union_set_list_from_union_set(uset);10541 str = "{ S2[i,j]; S3[i,j] }";10542 uset = isl_union_set_read_from_str(ctx, str);10543 filters = isl_union_set_list_add(filters, uset);10544 node = isl_schedule_node_insert_sequence(node, filters);10545 node = isl_schedule_node_grandchild(node, 1, 0);10546 str = "{ S2[i,j] }";10547 uset = isl_union_set_read_from_str(ctx, str);10548 filters = isl_union_set_list_from_union_set(uset);10549 str = "{ S3[i,j] }";10550 uset = isl_union_set_read_from_str(ctx, str);10551 filters = isl_union_set_list_add(filters, uset);10552 node = isl_schedule_node_insert_sequence(node, filters);10553 10554 schedule = isl_schedule_node_get_schedule(node);10555 umap1 = isl_schedule_get_map(schedule);10556 uset = isl_schedule_get_domain(schedule);10557 umap1 = isl_union_map_intersect_domain(umap1, uset);10558 isl_schedule_free(schedule);10559 10560 node = isl_schedule_node_grandparent(node);10561 id = isl_id_alloc(ctx, "group1", NULL);10562 node = isl_schedule_node_group(node, id);10563 node = isl_schedule_node_grandchild(node, 1, 0);10564 id = isl_id_alloc(ctx, "group2", NULL);10565 node = isl_schedule_node_group(node, id);10566 10567 schedule = isl_schedule_node_get_schedule(node);10568 umap2 = isl_schedule_get_map(schedule);10569 isl_schedule_free(schedule);10570 10571 node = isl_schedule_node_root(node);10572 node = isl_schedule_node_child(node, 0);10573 expansion1 = isl_schedule_node_get_subtree_expansion(node);10574 isl_schedule_node_free(node);10575 10576 str = "{ group1[i] -> S1[i,j] : 0 <= i,j < 10; "10577 "group1[i] -> S2[i,j] : 0 <= i,j < 10; "10578 "group1[i] -> S3[i,j] : 0 <= i,j < 10 }";10579 10580 expansion2 = isl_union_map_read_from_str(ctx, str);10581 10582 equal = isl_union_map_is_equal(umap1, umap2);10583 equal_expansion = isl_union_map_is_equal(expansion1, expansion2);10584 10585 isl_union_map_free(umap1);10586 isl_union_map_free(umap2);10587 isl_union_map_free(expansion1);10588 isl_union_map_free(expansion2);10589 10590 if (equal < 0 || equal_expansion < 0)10591 return -1;10592 if (!equal)10593 isl_die(ctx, isl_error_unknown,10594 "expressions not equal", return -1);10595 if (!equal_expansion)10596 isl_die(ctx, isl_error_unknown,10597 "unexpected expansion", return -1);10598 10599 return 0;10600}10601 10602/* Some tests for the isl_schedule_node_group function.10603 */10604static int test_schedule_tree_group(isl_ctx *ctx)10605{10606 if (test_schedule_tree_group_1(ctx) < 0)10607 return -1;10608 if (test_schedule_tree_group_2(ctx) < 0)10609 return -1;10610 return 0;10611}10612 10613struct {10614 const char *set;10615 const char *dual;10616} coef_tests[] = {10617 { "{ rat: [i] : 0 <= i <= 10 }",10618 "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" },10619 { "{ rat: [i] : FALSE }",10620 "{ rat: coefficients[[cst] -> [a]] }" },10621 { "{ rat: [i] : }",10622 "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" },10623 { "{ [0:,1,2:3] }",10624 "{ rat: coefficients[[c_cst] -> [a, b, c]] : "10625 "a >= 0 and 2c >= -c_cst - b and 3c >= -c_cst - b }" },10626 { "[M, N] -> { [x = (1 - N):-1, -4x:(M - 4x)] }",10627 "{ rat: coefficients[[c_cst, c_M = 0:, c_N = 0:] -> [a, b = -c_M:]] :"10628 "4b >= -c_N + a and 4b >= -c_cst - 2c_N + a }" },10629 { "{ rat : [x, y] : 1 <= 2x <= 9 and 2 <= 3y <= 16 }",10630 "{ rat: coefficients[[c_cst] -> [c_x, c_y]] : "10631 "4c_y >= -6c_cst - 3c_x and 4c_y >= -6c_cst - 27c_x and "10632 "32c_y >= -6c_cst - 3c_x and 32c_y >= -6c_cst - 27c_x }" },10633 { "{ [x, y, z] : 3y <= 2x - 2 and y >= -2 + 2x and 2y >= 2 - x }",10634 "{ rat: coefficients[[cst] -> [a, b, c]] }" },10635};10636 10637struct {10638 const char *set;10639 const char *dual;10640} sol_tests[] = {10641 { "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }",10642 "{ rat: [i] : 0 <= i <= 10 }" },10643 { "{ rat: coefficients[[cst] -> [a]] : FALSE }",10644 "{ rat: [i] }" },10645 { "{ rat: coefficients[[cst] -> [a]] }",10646 "{ rat: [i] : FALSE }" },10647};10648 10649/* Test the basic functionality of isl_basic_set_coefficients and10650 * isl_basic_set_solutions.10651 */10652static int test_dual(isl_ctx *ctx)10653{10654 int i;10655 10656 for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) {10657 int equal;10658 isl_basic_set *bset1, *bset2;10659 10660 bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set);10661 bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual);10662 bset1 = isl_basic_set_coefficients(bset1);10663 equal = isl_basic_set_is_equal(bset1, bset2);10664 isl_basic_set_free(bset1);10665 isl_basic_set_free(bset2);10666 if (equal < 0)10667 return -1;10668 if (!equal)10669 isl_die(ctx, isl_error_unknown,10670 "incorrect dual", return -1);10671 }10672 10673 for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) {10674 int equal;10675 isl_basic_set *bset1, *bset2;10676 10677 bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set);10678 bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual);10679 bset1 = isl_basic_set_solutions(bset1);10680 equal = isl_basic_set_is_equal(bset1, bset2);10681 isl_basic_set_free(bset1);10682 isl_basic_set_free(bset2);10683 if (equal < 0)10684 return -1;10685 if (!equal)10686 isl_die(ctx, isl_error_unknown,10687 "incorrect dual", return -1);10688 }10689 10690 return 0;10691}10692 10693struct {10694 int scale_tile;10695 int shift_point;10696 const char *domain;10697 const char *schedule;10698 const char *sizes;10699 const char *tile;10700 const char *point;10701} tile_tests[] = {10702 { 0, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",10703 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10704 "{ [32,32] }",10705 "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",10706 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10707 },10708 { 1, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",10709 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10710 "{ [32,32] }",10711 "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",10712 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10713 },10714 { 0, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",10715 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10716 "{ [32,32] }",10717 "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",10718 "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",10719 },10720 { 1, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",10721 "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",10722 "{ [32,32] }",10723 "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",10724 "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",10725 },10726};10727 10728/* Basic tiling tests. Create a schedule tree with a domain and a band node,10729 * tile the band and then check if the tile and point bands have the10730 * expected partial schedule.10731 */10732static int test_tile(isl_ctx *ctx)10733{10734 int i;10735 int scale;10736 int shift;10737 10738 scale = isl_options_get_tile_scale_tile_loops(ctx);10739 shift = isl_options_get_tile_shift_point_loops(ctx);10740 10741 for (i = 0; i < ARRAY_SIZE(tile_tests); ++i) {10742 int opt;10743 int equal;10744 const char *str;10745 isl_union_set *domain;10746 isl_multi_union_pw_aff *mupa, *mupa2;10747 isl_schedule_node *node;10748 isl_multi_val *sizes;10749 10750 opt = tile_tests[i].scale_tile;10751 isl_options_set_tile_scale_tile_loops(ctx, opt);10752 opt = tile_tests[i].shift_point;10753 isl_options_set_tile_shift_point_loops(ctx, opt);10754 10755 str = tile_tests[i].domain;10756 domain = isl_union_set_read_from_str(ctx, str);10757 node = isl_schedule_node_from_domain(domain);10758 node = isl_schedule_node_child(node, 0);10759 str = tile_tests[i].schedule;10760 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10761 node = isl_schedule_node_insert_partial_schedule(node, mupa);10762 str = tile_tests[i].sizes;10763 sizes = isl_multi_val_read_from_str(ctx, str);10764 node = isl_schedule_node_band_tile(node, sizes);10765 10766 str = tile_tests[i].tile;10767 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10768 mupa2 = isl_schedule_node_band_get_partial_schedule(node);10769 equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);10770 isl_multi_union_pw_aff_free(mupa);10771 isl_multi_union_pw_aff_free(mupa2);10772 10773 node = isl_schedule_node_child(node, 0);10774 10775 str = tile_tests[i].point;10776 mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);10777 mupa2 = isl_schedule_node_band_get_partial_schedule(node);10778 if (equal >= 0 && equal)10779 equal = isl_multi_union_pw_aff_plain_is_equal(mupa,10780 mupa2);10781 isl_multi_union_pw_aff_free(mupa);10782 isl_multi_union_pw_aff_free(mupa2);10783 10784 isl_schedule_node_free(node);10785 10786 if (equal < 0)10787 return -1;10788 if (!equal)10789 isl_die(ctx, isl_error_unknown,10790 "unexpected result", return -1);10791 }10792 10793 isl_options_set_tile_scale_tile_loops(ctx, scale);10794 isl_options_set_tile_shift_point_loops(ctx, shift);10795 10796 return 0;10797}10798 10799/* Check that the domain hash of a space is equal to the hash10800 * of the domain of the space, both ignoring parameters.10801 */10802static int test_domain_hash(isl_ctx *ctx)10803{10804 isl_map *map;10805 isl_space *space;10806 uint32_t hash1, hash2;10807 10808 map = isl_map_read_from_str(ctx, "[n] -> { A[B[x] -> C[]] -> D[] }");10809 space = isl_map_get_space(map);10810 isl_map_free(map);10811 hash1 = isl_space_get_tuple_domain_hash(space);10812 space = isl_space_domain(space);10813 hash2 = isl_space_get_tuple_hash(space);10814 isl_space_free(space);10815 10816 if (!space)10817 return -1;10818 if (hash1 != hash2)10819 isl_die(ctx, isl_error_unknown,10820 "domain hash not equal to hash of domain", return -1);10821 10822 return 0;10823}10824 10825/* Check that a universe basic set that is not obviously equal to the universe10826 * is still recognized as being equal to the universe.10827 */10828static int test_universe(isl_ctx *ctx)10829{10830 const char *s;10831 isl_basic_set *bset;10832 isl_bool is_univ;10833 10834 s = "{ [] : exists x, y : 3y <= 2x and y >= -3 + 2x and 2y >= 2 - x }";10835 bset = isl_basic_set_read_from_str(ctx, s);10836 is_univ = isl_basic_set_is_universe(bset);10837 isl_basic_set_free(bset);10838 10839 if (is_univ < 0)10840 return -1;10841 if (!is_univ)10842 isl_die(ctx, isl_error_unknown,10843 "not recognized as universe set", return -1);10844 10845 return 0;10846}10847 10848/* Sets for which chambers are computed and checked.10849 */10850const char *chambers_tests[] = {10851 "[A, B, C] -> { [x, y, z] : x >= 0 and y >= 0 and y <= A - x and "10852 "z >= 0 and z <= C - y and z <= B - x - y }",10853};10854 10855/* Add the domain of "cell" to "cells".10856 */10857static isl_stat add_cell(__isl_take isl_cell *cell, void *user)10858{10859 isl_basic_set_list **cells = user;10860 isl_basic_set *dom;10861 10862 dom = isl_cell_get_domain(cell);10863 isl_cell_free(cell);10864 *cells = isl_basic_set_list_add(*cells, dom);10865 10866 return *cells ? isl_stat_ok : isl_stat_error;10867}10868 10869/* Check that the elements of "list" are pairwise disjoint.10870 */10871static isl_stat check_pairwise_disjoint(__isl_keep isl_basic_set_list *list)10872{10873 int i, j;10874 isl_size n;10875 10876 n = isl_basic_set_list_n_basic_set(list);10877 if (n < 0)10878 return isl_stat_error;10879 10880 for (i = 0; i < n; ++i) {10881 isl_basic_set *bset_i;10882 10883 bset_i = isl_basic_set_list_get_basic_set(list, i);10884 for (j = i + 1; j < n; ++j) {10885 isl_basic_set *bset_j;10886 isl_bool disjoint;10887 10888 bset_j = isl_basic_set_list_get_basic_set(list, j);10889 disjoint = isl_basic_set_is_disjoint(bset_i, bset_j);10890 isl_basic_set_free(bset_j);10891 if (!disjoint)10892 isl_die(isl_basic_set_list_get_ctx(list),10893 isl_error_unknown, "not disjoint",10894 break);10895 if (disjoint < 0 || !disjoint)10896 break;10897 }10898 isl_basic_set_free(bset_i);10899 if (j < n)10900 return isl_stat_error;10901 }10902 10903 return isl_stat_ok;10904}10905 10906/* Check that the chambers computed by isl_vertices_foreach_disjoint_cell10907 * are pairwise disjoint.10908 */10909static int test_chambers(isl_ctx *ctx)10910{10911 int i;10912 10913 for (i = 0; i < ARRAY_SIZE(chambers_tests); ++i) {10914 isl_basic_set *bset;10915 isl_vertices *vertices;10916 isl_basic_set_list *cells;10917 isl_stat ok;10918 10919 bset = isl_basic_set_read_from_str(ctx, chambers_tests[i]);10920 vertices = isl_basic_set_compute_vertices(bset);10921 cells = isl_basic_set_list_alloc(ctx, 0);10922 if (isl_vertices_foreach_disjoint_cell(vertices, &add_cell,10923 &cells) < 0)10924 cells = isl_basic_set_list_free(cells);10925 ok = check_pairwise_disjoint(cells);10926 isl_basic_set_list_free(cells);10927 isl_vertices_free(vertices);10928 isl_basic_set_free(bset);10929 10930 if (ok < 0)10931 return -1;10932 }10933 10934 return 0;10935}10936 10937struct {10938 const char *name;10939 int (*fn)(isl_ctx *ctx);10940} tests [] = {10941 { "universe", &test_universe },10942 { "domain hash", &test_domain_hash },10943 { "dual", &test_dual },10944 { "dependence analysis", &test_flow },10945 { "val", &test_val },10946 { "compute divs", &test_compute_divs },10947 { "partial lexmin", &test_partial_lexmin },10948 { "simplify", &test_simplify },10949 { "curry", &test_curry },10950 { "piecewise multi affine expressions", &test_pw_multi_aff },10951 { "multi piecewise affine expressions", &test_multi_pw_aff },10952 { "conversion", &test_conversion },10953 { "list", &test_list },10954 { "align parameters", &test_align_parameters },10955 { "drop unused parameters", &test_drop_unused_parameters },10956 { "pullback", &test_pullback },10957 { "AST", &test_ast },10958 { "AST build", &test_ast_build },10959 { "AST generation", &test_ast_gen },10960 { "eliminate", &test_eliminate },10961 { "deltas_map", &test_deltas_map },10962 { "residue class", &test_residue_class },10963 { "div", &test_div },10964 { "slice", &test_slice },10965 { "sample", &test_sample },10966 { "empty projection", &test_empty_projection },10967 { "output", &test_output },10968 { "vertices", &test_vertices },10969 { "chambers", &test_chambers },10970 { "fixed", &test_fixed },10971 { "equal", &test_equal },10972 { "disjoint", &test_disjoint },10973 { "product", &test_product },10974 { "dim_max", &test_dim_max },10975 { "affine", &test_aff },10976 { "injective", &test_injective },10977 { "schedule (whole component)", &test_schedule_whole },10978 { "schedule (incremental)", &test_schedule_incremental },10979 { "schedule tree", &test_schedule_tree },10980 { "schedule tree prefix", &test_schedule_tree_prefix },10981 { "schedule tree grouping", &test_schedule_tree_group },10982 { "tile", &test_tile },10983 { "union map", &test_union_map },10984 { "union_pw", &test_union_pw },10985 { "locus", &test_locus },10986 { "eval", &test_eval },10987 { "parse", &test_parse },10988 { "single-valued", &test_sv },10989 { "recession cone", &test_recession_cone },10990 { "affine hull", &test_affine_hull },10991 { "simple_hull", &test_simple_hull },10992 { "box hull", &test_box_hull },10993 { "coalesce", &test_coalesce },10994 { "factorize", &test_factorize },10995 { "subset", &test_subset },10996 { "subtract", &test_subtract },10997 { "intersect", &test_intersect },10998 { "lexmin", &test_lexmin },10999 { "min", &test_min },11000 { "set lower bounds", &test_min_mpa },11001 { "gist", &test_gist },11002 { "piecewise quasi-polynomials", &test_pwqp },11003 { "lift", &test_lift },11004 { "bind parameters", &test_bind },11005 { "unbind parameters", &test_unbind },11006 { "bound", &test_bound },11007 { "get lists", &test_get_list },11008 { "union", &test_union },11009 { "split periods", &test_split_periods },11010 { "lexicographic order", &test_lex },11011 { "bijectivity", &test_bijective },11012 { "dataflow analysis", &test_dep },11013 { "reading", &test_read },11014 { "bounded", &test_bounded },11015 { "construction", &test_construction },11016 { "dimension manipulation", &test_dim },11017 { "map application", &test_application },11018 { "convex hull", &test_convex_hull },11019 { "transitive closure", &test_closure },11020 { "isl_bool", &test_isl_bool},11021};11022 11023int main(int argc, char **argv)11024{11025 int i;11026 struct isl_ctx *ctx;11027 struct isl_options *options;11028 11029 options = isl_options_new_with_defaults();11030 assert(options);11031 argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);11032 11033 ctx = isl_ctx_alloc_with_options(&isl_options_args, options);11034 for (i = 0; i < ARRAY_SIZE(tests); ++i) {11035 printf("%s\n", tests[i].name);11036 if (tests[i].fn(ctx) < 0)11037 goto error;11038 }11039 isl_ctx_free(ctx);11040 return 0;11041error:11042 isl_ctx_free(ctx);11043 return -1;11044}11045