[polly] r294092 - [Support] Add computeReachingWrite. NFC.
Michael Kruse via llvm-commits
llvm-commits at lists.llvm.org
Sat Feb 4 07:42:03 PST 2017
Author: meinersbur
Date: Sat Feb 4 09:42:01 2017
New Revision: 294092
URL: http://llvm.org/viewvc/llvm-project?rev=294092&view=rev
Log:
[Support] Add computeReachingWrite. NFC.
This function has been extracted from the upcoming DeLICM patch
(https://reviews.llvm.org/D24716).
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=294092&r1=294091&r2=294092&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/ISLTools.h (original)
+++ polly/trunk/include/polly/Support/ISLTools.h Sat Feb 4 09:42:01 2017
@@ -175,6 +175,64 @@ void simplify(IslPtr<isl_map> &Map);
/// Simplify a union map inplace.
void simplify(IslPtr<isl_union_map> &UMap);
+/// Compute the reaching definition statement or the next overwrite for each
+/// definition of an array element.
+///
+/// The reaching definition of an array element at a specific timepoint is the
+/// statement instance that has written the current element's content.
+/// Alternatively, this function determines for each timepoint and element which
+/// write is going to overwrite an element at a future timepoint. This can be
+/// seen as "reaching definition in reverse" where definitions are found in the
+/// past.
+///
+/// For example:
+///
+/// Schedule := { Write[] -> [0]; Overwrite[] -> [10] }
+/// Defs := { Write[] -> A[5]; Overwrite[] -> A[5] }
+///
+/// If index 5 of array A is written at timepoint 0 and 10, the resulting
+/// reaching definitions are:
+///
+/// { [A[5] -> [i]] -> Write[] : 0 < i < 10;
+/// [A[5] -> [i]] -> Overwrite[] : 10 < i }
+///
+/// Between timepoint 0 (Write[]) and timepoint 10 (Overwrite[]), the
+/// content of A[5] is written by statement instance Write[] and after
+/// timepoint 10 by Overwrite[]. Values not defined in the map have no known
+/// definition. This includes the statement instance timepoints themselves,
+/// because reads at those timepoints could either read the old or the new
+/// value, defined only by the statement itself. But this can be changed by @p
+/// InclPrevDef and @p InclNextDef. InclPrevDef=false and InclNextDef=true
+/// returns a zone. Unless @p InclPrevDef and @p InclNextDef are both true,
+/// there is only one unique definition per element and timepoint.
+///
+/// @param Schedule { DomainWrite[] -> Scatter[] }
+/// Schedule of (at least) all array writes. Instances not in
+/// @p Writes are ignored.
+/// @param Writes { DomainWrite[] -> Element[] }
+/// Elements written to by the statement instances.
+/// @param Reverse If true, look for definitions in the future. That is,
+/// find the write that is overwrites the current value.
+/// @param InclPrevDef Include the definition's timepoint to the set of
+/// well-defined elements (any load at that timepoint happen
+/// at the writes). In the example, enabling this option adds
+/// {[A[5] -> [0]] -> Write[]; [A[5] -> [10]] -> Overwrite[]}
+/// to the result.
+/// @param InclNextDef Whether to assume that at the timepoint where an element
+/// is overwritten, it still contains the old value (any load
+/// at that timepoint would happen before the overwrite). In
+/// this example, enabling this adds
+/// { [A[] -> [10]] -> Write[] } to the result.
+///
+/// @return { [Element[] -> Scatter[]] -> DomainWrite[] }
+/// The reaching definitions or future overwrite as described above, or
+/// nullptr if either @p Schedule or @p Writes is nullptr, or the isl
+/// max operations count has exceeded.
+IslPtr<isl_union_map> computeReachingWrite(IslPtr<isl_union_map> Schedule,
+ IslPtr<isl_union_map> Writes,
+ bool Reverse, bool InclPrevDef,
+ bool InclNextDef);
+
} // 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=294092&r1=294091&r2=294092&view=diff
==============================================================================
--- polly/trunk/lib/Support/ISLTools.cpp (original)
+++ polly/trunk/lib/Support/ISLTools.cpp Sat Feb 4 09:42:01 2017
@@ -260,3 +260,63 @@ void polly::simplify(IslPtr<isl_union_ma
UMap = give(isl_union_map_detect_equalities(UMap.take()));
UMap = give(isl_union_map_coalesce(UMap.take()));
}
+
+IslPtr<isl_union_map>
+polly::computeReachingWrite(IslPtr<isl_union_map> Schedule,
+ IslPtr<isl_union_map> Writes, bool Reverse,
+ bool InclPrevDef, bool InclNextDef) {
+
+ // { Scatter[] }
+ auto ScatterSpace = getScatterSpace(Schedule);
+
+ // { ScatterRead[] -> ScatterWrite[] }
+ IslPtr<isl_map> Relation;
+ if (Reverse)
+ Relation = give(InclPrevDef ? isl_map_lex_lt(ScatterSpace.take())
+ : isl_map_lex_le(ScatterSpace.take()));
+ else
+ Relation = give(InclNextDef ? isl_map_lex_gt(ScatterSpace.take())
+ : isl_map_lex_ge(ScatterSpace.take()));
+
+ // { ScatterWrite[] -> [ScatterRead[] -> ScatterWrite[]] }
+ auto RelationMap = give(isl_map_reverse(isl_map_range_map(Relation.take())));
+
+ // { Element[] -> ScatterWrite[] }
+ auto WriteAction =
+ give(isl_union_map_apply_domain(Schedule.copy(), Writes.take()));
+
+ // { ScatterWrite[] -> Element[] }
+ auto WriteActionRev = give(isl_union_map_reverse(WriteAction.copy()));
+
+ // { Element[] -> [ScatterUse[] -> ScatterWrite[]] }
+ auto DefSchedRelation = give(isl_union_map_apply_domain(
+ isl_union_map_from_map(RelationMap.take()), WriteActionRev.take()));
+
+ // For each element, at every point in time, map to the times of previous
+ // definitions. { [Element[] -> ScatterRead[]] -> ScatterWrite[] }
+ auto ReachableWrites = give(isl_union_map_uncurry(DefSchedRelation.take()));
+ if (Reverse)
+ ReachableWrites = give(isl_union_map_lexmin(ReachableWrites.copy()));
+ else
+ ReachableWrites = give(isl_union_map_lexmax(ReachableWrites.copy()));
+
+ // { [Element[] -> ScatterWrite[]] -> ScatterWrite[] }
+ auto SelfUse = give(isl_union_map_range_map(WriteAction.take()));
+
+ if (InclPrevDef && InclNextDef) {
+ // Add the Def itself to the solution.
+ ReachableWrites =
+ give(isl_union_map_union(ReachableWrites.take(), SelfUse.take()));
+ ReachableWrites = give(isl_union_map_coalesce(ReachableWrites.take()));
+ } else if (!InclPrevDef && !InclNextDef) {
+ // Remove Def itself from the solution.
+ ReachableWrites =
+ give(isl_union_map_subtract(ReachableWrites.take(), SelfUse.take()));
+ }
+
+ // { [Element[] -> ScatterRead[]] -> Domain[] }
+ auto ReachableWriteDomain = give(isl_union_map_apply_range(
+ ReachableWrites.take(), isl_union_map_reverse(Schedule.take())));
+
+ return ReachableWriteDomain;
+}
Modified: polly/trunk/unittests/Isl/IslTest.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/unittests/Isl/IslTest.cpp?rev=294092&r1=294091&r2=294092&view=diff
==============================================================================
--- polly/trunk/unittests/Isl/IslTest.cpp (original)
+++ polly/trunk/unittests/Isl/IslTest.cpp Sat Feb 4 09:42:01 2017
@@ -637,4 +637,108 @@ TEST(ISLTools, shiftDim) {
EXPECT_EQ(USET("[n] -> { [n+1] }"), shiftDim(USET("[n] -> { [n] }"), 0, 1));
}
+TEST(DeLICM, computeReachingWrite) {
+ std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
+ &isl_ctx_free);
+
+ // Basic usage
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : 0 < i }"),
+ computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
+ UMAP("{ Dom[] -> Elt[] }"), false, false,
+ false));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : 0 < i }"),
+ computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
+ UMAP("{ Dom[] -> Elt[] }"), false, false,
+ true));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : 0 <= i }"),
+ computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
+ UMAP("{ Dom[] -> Elt[] }"), false, true,
+ false));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : 0 <= i }"),
+ computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
+ UMAP("{ Dom[] -> Elt[] }"), false, true,
+ false));
+
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : i < 0 }"),
+ computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
+ UMAP("{ Dom[] -> Elt[] }"), true, false,
+ false));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : i <= 0 }"),
+ computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
+ UMAP("{ Dom[] -> Elt[] }"), true, false,
+ true));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : i < 0 }"),
+ computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
+ UMAP("{ Dom[] -> Elt[] }"), true, true,
+ false));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[] : i <= 0 }"),
+ computeReachingWrite(UMAP("{ Dom[] -> [0] }"),
+ UMAP("{ Dom[] -> Elt[] }"), true, true, true));
+
+ // Two writes
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom1[] : 0 < i < 10; [Elt[] -> [i]] -> "
+ "Dom2[] : 10 < i }"),
+ computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
+ UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
+ false, false, false));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom1[] : 0 <= i < 10; [Elt[] -> [i]] -> "
+ "Dom2[] : 10 <= i }"),
+ computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
+ UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
+ false, true, false));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom1[] : 0 < i <= 10; [Elt[] -> [i]] -> "
+ "Dom2[] : 10 < i }"),
+ computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
+ UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
+ false, false, true));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom1[] : 0 <= i <= 10; [Elt[] -> [i]] -> "
+ "Dom2[] : 10 <= i }"),
+ computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
+ UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
+ false, true, true));
+
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom2[] : 0 < i < 10; [Elt[] -> [i]] -> "
+ "Dom1[] : i < 0 }"),
+ computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
+ UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
+ true, false, false));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom2[] : 0 <= i < 10; [Elt[] -> [i]] -> "
+ "Dom1[] : i < 0 }"),
+ computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
+ UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
+ true, true, false));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom2[] : 0 < i <= 10; [Elt[] -> [i]] -> "
+ "Dom1[] : i <= 0 }"),
+ computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
+ UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
+ true, false, true));
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom2[] : 0 <= i <= 10; [Elt[] -> [i]] -> "
+ "Dom1[] : i <= 0 }"),
+ computeReachingWrite(UMAP("{ Dom1[] -> [0]; Dom2[] -> [10] }"),
+ UMAP("{ Dom1[] -> Elt[]; Dom2[] -> Elt[] }"),
+ true, true, true));
+
+ // Domain in same space
+ EXPECT_EQ(UMAP("{ [Elt[] -> [i]] -> Dom[1] : 0 < i <= 10; [Elt[] -> [i]] -> "
+ "Dom[2] : 10 < i }"),
+ computeReachingWrite(UMAP("{ Dom[i] -> [10i - 10] }"),
+ UMAP("{ Dom[1] -> Elt[]; Dom[2] -> Elt[] }"),
+ false, false, true));
+
+ // Parametric
+ EXPECT_EQ(UMAP("[p] -> { [Elt[] -> [i]] -> Dom[] : p < i }"),
+ computeReachingWrite(UMAP("[p] -> { Dom[] -> [p] }"),
+ UMAP("{ Dom[] -> Elt[] }"), false, false,
+ false));
+
+ // More realistic example (from reduction_embedded.ll)
+ EXPECT_EQ(
+ UMAP("{ [Elt[] -> [i]] -> Dom[0] : 0 < i <= 3; [Elt[] -> [i]] -> Dom[1] "
+ ": 3 < i <= 6; [Elt[] -> [i]] -> Dom[2] : 6 < i <= 9; [Elt[] -> "
+ "[i]] -> Dom[3] : 9 < i <= 12; [Elt[] -> [i]] -> Dom[4] : 12 < i }"),
+ computeReachingWrite(UMAP("{ Dom[i] -> [3i] : 0 <= i <= 4 }"),
+ UMAP("{ Dom[i] -> Elt[] : 0 <= i <= 4 }"), false,
+ false, true));
+}
+
} // anonymous namespace
More information about the llvm-commits
mailing list