[polly] r298543 - [Support] Add functions to ISLTools.
Michael Kruse via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 22 12:31:07 PDT 2017
Author: meinersbur
Date: Wed Mar 22 14:31:06 2017
New Revision: 298543
URL: http://llvm.org/viewvc/llvm-project?rev=298543&view=rev
Log:
[Support] Add functions to ISLTools.
Add shiftDim and convertZoneToTimepoints overloads for isl maps.
Add distributeDomain, liftDomains and applyDomainRange functions.
These are going to be used in https://reviews.llvm.org/D31247
(Add known array contents to Knowledge)
Modified:
polly/trunk/include/polly/Support/ISLTools.h
polly/trunk/lib/Support/ISLTools.cpp
polly/trunk/unittests/Isl/IslTest.cpp
Modified: polly/trunk/include/polly/Support/ISLTools.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/ISLTools.h?rev=298543&r1=298542&r2=298543&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/ISLTools.h (original)
+++ polly/trunk/include/polly/Support/ISLTools.h Wed Mar 22 14:31:06 2017
@@ -157,6 +157,30 @@ isl::set shiftDim(isl::set Set, int Pos,
/// Piecewise shiftDim(isl::set,int,int).
isl::union_set shiftDim(isl::union_set USet, int Pos, int Amount);
+/// Add a constant to one dimension of a map.
+///
+/// @param Map The map to shift a dimension in.
+/// @param Type A tuple of @p Map which contains the dimension to shift.
+/// @param Pos The dimension to shift. If negative, the dimensions are
+/// counted from the end instead from the beginning. Eg. -1 is the last
+/// dimension in the tuple.
+/// @param Amount The offset to add to the specified dimension.
+///
+/// @return The modified map.
+isl::map shiftDim(isl::map Map, isl::dim Dim, int Pos, int Amount);
+
+/// Add a constant to one dimension of a each map in a union map.
+///
+/// @param UMap The maps to shift a dimension in.
+/// @param Type The tuple which contains the dimension to shift.
+/// @param Pos The dimension to shift. If negative, the dimensions are
+/// counted from the ends of each map of union instead from their
+/// beginning. E.g. -1 is the last dimension of any map.
+/// @param Amount The offset to add to the specified dimension.
+///
+/// @return The union of all modified maps.
+isl::union_map shiftDim(isl::union_map UMap, isl::dim Dim, int Pos, int Amount);
+
/// Simplify a set inplace.
void simplify(isl::set &Set);
@@ -338,6 +362,37 @@ isl::union_map computeArrayUnused(isl::u
/// @return { Scatter[] }
isl::union_set convertZoneToTimepoints(isl::union_set Zone, bool InclStart,
bool InclEnd);
+
+/// Like convertZoneToTimepoints(isl::union_set,InclStart,InclEnd), but convert
+/// either the domain or the range of a map.
+isl::union_map convertZoneToTimepoints(isl::union_map Zone, isl::dim Dim,
+ bool InclStart, bool InclEnd);
+
+/// Distribute the domain to the tuples of a wrapped range map.
+///
+/// @param Map { Domain[] -> [Range1[] -> Range2[]] }
+///
+/// @return { [Domain[] -> Range1[]] -> [Domain[] -> Range2[]] }
+isl::map distributeDomain(isl::map Map);
+
+/// Apply distributeDomain(isl::map) to each map in the union.
+isl::union_map distributeDomain(isl::union_map UMap);
+
+/// Prepend a space to the tuples of a map.
+///
+/// @param UMap { Domain[] -> Range[] }
+/// @param Factor { Factor[] }
+///
+/// @return { [Factor[] -> Domain[]] -> [Factor[] -> Range[]] }
+isl::union_map liftDomains(isl::union_map UMap, isl::union_set Factor);
+
+/// Apply a map to the 'middle' of another relation.
+///
+/// @param UMap { [DomainDomain[] -> DomainRange[]] -> Range[] }
+/// @param Func { DomainRange[] -> NewDomainRange[] }
+///
+/// @return { [DomainDomain[] -> NewDomainRange[]] -> Range[] }
+isl::union_map applyDomainRange(isl::union_map UMap, isl::union_map Func);
} // namespace polly
#endif /* POLLY_ISLTOOLS_H */
Modified: polly/trunk/lib/Support/ISLTools.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/ISLTools.cpp?rev=298543&r1=298542&r2=298543&view=diff
==============================================================================
--- polly/trunk/lib/Support/ISLTools.cpp (original)
+++ polly/trunk/lib/Support/ISLTools.cpp Wed Mar 22 14:31:06 2017
@@ -226,6 +226,46 @@ isl::union_set polly::shiftDim(isl::unio
return Result;
}
+isl::map polly::shiftDim(isl::map Map, isl::dim Dim, int Pos, int Amount) {
+ int NumDims = Map.dim(Dim);
+ if (Pos < 0)
+ Pos = NumDims + Pos;
+ assert(Pos < NumDims && "Dimension index must be in range");
+ auto Space = give(isl_map_get_space(Map.keep()));
+ switch (Dim) {
+ case isl::dim::in:
+ Space = std::move(Space).domain();
+ break;
+ case isl::dim::out:
+ Space = give(isl_space_range(Space.take()));
+ break;
+ default:
+ llvm_unreachable("Unsupported value for 'dim'");
+ }
+ 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()));
+ switch (Dim) {
+ case isl::dim::in:
+ return Map.apply_domain(TranslatorMap);
+ case isl::dim::out:
+ return Map.apply_range(TranslatorMap);
+ default:
+ llvm_unreachable("Unsupported value for 'dim'");
+ }
+}
+
+isl::union_map polly::shiftDim(isl::union_map UMap, isl::dim Dim, int Pos,
+ int Amount) {
+ auto Result = isl::union_map::empty(UMap.get_space());
+
+ foreachElt(UMap, [=, &Result](isl::map Map) {
+ auto Shifted = shiftDim(Map, Dim, Pos, Amount);
+ Result = std::move(Result).add_map(Shifted);
+ });
+ return Result;
+}
+
void polly::simplify(isl::set &Set) {
Set = give(isl_set_compute_divs(Set.take()));
Set = give(isl_set_detect_equalities(Set.take()));
@@ -368,3 +408,102 @@ isl::union_set polly::convertZoneToTimep
assert(InclStart && InclEnd);
return give(isl_union_set_union(Zone.take(), ShiftedZone.take()));
}
+
+isl::union_map polly::convertZoneToTimepoints(isl::union_map Zone, isl::dim Dim,
+ bool InclStart, bool InclEnd) {
+ if (!InclStart && InclEnd)
+ return Zone;
+
+ auto ShiftedZone = shiftDim(Zone, Dim, -1, -1);
+ if (InclStart && !InclEnd)
+ return ShiftedZone;
+ else if (!InclStart && !InclEnd)
+ return give(isl_union_map_intersect(Zone.take(), ShiftedZone.take()));
+
+ assert(InclStart && InclEnd);
+ return give(isl_union_map_union(Zone.take(), ShiftedZone.take()));
+}
+
+isl::map polly::distributeDomain(isl::map Map) {
+ // Note that we cannot take Map apart into { Domain[] -> Range1[] } and {
+ // Domain[] -> Range2[] } and combine again. We would loose any relation
+ // between Range1[] and Range2[] that is not also a constraint to Domain[].
+
+ auto Space = give(isl_map_get_space(Map.keep()));
+ auto DomainSpace = give(isl_space_domain(Space.copy()));
+ assert(DomainSpace);
+ auto DomainDims = isl_space_dim(DomainSpace.keep(), isl_dim_set);
+ auto RangeSpace = give(isl_space_unwrap(isl_space_range(Space.copy())));
+ auto Range1Space = give(isl_space_domain(RangeSpace.copy()));
+ assert(Range1Space);
+ auto Range1Dims = isl_space_dim(Range1Space.keep(), isl_dim_set);
+ auto Range2Space = give(isl_space_range(RangeSpace.copy()));
+ assert(Range2Space);
+ auto Range2Dims = isl_space_dim(Range2Space.keep(), isl_dim_set);
+
+ auto OutputSpace = give(isl_space_map_from_domain_and_range(
+ isl_space_wrap(isl_space_map_from_domain_and_range(DomainSpace.copy(),
+ Range1Space.copy())),
+ isl_space_wrap(isl_space_map_from_domain_and_range(DomainSpace.copy(),
+ Range2Space.copy()))));
+
+ auto Translator =
+ give(isl_basic_map_universe(isl_space_map_from_domain_and_range(
+ isl_space_wrap(Space.copy()), isl_space_wrap(OutputSpace.copy()))));
+
+ for (unsigned i = 0; i < DomainDims; i += 1) {
+ Translator = give(
+ isl_basic_map_equate(Translator.take(), isl_dim_in, i, isl_dim_out, i));
+ Translator =
+ give(isl_basic_map_equate(Translator.take(), isl_dim_in, i, isl_dim_out,
+ DomainDims + Range1Dims + i));
+ }
+ for (unsigned i = 0; i < Range1Dims; i += 1) {
+ Translator =
+ give(isl_basic_map_equate(Translator.take(), isl_dim_in, DomainDims + i,
+ isl_dim_out, DomainDims + i));
+ }
+ for (unsigned i = 0; i < Range2Dims; i += 1) {
+ Translator = give(isl_basic_map_equate(
+ Translator.take(), isl_dim_in, DomainDims + Range1Dims + i, isl_dim_out,
+ DomainDims + Range1Dims + DomainDims + i));
+ }
+
+ return give(isl_set_unwrap(isl_set_apply(
+ isl_map_wrap(Map.copy()), isl_map_from_basic_map(Translator.copy()))));
+}
+
+isl::union_map polly::distributeDomain(isl::union_map UMap) {
+ auto Result = give(isl_union_map_empty(isl_union_map_get_space(UMap.keep())));
+ foreachElt(UMap, [=, &Result](isl::map Map) {
+ auto Distributed = distributeDomain(Map);
+ Result = give(isl_union_map_add_map(Result.take(), Distributed.copy()));
+ });
+ return Result;
+}
+
+isl::union_map polly::liftDomains(isl::union_map UMap, isl::union_set Factor) {
+
+ // { Factor[] -> Factor[] }
+ auto Factors = makeIdentityMap(std::move(Factor), true);
+
+ return std::move(Factors).product(std::move(UMap));
+}
+
+isl::union_map polly::applyDomainRange(isl::union_map UMap,
+ isl::union_map Func) {
+ // This implementation creates unnecessary cross products of the
+ // DomainDomain[] and Func. An alternative implementation could reverse
+ // domain+uncurry,apply Func to what now is the domain, then undo the
+ // preparing transformation. Another alternative implementation could create a
+ // translator map for each piece.
+
+ // { DomainDomain[] }
+ auto DomainDomain = UMap.domain().unwrap().domain();
+
+ // { [DomainDomain[] -> DomainRange[]] -> [DomainDomain[] -> NewDomainRange[]]
+ // }
+ auto LifetedFunc = liftDomains(std::move(Func), DomainDomain);
+
+ return std::move(UMap).apply_domain(std::move(LifetedFunc));
+}
Modified: polly/trunk/unittests/Isl/IslTest.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/unittests/Isl/IslTest.cpp?rev=298543&r1=298542&r2=298543&view=diff
==============================================================================
--- polly/trunk/unittests/Isl/IslTest.cpp (original)
+++ polly/trunk/unittests/Isl/IslTest.cpp Wed Mar 22 14:31:06 2017
@@ -615,6 +615,16 @@ TEST(ISLTools, shiftDim) {
// Parametrized
EXPECT_EQ(USET("[n] -> { [n+1] }"), shiftDim(USET("[n] -> { [n] }"), 0, 1));
+
+ // Union maps
+ EXPECT_EQ(MAP("{ [1] -> [] }"),
+ shiftDim(MAP("{ [0] -> [] }"), isl::dim::in, 0, 1));
+ EXPECT_EQ(UMAP("{ [1] -> [] }"),
+ shiftDim(UMAP("{ [0] -> [] }"), isl::dim::in, 0, 1));
+ EXPECT_EQ(MAP("{ [] -> [1] }"),
+ shiftDim(MAP("{ [] -> [0] }"), isl::dim::out, 0, 1));
+ EXPECT_EQ(UMAP("{ [] -> [1] }"),
+ shiftDim(UMAP("{ [] -> [0] }"), isl::dim::out, 0, 1));
}
TEST(DeLICM, computeReachingWrite) {
@@ -838,6 +848,99 @@ TEST(DeLICM, convertZoneToTimepoints) {
convertZoneToTimepoints(USET("{ [0,1] }"), false, true));
EXPECT_EQ(USET("{ [0,0]; [0,1] }"),
convertZoneToTimepoints(USET("{ [0,1] }"), true, true));
+
+ // Map domains
+ EXPECT_EQ(UMAP("{}"), convertZoneToTimepoints(UMAP("{ [1] -> [] }"),
+ isl::dim::in, false, false));
+ EXPECT_EQ(UMAP("{ [0] -> [] }"),
+ convertZoneToTimepoints(UMAP("{ [1] -> [] }"), isl::dim::in, true,
+ false));
+ EXPECT_EQ(UMAP("{ [1] -> [] }"),
+ convertZoneToTimepoints(UMAP("{ [1] -> [] }"), isl::dim::in, false,
+ true));
+ EXPECT_EQ(
+ UMAP("{ [0] -> []; [1] -> [] }"),
+ convertZoneToTimepoints(UMAP("{ [1] -> [] }"), isl::dim::in, true, true));
+
+ // Map ranges
+ EXPECT_EQ(UMAP("{}"), convertZoneToTimepoints(UMAP("{ [] -> [1] }"),
+ isl::dim::out, false, false));
+ EXPECT_EQ(UMAP("{ [] -> [0] }"),
+ convertZoneToTimepoints(UMAP("{ [] -> [1] }"), isl::dim::out, true,
+ false));
+ EXPECT_EQ(UMAP("{ [] -> [1] }"),
+ convertZoneToTimepoints(UMAP("{ [] -> [1] }"), isl::dim::out, false,
+ true));
+ EXPECT_EQ(UMAP("{ [] -> [0]; [] -> [1] }"),
+ convertZoneToTimepoints(UMAP("{ [] -> [1] }"), isl::dim::out, true,
+ true));
+}
+
+TEST(DeLICM, distribute) {
+ std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
+ &isl_ctx_free);
+
+ // Basic usage
+ EXPECT_EQ(MAP("{ [Domain[] -> Range1[]] -> [Domain[] -> Range2[]] }"),
+ distributeDomain(MAP("{ Domain[] -> [Range1[] -> Range2[]] }")));
+ EXPECT_EQ(
+ MAP("{ [Domain[i,j] -> Range1[i,k]] -> [Domain[i,j] -> Range2[j,k]] }"),
+ distributeDomain(MAP("{ Domain[i,j] -> [Range1[i,k] -> Range2[j,k]] }")));
+
+ // Union maps
+ EXPECT_EQ(
+ UMAP(
+ "{ [DomainA[i,j] -> RangeA1[i,k]] -> [DomainA[i,j] -> RangeA2[j,k]];"
+ "[DomainB[i,j] -> RangeB1[i,k]] -> [DomainB[i,j] -> RangeB2[j,k]] }"),
+ distributeDomain(
+ UMAP("{ DomainA[i,j] -> [RangeA1[i,k] -> RangeA2[j,k]];"
+ "DomainB[i,j] -> [RangeB1[i,k] -> RangeB2[j,k]] }")));
+}
+
+TEST(DeLICM, lift) {
+ std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
+ &isl_ctx_free);
+
+ // Basic usage
+ EXPECT_EQ(UMAP("{ [Factor[] -> Domain[]] -> [Factor[] -> Range[]] }"),
+ liftDomains(UMAP("{ Domain[] -> Range[] }"), USET("{ Factor[] }")));
+ EXPECT_EQ(UMAP("{ [Factor[l] -> Domain[i,k]] -> [Factor[l] -> Range[j,k]] }"),
+ liftDomains(UMAP("{ Domain[i,k] -> Range[j,k] }"),
+ USET("{ Factor[l] }")));
+
+ // Multiple maps in union
+ EXPECT_EQ(
+ UMAP("{ [FactorA[] -> DomainA[]] -> [FactorA[] -> RangeA[]];"
+ "[FactorB[] -> DomainA[]] -> [FactorB[] -> RangeA[]];"
+ "[FactorA[] -> DomainB[]] -> [FactorA[] -> RangeB[]];"
+ "[FactorB[] -> DomainB[]] -> [FactorB[] -> RangeB[]] }"),
+ liftDomains(UMAP("{ DomainA[] -> RangeA[]; DomainB[] -> RangeB[] }"),
+ USET("{ FactorA[]; FactorB[] }")));
+}
+
+TEST(DeLICM, apply) {
+ std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
+ &isl_ctx_free);
+
+ // Basic usage
+ EXPECT_EQ(
+ UMAP("{ [DomainDomain[] -> NewDomainRange[]] -> Range[] }"),
+ applyDomainRange(UMAP("{ [DomainDomain[] -> DomainRange[]] -> Range[] }"),
+ UMAP("{ DomainRange[] -> NewDomainRange[] }")));
+ EXPECT_EQ(
+ UMAP("{ [DomainDomain[i,k] -> NewDomainRange[j,k,l]] -> Range[i,j] }"),
+ applyDomainRange(
+ UMAP("{ [DomainDomain[i,k] -> DomainRange[j,k]] -> Range[i,j] }"),
+ UMAP("{ DomainRange[j,k] -> NewDomainRange[j,k,l] }")));
+
+ // Multiple maps in union
+ EXPECT_EQ(UMAP("{ [DomainDomainA[] -> NewDomainRangeA[]] -> RangeA[];"
+ "[DomainDomainB[] -> NewDomainRangeB[]] -> RangeB[] }"),
+ applyDomainRange(
+ UMAP("{ [DomainDomainA[] -> DomainRangeA[]] -> RangeA[];"
+ "[DomainDomainB[] -> DomainRangeB[]] -> RangeB[] }"),
+ UMAP("{ DomainRangeA[] -> NewDomainRangeA[];"
+ "DomainRangeB[] -> NewDomainRangeB[] }")));
}
} // anonymous namespace
More information about the llvm-commits
mailing list