[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