@@ -31,10 +31,50 @@ namespace polyhedral {
3131using detail::ScheduleTree;
3232
3333namespace {
34+ // Remove strides specified by "strides" and "offsets" from the range of
35+ // "relation". In particular, relation has a shape
36+ //
37+ // D -> O: o_i = offset_i + stride_i * f(D)
38+ //
39+ // transform it into
40+ //
41+ // D -> O: o_i = f(D)
42+ //
43+ // by subtracting "offsets" and by dividing the result by "strides".
44+ isl::map removeRangeStrides (
45+ isl::map relation,
46+ isl::multi_val strides,
47+ isl::multi_aff offsets) {
48+ CHECK_EQ (strides.size (), offsets.size ());
49+
50+ auto space = relation.get_space ();
51+ auto stridesMA = isl::multi_aff::identity (space.range ().map_from_set ());
52+ stridesMA = stridesMA / strides;
53+
54+ return relation.sum (isl::map (offsets.neg ())).apply_range (isl::map (stridesMA));
55+ }
56+
57+ // Compute a box approximation of the range of the given relation,
58+ // including the lower bounds, the box sizes, and the strides.
59+ // If the range has strides, remove them first.
3460ScopedFootprint outputRanges (isl::map access) {
61+ auto ctx = access.get_ctx ();
62+ int nSubscripts = access.dim (isl::dim_type::out);
63+
64+ auto strides = isl::val_list (ctx, nSubscripts);
65+ auto strideOffsets = isl::aff_list (ctx, nSubscripts);
66+ for (int i = 0 ; i < nSubscripts; ++i) {
67+ auto si = access.get_range_stride_info (i);
68+ strides = strides.add (si.get_stride ());
69+ strideOffsets = strideOffsets.add (si.get_offset ());
70+ }
71+
3572 ScopedFootprint footprint;
73+ footprint.strideValues = isl::multi_val (access.get_space ().range (), strides);
74+ footprint.strideOffsets = isl::multi_aff (access.get_space (), strideOffsets);
3675
37- // TODO: also compute strides
76+ access = removeRangeStrides (
77+ access, footprint.strideValues , footprint.strideOffsets );
3878
3979 footprint.box = access.get_range_simple_fixed_box_hull ();
4080 return footprint;
@@ -77,16 +117,23 @@ std::unique_ptr<TensorReferenceGroup> TensorReferenceGroup::makeSingleton(
77117 return group;
78118}
79119
80- isl::set ScopedFootprint::footprint (isl::set domain) const {
81- auto space = box.get_space ();
82- auto accessed = isl::map::universe (space).intersect_domain (domain);
120+ isl::set TensorReferenceGroup::approximateFootprint () const {
121+ auto scopedDomain = scopedAccesses ().domain ();
122+ auto space = approximation.box .get_space ();
123+ auto accessed = isl::map::universe (space).intersect_domain (scopedDomain);
83124 auto lspace = isl::local_space (accessed.get_space ().range ());
84125
85- for (size_t i = 0 ; i < dim (); ++i) {
86- auto dimLowerBound = lowerBound (i);
126+ for (size_t i = 0 ; i < approximation.dim (); ++i) {
127+ auto offset = approximation.lowerBound (i);
128+ auto stride = approximation.stride (i);
129+ auto strideOffset = approximation.strideOffset (i);
130+ auto size = approximation.size (i);
87131 auto rhs = isl::aff (lspace, isl::dim_type::set, i);
88- isl::map partial = (isl::aff_map (dimLowerBound) <= rhs) &
89- (isl::aff_map (dimLowerBound + size (i)) > rhs);
132+ auto lowerBound = offset * stride + strideOffset;
133+ auto upperBound = (offset + size) * stride + strideOffset;
134+ auto partial =
135+ (isl::aff_map (lowerBound) <= rhs) & (isl::aff_map (upperBound) > rhs);
136+
90137 accessed = accessed & partial;
91138 }
92139 return accessed.range ();
@@ -303,7 +350,9 @@ TensorGroups TensorReferenceGroup::accessedBySubtree(
303350
304351// Compute the relation between schedule dimensions, original and promoted array
305352// subscripts, in the space
306- // [S -> O] -> P
353+ // [S -> O] -> O.
354+ // The caller is in charge of updating the tuple of the target space with the
355+ // group identifier.
307356// The mapping depends on the original schedule dimensions because the same
308357// elements of the promoted array get assigned different values of the original
309358// array in different outer loop iterations; it's impossible to project out the
@@ -313,10 +362,20 @@ isl::multi_aff TensorReferenceGroup::promotion() const {
313362 isl::map map = scopedAccesses ();
314363 auto accessSpace = map.get_space ();
315364
316- // lower bounds space is S -> P; which we transform into [S -> O] -> P
317- auto lowerBounds = approximation.lowerBounds ().pullback (
318- isl::multi_aff::domain_map (accessSpace));
319- auto promotion = isl::multi_aff::range_map (accessSpace) - lowerBounds;
365+ // Construct a projection multi-aff in [S -> O] -> S
366+ // for further precomposition.
367+ auto originalSpaceInserter = isl::multi_aff::domain_map (accessSpace);
368+
369+ // Lower bounds and offsets space is S -> O; transform into [S -> O] -> O.
370+ auto lowerBounds =
371+ approximation.lowerBounds ().pullback (originalSpaceInserter);
372+ auto offsets = approximation.strideOffsets .pullback (originalSpaceInserter);
373+
374+ // Create promotion starting by identity in [S -> O] -> O.
375+ auto original = isl::multi_aff::range_map (accessSpace);
376+ auto promotion =
377+ (original - offsets) / approximation.strideValues - lowerBounds;
378+
320379 return promotion;
321380}
322381
0 commit comments