From 52025af1daa5ea6da680220c1c4a8eaf7ca8efe0 Mon Sep 17 00:00:00 2001 From: Philip Pfaffe Date: Fri, 29 Jun 2018 08:17:03 +0000 Subject: [PATCH] Implement an iterator for isl maps, basic_maps, sets, basic_sets Summary: Provide an iterator to simplify iteration over some isl collections. Since these types do not natively support iteration, they have to be converted to an list first by the caller, but can then be used in a ranged for loop: ``` isl::set S; for (auto SubSet : S.get_basic_set_list ()) { // ... } ``` Reviewers: bollu, Meinersbur, grosser, dexonsmith Reviewed By: bollu Subscribers: hfinkel, mgorny, Meinersbur, mehdi_amini, bollu, steven_wu, llvm-commits Differential Revision: https://reviews.llvm.org/D48136 llvm-svn: 335951 --- polly/include/polly/Support/ISLTools.h | 90 ++++++++++++++++++++++++++ polly/unittests/CMakeLists.txt | 1 + polly/unittests/Support/CMakeLists.txt | 3 + polly/unittests/Support/ISLTools.cpp | 27 ++++++++ 4 files changed, 121 insertions(+) create mode 100644 polly/unittests/Support/CMakeLists.txt create mode 100644 polly/unittests/Support/ISLTools.cpp diff --git a/polly/include/polly/Support/ISLTools.h b/polly/include/polly/Support/ISLTools.h index 25da2a43ba53..245c3fcf79db 100644 --- a/polly/include/polly/Support/ISLTools.h +++ b/polly/include/polly/Support/ISLTools.h @@ -16,6 +16,96 @@ #define POLLY_ISLTOOLS_H #include "polly/Support/GICHelper.h" +#include "llvm/ADT/iterator_range.h" + +namespace isl { +inline namespace noexceptions { + +template +struct iterator_base : public llvm::iterator_facade_base< + iterator_base, + std::forward_iterator_tag, ElementT> { + explicit iterator_base(const ListT &List) : List(&List) { + Position = static_cast(this)->list_size(); + } + iterator_base(const ListT &List, int Position) : List(&List), Position(Position) {} + iterator_base &operator=(const iterator_base &R) = default; + + bool operator==(const iterator_base &O) const { + return List == O.List && Position == O.Position; + } + + DerivedT &operator++() { + ++Position; + return *static_cast(this); + } + + DerivedT operator++(int) { + DerivedT Copy{static_cast(this)}; + ++Position; + return Copy; + } + +protected: + const ListT *List; + int Position = 0; +}; + +struct map_iterator : iterator_base { + using BaseT = iterator_base; + using BaseT::BaseT; + isl::map operator*() const { return List->get_map(this->Position); } + int list_size() const { return this->List->n_map(); } +}; + +struct basic_map_iterator + : iterator_base { + using BaseT = + iterator_base; + using BaseT::BaseT; + isl::basic_map operator*() const { + return List->get_basic_map(this->Position); + } + int list_size() const { return this->List->n_basic_map(); } +}; + +struct set_iterator : iterator_base { + using BaseT = iterator_base; + using BaseT::BaseT; + isl::set operator*() const { return List->get_set(this->Position); } + int list_size() const { return this->List->n_set(); } +}; + +struct basic_set_iterator + : iterator_base { + using BaseT = + iterator_base; + using BaseT::BaseT; + isl::basic_set operator*() const { + return List->get_basic_set(this->Position); + } + int list_size() const { return this->List->n_basic_set(); } +}; + +inline map_iterator begin(const isl::map_list &M) { return map_iterator(M, 0); } +inline map_iterator end(const isl::map_list &M) { return map_iterator(M); } +inline set_iterator begin(const isl::set_list &M) { return set_iterator(M, 0); } +inline set_iterator end(const isl::set_list &M) { return set_iterator(M); } +inline basic_map_iterator begin(const isl::basic_map_list &M) { + return basic_map_iterator(M, 0); +} +inline basic_map_iterator end(const isl::basic_map_list &M) { + return basic_map_iterator(M); +} +inline basic_set_iterator begin(const isl::basic_set_list &M) { + return basic_set_iterator(M, 0); +} +inline basic_set_iterator end(const isl::basic_set_list &M) { + return basic_set_iterator(M); +} + +} // namespace noexceptions +} // namespace isl namespace polly { diff --git a/polly/unittests/CMakeLists.txt b/polly/unittests/CMakeLists.txt index cac10df6820d..fac70383de94 100644 --- a/polly/unittests/CMakeLists.txt +++ b/polly/unittests/CMakeLists.txt @@ -24,3 +24,4 @@ add_subdirectory(Flatten) add_subdirectory(DeLICM) add_subdirectory(ScopPassManager) add_subdirectory(ScheduleOptimizer) +add_subdirectory(Support) diff --git a/polly/unittests/Support/CMakeLists.txt b/polly/unittests/Support/CMakeLists.txt new file mode 100644 index 000000000000..3cc52c14f2bb --- /dev/null +++ b/polly/unittests/Support/CMakeLists.txt @@ -0,0 +1,3 @@ +add_polly_unittest(ISLToolsTests + ISLTools.cpp + ) diff --git a/polly/unittests/Support/ISLTools.cpp b/polly/unittests/Support/ISLTools.cpp new file mode 100644 index 000000000000..f33c56c520d2 --- /dev/null +++ b/polly/unittests/Support/ISLTools.cpp @@ -0,0 +1,27 @@ +#include "polly/Support/ISLTools.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace isl { +static bool operator==(const isl::basic_set &A, const isl::basic_set &B) { + return A.is_equal(B); +} +} + +TEST(Support, isl_iterator) { + std::unique_ptr RawCtx(isl_ctx_alloc(), + &isl_ctx_free); + isl::ctx Ctx(RawCtx.get()); + + isl::basic_set A( + Ctx, "{ [x, y] : 0 <= x <= 5 and y >= 0 and x > 0 and 0 < y <= 5 }"); + isl::basic_set B( + Ctx, "{ [x, y] : 0 <= x <= 5 and y >= 0 and x <= 4 and y <= 3 + x }"); + isl::set S = A.unite(B); + + ASSERT_EQ(S.n_basic_set(), 2); + std::vector Sets; + for (auto BS : S.get_basic_set_list()) + Sets.push_back(BS); + EXPECT_THAT(Sets, testing::UnorderedElementsAre(A, B)); +}