[Mlir-commits] [mlir] [mlir][linalg] Hoist transfer pairs through disjoint subview slices (PR #220244)
Andrzej Warzyński
llvmlistbot at llvm.org
Wed Sep 9 02:54:25 PDT 2026
================
@@ -351,5 +352,135 @@ bool hasNegativeStaticStride(MemRefType memRefTy) {
});
}
+namespace {
+// TODO: This footprint modelling and its logic overlap with
+// `SubsetOpInterface`, which is unfortunately tensor-only today; if it gains
+// memref support, look into unifying with it to improve code reuse.
+//
+/// Footprint of a memref value relative to a `root` memref reached through a
+/// chain of rank-preserving `memref.subview` ops whose `strides` operand is all
+/// ones (so each result index steps one source element in every dimension): per
+/// `root` dimension, the `[offset, offset + size)` interval the value covers (a
+/// `size` may be dynamic). The root is the underlying buffer if the whole chain
+/// composes, otherwise the result of the first subview (walking toward the
+/// root) that cannot be composed. Two footprints are therefore comparable only
+/// when they resolve to the *same* root value.
+struct SubviewFootprint {
+ Value root;
+ SmallVector<int64_t> offsets;
+ SmallVector<int64_t> sizes;
+};
+} // namespace
+
+/// Resolve `base` through a `memref.subview` chain to a footprint, or
+/// `std::nullopt` if it cannot be modelled. Composition stops at the first
+/// subview with a dynamic offset, a `strides` operand other than all ones, or a
+/// rank reduction; that subview's own result becomes the footprint root. This
+/// keeps two slices that share a common (possibly dynamically-offset) base
+/// comparable through their static offsets relative to that base. Sizes may be
+/// dynamic: such dimensions simply cannot be used to prove disjointness.
+static std::optional<SubviewFootprint> resolveSubviewFootprint(Value base) {
+ auto baseTy = dyn_cast<MemRefType>(base.getType());
+ if (!baseTy)
+ return std::nullopt;
+ SubviewFootprint footprint;
+ // Size is fixed by `base` itself; offset accumulates the static offsets of
+ // the composable subviews walked toward the root.
+ footprint.offsets.assign(baseTy.getRank(), 0);
+ footprint.sizes.assign(baseTy.getShape().begin(), baseTy.getShape().end());
+
+ Value cur = base;
+ while (auto sv = cur.getDefiningOp<SubViewOp>()) {
+ ArrayRef<int64_t> staticOffsets = sv.getStaticOffsets();
+ ArrayRef<int64_t> staticStrides = sv.getStaticStrides();
+ // Rank-reducing subviews, or those with a dynamic offset or a `strides`
+ // operand other than all ones, cannot be composed: stop here and use `sv`'s
+ // result as the root.
+ if (sv.getSourceType().getRank() != sv.getType().getRank() ||
+ llvm::any_of(staticOffsets, ShapedType::isDynamic) ||
+ llvm::any_of(staticStrides, [](int64_t s) { return s != 1; }))
----------------
banach-space wrote:
This is confusing - it checks for strides == 1, yet from `@hoist_disjoint_static_subviews_3d`:
```mlir
// Note non-unit strides
%sv0 = memref.subview %mem[0, 0, 0][2, 2, 2][1, 1, 1] : memref<2x4x2xf32> to memref<2x2x2xf32, strided<[8, 2, 1]>>
```
What am I missing? 🤔
https://github.com/llvm/llvm-project/pull/220244
More information about the Mlir-commits
mailing list