1 //===- IslTest.cpp ----------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "polly/Support/GICHelper.h"
10 #include "polly/Support/ISLOperators.h"
11 #include "polly/Support/ISLTools.h"
12 #include "gtest/gtest.h"
13 #include "isl/stream.h"
17 using namespace polly
;
19 static isl::space
parseSpace(isl_ctx
*Ctx
, const char *Str
) {
20 isl_stream
*Stream
= isl_stream_new_str(Ctx
, Str
);
21 auto Obj
= isl_stream_read_obj(Stream
);
24 if (Obj
.type
== isl_obj_set
)
25 Result
= isl::manage(isl_set_get_space(static_cast<isl_set
*>(Obj
.v
)));
26 else if (Obj
.type
== isl_obj_map
)
27 Result
= isl::manage(isl_map_get_space(static_cast<isl_map
*>(Obj
.v
)));
29 isl_stream_free(Stream
);
31 Obj
.type
->free(Obj
.v
);
35 #define SPACE(Str) parseSpace(Ctx.get(), Str)
37 #define SET(Str) isl::set(Ctx.get(), Str)
38 #define MAP(Str) isl::map(Ctx.get(), Str)
40 #define USET(Str) isl::union_set(Ctx.get(), Str)
41 #define UMAP(Str) isl::union_map(Ctx.get(), Str)
44 inline namespace noexceptions
{
46 static bool operator==(const isl::space
&LHS
, const isl::space
&RHS
) {
47 return bool(LHS
.is_equal(RHS
));
50 static bool operator==(const isl::set
&LHS
, const isl::set
&RHS
) {
51 return bool(LHS
.is_equal(RHS
));
54 static bool operator==(const isl::map
&LHS
, const isl::map
&RHS
) {
55 return bool(LHS
.is_equal(RHS
));
58 static bool operator==(const isl::union_set
&LHS
, const isl::union_set
&RHS
) {
59 return bool(LHS
.is_equal(RHS
));
62 static bool operator==(const isl::union_map
&LHS
, const isl::union_map
&RHS
) {
63 return bool(LHS
.is_equal(RHS
));
66 static bool operator==(const isl::val
&LHS
, const isl::val
&RHS
) {
67 return bool(LHS
.eq(RHS
));
70 static bool operator==(const isl::pw_aff
&LHS
, const isl::pw_aff
&RHS
) {
71 return bool(LHS
.is_equal(RHS
));
73 } // namespace noexceptions
78 TEST(Isl
, APIntToIslVal
) {
79 isl_ctx
*IslCtx
= isl_ctx_alloc();
82 APInt
APZero(1, 0, true);
83 auto IslZero
= valFromAPInt(IslCtx
, APZero
, true);
84 EXPECT_TRUE(IslZero
.is_zero());
88 APInt
APNOne(1, -1, true);
89 auto IslNOne
= valFromAPInt(IslCtx
, APNOne
, true);
90 EXPECT_TRUE(IslNOne
.is_negone());
94 APInt
APZero(1, 0, false);
95 auto IslZero
= valFromAPInt(IslCtx
, APZero
, false);
96 EXPECT_TRUE(IslZero
.is_zero());
100 APInt
APOne(1, 1, false);
101 auto IslOne
= valFromAPInt(IslCtx
, APOne
, false);
102 EXPECT_TRUE(IslOne
.is_one());
106 APInt
APNTwo(2, -2, true);
107 auto IslNTwo
= valFromAPInt(IslCtx
, APNTwo
, true);
108 auto IslNTwoCmp
= isl::val(IslCtx
, -2);
109 EXPECT_EQ(IslNTwo
, IslNTwoCmp
);
113 APInt
APNOne(32, -1, true);
114 auto IslNOne
= valFromAPInt(IslCtx
, APNOne
, true);
115 EXPECT_TRUE(IslNOne
.is_negone());
119 APInt
APZero(32, 0, false);
120 auto IslZero
= valFromAPInt(IslCtx
, APZero
, false);
121 EXPECT_TRUE(IslZero
.is_zero());
125 APInt
APOne(32, 1, false);
126 auto IslOne
= valFromAPInt(IslCtx
, APOne
, false);
127 EXPECT_TRUE(IslOne
.is_one());
131 APInt
APTwo(32, 2, false);
132 auto IslTwo
= valFromAPInt(IslCtx
, APTwo
, false);
133 EXPECT_EQ(0, IslTwo
.cmp_si(2));
137 APInt
APNOne(32, (1ull << 32) - 1, false);
138 auto IslNOne
= valFromAPInt(IslCtx
, APNOne
, false);
139 auto IslRef
= isl::val(IslCtx
, 32).pow2().sub(1);
140 EXPECT_EQ(IslNOne
, IslRef
);
144 APInt
APLarge(130, 2, false);
145 APLarge
= APLarge
.shl(70);
146 auto IslLarge
= valFromAPInt(IslCtx
, APLarge
, false);
147 auto IslRef
= isl::val(IslCtx
, 71);
148 IslRef
= IslRef
.pow2();
149 EXPECT_EQ(IslLarge
, IslRef
);
152 isl_ctx_free(IslCtx
);
155 TEST(Isl
, IslValToAPInt
) {
156 isl_ctx
*IslCtx
= isl_ctx_alloc();
159 auto IslNOne
= isl::val(IslCtx
, -1);
160 auto APNOne
= APIntFromVal(IslNOne
);
161 // Compare with the two's complement of -1 in a 1-bit integer.
162 EXPECT_EQ(1, APNOne
);
163 EXPECT_EQ(1u, APNOne
.getBitWidth());
167 auto IslNTwo
= isl::val(IslCtx
, -2);
168 auto APNTwo
= APIntFromVal(IslNTwo
);
169 // Compare with the two's complement of -2 in a 2-bit integer.
170 EXPECT_EQ(2, APNTwo
);
171 EXPECT_EQ(2u, APNTwo
.getBitWidth());
175 auto IslNThree
= isl::val(IslCtx
, -3);
176 auto APNThree
= APIntFromVal(IslNThree
);
177 // Compare with the two's complement of -3 in a 3-bit integer.
178 EXPECT_EQ(5, APNThree
);
179 EXPECT_EQ(3u, APNThree
.getBitWidth());
183 auto IslNFour
= isl::val(IslCtx
, -4);
184 auto APNFour
= APIntFromVal(IslNFour
);
185 // Compare with the two's complement of -4 in a 3-bit integer.
186 EXPECT_EQ(4, APNFour
);
187 EXPECT_EQ(3u, APNFour
.getBitWidth());
191 auto IslZero
= isl::val(IslCtx
, 0);
192 auto APZero
= APIntFromVal(IslZero
);
193 EXPECT_EQ(0, APZero
);
194 EXPECT_EQ(1u, APZero
.getBitWidth());
198 auto IslOne
= isl::val(IslCtx
, 1);
199 auto APOne
= APIntFromVal(IslOne
);
201 EXPECT_EQ(2u, APOne
.getBitWidth());
205 auto IslTwo
= isl::val(IslCtx
, 2);
206 auto APTwo
= APIntFromVal(IslTwo
);
208 EXPECT_EQ(3u, APTwo
.getBitWidth());
212 auto IslThree
= isl::val(IslCtx
, 3);
213 auto APThree
= APIntFromVal(IslThree
);
214 EXPECT_EQ(3, APThree
);
215 EXPECT_EQ(3u, APThree
.getBitWidth());
219 auto IslFour
= isl::val(IslCtx
, 4);
220 auto APFour
= APIntFromVal(IslFour
);
221 EXPECT_EQ(4, APFour
);
222 EXPECT_EQ(4u, APFour
.getBitWidth());
226 auto IslNOne
= isl::val(IslCtx
, 32).pow2().sub(1);
227 auto APNOne
= APIntFromVal(IslNOne
);
228 EXPECT_EQ((1ull << 32) - 1, APNOne
);
229 EXPECT_EQ(33u, APNOne
.getBitWidth());
233 auto IslLargeNum
= isl::val(IslCtx
, 60);
234 IslLargeNum
= IslLargeNum
.pow2();
235 IslLargeNum
= IslLargeNum
.sub(1);
236 auto APLargeNum
= APIntFromVal(IslLargeNum
);
237 EXPECT_EQ((1ull << 60) - 1, APLargeNum
);
238 EXPECT_EQ(61u, APLargeNum
.getBitWidth());
242 auto IslExp
= isl::val(IslCtx
, 500);
243 auto IslLargePow2
= IslExp
.pow2();
244 auto APLargePow2
= APIntFromVal(IslLargePow2
);
245 EXPECT_TRUE(APLargePow2
.isPowerOf2());
246 EXPECT_EQ(502u, APLargePow2
.getBitWidth());
247 EXPECT_EQ(502u, APLargePow2
.getSignificantBits());
251 auto IslExp
= isl::val(IslCtx
, 500);
252 auto IslLargeNPow2
= IslExp
.pow2().neg();
253 auto APLargeNPow2
= APIntFromVal(IslLargeNPow2
);
254 EXPECT_EQ(501u, APLargeNPow2
.getBitWidth());
255 EXPECT_EQ(501u, APLargeNPow2
.getSignificantBits());
256 EXPECT_EQ(500, (-APLargeNPow2
).exactLogBase2());
260 auto IslExp
= isl::val(IslCtx
, 512);
261 auto IslLargePow2
= IslExp
.pow2();
262 auto APLargePow2
= APIntFromVal(IslLargePow2
);
263 EXPECT_TRUE(APLargePow2
.isPowerOf2());
264 EXPECT_EQ(514u, APLargePow2
.getBitWidth());
265 EXPECT_EQ(514u, APLargePow2
.getSignificantBits());
269 auto IslExp
= isl::val(IslCtx
, 512);
270 auto IslLargeNPow2
= IslExp
.pow2().neg();
271 auto APLargeNPow2
= APIntFromVal(IslLargeNPow2
);
272 EXPECT_EQ(513u, APLargeNPow2
.getBitWidth());
273 EXPECT_EQ(513u, APLargeNPow2
.getSignificantBits());
274 EXPECT_EQ(512, (-APLargeNPow2
).exactLogBase2());
277 isl_ctx_free(IslCtx
);
280 TEST(Isl
, Operators
) {
281 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> IslCtx(isl_ctx_alloc(),
284 isl::val ValOne
= isl::val(IslCtx
.get(), 1);
285 isl::val ValTwo
= isl::val(IslCtx
.get(), 2);
286 isl::val ValThree
= isl::val(IslCtx
.get(), 3);
287 isl::val ValFour
= isl::val(IslCtx
.get(), 4);
288 isl::val ValNegOne
= isl::val(IslCtx
.get(), -1);
289 isl::val ValNegTwo
= isl::val(IslCtx
.get(), -2);
290 isl::val ValNegThree
= isl::val(IslCtx
.get(), -3);
291 isl::val ValNegFour
= isl::val(IslCtx
.get(), -4);
293 isl::space Space
= isl::space(IslCtx
.get(), 0, 0);
294 isl::local_space LS
= isl::local_space(Space
);
296 isl::pw_aff AffOne
= isl::aff(LS
, ValOne
);
297 isl::pw_aff AffTwo
= isl::aff(LS
, ValTwo
);
298 isl::pw_aff AffThree
= isl::aff(LS
, ValThree
);
299 isl::pw_aff AffFour
= isl::aff(LS
, ValFour
);
300 isl::pw_aff AffNegOne
= isl::aff(LS
, ValNegOne
);
301 isl::pw_aff AffNegTwo
= isl::aff(LS
, ValNegTwo
);
302 isl::pw_aff AffNegThree
= isl::aff(LS
, ValNegThree
);
303 isl::pw_aff AffNegFour
= isl::aff(LS
, ValNegFour
);
307 EXPECT_EQ(AffOne
+ AffOne
, AffTwo
);
308 EXPECT_EQ(AffOne
+ 1, AffTwo
);
309 EXPECT_EQ(1 + AffOne
, AffTwo
);
310 EXPECT_EQ(AffOne
+ ValOne
, AffTwo
);
311 EXPECT_EQ(ValOne
+ AffOne
, AffTwo
);
316 EXPECT_EQ(AffTwo
* AffTwo
, AffFour
);
317 EXPECT_EQ(AffTwo
* 2, AffFour
);
318 EXPECT_EQ(2 * AffTwo
, AffFour
);
319 EXPECT_EQ(AffTwo
* ValTwo
, AffFour
);
320 EXPECT_EQ(ValTwo
* AffTwo
, AffFour
);
325 EXPECT_EQ(AffTwo
- AffOne
, AffOne
);
326 EXPECT_EQ(AffTwo
- 1, AffOne
);
327 EXPECT_EQ(2 - AffOne
, AffOne
);
328 EXPECT_EQ(AffTwo
- ValOne
, AffOne
);
329 EXPECT_EQ(ValTwo
- AffOne
, AffOne
);
334 EXPECT_EQ(AffFour
/ AffTwo
, AffTwo
);
335 EXPECT_EQ(AffFour
/ 2, AffTwo
);
336 EXPECT_EQ(4 / AffTwo
, AffTwo
);
337 EXPECT_EQ(AffFour
/ ValTwo
, AffTwo
);
338 EXPECT_EQ(AffFour
/ 2, AffTwo
);
340 // Dividend is negative (should be rounded towards zero)
341 EXPECT_EQ(AffNegFour
/ AffThree
, AffNegOne
);
342 EXPECT_EQ(AffNegFour
/ 3, AffNegOne
);
343 EXPECT_EQ((-4) / AffThree
, AffNegOne
);
344 EXPECT_EQ(AffNegFour
/ ValThree
, AffNegOne
);
345 EXPECT_EQ(AffNegFour
/ 3, AffNegOne
);
347 // Divisor is negative (should be rounded towards zero)
348 EXPECT_EQ(AffFour
/ AffNegThree
, AffNegOne
);
349 EXPECT_EQ(AffFour
/ -3, AffNegOne
);
350 EXPECT_EQ(4 / AffNegThree
, AffNegOne
);
351 EXPECT_EQ(AffFour
/ ValNegThree
, AffNegOne
);
352 EXPECT_EQ(AffFour
/ -3, AffNegOne
);
357 EXPECT_EQ(AffThree
% AffTwo
, AffOne
);
358 EXPECT_EQ(AffThree
% 2, AffOne
);
359 EXPECT_EQ(3 % AffTwo
, AffOne
);
360 EXPECT_EQ(AffThree
% ValTwo
, AffOne
);
361 EXPECT_EQ(ValThree
% AffTwo
, AffOne
);
363 // Dividend is negative (should be rounded towards zero)
364 EXPECT_EQ(AffNegFour
% AffThree
, AffNegOne
);
365 EXPECT_EQ(AffNegFour
% 3, AffNegOne
);
366 EXPECT_EQ((-4) % AffThree
, AffNegOne
);
367 EXPECT_EQ(AffNegFour
% ValThree
, AffNegOne
);
368 EXPECT_EQ(AffNegFour
% 3, AffNegOne
);
370 // Divisor is negative (should be rounded towards zero)
371 EXPECT_EQ(AffFour
% AffNegThree
, AffOne
);
372 EXPECT_EQ(AffFour
% -3, AffOne
);
373 EXPECT_EQ(4 % AffNegThree
, AffOne
);
374 EXPECT_EQ(AffFour
% ValNegThree
, AffOne
);
375 EXPECT_EQ(AffFour
% -3, AffOne
);
380 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
383 isl::map TestMap
{Ctx
.get(), "{ [2] -> [7]; [5] -> [7] }"};
384 isl::union_map TestUMap
{Ctx
.get(), "{ A[i] -> [7]; B[i] -> [7] }"};
386 isl::set TestSet
{Ctx
.get(), "{ [0,7]; [i,7]: i >= 2 }"};
387 isl::union_set TestUSet
{Ctx
.get(), "{ A[0,7]; B[i,7] }"};
389 isl::set Seven
{Ctx
.get(), "{ [7] }"};
394 TestMap
.foreach_basic_map([&](isl::basic_map BMap
) -> isl::stat
{
395 EXPECT_EQ(BMap
.range(), Seven
);
397 return isl::stat::ok();
400 EXPECT_TRUE(Stat
.is_ok());
401 EXPECT_EQ(2, NumBMaps
);
407 TestSet
.foreach_basic_set([&](isl::basic_set BSet
) -> isl::stat
{
408 EXPECT_EQ(BSet
.project_out(isl::dim::set
, 0, 1), Seven
);
410 return isl::stat::ok();
412 EXPECT_TRUE(Stat
.is_ok());
413 EXPECT_EQ(2, NumBSets
);
418 isl::stat Stat
= TestUMap
.foreach_map([&](isl::map Map
) -> isl::stat
{
419 EXPECT_EQ(Map
.range(), Seven
);
421 return isl::stat::ok();
423 EXPECT_TRUE(Stat
.is_ok());
424 EXPECT_EQ(2, NumMaps
);
429 isl::stat Stat
= TestUSet
.foreach_set([&](isl::set Set
) -> isl::stat
{
430 EXPECT_EQ(Set
.project_out(isl::dim::set
, 0, 1), Seven
);
432 return isl::stat::ok();
434 EXPECT_TRUE(Stat
.is_ok());
435 EXPECT_EQ(2, NumSets
);
439 auto UPwAff
= isl::union_pw_aff(TestUSet
, isl::val::zero(Ctx
.get()));
441 isl::stat Stat
= UPwAff
.foreach_pw_aff([&](isl::pw_aff PwAff
) -> isl::stat
{
442 EXPECT_TRUE(PwAff
.is_cst());
444 return isl::stat::ok();
446 EXPECT_TRUE(Stat
.is_ok());
447 EXPECT_EQ(2, NumPwAffs
);
453 .foreach_basic_map([&](isl::basic_map BMap
) -> isl::stat
{
454 EXPECT_EQ(BMap
.range(), Seven
);
456 return isl::stat::error();
459 EXPECT_EQ(1, NumBMaps
);
465 .foreach_map([&](isl::map Map
) -> isl::stat
{
466 EXPECT_EQ(Map
.range(), Seven
);
468 return isl::stat::error();
471 EXPECT_EQ(1, NumMaps
);
475 auto TestPwAff
= isl::pw_aff(TestSet
, isl::val::zero(Ctx
.get()));
477 isl::stat Stat
= TestPwAff
.foreach_piece(
478 [&](isl::set Domain
, isl::aff Aff
) -> isl::stat
{
479 EXPECT_EQ(Domain
, TestSet
);
480 EXPECT_TRUE(Aff
.is_cst());
482 return isl::stat::error();
484 EXPECT_TRUE(Stat
.is_error());
485 EXPECT_EQ(1, NumPieces
);
489 TEST(ISLTools
, beforeScatter
) {
490 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
493 // Basic usage with isl_map
494 EXPECT_EQ(MAP("{ [] -> [i] : i <= 0 }"),
495 beforeScatter(MAP("{ [] -> [0] }"), false));
496 EXPECT_EQ(MAP("{ [] -> [i] : i < 0 }"),
497 beforeScatter(MAP("{ [] -> [0] }"), true));
499 // Basic usage with isl_union_map
500 EXPECT_EQ(UMAP("{ A[] -> [i] : i <= 0; B[] -> [i] : i <= 0 }"),
501 beforeScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"), false));
502 EXPECT_EQ(UMAP("{ A[] -> [i] : i < 0; B[] -> [i] : i < 0 }"),
503 beforeScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"), true));
505 // More than one dimension
506 EXPECT_EQ(UMAP("{ [] -> [i, j] : i < 0; [] -> [i, j] : i = 0 and j <= 0 }"),
507 beforeScatter(UMAP("{ [] -> [0, 0] }"), false));
508 EXPECT_EQ(UMAP("{ [] -> [i, j] : i < 0; [] -> [i, j] : i = 0 and j < 0 }"),
509 beforeScatter(UMAP("{ [] -> [0, 0] }"), true));
512 EXPECT_EQ(UMAP("{ [i] -> [j] : j <= i }"),
513 beforeScatter(UMAP("{ [i] -> [i] }"), false));
514 EXPECT_EQ(UMAP("{ [i] -> [j] : j < i }"),
515 beforeScatter(UMAP("{ [i] -> [i] }"), true));
518 EXPECT_EQ(UMAP("[i] -> { [] -> [j] : j <= i }"),
519 beforeScatter(UMAP("[i] -> { [] -> [i] }"), false));
520 EXPECT_EQ(UMAP("[i] -> { [] -> [j] : j < i }"),
521 beforeScatter(UMAP("[i] -> { [] -> [i] }"), true));
523 // More than one range
524 EXPECT_EQ(UMAP("{ [] -> [i] : i <= 10 }"),
525 beforeScatter(UMAP("{ [] -> [0]; [] -> [10] }"), false));
526 EXPECT_EQ(UMAP("{ [] -> [i] : i < 10 }"),
527 beforeScatter(UMAP("{ [] -> [0]; [] -> [10] }"), true));
530 EXPECT_EQ(UMAP("{ [] -> [i] : 1 = 0 }"),
531 beforeScatter(UMAP("{ [] -> [i] : 1 = 0 }"), false));
532 EXPECT_EQ(UMAP("{ [] -> [i] : 1 = 0 }"),
533 beforeScatter(UMAP("{ [] -> [i] : 1 = 0 }"), true));
536 TEST(ISLTools
, afterScatter
) {
537 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
540 // Basic usage with isl_map
541 EXPECT_EQ(MAP("{ [] -> [i] : i >= 0 }"),
542 afterScatter(MAP("{ [] -> [0] }"), false));
543 EXPECT_EQ(MAP("{ [] -> [i] : i > 0 }"),
544 afterScatter(MAP("{ [] -> [0] }"), true));
546 // Basic usage with isl_union_map
547 EXPECT_EQ(UMAP("{ A[] -> [i] : i >= 0; B[] -> [i] : i >= 0 }"),
548 afterScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"), false));
549 EXPECT_EQ(UMAP("{ A[] -> [i] : i > 0; B[] -> [i] : i > 0 }"),
550 afterScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"), true));
552 // More than one dimension
553 EXPECT_EQ(UMAP("{ [] -> [i, j] : i > 0; [] -> [i, j] : i = 0 and j >= 0 }"),
554 afterScatter(UMAP("{ [] -> [0, 0] }"), false));
555 EXPECT_EQ(UMAP("{ [] -> [i, j] : i > 0; [] -> [i, j] : i = 0 and j > 0 }"),
556 afterScatter(UMAP("{ [] -> [0, 0] }"), true));
559 EXPECT_EQ(UMAP("{ [i] -> [j] : j >= i }"),
560 afterScatter(UMAP("{ [i] -> [i] }"), false));
561 EXPECT_EQ(UMAP("{ [i] -> [j] : j > i }"),
562 afterScatter(UMAP("{ [i] -> [i] }"), true));
565 EXPECT_EQ(UMAP("[i] -> { [] -> [j] : j >= i }"),
566 afterScatter(UMAP("[i] -> { [] -> [i] }"), false));
567 EXPECT_EQ(UMAP("[i] -> { [] -> [j] : j > i }"),
568 afterScatter(UMAP("[i] -> { [] -> [i] }"), true));
570 // More than one range
571 EXPECT_EQ(UMAP("{ [] -> [i] : i >= 0 }"),
572 afterScatter(UMAP("{ [] -> [0]; [] -> [10] }"), false));
573 EXPECT_EQ(UMAP("{ [] -> [i] : i > 0 }"),
574 afterScatter(UMAP("{ [] -> [0]; [] -> [10] }"), true));
577 EXPECT_EQ(UMAP("{ }"), afterScatter(UMAP("{ }"), false));
578 EXPECT_EQ(UMAP("{ }"), afterScatter(UMAP("{ }"), true));
581 TEST(ISLTools
, betweenScatter
) {
582 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
585 // Basic usage with isl_map
586 EXPECT_EQ(MAP("{ [] -> [i] : 0 < i < 10 }"),
587 betweenScatter(MAP("{ [] -> [0] }"), MAP("{ [] -> [10] }"), false,
590 MAP("{ [] -> [i] : 0 <= i < 10 }"),
591 betweenScatter(MAP("{ [] -> [0] }"), MAP("{ [] -> [10] }"), true, false));
593 MAP("{ [] -> [i] : 0 < i <= 10 }"),
594 betweenScatter(MAP("{ [] -> [0] }"), MAP("{ [] -> [10] }"), false, true));
596 MAP("{ [] -> [i] : 0 <= i <= 10 }"),
597 betweenScatter(MAP("{ [] -> [0] }"), MAP("{ [] -> [10] }"), true, true));
599 // Basic usage with isl_union_map
600 EXPECT_EQ(UMAP("{ A[] -> [i] : 0 < i < 10; B[] -> [i] : 0 < i < 10 }"),
601 betweenScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"),
602 UMAP("{ A[] -> [10]; B[] -> [10] }"), false, false));
603 EXPECT_EQ(UMAP("{ A[] -> [i] : 0 <= i < 10; B[] -> [i] : 0 <= i < 10 }"),
604 betweenScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"),
605 UMAP("{ A[] -> [10]; B[] -> [10] }"), true, false));
606 EXPECT_EQ(UMAP("{ A[] -> [i] : 0 < i <= 10; B[] -> [i] : 0 < i <= 10 }"),
607 betweenScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"),
608 UMAP("{ A[] -> [10]; B[] -> [10] }"), false, true));
609 EXPECT_EQ(UMAP("{ A[] -> [i] : 0 <= i <= 10; B[] -> [i] : 0 <= i <= 10 }"),
610 betweenScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"),
611 UMAP("{ A[] -> [10]; B[] -> [10] }"), true, true));
614 TEST(ISLTools
, singleton
) {
615 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
619 EXPECT_EQ(SET("{ [] : 1 = 0 }"), singleton(USET("{ }"), SPACE("{ [] }")));
620 EXPECT_EQ(MAP("{ [] -> [] : 1 = 0 }"),
621 singleton(UMAP("{ }"), SPACE("{ [] -> [] }")));
624 EXPECT_EQ(SET("{ [] }"), singleton(USET("{ [] }"), SPACE("{ [] }")));
625 EXPECT_EQ(MAP("{ [] -> [] }"),
626 singleton(UMAP("{ [] -> [] }"), SPACE("{ [] -> [] }")));
628 // Many elements found
629 EXPECT_EQ(SET("{ [i] : 0 <= i < 10 }"),
630 singleton(USET("{ [i] : 0 <= i < 10 }"), SPACE("{ [i] }")));
632 MAP("{ [i] -> [i] : 0 <= i < 10 }"),
633 singleton(UMAP("{ [i] -> [i] : 0 <= i < 10 }"), SPACE("{ [i] -> [j] }")));
635 // Different parameters
636 EXPECT_EQ(SET("[i] -> { [i] }"),
637 singleton(USET("[i] -> { [i] }"), SPACE("{ [i] }")));
638 EXPECT_EQ(MAP("[i] -> { [i] -> [i] }"),
639 singleton(UMAP("[i] -> { [i] -> [i] }"), SPACE("{ [i] -> [j] }")));
642 TEST(ISLTools
, getNumScatterDims
) {
643 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
647 EXPECT_EQ(0u, getNumScatterDims(UMAP("{ [] -> [] }")));
648 EXPECT_EQ(1u, getNumScatterDims(UMAP("{ [] -> [i] }")));
649 EXPECT_EQ(2u, getNumScatterDims(UMAP("{ [] -> [i,j] }")));
650 EXPECT_EQ(3u, getNumScatterDims(UMAP("{ [] -> [i,j,k] }")));
652 // Different scatter spaces
653 EXPECT_EQ(0u, getNumScatterDims(UMAP("{ A[] -> []; [] -> []}")));
654 EXPECT_EQ(1u, getNumScatterDims(UMAP("{ A[] -> []; [] -> [i] }")));
655 EXPECT_EQ(2u, getNumScatterDims(UMAP("{ A[] -> [i]; [] -> [i,j] }")));
656 EXPECT_EQ(3u, getNumScatterDims(UMAP("{ A[] -> [i]; [] -> [i,j,k] }")));
659 TEST(ISLTools
, getScatterSpace
) {
660 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
664 EXPECT_EQ(SPACE("{ [] }"), getScatterSpace(UMAP("{ [] -> [] }")));
665 EXPECT_EQ(SPACE("{ [i] }"), getScatterSpace(UMAP("{ [] -> [i] }")));
666 EXPECT_EQ(SPACE("{ [i,j] }"), getScatterSpace(UMAP("{ [] -> [i,j] }")));
667 EXPECT_EQ(SPACE("{ [i,j,k] }"), getScatterSpace(UMAP("{ [] -> [i,j,k] }")));
669 // Different scatter spaces
670 EXPECT_EQ(SPACE("{ [] }"), getScatterSpace(UMAP("{ A[] -> []; [] -> [] }")));
671 EXPECT_EQ(SPACE("{ [i] }"),
672 getScatterSpace(UMAP("{ A[] -> []; [] -> [i] }")));
673 EXPECT_EQ(SPACE("{ [i,j] }"),
674 getScatterSpace(UMAP("{ A[] -> [i]; [] -> [i,j] }")));
675 EXPECT_EQ(SPACE("{ [i,j,k] }"),
676 getScatterSpace(UMAP("{ A[] -> [i]; [] -> [i,j,k] }")));
679 TEST(ISLTools
, makeIdentityMap
) {
680 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
684 EXPECT_EQ(UMAP("{ [i] -> [i] }"), makeIdentityMap(USET("{ [0] }"), false));
685 EXPECT_EQ(UMAP("{ [0] -> [0] }"), makeIdentityMap(USET("{ [0] }"), true));
688 EXPECT_EQ(UMAP("{ [] -> []; [i] -> [i] }"),
689 makeIdentityMap(USET("{ []; [0] }"), false));
690 EXPECT_EQ(UMAP("{ [] -> []; [0] -> [0] }"),
691 makeIdentityMap(USET("{ []; [0] }"), true));
694 EXPECT_EQ(UMAP("{ }"), makeIdentityMap(USET("{ }"), false));
695 EXPECT_EQ(UMAP("{ }"), makeIdentityMap(USET("{ }"), true));
698 TEST(ISLTools
, reverseDomain
) {
699 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
703 EXPECT_EQ(MAP("{ [B[] -> A[]] -> [] }"),
704 reverseDomain(MAP("{ [A[] -> B[]] -> [] }")));
705 EXPECT_EQ(UMAP("{ [B[] -> A[]] -> [] }"),
706 reverseDomain(UMAP("{ [A[] -> B[]] -> [] }")));
709 TEST(ISLTools
, shiftDim
) {
710 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
714 EXPECT_EQ(SET("{ [1] }"), shiftDim(SET("{ [0] }"), 0, 1));
715 EXPECT_EQ(USET("{ [1] }"), shiftDim(USET("{ [0] }"), 0, 1));
718 EXPECT_EQ(USET("{ [0,0,1] }"), shiftDim(USET("{ [0,0,0] }"), -1, 1));
719 EXPECT_EQ(USET("{ [0,1,0] }"), shiftDim(USET("{ [0,0,0] }"), -2, 1));
720 EXPECT_EQ(USET("{ [1,0,0] }"), shiftDim(USET("{ [0,0,0] }"), -3, 1));
723 EXPECT_EQ(USET("[n] -> { [n+1] }"), shiftDim(USET("[n] -> { [n] }"), 0, 1));
726 EXPECT_EQ(MAP("{ [1] -> [] }"),
727 shiftDim(MAP("{ [0] -> [] }"), isl::dim::in
, 0, 1));
728 EXPECT_EQ(UMAP("{ [1] -> [] }"),
729 shiftDim(UMAP("{ [0] -> [] }"), isl::dim::in
, 0, 1));
730 EXPECT_EQ(MAP("{ [] -> [1] }"),
731 shiftDim(MAP("{ [] -> [0] }"), isl::dim::out
, 0, 1));
732 EXPECT_EQ(UMAP("{ [] -> [1] }"),
733 shiftDim(UMAP("{ [] -> [0] }"), isl::dim::out
, 0, 1));
736 TEST(DeLICM
, computeReachingWrite
) {
737 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
741 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : 0 < i }"),
742 computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
743 UMAP("{ Dom[] -> Elt[] }"), false, false,
745 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : 0 < i }"),
746 computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
747 UMAP("{ Dom[] -> Elt[] }"), false, false,
749 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : 0 <= i }"),
750 computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
751 UMAP("{ Dom[] -> Elt[] }"), false, true,
753 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : 0 <= i }"),
754 computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
755 UMAP("{ Dom[] -> Elt[] }"), false, true,
758 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : i < 0 }"),
759 computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
760 UMAP("{ Dom[] -> Elt[] }"), true, false,
762 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : i <= 0 }"),
763 computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
764 UMAP("{ Dom[] -> Elt[] }"), true, false,
766 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : i < 0 }"),
767 computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
768 UMAP("{ Dom[] -> Elt[] }"), true, true,
770 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : i <= 0 }"),
771 computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
772 UMAP("{ Dom[] -> Elt[] }"), true, true, true));
775 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom1[] : 0 < i < 10; [Elt[] -> [i]] -> "
776 "Dom2[] : 10 < i }"),
777 computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
778 UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
779 false, false, false));
780 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom1[] : 0 <= i < 10; [Elt[] -> [i]] -> "
781 "Dom2[] : 10 <= i }"),
782 computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
783 UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
784 false, true, false));
785 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom1[] : 0 < i <= 10; [Elt[] -> [i]] -> "
786 "Dom2[] : 10 < i }"),
787 computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
788 UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
789 false, false, true));
790 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom1[] : 0 <= i <= 10; [Elt[] -> [i]] -> "
791 "Dom2[] : 10 <= i }"),
792 computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
793 UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
796 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom2[] : 0 < i < 10; [Elt[] -> [i]] -> "
798 computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
799 UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
800 true, false, false));
801 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom2[] : 0 <= i < 10; [Elt[] -> [i]] -> "
803 computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
804 UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
806 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom2[] : 0 < i <= 10; [Elt[] -> [i]] -> "
807 "Dom1[] : i <= 0 }"),
808 computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
809 UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
811 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom2[] : 0 <= i <= 10; [Elt[] -> [i]] -> "
812 "Dom1[] : i <= 0 }"),
813 computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
814 UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
817 // Domain in same space
818 EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[1] : 0 < i <= 10; [Elt[] -> [i]] -> "
819 "Dom[2] : 10 < i }"),
820 computeReachingWrite(UMAP("{ Dom[i] -> [10i - 10] }"),
821 UMAP("{ Dom[1] -> Elt[]; Dom[2] -> Elt[] }"),
822 false, false, true));
825 EXPECT_EQ(UMAP("[p] -> { [Elt[] -> [i]] -> Dom[] : p < i }"),
826 computeReachingWrite(UMAP("[p] -> { Dom[] -> [p] }"),
827 UMAP("{ Dom[] -> Elt[] }"), false, false,
830 // More realistic example (from reduction_embedded.ll)
832 UMAP("{ [Elt[] -> [i]] -> Dom[0] : 0 < i <= 3; [Elt[] -> [i]] -> Dom[1] "
833 ": 3 < i <= 6; [Elt[] -> [i]] -> Dom[2] : 6 < i <= 9; [Elt[] -> "
834 "[i]] -> Dom[3] : 9 < i <= 12; [Elt[] -> [i]] -> Dom[4] : 12 < i }"),
835 computeReachingWrite(UMAP("{ Dom[i] -> [3i] : 0 <= i <= 4 }"),
836 UMAP("{ Dom[i] -> Elt[] : 0 <= i <= 4 }"), false,
840 TEST(DeLICM
, computeArrayUnused
) {
841 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
844 // The ReadEltInSameInst parameter doesn't matter in simple cases. To also
845 // cover the parameter without duplicating the tests, this loops runs over
846 // other in both settings.
847 for (bool ReadEltInSameInst
= false, Done
= false; !Done
;
848 Done
= ReadEltInSameInst
, ReadEltInSameInst
= true) {
849 // Basic usage: one read, one write
850 EXPECT_EQ(UMAP("{ Elt[] -> [i] : 0 < i < 10 }"),
851 computeArrayUnused(UMAP("{ Read[] -> [0]; Write[] -> [10] }"),
852 UMAP("{ Write[] -> Elt[] }"),
853 UMAP("{ Read[] -> Elt[] }"), ReadEltInSameInst
,
855 EXPECT_EQ(UMAP("{ Elt[] -> [i] : 0 < i <= 10 }"),
856 computeArrayUnused(UMAP("{ Read[] -> [0]; Write[] -> [10] }"),
857 UMAP("{ Write[] -> Elt[] }"),
858 UMAP("{ Read[] -> Elt[] }"), ReadEltInSameInst
,
860 EXPECT_EQ(UMAP("{ Elt[] -> [i] : 0 <= i < 10 }"),
861 computeArrayUnused(UMAP("{ Read[] -> [0]; Write[] -> [10] }"),
862 UMAP("{ Write[] -> Elt[] }"),
863 UMAP("{ Read[] -> Elt[] }"), ReadEltInSameInst
,
865 EXPECT_EQ(UMAP("{ Elt[] -> [i] : 0 <= i <= 10 }"),
866 computeArrayUnused(UMAP("{ Read[] -> [0]; Write[] -> [10] }"),
867 UMAP("{ Write[] -> Elt[] }"),
868 UMAP("{ Read[] -> Elt[] }"), ReadEltInSameInst
,
872 EXPECT_EQ(UMAP("{ Elt[] -> [i] : 0 < i <= 10 }"),
874 UMAP("{ Read[0] -> [-10]; Read[1] -> [0]; Write[] -> [10] }"),
875 UMAP("{ Write[] -> Elt[] }"), UMAP("{ Read[i] -> Elt[] }"),
876 ReadEltInSameInst
, false, true));
878 // Corner case: no writes
879 EXPECT_EQ(UMAP("{}"),
880 computeArrayUnused(UMAP("{ Read[] -> [0] }"), UMAP("{}"),
881 UMAP("{ Read[] -> Elt[] }"), ReadEltInSameInst
,
884 // Corner case: no reads
885 EXPECT_EQ(UMAP("{ Elt[] -> [i] : i <= 0 }"),
886 computeArrayUnused(UMAP("{ Write[] -> [0] }"),
887 UMAP("{ Write[] -> Elt[] }"), UMAP("{}"),
888 ReadEltInSameInst
, false, true));
892 UMAP("{ Elt[] -> [i] : i <= 10 }"),
893 computeArrayUnused(UMAP("{ WriteA[] -> [0]; WriteB[] -> [10] }"),
894 UMAP("{ WriteA[] -> Elt[]; WriteB[] -> Elt[] }"),
895 UMAP("{}"), ReadEltInSameInst
, false, true));
898 // read,write,read,write
900 UMAP("{ Elt[] -> [i] : 0 < i <= 10; Elt[] -> [i] : 20 < i <= 30 }"),
901 computeArrayUnused(UMAP("{ ReadA[] -> [0]; WriteA[] -> [10]; ReadB[] "
902 "-> [20]; WriteB[] -> [30] }"),
903 UMAP("{ WriteA[] -> Elt[]; WriteB[] -> Elt[] }"),
904 UMAP("{ ReadA[] -> Elt[]; ReadB[] -> Elt[] }"),
905 ReadEltInSameInst
, false, true));
909 UMAP("{ Elt[] -> [i] : i <= 10 }"),
911 UMAP("{ WriteA[] -> [0]; WriteB[] -> [10]; Read[] -> [20] }"),
912 UMAP("{ WriteA[] -> Elt[]; WriteB[] -> Elt[] }"),
913 UMAP("{ Read[] -> Elt[] }"), ReadEltInSameInst
, false, true));
916 EXPECT_EQ(UMAP("{ Elt[] -> [i] : i <= 0 }"),
917 computeArrayUnused(UMAP("{ Write[] -> [0]; Read[] -> [10] }"),
918 UMAP("{ Write[] -> Elt[] }"),
919 UMAP("{ Read[] -> Elt[] }"), ReadEltInSameInst
,
923 EXPECT_EQ(UMAP("{ Elt[] -> [i] : 0 < i <= 10 }"),
925 UMAP("{ ReadA[] -> [0]; Write[] -> [10]; ReadB[] -> [20] }"),
926 UMAP("{ Write[] -> Elt[] }"),
927 UMAP("{ ReadA[] -> Elt[]; ReadB[] -> Elt[] }"),
928 ReadEltInSameInst
, false, true));
930 // read, write, write
932 UMAP("{ Elt[] -> [i] : 0 < i <= 20 }"),
934 UMAP("{ Read[] -> [0]; WriteA[] -> [10]; WriteB[] -> [20] }"),
935 UMAP("{ WriteA[] -> Elt[]; WriteB[] -> Elt[] }"),
936 UMAP("{ Read[] -> Elt[] }"), ReadEltInSameInst
, false, true));
938 // read, write, write, read
940 UMAP("{ Elt[] -> [i] : 0 < i <= 20 }"),
941 computeArrayUnused(UMAP("{ ReadA[] -> [0]; WriteA[] -> [10]; WriteB[] "
942 "-> [20]; ReadB[] -> [30] }"),
943 UMAP("{ WriteA[] -> Elt[]; WriteB[] -> Elt[] }"),
944 UMAP("{ ReadA[] -> Elt[]; ReadB[] -> Elt[] }"),
945 ReadEltInSameInst
, false, true));
948 // Read and write in same statement
949 EXPECT_EQ(UMAP("{ Elt[] -> [i] : i < 0 }"),
950 computeArrayUnused(UMAP("{ RW[] -> [0] }"),
951 UMAP("{ RW[] -> Elt[] }"),
952 UMAP("{ RW[] -> Elt[] }"), true, false, false));
953 EXPECT_EQ(UMAP("{ Elt[] -> [i] : i <= 0 }"),
954 computeArrayUnused(UMAP("{ RW[] -> [0] }"),
955 UMAP("{ RW[] -> Elt[] }"),
956 UMAP("{ RW[] -> Elt[] }"), true, false, true));
957 EXPECT_EQ(UMAP("{ Elt[] -> [0] }"),
958 computeArrayUnused(UMAP("{ RW[] -> [0] }"),
959 UMAP("{ RW[] -> Elt[] }"),
960 UMAP("{ RW[] -> Elt[] }"), false, true, true));
963 TEST(DeLICM
, convertZoneToTimepoints
) {
964 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
967 // Corner case: empty set
968 EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{}"), false, false));
969 EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{}"), true, false));
970 EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{}"), false, true));
971 EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{}"), true, true));
974 EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{ [1] }"), false, false));
975 EXPECT_EQ(USET("{ [0] }"),
976 convertZoneToTimepoints(USET("{ [1] }"), true, false));
977 EXPECT_EQ(USET("{ [1] }"),
978 convertZoneToTimepoints(USET("{ [1] }"), false, true));
979 EXPECT_EQ(USET("{ [0]; [1] }"),
980 convertZoneToTimepoints(USET("{ [1] }"), true, true));
982 // Non-adjacent ranges
983 EXPECT_EQ(USET("{}"),
984 convertZoneToTimepoints(USET("{ [1]; [11] }"), false, false));
985 EXPECT_EQ(USET("{ [0]; [10] }"),
986 convertZoneToTimepoints(USET("{ [1]; [11] }"), true, false));
987 EXPECT_EQ(USET("{ [1]; [11] }"),
988 convertZoneToTimepoints(USET("{ [1]; [11] }"), false, true));
989 EXPECT_EQ(USET("{ [0]; [1]; [10]; [11] }"),
990 convertZoneToTimepoints(USET("{ [1]; [11] }"), true, true));
992 // Adjacent unit ranges
994 USET("{ [i] : 0 < i < 10 }"),
995 convertZoneToTimepoints(USET("{ [i] : 0 < i <= 10 }"), false, false));
997 USET("{ [i] : 0 <= i < 10 }"),
998 convertZoneToTimepoints(USET("{ [i] : 0 < i <= 10 }"), true, false));
1000 USET("{ [i] : 0 < i <= 10 }"),
1001 convertZoneToTimepoints(USET("{ [i] : 0 < i <= 10 }"), false, true));
1002 EXPECT_EQ(USET("{ [i] : 0 <= i <= 10 }"),
1003 convertZoneToTimepoints(USET("{ [i] : 0 < i <= 10 }"), true, true));
1005 // More than one dimension
1006 EXPECT_EQ(USET("{}"),
1007 convertZoneToTimepoints(USET("{ [0,1] }"), false, false));
1008 EXPECT_EQ(USET("{ [0,0] }"),
1009 convertZoneToTimepoints(USET("{ [0,1] }"), true, false));
1010 EXPECT_EQ(USET("{ [0,1] }"),
1011 convertZoneToTimepoints(USET("{ [0,1] }"), false, true));
1012 EXPECT_EQ(USET("{ [0,0]; [0,1] }"),
1013 convertZoneToTimepoints(USET("{ [0,1] }"), true, true));
1016 EXPECT_EQ(UMAP("{}"), convertZoneToTimepoints(UMAP("{ [1] -> [] }"),
1017 isl::dim::in
, false, false));
1018 EXPECT_EQ(UMAP("{ [0] -> [] }"),
1019 convertZoneToTimepoints(UMAP("{ [1] -> [] }"), isl::dim::in
, true,
1021 EXPECT_EQ(UMAP("{ [1] -> [] }"),
1022 convertZoneToTimepoints(UMAP("{ [1] -> [] }"), isl::dim::in
, false,
1025 UMAP("{ [0] -> []; [1] -> [] }"),
1026 convertZoneToTimepoints(UMAP("{ [1] -> [] }"), isl::dim::in
, true, true));
1029 EXPECT_EQ(UMAP("{}"), convertZoneToTimepoints(UMAP("{ [] -> [1] }"),
1030 isl::dim::out
, false, false));
1031 EXPECT_EQ(UMAP("{ [] -> [0] }"),
1032 convertZoneToTimepoints(UMAP("{ [] -> [1] }"), isl::dim::out
, true,
1034 EXPECT_EQ(UMAP("{ [] -> [1] }"),
1035 convertZoneToTimepoints(UMAP("{ [] -> [1] }"), isl::dim::out
, false,
1037 EXPECT_EQ(UMAP("{ [] -> [0]; [] -> [1] }"),
1038 convertZoneToTimepoints(UMAP("{ [] -> [1] }"), isl::dim::out
, true,
1042 TEST(DeLICM
, distribute
) {
1043 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
1047 EXPECT_EQ(MAP("{ [Domain[] -> Range1[]] -> [Domain[] -> Range2[]] }"),
1048 distributeDomain(MAP("{ Domain[] -> [Range1[] -> Range2[]] }")));
1050 MAP("{ [Domain[i,j] -> Range1[i,k]] -> [Domain[i,j] -> Range2[j,k]] }"),
1051 distributeDomain(MAP("{ Domain[i,j] -> [Range1[i,k] -> Range2[j,k]] }")));
1056 "{ [DomainA[i,j] -> RangeA1[i,k]] -> [DomainA[i,j] -> RangeA2[j,k]];"
1057 "[DomainB[i,j] -> RangeB1[i,k]] -> [DomainB[i,j] -> RangeB2[j,k]] }"),
1059 UMAP("{ DomainA[i,j] -> [RangeA1[i,k] -> RangeA2[j,k]];"
1060 "DomainB[i,j] -> [RangeB1[i,k] -> RangeB2[j,k]] }")));
1063 TEST(DeLICM
, lift
) {
1064 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
1068 EXPECT_EQ(UMAP("{ [Factor[] -> Domain[]] -> [Factor[] -> Range[]] }"),
1069 liftDomains(UMAP("{ Domain[] -> Range[] }"), USET("{ Factor[] }")));
1070 EXPECT_EQ(UMAP("{ [Factor[l] -> Domain[i,k]] -> [Factor[l] -> Range[j,k]] }"),
1071 liftDomains(UMAP("{ Domain[i,k] -> Range[j,k] }"),
1072 USET("{ Factor[l] }")));
1074 // Multiple maps in union
1076 UMAP("{ [FactorA[] -> DomainA[]] -> [FactorA[] -> RangeA[]];"
1077 "[FactorB[] -> DomainA[]] -> [FactorB[] -> RangeA[]];"
1078 "[FactorA[] -> DomainB[]] -> [FactorA[] -> RangeB[]];"
1079 "[FactorB[] -> DomainB[]] -> [FactorB[] -> RangeB[]] }"),
1080 liftDomains(UMAP("{ DomainA[] -> RangeA[]; DomainB[] -> RangeB[] }"),
1081 USET("{ FactorA[]; FactorB[] }")));
1084 TEST(DeLICM
, apply
) {
1085 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
1090 UMAP("{ [DomainDomain[] -> NewDomainRange[]] -> Range[] }"),
1091 applyDomainRange(UMAP("{ [DomainDomain[] -> DomainRange[]] -> Range[] }"),
1092 UMAP("{ DomainRange[] -> NewDomainRange[] }")));
1094 UMAP("{ [DomainDomain[i,k] -> NewDomainRange[j,k,l]] -> Range[i,j] }"),
1096 UMAP("{ [DomainDomain[i,k] -> DomainRange[j,k]] -> Range[i,j] }"),
1097 UMAP("{ DomainRange[j,k] -> NewDomainRange[j,k,l] }")));
1099 // Multiple maps in union
1100 EXPECT_EQ(UMAP("{ [DomainDomainA[] -> NewDomainRangeA[]] -> RangeA[];"
1101 "[DomainDomainB[] -> NewDomainRangeB[]] -> RangeB[] }"),
1103 UMAP("{ [DomainDomainA[] -> DomainRangeA[]] -> RangeA[];"
1104 "[DomainDomainB[] -> DomainRangeB[]] -> RangeB[] }"),
1105 UMAP("{ DomainRangeA[] -> NewDomainRangeA[];"
1106 "DomainRangeB[] -> NewDomainRangeB[] }")));
1110 std::unique_ptr
<isl_ctx
, decltype(&isl_ctx_free
)> Ctx(isl_ctx_alloc(),
1113 isl::set TestSet1
{Ctx
.get(), "{ [0] }"};
1114 isl::set TestSet2
{Ctx
.get(), "{ [i] : i > 0 }"};
1117 IslMaxOperationsGuard
MaxOpGuard(Ctx
.get(), 1);
1118 ASSERT_EQ(isl_options_get_on_error(Ctx
.get()), ISL_ON_ERROR_CONTINUE
);
1119 ASSERT_EQ(isl_ctx_get_max_operations(Ctx
.get()), 1ul);
1120 ASSERT_FALSE(MaxOpGuard
.hasQuotaExceeded());
1122 // Intentionally exceed the quota. Each allocation will use at least one
1123 // operation, guaranteed to exceed the max_operations of 1.
1124 isl::id::alloc(Ctx
.get(), "A", nullptr);
1125 isl::id::alloc(Ctx
.get(), "B", nullptr);
1126 ASSERT_TRUE(MaxOpGuard
.hasQuotaExceeded());
1128 // Check returned object after exceeded quota.
1129 isl::set Union
= TestSet1
.unite(TestSet2
);
1130 EXPECT_TRUE(Union
.is_null());
1132 // Check isl::boolean result after exceeded quota.
1133 isl::boolean BoolResult
= TestSet1
.is_empty();
1134 EXPECT_TRUE(BoolResult
.is_error());
1135 EXPECT_FALSE(BoolResult
.is_false());
1136 EXPECT_FALSE(BoolResult
.is_true());
1137 EXPECT_DEATH((void)(bool)BoolResult
,
1138 "IMPLEMENTATION ERROR: Unhandled error state");
1139 EXPECT_DEATH((void)(bool)!BoolResult
,
1140 "IMPLEMENTATION ERROR: Unhandled error state");
1146 "IMPLEMENTATION ERROR: Unhandled error state");
1147 EXPECT_DEATH((void)(BoolResult
== false),
1148 "IMPLEMENTATION ERROR: Unhandled error state");
1149 EXPECT_DEATH((void)(BoolResult
== true),
1150 "IMPLEMENTATION ERROR: Unhandled error state");
1152 // Check isl::stat result after exceeded quota.
1153 isl::stat StatResult
=
1154 TestSet1
.foreach_point([](isl::point
) { return isl::stat::ok(); });
1155 EXPECT_TRUE(StatResult
.is_error());
1156 EXPECT_FALSE(StatResult
.is_ok());
1158 ASSERT_EQ(isl_ctx_last_error(Ctx
.get()), isl_error_quota
);
1159 ASSERT_EQ(isl_options_get_on_error(Ctx
.get()), ISL_ON_ERROR_WARN
);
1160 ASSERT_EQ(isl_ctx_get_max_operations(Ctx
.get()), 0ul);
1162 // Operations must work again after leaving the quota scope.
1164 isl::set Union
= TestSet1
.unite(TestSet2
);
1165 EXPECT_FALSE(Union
.is_null());
1167 isl::boolean BoolResult
= TestSet1
.is_empty();
1168 EXPECT_FALSE(BoolResult
.is_error());
1169 EXPECT_TRUE(BoolResult
.is_false());
1170 EXPECT_FALSE(BoolResult
.is_true());
1171 EXPECT_FALSE(BoolResult
);
1172 EXPECT_TRUE(!BoolResult
);
1174 isl::stat StatResult
=
1175 TestSet1
.foreach_point([](isl::point
) { return isl::stat::ok(); });
1176 EXPECT_FALSE(StatResult
.is_error());
1177 EXPECT_TRUE(StatResult
.is_ok());
1181 } // anonymous namespace