[Support] Add convertZoneToTimepoints. NFC.

This function has been extracted from the upcoming DeLICM patch
(https://reviews.llvm.org/D24716).

In contrast to computeReachingWrite and computeArrayUnused,
convertZoneToTimepoints implies a format for zones (ranges between timepoints).
Zones at the moment are unique to DeLICM, but convertZoneToTimepoints makes most
sense in conjunction with the previous two functions.

llvm-svn: 294094
This commit is contained in:
Michael Kruse 2017-02-04 15:42:17 +00:00
parent ec67d36493
commit acb08aaed5
3 changed files with 116 additions and 0 deletions

View File

@ -299,6 +299,53 @@ IslPtr<isl_union_map> computeArrayUnused(IslPtr<isl_union_map> Schedule,
bool ReadEltInSameInst,
bool InclLastRead, bool InclWrite);
/// Convert a zone (range between timepoints) to timepoints.
///
/// A zone represents the time between (integer) timepoints, but not the
/// timepoints themselves. This function can be used to determine whether a
/// timepoint lies within a zone.
///
/// For instance, the range (1,3), representing the time between 1 and 3, is
/// represented by the zone
///
/// { [i] : 1 < i <= 3 }
///
/// The set of timepoints that lie completely within this range is
///
/// { [i] : 1 < i < 3 }
///
/// A typical use-case is the range in which a value written by a store is
/// available until it is overwritten by another value. If the write is at
/// timepoint 1 and its value is overwritten by another value at timepoint 3,
/// the value is available between those timepoints: timepoint 2 in this
/// example.
///
///
/// When InclStart is true, the range is interpreted left-inclusive, i.e. adds
/// the timepoint 1 to the result:
///
/// { [i] : 1 <= i < 3 }
///
/// In the use-case mentioned above that means that the value written at
/// timepoint 1 is already available in timepoint 1 (write takes place before
/// any read of it even if executed at the same timepoint)
///
/// When InclEnd is true, the range is interpreted right-inclusive, i.e. adds
/// the timepoint 3 to the result:
///
/// { [i] : 1 < i <= 3 }
///
/// In the use-case mentioned above that means that although the value is
/// overwritten in timepoint 3, the old value is still available at timepoint 3
/// (write takes place after any read even if executed at the same timepoint)
///
/// @param Zone { Zone[] }
/// @param InclStart Include timepoints adjacent to the beginning of a zone.
/// @param InclEnd Include timepoints adjacent to the ending of a zone.
///
/// @return { Scatter[] }
IslPtr<isl_union_set> convertZoneToTimepoints(IslPtr<isl_union_set> Zone,
bool InclStart, bool InclEnd);
} // namespace polly
#endif /* POLLY_ISLTOOLS_H */

View File

@ -367,3 +367,19 @@ IslPtr<isl_union_map> polly::computeArrayUnused(IslPtr<isl_union_map> Schedule,
BeforeWritesBeforeAnyReads.take(),
isl_union_map_domain_factor_domain(BetweenLastReadOverwrite.take())));
}
IslPtr<isl_union_set> polly::convertZoneToTimepoints(IslPtr<isl_union_set> Zone,
bool InclStart,
bool InclEnd) {
if (!InclStart && InclEnd)
return Zone;
auto ShiftedZone = shiftDim(Zone, -1, -1);
if (InclStart && !InclEnd)
return ShiftedZone;
else if (!InclStart && !InclEnd)
return give(isl_union_set_intersect(Zone.take(), ShiftedZone.take()));
assert(InclStart && InclEnd);
return give(isl_union_set_union(Zone.take(), ShiftedZone.take()));
}

View File

@ -807,4 +807,57 @@ TEST(DeLICM, computeArrayUnused) {
UMAP("{ RW[] -> Elt[] }"), false, true, true));
}
TEST(DeLICM, convertZoneToTimepoints) {
std::unique_ptr<isl_ctx, decltype(&isl_ctx_free)> Ctx(isl_ctx_alloc(),
&isl_ctx_free);
// Corner case: empty set
EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{}"), false, false));
EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{}"), true, false));
EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{}"), false, true));
EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{}"), true, true));
// Basic usage
EXPECT_EQ(USET("{}"), convertZoneToTimepoints(USET("{ [1] }"), false, false));
EXPECT_EQ(USET("{ [0] }"),
convertZoneToTimepoints(USET("{ [1] }"), true, false));
EXPECT_EQ(USET("{ [1] }"),
convertZoneToTimepoints(USET("{ [1] }"), false, true));
EXPECT_EQ(USET("{ [0]; [1] }"),
convertZoneToTimepoints(USET("{ [1] }"), true, true));
// Non-adjacent ranges
EXPECT_EQ(USET("{}"),
convertZoneToTimepoints(USET("{ [1]; [11] }"), false, false));
EXPECT_EQ(USET("{ [0]; [10] }"),
convertZoneToTimepoints(USET("{ [1]; [11] }"), true, false));
EXPECT_EQ(USET("{ [1]; [11] }"),
convertZoneToTimepoints(USET("{ [1]; [11] }"), false, true));
EXPECT_EQ(USET("{ [0]; [1]; [10]; [11] }"),
convertZoneToTimepoints(USET("{ [1]; [11] }"), true, true));
// Adjacent unit ranges
EXPECT_EQ(
USET("{ [i] : 0 < i < 10 }"),
convertZoneToTimepoints(USET("{ [i] : 0 < i <= 10 }"), false, false));
EXPECT_EQ(
USET("{ [i] : 0 <= i < 10 }"),
convertZoneToTimepoints(USET("{ [i] : 0 < i <= 10 }"), true, false));
EXPECT_EQ(
USET("{ [i] : 0 < i <= 10 }"),
convertZoneToTimepoints(USET("{ [i] : 0 < i <= 10 }"), false, true));
EXPECT_EQ(USET("{ [i] : 0 <= i <= 10 }"),
convertZoneToTimepoints(USET("{ [i] : 0 < i <= 10 }"), true, true));
// More than one dimension
EXPECT_EQ(USET("{}"),
convertZoneToTimepoints(USET("{ [0,1] }"), false, false));
EXPECT_EQ(USET("{ [0,0] }"),
convertZoneToTimepoints(USET("{ [0,1] }"), true, false));
EXPECT_EQ(USET("{ [0,1] }"),
convertZoneToTimepoints(USET("{ [0,1] }"), false, true));
EXPECT_EQ(USET("{ [0,0]; [0,1] }"),
convertZoneToTimepoints(USET("{ [0,1] }"), true, true));
}
} // anonymous namespace