[polly] r293340 - [Support] Add general isl tools for DeLICM. NFC.
Tobias Grosser via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 28 00:22:30 PST 2017
On Fri, Jan 27, 2017, at 11:51 PM, Michael Kruse via llvm-commits wrote:
> Author: meinersbur
> Date: Fri Jan 27 16:51:36 2017
> New Revision: 293340
>
> URL: http://llvm.org/viewvc/llvm-project?rev=293340&view=rev
> Log:
> [Support] Add general isl tools for DeLICM. NFC.
>
> Add some generally useful isl tools into a their own new ISLTools.cpp.
> These are the helpers were extracted from and will be use by the DeLICM
> algorithm (https://reviews.llvm.org/D24716).
Very nice. I especially like the extensive testing.
Also, the code would certainly benefit our C++ bindings.
Best,
Tobias
>
> Suggested-by: Tobias Grosser <tobias at grosser.es>
>
> Added:
> polly/trunk/include/polly/Support/ISLTools.h
> polly/trunk/lib/Support/ISLTools.cpp
> Modified:
> polly/trunk/lib/CMakeLists.txt
> polly/trunk/unittests/Isl/IslTest.cpp
>
> Added: polly/trunk/include/polly/Support/ISLTools.h
> URL:
> http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/ISLTools.h?rev=293340&view=auto
> ==============================================================================
> --- polly/trunk/include/polly/Support/ISLTools.h (added)
> +++ polly/trunk/include/polly/Support/ISLTools.h Fri Jan 27 16:51:36 2017
> @@ -0,0 +1,180 @@
> +//===------ ISLTools.h ------------------------------------------*- C++
> -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// Tools, utilities, helpers and extensions useful in conjunction with
> the
> +// Integer Set Library (isl).
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef POLLY_ISLTOOLS_H
> +#define POLLY_ISLTOOLS_H
> +
> +#include "polly/Support/GICHelper.h"
> +
> +namespace polly {
> +
> +/// Return the range elements that are lexicographically smaller.
> +///
> +/// @param Map { Space[] -> Scatter[] }
> +/// @param Strict True for strictly lexicographically smaller elements
> (exclude
> +/// same timepoints from the result).
> +///
> +/// @return { Space[] -> Scatter[] }
> +/// A map to all timepoints that happen before the timepoints
> the input
> +/// mapped to.
> +IslPtr<isl_map> beforeScatter(IslPtr<isl_map> Map, bool Strict);
> +
> +/// Piecewise beforeScatter(IslPtr<isl_map>,bool).
> +IslPtr<isl_union_map> beforeScatter(IslPtr<isl_union_map> UMap, bool
> Strict);
> +
> +/// Return the range elements that are lexicographically larger.
> +///
> +/// @param Map { Space[] -> Scatter[] }
> +/// @param Strict True for strictly lexicographically larger elements
> (exclude
> +/// same timepoints from the result).
> +///
> +/// @return { Space[] -> Scatter[] }
> +/// A map to all timepoints that happen after the timepoints the
> input
> +/// map originally mapped to.
> +IslPtr<isl_map> afterScatter(IslPtr<isl_map> Map, bool Strict);
> +
> +/// Piecewise afterScatter(IslPtr<isl_map>,bool).
> +IslPtr<isl_union_map> afterScatter(NonowningIslPtr<isl_union_map> UMap,
> + bool Strict);
> +
> +/// Construct a range of timepoints between two timepoints.
> +///
> +/// Example:
> +/// From := { A[] -> [0]; B[] -> [0] }
> +/// To := { B[] -> [10]; C[] -> [20] }
> +///
> +/// Result:
> +/// { B[] -> [i] : 0 < i < 10 }
> +///
> +/// Note that A[] and C[] are not in the result because they do not have
> a start
> +/// or end timepoint. If a start (or end) timepoint is not unique, the
> first
> +/// (respectively last) is chosen.
> +///
> +/// @param From { Space[] -> Scatter[] }
> +/// Map to start timepoints.
> +/// @param To { Space[] -> Scatter[] }
> +/// Map to end timepoints.
> +/// @param InclFrom Whether to include the start timepoints in the
> result. In
> +/// the example, this would add { B[] -> [0] }
> +/// @param InclTo Whether to include the end timepoints in the result.
> In this
> +/// example, this would add { B[] -> [10] }
> +///
> +/// @return { Space[] -> Scatter[] }
> +/// A map for each domain element of timepoints between two
> extreme
> +/// points, or nullptr if @p From or @p To is nullptr, or the
> isl max
> +/// operations is exceeded.
> +IslPtr<isl_map> betweenScatter(IslPtr<isl_map> From, IslPtr<isl_map> To,
> + bool InclFrom, bool InclTo);
> +
> +/// Piecewise betweenScatter(IslPtr<isl_map>,IslPtr<isl_map>,bool,bool).
> +IslPtr<isl_union_map> betweenScatter(IslPtr<isl_union_map> From,
> + IslPtr<isl_union_map> To, bool
> InclFrom,
> + bool InclTo);
> +
> +/// If by construction a union map is known to contain only a single
> map, return
> +/// it.
> +///
> +/// This function combines isl_map_from_union_map() and
> +/// isl_union_map_extract_map(). isl_map_from_union_map() fails if the
> map is
> +/// empty because it does not know which space it would be in.
> +/// isl_union_map_extract_map() on the other hand does not check whether
> there
> +/// is (at most) one isl_map in the union, i.e. how it has been
> constructed is
> +/// probably wrong.
> +IslPtr<isl_map> singleton(IslPtr<isl_union_map> UMap,
> + IslPtr<isl_space> ExpectedSpace);
> +
> +/// If by construction an isl_union_set is known to contain only a
> single
> +/// isl_set, return it.
> +///
> +/// This function combines isl_set_from_union_set() and
> +/// isl_union_set_extract_set(). isl_map_from_union_set() fails if the
> set is
> +/// empty because it does not know which space it would be in.
> +/// isl_union_set_extract_set() on the other hand does not check whether
> there
> +/// is (at most) one isl_set in the union, i.e. how it has been
> constructed is
> +/// probably wrong.
> +IslPtr<isl_set> singleton(IslPtr<isl_union_set> USet,
> + IslPtr<isl_space> ExpectedSpace);
> +
> +/// Determine how many dimensions the scatter space of @p Schedule has.
> +///
> +/// The schedule must not be empty and have equal number of dimensions
> of any
> +/// subspace it contains.
> +///
> +/// The implementation currently returns the maximum number of
> dimensions it
> +/// encounters, if different, and 0 if none is encountered. However,
> most other
> +/// code will most likely fail if one of these happen.
> +unsigned getNumScatterDims(NonowningIslPtr<isl_union_map> Schedule);
> +
> +/// Return the scatter space of a @p Schedule.
> +///
> +/// This is basically the range space of the schedule map, but harder to
> +/// determine because it is an isl_union_map.
> +IslPtr<isl_space> getScatterSpace(NonowningIslPtr<isl_union_map>
> Schedule);
> +
> +/// Construct an identity map for the given domain values.
> +///
> +/// There is no type resembling isl_union_space, hence we have to pass
> an
> +/// isl_union_set as the map's domain and range space.
> +///
> +/// @param USet { Space[] }
> +/// The returned map's domain and range.
> +/// @param RestrictDomain If true, the returned map only maps elements
> contained
> +/// in @p USet and no other. If false, it returns
> an
> +/// overapproximation with the identity maps of
> any space
> +/// in @p USet, not just the elements in it.
> +///
> +/// @return { Space[] -> Space[] }
> +/// A map that maps each value of @p USet to itself.
> +IslPtr<isl_union_map> makeIdentityMap(NonowningIslPtr<isl_union_set>
> USet,
> + bool RestrictDomain);
> +
> +/// Reverse the nested map tuple in @p Map's domain.
> +///
> +/// @param Map { [Space1[] -> Space2[]] -> Space3[] }
> +///
> +/// @return { [Space2[] -> Space1[]] -> Space3[] }
> +IslPtr<isl_map> reverseDomain(IslPtr<isl_map> Map);
> +
> +/// Piecewise reverseDomain(IslPtr<isl_map>).
> +IslPtr<isl_union_map> reverseDomain(NonowningIslPtr<isl_union_map>
> UMap);
> +
> +/// Add a constant to one dimension of a set.
> +///
> +/// @param Map The set to shift a dimension in.
> +/// @param Pos The dimension to shift. If negative, the dimensions
> are
> +/// counted from the end instead from the beginning. E.g.
> -1 is
> +/// the last dimension in the tuple.
> +/// @param Amount The offset to add to the specified dimension.
> +///
> +/// @return The modified set.
> +IslPtr<isl_set> shiftDim(IslPtr<isl_set> Set, int Pos, int Amount);
> +
> +/// Piecewise shiftDim(IslPtr<isl_set>,int,int).
> +IslPtr<isl_union_set> shiftDim(IslPtr<isl_union_set> USet, int Pos, int
> Amount);
> +
> +/// Simplify a set inplace.
> +void simplify(IslPtr<isl_set> &Set);
> +
> +/// Simplify a union set inplace.
> +void simplify(IslPtr<isl_union_set> &USet);
> +
> +/// Simplify a map inplace.
> +void simplify(IslPtr<isl_map> &Map);
> +
> +/// Simplify a union map inplace.
> +void simplify(IslPtr<isl_union_map> &UMap);
> +
> +} // namespace polly
> +
> +#endif /* POLLY_ISLTOOLS_H */
>
> Modified: polly/trunk/lib/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CMakeLists.txt?rev=293340&r1=293339&r2=293340&view=diff
> ==============================================================================
> --- polly/trunk/lib/CMakeLists.txt (original)
> +++ polly/trunk/lib/CMakeLists.txt Fri Jan 27 16:51:36 2017
> @@ -50,6 +50,7 @@ add_polly_library(Polly
> Support/RegisterPasses.cpp
> Support/ScopHelper.cpp
> Support/ScopLocation.cpp
> + Support/ISLTools.cpp
> ${POLLY_JSON_FILES}
> Transform/Canonicalization.cpp
> Transform/CodePreparation.cpp
>
> Added: polly/trunk/lib/Support/ISLTools.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/ISLTools.cpp?rev=293340&view=auto
> ==============================================================================
> --- polly/trunk/lib/Support/ISLTools.cpp (added)
> +++ polly/trunk/lib/Support/ISLTools.cpp Fri Jan 27 16:51:36 2017
> @@ -0,0 +1,264 @@
> +//===------ ISLTools.cpp ----------------------------------------*- C++
> -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// Tools, utilities, helpers and extensions useful in conjunction with
> the
> +// Integer Set Library (isl).
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "polly/Support/ISLTools.h"
> +
> +using namespace polly;
> +
> +namespace {
> +/// Create a map that shifts one dimension by an offset.
> +///
> +/// Example:
> +/// makeShiftDimAff({ [i0, i1] -> [o0, o1] }, 1, -2)
> +/// = { [i0, i1] -> [i0, i1 - 1] }
> +///
> +/// @param Space The map space of the result. Must have equal number of
> in- and
> +/// out-dimensions.
> +/// @param Pos Position to shift.
> +/// @param Amount Value added to the shifted dimension.
> +///
> +/// @return An isl_multi_aff for the map with this shifted dimension.
> +IslPtr<isl_multi_aff> makeShiftDimAff(IslPtr<isl_space> Space, int Pos,
> + int Amount) {
> + auto Identity = give(isl_multi_aff_identity(Space.take()));
> + if (Amount == 0)
> + return Identity;
> + auto ShiftAff = give(isl_multi_aff_get_aff(Identity.keep(), Pos));
> + ShiftAff = give(isl_aff_set_constant_si(ShiftAff.take(), Amount));
> + return give(isl_multi_aff_set_aff(Identity.take(), Pos,
> ShiftAff.take()));
> +}
> +
> +/// Construct a map that swaps two nested tuples.
> +///
> +/// @param FromSpace1 { Space1[] }
> +/// @param FromSpace2 { Space2[] }
> +///
> +/// @return { [Space1[] -> Space2[]] -> [Space2[] -> Space1[]] }
> +IslPtr<isl_basic_map> makeTupleSwapBasicMap(IslPtr<isl_space>
> FromSpace1,
> + IslPtr<isl_space>
> FromSpace2) {
> + assert(isl_space_is_set(FromSpace1.keep()) != isl_bool_false);
> + assert(isl_space_is_set(FromSpace2.keep()) != isl_bool_false);
> +
> + auto Dims1 = isl_space_dim(FromSpace1.keep(), isl_dim_set);
> + auto Dims2 = isl_space_dim(FromSpace2.keep(), isl_dim_set);
> + auto FromSpace =
> give(isl_space_wrap(isl_space_map_from_domain_and_range(
> + FromSpace1.copy(), FromSpace2.copy())));
> + auto ToSpace =
> give(isl_space_wrap(isl_space_map_from_domain_and_range(
> + FromSpace2.take(), FromSpace1.take())));
> + auto MapSpace = give(
> + isl_space_map_from_domain_and_range(FromSpace.take(),
> ToSpace.take()));
> +
> + auto Result = give(isl_basic_map_universe(MapSpace.take()));
> + for (auto i = Dims1 - Dims1; i < Dims1; i += 1) {
> + Result = give(isl_basic_map_equate(Result.take(), isl_dim_in, i,
> + isl_dim_out, Dims2 + i));
> + }
> + for (auto i = Dims2 - Dims2; i < Dims2; i += 1) {
> + Result = give(isl_basic_map_equate(Result.take(), isl_dim_in, Dims1
> + i,
> + isl_dim_out, i));
> + }
> +
> + return Result;
> +}
> +
> +/// Like makeTupleSwapBasicMap(IslPtr<isl_space>,IslPtr<isl_space>), but
> returns
> +/// an isl_map.
> +IslPtr<isl_map> makeTupleSwapMap(IslPtr<isl_space> FromSpace1,
> + IslPtr<isl_space> FromSpace2) {
> + auto BMapResult =
> + makeTupleSwapBasicMap(std::move(FromSpace1),
> std::move(FromSpace2));
> + return give(isl_map_from_basic_map(BMapResult.take()));
> +}
> +} // anonymous namespace
> +
> +IslPtr<isl_map> polly::beforeScatter(IslPtr<isl_map> Map, bool Strict) {
> + auto RangeSpace =
> give(isl_space_range(isl_map_get_space(Map.keep())));
> + auto ScatterRel = give(Strict ? isl_map_lex_gt(RangeSpace.take())
> + : isl_map_lex_ge(RangeSpace.take()));
> + return give(isl_map_apply_range(Map.take(), ScatterRel.take()));
> +}
> +
> +IslPtr<isl_union_map> polly::beforeScatter(IslPtr<isl_union_map> UMap,
> + bool Strict) {
> + auto Result =
> give(isl_union_map_empty(isl_union_map_get_space(UMap.keep())));
> + foreachElt(UMap, [=, &Result](IslPtr<isl_map> Map) {
> + auto After = beforeScatter(Map, Strict);
> + Result = give(isl_union_map_add_map(Result.take(), After.take()));
> + });
> + return Result;
> +}
> +
> +IslPtr<isl_map> polly::afterScatter(IslPtr<isl_map> Map, bool Strict) {
> + auto RangeSpace =
> give(isl_space_range(isl_map_get_space(Map.keep())));
> + auto ScatterRel = give(Strict ? isl_map_lex_lt(RangeSpace.take())
> + : isl_map_lex_le(RangeSpace.take()));
> + return give(isl_map_apply_range(Map.take(), ScatterRel.take()));
> +}
> +
> +IslPtr<isl_union_map> polly::afterScatter(NonowningIslPtr<isl_union_map>
> UMap,
> + bool Strict) {
> + auto Result =
> give(isl_union_map_empty(isl_union_map_get_space(UMap.keep())));
> + foreachElt(UMap, [=, &Result](IslPtr<isl_map> Map) {
> + auto After = afterScatter(Map, Strict);
> + Result = give(isl_union_map_add_map(Result.take(), After.take()));
> + });
> + return Result;
> +}
> +
> +IslPtr<isl_map> polly::betweenScatter(IslPtr<isl_map> From,
> IslPtr<isl_map> To,
> + bool InclFrom, bool InclTo) {
> + auto AfterFrom = afterScatter(From, !InclFrom);
> + auto BeforeTo = beforeScatter(To, !InclTo);
> +
> + return give(isl_map_intersect(AfterFrom.take(), BeforeTo.take()));
> +}
> +
> +IslPtr<isl_union_map> polly::betweenScatter(IslPtr<isl_union_map> From,
> + IslPtr<isl_union_map> To,
> + bool InclFrom, bool InclTo)
> {
> + auto AfterFrom = afterScatter(From, !InclFrom);
> + auto BeforeTo = beforeScatter(To, !InclTo);
> +
> + return give(isl_union_map_intersect(AfterFrom.take(),
> BeforeTo.take()));
> +}
> +
> +IslPtr<isl_map> polly::singleton(IslPtr<isl_union_map> UMap,
> + IslPtr<isl_space> ExpectedSpace) {
> + if (!UMap)
> + return nullptr;
> +
> + if (isl_union_map_n_map(UMap.keep()) == 0)
> + return give(isl_map_empty(ExpectedSpace.take()));
> +
> + auto Result = give(isl_map_from_union_map(UMap.take()));
> + assert(
> + !Result ||
> +
> isl_space_has_equal_tuples(give(isl_map_get_space(Result.keep())).keep(),
> + ExpectedSpace.keep()) ==
> isl_bool_true);
> + return Result;
> +}
> +
> +IslPtr<isl_set> polly::singleton(IslPtr<isl_union_set> USet,
> + IslPtr<isl_space> ExpectedSpace) {
> + if (!USet)
> + return nullptr;
> +
> + if (isl_union_set_n_set(USet.keep()) == 0)
> + return give(isl_set_empty(ExpectedSpace.copy()));
> +
> + auto Result = give(isl_set_from_union_set(USet.take()));
> + assert(
> + !Result ||
> +
> isl_space_has_equal_tuples(give(isl_set_get_space(Result.keep())).keep(),
> + ExpectedSpace.keep()) ==
> isl_bool_true);
> + return Result;
> +}
> +
> +unsigned polly::getNumScatterDims(NonowningIslPtr<isl_union_map>
> Schedule) {
> + unsigned Dims = 0;
> + foreachElt(Schedule, [&Dims](IslPtr<isl_map> Map) {
> + Dims = std::max(Dims, isl_map_dim(Map.keep(), isl_dim_out));
> + });
> + return Dims;
> +}
> +
> +IslPtr<isl_space>
> +polly::getScatterSpace(NonowningIslPtr<isl_union_map> Schedule) {
> + if (!Schedule)
> + return nullptr;
> + auto Dims = getNumScatterDims(Schedule);
> + auto ScatterSpace =
> +
> give(isl_space_set_from_params(isl_union_map_get_space(Schedule.keep())));
> + return give(isl_space_add_dims(ScatterSpace.take(), isl_dim_set,
> Dims));
> +}
> +
> +IslPtr<isl_union_map>
> +polly::makeIdentityMap(NonowningIslPtr<isl_union_set> USet,
> + bool RestrictDomain) {
> + auto Result =
> give(isl_union_map_empty(isl_union_set_get_space(USet.keep())));
> + foreachElt(USet, [=, &Result](IslPtr<isl_set> Set) {
> + auto IdentityMap = give(isl_map_identity(
> + isl_space_map_from_set(isl_set_get_space(Set.keep()))));
> + if (RestrictDomain)
> + IdentityMap =
> + give(isl_map_intersect_domain(IdentityMap.take(),
> Set.take()));
> + Result = give(isl_union_map_add_map(Result.take(),
> IdentityMap.take()));
> + });
> + return Result;
> +}
> +
> +IslPtr<isl_map> polly::reverseDomain(IslPtr<isl_map> Map) {
> + auto DomSpace =
> +
> give(isl_space_unwrap(isl_space_domain(isl_map_get_space(Map.keep()))));
> + auto Space1 = give(isl_space_domain(DomSpace.copy()));
> + auto Space2 = give(isl_space_range(DomSpace.take()));
> + auto Swap = makeTupleSwapMap(std::move(Space1), std::move(Space2));
> + return give(isl_map_apply_domain(Map.take(), Swap.take()));
> +}
> +
> +IslPtr<isl_union_map>
> +polly::reverseDomain(NonowningIslPtr<isl_union_map> UMap) {
> + auto Result =
> give(isl_union_map_empty(isl_union_map_get_space(UMap.keep())));
> + foreachElt(UMap, [=, &Result](IslPtr<isl_map> Map) {
> + auto Reversed = reverseDomain(std::move(Map));
> + Result = give(isl_union_map_add_map(Result.take(),
> Reversed.take()));
> + });
> + return Result;
> +}
> +
> +IslPtr<isl_set> polly::shiftDim(IslPtr<isl_set> Set, int Pos, int
> Amount) {
> + int NumDims = isl_set_dim(Set.keep(), isl_dim_set);
> + if (Pos < 0)
> + Pos = NumDims + Pos;
> + assert(Pos < NumDims && "Dimension index must be in range");
> + auto Space = give(isl_set_get_space(Set.keep()));
> + Space = give(isl_space_map_from_domain_and_range(Space.copy(),
> Space.copy()));
> + auto Translator = makeShiftDimAff(std::move(Space), Pos, Amount);
> + auto TranslatorMap = give(isl_map_from_multi_aff(Translator.take()));
> + return give(isl_set_apply(Set.take(), TranslatorMap.take()));
> +}
> +
> +IslPtr<isl_union_set> polly::shiftDim(IslPtr<isl_union_set> USet, int
> Pos,
> + int Amount) {
> + auto Result =
> give(isl_union_set_empty(isl_union_set_get_space(USet.keep())));
> + foreachElt(USet, [=, &Result](IslPtr<isl_set> Set) {
> + auto Shifted = shiftDim(Set, Pos, Amount);
> + Result = give(isl_union_set_add_set(Result.take(), Shifted.take()));
> + });
> + return Result;
> +}
> +
> +void polly::simplify(IslPtr<isl_set> &Set) {
> + Set = give(isl_set_compute_divs(Set.take()));
> + Set = give(isl_set_detect_equalities(Set.take()));
> + Set = give(isl_set_coalesce(Set.take()));
> +}
> +
> +void polly::simplify(IslPtr<isl_union_set> &USet) {
> + USet = give(isl_union_set_compute_divs(USet.take()));
> + USet = give(isl_union_set_detect_equalities(USet.take()));
> + USet = give(isl_union_set_coalesce(USet.take()));
> +}
> +
> +void polly::simplify(IslPtr<isl_map> &Map) {
> + Map = give(isl_map_compute_divs(Map.take()));
> + Map = give(isl_map_detect_equalities(Map.take()));
> + Map = give(isl_map_coalesce(Map.take()));
> +}
> +
> +void polly::simplify(IslPtr<isl_union_map> &UMap) {
> + UMap = give(isl_union_map_compute_divs(UMap.take()));
> + UMap = give(isl_union_map_detect_equalities(UMap.take()));
> + UMap = give(isl_union_map_coalesce(UMap.take()));
> +}
>
> Modified: polly/trunk/unittests/Isl/IslTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/polly/trunk/unittests/Isl/IslTest.cpp?rev=293340&r1=293339&r2=293340&view=diff
> ==============================================================================
> --- polly/trunk/unittests/Isl/IslTest.cpp (original)
> +++ polly/trunk/unittests/Isl/IslTest.cpp Fri Jan 27 16:51:36 2017
> @@ -8,12 +8,71 @@
> //===----------------------------------------------------------------------===//
>
> #include "polly/Support/GICHelper.h"
> +#include "polly/Support/ISLTools.h"
> #include "gtest/gtest.h"
> +#include "isl/stream.h"
> #include "isl/val.h"
>
> using namespace llvm;
> using namespace polly;
>
> +static IslPtr<isl_space> parseSpace(isl_ctx *Ctx, const char *Str) {
> + isl_stream *Stream = isl_stream_new_str(Ctx, Str);
> + auto Obj = isl_stream_read_obj(Stream);
> +
> + IslPtr<isl_space> Result;
> + if (Obj.type == isl_obj_set)
> + Result = give(isl_set_get_space(static_cast<isl_set *>(Obj.v)));
> + else if (Obj.type == isl_obj_map)
> + Result = give(isl_map_get_space(static_cast<isl_map *>(Obj.v)));
> +
> + isl_stream_free(Stream);
> + if (Obj.type)
> + Obj.type->free(Obj.v);
> + return Result;
> +}
> +
> +#define SPACE(Str) parseSpace(Ctx.get(), Str)
> +
> +#define SET(Str) give(isl_set_read_from_str(Ctx.get(), Str))
> +#define MAP(Str) give(isl_map_read_from_str(Ctx.get(), Str))
> +
> +#define USET(Str) give(isl_union_set_read_from_str(Ctx.get(), Str))
> +#define UMAP(Str) give(isl_union_map_read_from_str(Ctx.get(), Str))
> +
> +static bool operator==(const IslPtr<isl_space> &LHS,
> + const IslPtr<isl_space> &RHS) {
> + auto IsEqual = isl_space_is_equal(LHS.keep(), RHS.keep());
> + EXPECT_NE(isl_bool_error, IsEqual);
> + return IsEqual;
> +}
> +
> +static bool operator==(const IslPtr<isl_set> &LHS, const IslPtr<isl_set>
> &RHS) {
> + auto IsEqual = isl_set_is_equal(LHS.keep(), RHS.keep());
> + EXPECT_NE(isl_bool_error, IsEqual);
> + return IsEqual;
> +}
> +
> +static bool operator==(const IslPtr<isl_map> &LHS, const IslPtr<isl_map>
> &RHS) {
> + auto IsEqual = isl_map_is_equal(LHS.keep(), RHS.keep());
> + EXPECT_NE(isl_bool_error, IsEqual);
> + return IsEqual;
> +}
> +
> +static bool operator==(const IslPtr<isl_union_set> &LHS,
> + const IslPtr<isl_union_set> &RHS) {
> + auto IsEqual = isl_union_set_is_equal(LHS.keep(), RHS.keep());
> + EXPECT_NE(isl_bool_error, IsEqual);
> + return IsEqual;
> +}
> +
> +static bool operator==(const IslPtr<isl_union_map> &LHS,
> + const IslPtr<isl_union_map> &RHS) {
> + auto IsEqual = isl_union_map_is_equal(LHS.keep(), RHS.keep());
> + EXPECT_NE(isl_bool_error, IsEqual);
> + return IsEqual;
> +}
> +
> namespace {
>
> TEST(Isl, APIntToIslVal) {
> @@ -342,4 +401,241 @@ TEST(Isl, Foreach) {
> }
> }
>
> +TEST(ISLTools, beforeScatter) {
> + std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
> + &isl_ctx_free);
> +
> + // Basic usage with isl_map
> + EXPECT_EQ(MAP("{ [] -> [i] : i <= 0 }"),
> + beforeScatter(MAP("{ [] -> [0] }"), false));
> + EXPECT_EQ(MAP("{ [] -> [i] : i < 0 }"),
> + beforeScatter(MAP("{ [] -> [0] }"), true));
> +
> + // Basic usage with isl_union_map
> + EXPECT_EQ(UMAP("{ A[] -> [i] : i <= 0; B[] -> [i] : i <= 0 }"),
> + beforeScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"), false));
> + EXPECT_EQ(UMAP("{ A[] -> [i] : i < 0; B[] -> [i] : i < 0 }"),
> + beforeScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"), true));
> +
> + // More than one dimension
> + EXPECT_EQ(UMAP("{ [] -> [i, j] : i < 0; [] -> [i, j] : i = 0 and j <=
> 0 }"),
> + beforeScatter(UMAP("{ [] -> [0, 0] }"), false));
> + EXPECT_EQ(UMAP("{ [] -> [i, j] : i < 0; [] -> [i, j] : i = 0 and j <
> 0 }"),
> + beforeScatter(UMAP("{ [] -> [0, 0] }"), true));
> +
> + // Functional
> + EXPECT_EQ(UMAP("{ [i] -> [j] : j <= i }"),
> + beforeScatter(UMAP("{ [i] -> [i] }"), false));
> + EXPECT_EQ(UMAP("{ [i] -> [j] : j < i }"),
> + beforeScatter(UMAP("{ [i] -> [i] }"), true));
> +
> + // Parametrized
> + EXPECT_EQ(UMAP("[i] -> { [] -> [j] : j <= i }"),
> + beforeScatter(UMAP("[i] -> { [] -> [i] }"), false));
> + EXPECT_EQ(UMAP("[i] -> { [] -> [j] : j < i }"),
> + beforeScatter(UMAP("[i] -> { [] -> [i] }"), true));
> +
> + // More than one range
> + EXPECT_EQ(UMAP("{ [] -> [i] : i <= 10 }"),
> + beforeScatter(UMAP("{ [] -> [0]; [] -> [10] }"), false));
> + EXPECT_EQ(UMAP("{ [] -> [i] : i < 10 }"),
> + beforeScatter(UMAP("{ [] -> [0]; [] -> [10] }"), true));
> +
> + // Edge case: empty
> + EXPECT_EQ(UMAP("{ [] -> [i] : 1 = 0 }"),
> + beforeScatter(UMAP("{ [] -> [i] : 1 = 0 }"), false));
> + EXPECT_EQ(UMAP("{ [] -> [i] : 1 = 0 }"),
> + beforeScatter(UMAP("{ [] -> [i] : 1 = 0 }"), true));
> +}
> +
> +TEST(ISLTools, afterScatter) {
> + std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
> + &isl_ctx_free);
> +
> + // Basic usage with isl_map
> + EXPECT_EQ(MAP("{ [] -> [i] : i >= 0 }"),
> + afterScatter(MAP("{ [] -> [0] }"), false));
> + EXPECT_EQ(MAP("{ [] -> [i] : i > 0 }"),
> + afterScatter(MAP("{ [] -> [0] }"), true));
> +
> + // Basic usage with isl_union_map
> + EXPECT_EQ(UMAP("{ A[] -> [i] : i >= 0; B[] -> [i] : i >= 0 }"),
> + afterScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"), false));
> + EXPECT_EQ(UMAP("{ A[] -> [i] : i > 0; B[] -> [i] : i > 0 }"),
> + afterScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"), true));
> +
> + // More than one dimension
> + EXPECT_EQ(UMAP("{ [] -> [i, j] : i > 0; [] -> [i, j] : i = 0 and j >=
> 0 }"),
> + afterScatter(UMAP("{ [] -> [0, 0] }"), false));
> + EXPECT_EQ(UMAP("{ [] -> [i, j] : i > 0; [] -> [i, j] : i = 0 and j >
> 0 }"),
> + afterScatter(UMAP("{ [] -> [0, 0] }"), true));
> +
> + // Functional
> + EXPECT_EQ(UMAP("{ [i] -> [j] : j >= i }"),
> + afterScatter(UMAP("{ [i] -> [i] }"), false));
> + EXPECT_EQ(UMAP("{ [i] -> [j] : j > i }"),
> + afterScatter(UMAP("{ [i] -> [i] }"), true));
> +
> + // Parametrized
> + EXPECT_EQ(UMAP("[i] -> { [] -> [j] : j >= i }"),
> + afterScatter(UMAP("[i] -> { [] -> [i] }"), false));
> + EXPECT_EQ(UMAP("[i] -> { [] -> [j] : j > i }"),
> + afterScatter(UMAP("[i] -> { [] -> [i] }"), true));
> +
> + // More than one range
> + EXPECT_EQ(UMAP("{ [] -> [i] : i >= 0 }"),
> + afterScatter(UMAP("{ [] -> [0]; [] -> [10] }"), false));
> + EXPECT_EQ(UMAP("{ [] -> [i] : i > 0 }"),
> + afterScatter(UMAP("{ [] -> [0]; [] -> [10] }"), true));
> +
> + // Edge case: empty
> + EXPECT_EQ(UMAP("{ }"), afterScatter(UMAP("{ }"), false));
> + EXPECT_EQ(UMAP("{ }"), afterScatter(UMAP("{ }"), true));
> +}
> +
> +TEST(ISLTools, betweenScatter) {
> + std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
> + &isl_ctx_free);
> +
> + // Basic usage with isl_map
> + EXPECT_EQ(MAP("{ [] -> [i] : 0 < i < 10 }"),
> + betweenScatter(MAP("{ [] -> [0] }"), MAP("{ [] -> [10] }"),
> false,
> + false));
> + EXPECT_EQ(
> + MAP("{ [] -> [i] : 0 <= i < 10 }"),
> + betweenScatter(MAP("{ [] -> [0] }"), MAP("{ [] -> [10] }"), true,
> false));
> + EXPECT_EQ(
> + MAP("{ [] -> [i] : 0 < i <= 10 }"),
> + betweenScatter(MAP("{ [] -> [0] }"), MAP("{ [] -> [10] }"), false,
> true));
> + EXPECT_EQ(
> + MAP("{ [] -> [i] : 0 <= i <= 10 }"),
> + betweenScatter(MAP("{ [] -> [0] }"), MAP("{ [] -> [10] }"), true,
> true));
> +
> + // Basic usage with isl_union_map
> + EXPECT_EQ(UMAP("{ A[] -> [i] : 0 < i < 10; B[] -> [i] : 0 < i < 10
> }"),
> + betweenScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"),
> + UMAP("{ A[] -> [10]; B[] -> [10] }"), false,
> false));
> + EXPECT_EQ(UMAP("{ A[] -> [i] : 0 <= i < 10; B[] -> [i] : 0 <= i < 10
> }"),
> + betweenScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"),
> + UMAP("{ A[] -> [10]; B[] -> [10] }"), true,
> false));
> + EXPECT_EQ(UMAP("{ A[] -> [i] : 0 < i <= 10; B[] -> [i] : 0 < i <= 10
> }"),
> + betweenScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"),
> + UMAP("{ A[] -> [10]; B[] -> [10] }"), false,
> true));
> + EXPECT_EQ(UMAP("{ A[] -> [i] : 0 <= i <= 10; B[] -> [i] : 0 <= i <= 10
> }"),
> + betweenScatter(UMAP("{ A[] -> [0]; B[] -> [0] }"),
> + UMAP("{ A[] -> [10]; B[] -> [10] }"), true,
> true));
> +}
> +
> +TEST(ISLTools, singleton) {
> + std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
> + &isl_ctx_free);
> +
> + // No element found
> + EXPECT_EQ(SET("{ [] : 1 = 0 }"), singleton(USET("{ }"), SPACE("{ []
> }")));
> + EXPECT_EQ(MAP("{ [] -> [] : 1 = 0 }"),
> + singleton(UMAP("{ }"), SPACE("{ [] -> [] }")));
> +
> + // One element found
> + EXPECT_EQ(SET("{ [] }"), singleton(USET("{ [] }"), SPACE("{ [] }")));
> + EXPECT_EQ(MAP("{ [] -> [] }"),
> + singleton(UMAP("{ [] -> [] }"), SPACE("{ [] -> [] }")));
> +
> + // Many elements found
> + EXPECT_EQ(SET("{ [i] : 0 <= i < 10 }"),
> + singleton(USET("{ [i] : 0 <= i < 10 }"), SPACE("{ [i] }")));
> + EXPECT_EQ(
> + MAP("{ [i] -> [i] : 0 <= i < 10 }"),
> + singleton(UMAP("{ [i] -> [i] : 0 <= i < 10 }"), SPACE("{ [i] ->
> [j] }")));
> +
> + // Different parameters
> + EXPECT_EQ(SET("[i] -> { [i] }"),
> + singleton(USET("[i] -> { [i] }"), SPACE("{ [i] }")));
> + EXPECT_EQ(MAP("[i] -> { [i] -> [i] }"),
> + singleton(UMAP("[i] -> { [i] -> [i] }"), SPACE("{ [i] -> [j]
> }")));
> +}
> +
> +TEST(ISLTools, getNumScatterDims) {
> + std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
> + &isl_ctx_free);
> +
> + // Basic usage
> + EXPECT_EQ(0u, getNumScatterDims(UMAP("{ [] -> [] }")));
> + EXPECT_EQ(1u, getNumScatterDims(UMAP("{ [] -> [i] }")));
> + EXPECT_EQ(2u, getNumScatterDims(UMAP("{ [] -> [i,j] }")));
> + EXPECT_EQ(3u, getNumScatterDims(UMAP("{ [] -> [i,j,k] }")));
> +
> + // Different scatter spaces
> + EXPECT_EQ(0u, getNumScatterDims(UMAP("{ A[] -> []; [] -> []}")));
> + EXPECT_EQ(1u, getNumScatterDims(UMAP("{ A[] -> []; [] -> [i] }")));
> + EXPECT_EQ(2u, getNumScatterDims(UMAP("{ A[] -> [i]; [] -> [i,j] }")));
> + EXPECT_EQ(3u, getNumScatterDims(UMAP("{ A[] -> [i]; [] -> [i,j,k]
> }")));
> +}
> +
> +TEST(ISLTools, getScatterSpace) {
> + std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
> + &isl_ctx_free);
> +
> + // Basic usage
> + EXPECT_EQ(SPACE("{ [] }"), getScatterSpace(UMAP("{ [] -> [] }")));
> + EXPECT_EQ(SPACE("{ [i] }"), getScatterSpace(UMAP("{ [] -> [i] }")));
> + EXPECT_EQ(SPACE("{ [i,j] }"), getScatterSpace(UMAP("{ [] -> [i,j]
> }")));
> + EXPECT_EQ(SPACE("{ [i,j,k] }"), getScatterSpace(UMAP("{ [] -> [i,j,k]
> }")));
> +
> + // Different scatter spaces
> + EXPECT_EQ(SPACE("{ [] }"), getScatterSpace(UMAP("{ A[] -> []; [] -> []
> }")));
> + EXPECT_EQ(SPACE("{ [i] }"),
> + getScatterSpace(UMAP("{ A[] -> []; [] -> [i] }")));
> + EXPECT_EQ(SPACE("{ [i,j] }"),
> + getScatterSpace(UMAP("{ A[] -> [i]; [] -> [i,j] }")));
> + EXPECT_EQ(SPACE("{ [i,j,k] }"),
> + getScatterSpace(UMAP("{ A[] -> [i]; [] -> [i,j,k] }")));
> +}
> +
> +TEST(ISLTools, makeIdentityMap) {
> + std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
> + &isl_ctx_free);
> +
> + // Basic usage
> + EXPECT_EQ(UMAP("{ [i] -> [i] }"), makeIdentityMap(USET("{ [0] }"),
> false));
> + EXPECT_EQ(UMAP("{ [0] -> [0] }"), makeIdentityMap(USET("{ [0] }"),
> true));
> +
> + // Multiple spaces
> + EXPECT_EQ(UMAP("{ [] -> []; [i] -> [i] }"),
> + makeIdentityMap(USET("{ []; [0] }"), false));
> + EXPECT_EQ(UMAP("{ [] -> []; [0] -> [0] }"),
> + makeIdentityMap(USET("{ []; [0] }"), true));
> +
> + // Edge case: empty
> + EXPECT_EQ(UMAP("{ }"), makeIdentityMap(USET("{ }"), false));
> + EXPECT_EQ(UMAP("{ }"), makeIdentityMap(USET("{ }"), true));
> +}
> +
> +TEST(ISLTools, reverseDomain) {
> + std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
> + &isl_ctx_free);
> +
> + // Basic usage
> + EXPECT_EQ(MAP("{ [B[] -> A[]] -> [] }"),
> + reverseDomain(MAP("{ [A[] -> B[]] -> [] }")));
> + EXPECT_EQ(UMAP("{ [B[] -> A[]] -> [] }"),
> + reverseDomain(UMAP("{ [A[] -> B[]] -> [] }")));
> +}
> +
> +TEST(ISLTools, shiftDim) {
> + std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
> + &isl_ctx_free);
> +
> + // Basic usage
> + EXPECT_EQ(SET("{ [1] }"), shiftDim(SET("{ [0] }"), 0, 1));
> + EXPECT_EQ(USET("{ [1] }"), shiftDim(USET("{ [0] }"), 0, 1));
> +
> + // From-end indexing
> + EXPECT_EQ(USET("{ [0,0,1] }"), shiftDim(USET("{ [0,0,0] }"), -1, 1));
> + EXPECT_EQ(USET("{ [0,1,0] }"), shiftDim(USET("{ [0,0,0] }"), -2, 1));
> + EXPECT_EQ(USET("{ [1,0,0] }"), shiftDim(USET("{ [0,0,0] }"), -3, 1));
> +
> + // Parametrized
> + EXPECT_EQ(USET("[n] -> { [n+1] }"), shiftDim(USET("[n] -> { [n] }"),
> 0, 1));
> +}
> +
> } // anonymous namespace
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list