[Mlir-commits] [mlir] fc90bd3 - [mlir][MemRef] Move the implementation of Mem2Reg interface from Vector to MemRef (nfc) (#228459)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Oct 6 01:46:38 PDT 2026


Author: Andrzej WarzyƄski
Date: 2026-10-06T08:46:31Z
New Revision: fc90bd3cfb0bab14a2bf7cbd33f5f1e904c7e133

URL: https://github.com/llvm/llvm-project/commit/fc90bd3cfb0bab14a2bf7cbd33f5f1e904c7e133
DIFF: https://github.com/llvm/llvm-project/commit/fc90bd3cfb0bab14a2bf7cbd33f5f1e904c7e133.diff

LOG: [mlir][MemRef] Move the implementation of Mem2Reg interface from Vector to MemRef (nfc) (#228459)

Moves the `MemRefSlotInterface` implementations for MemRef dialect ops
from:
  * `lib/Dialect/Vector/Transforms`
to:
  * `lib/Dialect/MemRef/Transforms`.

This is preferable because external interface models for MemRef dialect
ops should, where possible, be owned by the MemRef dialect rather than by
another dialect.

This direction was not pursued in the PR that introduced the affected
implementations (#211880), in order to:
  * "(...) avoid cyclic dependence between memref and vector."
See:
* https://github.com/llvm/llvm-project/pull/211880#discussion_r3709075872

However, the `MemRef` transformation library
(`lib/Dialect/MemRef/Transforms`) already depends on the `Vector`
dialect. This is expected: `MemRef` transformations live in a library
separate from the `MemRef` dialect library and can depend on dialects
emitted by those transformations, including` Vector`. Therefore, this PR
can relocate the implementations without introducing any new dialect
dependency or dependency cycle.

Also note that some `MemRefSlotInterface` external models are currently
implemented under `lib/Dialect/MemRef/IR` (i.e. as part of the dialect
library). In a subsequent PR, I intend to move those to
`lib/Dialect/MemRef/Transforms` alongside the models affected by this
PR, which is a more suitable location.

In the meantime, this PR renames:
  * `registerMemorySlotExternalModels`
to:
  * `registerDestructableTypeExternalModels`

to reduce the potential for naming conflicts.

More generally, we should possibly revisit `MemRefSlotInterface` and
establish a cleaner separation between functionality used for:
  * Mem2Reg (e.g. `registerMemorySlotOpInterfaceExternalModels`), and
  * SROA (e.g. `registerDestructableTypeExternalModels`).

NOTE TO REVIEWERS:

The key modification in this PR is moving the code between:
  * mlir/lib/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.cpp,
 and
  * mlir/lib/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.cpp

No new functionality is added.

Added: 
    mlir/include/mlir/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.h
    mlir/lib/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.cpp

Modified: 
    mlir/include/mlir/Dialect/MemRef/IR/MemRefMemorySlot.h
    mlir/include/mlir/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.h
    mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp
    mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt
    mlir/lib/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.cpp
    mlir/lib/RegisterAllDialects.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRefMemorySlot.h b/mlir/include/mlir/Dialect/MemRef/IR/MemRefMemorySlot.h
index 6b56311ed8840..1bba85e2f2bd4 100644
--- a/mlir/include/mlir/Dialect/MemRef/IR/MemRefMemorySlot.h
+++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRefMemorySlot.h
@@ -13,7 +13,7 @@ namespace mlir {
 class DialectRegistry;
 
 namespace memref {
-void registerMemorySlotExternalModels(DialectRegistry &registry);
+void registerDestructurableTypeExternalModels(DialectRegistry &registry);
 } // namespace memref
 } // namespace mlir
 

diff  --git a/mlir/include/mlir/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.h b/mlir/include/mlir/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.h
new file mode 100644
index 0000000000000..70e356ae5a254
--- /dev/null
+++ b/mlir/include/mlir/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.h
@@ -0,0 +1,20 @@
+//===- MemorySlotOpInterfaceImpl.h - Mem2Reg for MemRef ops -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_MEMREF_TRANSFORMS_MEMORYSLOTOPINTERFACEIMPL_H
+#define MLIR_DIALECT_MEMREF_TRANSFORMS_MEMORYSLOTOPINTERFACEIMPL_H
+
+namespace mlir {
+class DialectRegistry;
+
+namespace memref {
+void registerMemorySlotOpInterfaceExternalModels(DialectRegistry &registry);
+} // namespace memref
+} // namespace mlir
+
+#endif // MLIR_DIALECT_MEMREF_TRANSFORMS_MEMORYSLOTOPINTERFACEIMPL_H

diff  --git a/mlir/include/mlir/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.h b/mlir/include/mlir/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.h
index 4c2e386728419..7c1746efe0710 100644
--- a/mlir/include/mlir/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.h
+++ b/mlir/include/mlir/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.h
@@ -14,7 +14,7 @@ namespace mlir {
 class DialectRegistry;
 
 namespace vector {
-void registerMemorySlotOpInterfaceExternalModels(DialectRegistry &registry);
+void registerMemorySlotExternalModels(DialectRegistry &registry);
 } // namespace vector
 } // namespace mlir
 

diff  --git a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp
index 7f58e099b45b5..a25d5678604d0 100644
--- a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp
+++ b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp
@@ -394,7 +394,8 @@ struct MemRefDestructurableTypeExternalModel
 //  Register external models
 //===----------------------------------------------------------------------===//
 
-void mlir::memref::registerMemorySlotExternalModels(DialectRegistry &registry) {
+void mlir::memref::registerDestructurableTypeExternalModels(
+    DialectRegistry &registry) {
   registry.addExtension(+[](MLIRContext *ctx, BuiltinDialect *dialect) {
     MemRefType::attachInterface<MemRefDestructurableTypeExternalModel>(*ctx);
   });

diff  --git a/mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt b/mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt
index 1a8b03dabcfb7..179d648c46a1b 100644
--- a/mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt
@@ -12,6 +12,7 @@ add_mlir_dialect_library(MLIRMemRefTransforms
   FlattenMemRefs.cpp
   FoldMemRefAliasOps.cpp
   IndependenceTransforms.cpp
+  MemorySlotOpInterfaceImpl.cpp
   MultiBuffer.cpp
   NormalizeMemRefs.cpp
   ReifyResultShapes.cpp
@@ -35,6 +36,7 @@ add_mlir_dialect_library(MLIRMemRefTransforms
   MLIRLoopLikeInterface
   MLIRMemRefDialect
   MLIRMemRefUtils
+  MLIRMemorySlotInterfaces
   MLIRPass
   MLIRSCFDialect
   MLIRTensorDialect

diff  --git a/mlir/lib/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.cpp b/mlir/lib/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.cpp
new file mode 100644
index 0000000000000..b64cdfc0a48c8
--- /dev/null
+++ b/mlir/lib/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.cpp
@@ -0,0 +1,192 @@
+//===- MemorySlotOpInterfaceImpl.cpp - Mem2Reg for MemRef ops -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Mem2Reg-related interfaces that let a statically-shaped
+// memref be promoted into a single SSA value, provided every access to
+// the buffer is a whole-buffer read or write (or a whole-sub-region access of
+// such a buffer via a subview). With these models, Mem2Reg replaces the memory
+// slot with a vector value (*), threading it as the reaching definition:
+//
+//   * a static, same-rank `memref.subview` is exposed as a promotable sub-slice
+//     alias of the buffer's slot (via `PromotableAliaserInterface`): a read of
+//     the subview projects out of the vector value with
+//     `vector.extract_strided_slice`, and a write into it composes back into
+//     the value with `vector.insert_strided_slice`. This lets a buffer that is
+//     only ever accessed through static subviews promote as well, with partial
+//     and overlapping sub-writes composing in program order.
+//
+// Accesses that are not whole-(sub-)buffer -- dynamic offsets, rank-reducing or
+// non-unit-stride subviews -- are left untouched, so the buffer is not
+// promoted.
+//
+// (*) Addging support for scalar values is left as a TODO.
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/MemRef/Transforms/MemorySlotOpInterfaceImpl.h"
+
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/Dialect/MemRef/IR/MemRefDialect.h"
+#include "mlir/Dialect/Vector/IR/VectorOps.h"
+#include "mlir/Interfaces/MemorySlotInterfaces.h"
+
+using namespace mlir;
+using namespace mlir::memref;
+using namespace mlir::vector;
+
+//===----------------------------------------------------------------------===//
+//  memref.subview aliaser
+//===----------------------------------------------------------------------===//
+
+/// Returns the offsets of `subView` as a static, contiguous, same-rank slice of
+/// its source, or nullopt if the subview is not promotable as a whole-buffer
+/// sub-slice. Promotion projects the parent buffer's vector value through
+/// `vector.extract_strided_slice` / `insert_strided_slice`, which require:
+///   * fully static offsets and sizes,
+///   * unit strides,
+///   * no rank reduction (result rank == source rank),
+/// so a dropped or dynamic dimension disqualifies the subview.
+static std::optional<SmallVector<int64_t>>
+getPromotableSubViewOffsets(memref::SubViewOp subView) {
+  auto srcType = dyn_cast<MemRefType>(subView.getSource().getType());
+  auto resType = dyn_cast<MemRefType>(subView.getResult().getType());
+  if (!srcType || !resType || !srcType.hasStaticShape() ||
+      !resType.hasStaticShape())
+    return std::nullopt;
+
+  // No rank reduction: extract/insert_strided_slice operate at a single rank.
+  if (srcType.getRank() != resType.getRank())
+    return std::nullopt;
+
+  // Unit strides only.
+  for (OpFoldResult stride : subView.getMixedStrides()) {
+    std::optional<int64_t> s = getConstantIntValue(stride);
+    if (!s || *s != 1)
+      return std::nullopt;
+  }
+
+  // Static offsets.
+  SmallVector<int64_t> offsets;
+  for (OpFoldResult offset : subView.getMixedOffsets()) {
+    std::optional<int64_t> o = getConstantIntValue(offset);
+    if (!o)
+      return std::nullopt;
+    offsets.push_back(*o);
+  }
+
+  // Static sizes (already implied by the result's static shape, but the sizes
+  // must match the result shape so the slice covers exactly the subview).
+  for (auto [size, dim] :
+       llvm::zip_equal(subView.getMixedSizes(), resType.getShape())) {
+    std::optional<int64_t> s = getConstantIntValue(size);
+    if (!s || *s != dim)
+      return std::nullopt;
+  }
+  return offsets;
+}
+namespace {
+/// Exposes a static, same-rank `memref.subview` as a sub-slice alias of a
+/// whole-buffer vector slot. Reads of the subview become
+/// `vector.extract_strided_slice` of the parent value; writes become
+/// `vector.insert_strided_slice` into the current reaching definition.
+struct SubViewOpAliasModel
+    : public PromotableAliaserInterface::ExternalModel<SubViewOpAliasModel,
+                                                       memref::SubViewOp> {
+  void getPromotableSlotAliases(Operation *op,
+
+                                OpOperand &aliasedSlotPointerOperand,
+                                const MemorySlot &parentSlot,
+                                SmallVectorImpl<MemorySlot> &newSlots) const {
+    auto subView = cast<memref::SubViewOp>(op);
+    if (aliasedSlotPointerOperand.get() != subView.getSource())
+      return;
+
+    // The parent slot must promote to a vector (whole-buffer promotion). A
+    // scalar (single-element) parent slot cannot be sliced.
+    auto parentVecType = dyn_cast<VectorType>(parentSlot.valueType);
+    if (!parentVecType)
+      return;
+
+    if (!getPromotableSubViewOffsets(subView))
+      return;
+
+    // The alias's value type is the sub-vector matching the subview's shape.
+    auto resType = cast<MemRefType>(subView.getResult().getType());
+    if (!VectorType::isValidElementType(resType.getElementType()))
+      return;
+    VectorType aliasVecType =
+        VectorType::get(resType.getShape(), resType.getElementType());
+    newSlots.push_back(MemorySlot{subView.getResult(), aliasVecType});
+  }
+
+  Value projectSlotValueToAliasValue(Operation *op,
+                                     OpOperand & /*aliasedSlotPointerOperand*/,
+                                     const MemorySlot & /*parentSlot*/,
+                                     const MemorySlot &aliasSlot,
+                                     Value slotValue,
+                                     OpBuilder &builder) const {
+    auto subView = cast<memref::SubViewOp>(op);
+    SmallVector<int64_t> offsets = *getPromotableSubViewOffsets(subView);
+    auto aliasVecType = cast<VectorType>(aliasSlot.valueType);
+    SmallVector<int64_t> strides(offsets.size(), 1);
+    return vector::ExtractStridedSliceOp::create(
+               builder, op->getLoc(), slotValue, offsets,
+               aliasVecType.getShape(), strides)
+        .getResult();
+  }
+
+  Value projectAliasValueToSlotValue(Operation *op,
+                                     OpOperand & /*aliasedSlotPointerOperand*/,
+                                     const MemorySlot & /*parentSlot*/,
+                                     const MemorySlot & /*aliasSlot*/,
+                                     Value aliasValue, Value reachingDef,
+                                     OpBuilder &builder) const {
+    auto subView = cast<memref::SubViewOp>(op);
+    SmallVector<int64_t> offsets = *getPromotableSubViewOffsets(subView);
+    SmallVector<int64_t> strides(offsets.size(), 1);
+    return vector::InsertStridedSliceOp::create(
+               builder, op->getLoc(), aliasValue, reachingDef, offsets, strides)
+        .getResult();
+  }
+};
+
+/// Companion `PromotableOpInterface` model: once the slot is promoted, the
+/// subview has no remaining memory uses and is erased.
+struct SubViewOpPromotableModel
+    : public PromotableOpInterface::ExternalModel<SubViewOpPromotableModel,
+                                                  memref::SubViewOp> {
+  bool canUsesBeRemoved(Operation *op,
+                        const SmallPtrSetImpl<OpOperand *> &blockingUses,
+                        SmallVectorImpl<OpOperand *> &newBlockingUses,
+                        const DataLayout &dataLayout) const {
+    // The subview result is itself a blocking use of the parent slot; its own
+    // users (the transfers) are resolved through the alias projections.
+    for (OpOperand &use : op->getResult(0).getUses())
+      newBlockingUses.push_back(&use);
+    return true;
+  }
+
+  DeletionKind
+  removeBlockingUses(Operation *op,
+                     const SmallPtrSetImpl<OpOperand *> &blockingUses,
+                     OpBuilder &builder) const {
+    return DeletionKind::Delete;
+  }
+};
+} // namespace
+
+//===----------------------------------------------------------------------===//
+//  Register external models
+//===----------------------------------------------------------------------===//
+
+void mlir::memref::registerMemorySlotOpInterfaceExternalModels(
+    DialectRegistry &registry) {
+  registry.addExtension(+[](MLIRContext *ctx, memref::MemRefDialect *dialect) {
+    memref::SubViewOp::attachInterface<SubViewOpAliasModel>(*ctx);
+    memref::SubViewOp::attachInterface<SubViewOpPromotableModel>(*ctx);
+  });
+}

diff  --git a/mlir/lib/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.cpp b/mlir/lib/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.cpp
index f33b746240d8e..e261dfd7c1d66 100644
--- a/mlir/lib/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.cpp
@@ -1,4 +1,4 @@
-//===- MemorySlotOpInterfaceImpl.cpp - Mem2Reg for vector ops -------------===//
+//===- MemorySlotOpInterfaceImpl.cpp - Mem2Reg for Vector ops -------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -16,23 +16,14 @@
 //     vector value; `vector.transfer_write` of the whole buffer becomes a new
 //     definition of it (see the `PromotableMemOpInterface` models below).
 //
-//   * a static, same-rank `memref.subview` is exposed as a promotable sub-slice
-//     alias of the buffer's slot (via `PromotableAliaserInterface`): a read of
-//     the subview projects out of the vector value with
-//     `vector.extract_strided_slice`, and a write into it composes back into
-//     the value with `vector.insert_strided_slice`. This lets a buffer that is
-//     only ever accessed through static subviews promote as well, with partial
-//     and overlapping sub-writes composing in program order.
-//
-// Accesses that are not whole-(sub-)buffer -- dynamic offsets, rank-reducing or
-// non-unit-stride subviews, masked or partial transfers, non-zero transfer
-// indices -- are left untouched, so the buffer is not promoted.
+// Accesses that are not whole-(sub-)buffer -- masked or partial transfers,
+// non-zero transfer indices -- are left untouched, so the buffer is not
+// promoted.
 //
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.h"
 
-#include "mlir/Dialect/MemRef/IR/MemRef.h"
 #include "mlir/Dialect/Utils/StaticValueUtils.h"
 #include "mlir/Dialect/Vector/IR/VectorOps.h"
 #include "mlir/IR/BuiltinTypes.h"
@@ -165,163 +156,13 @@ struct TransferWriteOpMemOpModel
 
 } // namespace
 
-//===----------------------------------------------------------------------===//
-//  memref.subview aliaser
-//===----------------------------------------------------------------------===//
-
-/// Returns the offsets of `subView` as a static, contiguous, same-rank slice of
-/// its source, or nullopt if the subview is not promotable as a whole-buffer
-/// sub-slice. Promotion projects the parent buffer's vector value through
-/// `vector.extract_strided_slice` / `insert_strided_slice`, which require:
-///   * fully static offsets and sizes,
-///   * unit strides,
-///   * no rank reduction (result rank == source rank),
-/// so a dropped or dynamic dimension disqualifies the subview.
-static std::optional<SmallVector<int64_t>>
-getPromotableSubViewOffsets(memref::SubViewOp subView) {
-  auto srcType = dyn_cast<MemRefType>(subView.getSource().getType());
-  auto resType = dyn_cast<MemRefType>(subView.getResult().getType());
-  if (!srcType || !resType || !srcType.hasStaticShape() ||
-      !resType.hasStaticShape())
-    return std::nullopt;
-
-  // No rank reduction: extract/insert_strided_slice operate at a single rank.
-  if (srcType.getRank() != resType.getRank())
-    return std::nullopt;
-
-  // Unit strides only.
-  for (OpFoldResult stride : subView.getMixedStrides()) {
-    std::optional<int64_t> s = getConstantIntValue(stride);
-    if (!s || *s != 1)
-      return std::nullopt;
-  }
-
-  // Static offsets.
-  SmallVector<int64_t> offsets;
-  for (OpFoldResult offset : subView.getMixedOffsets()) {
-    std::optional<int64_t> o = getConstantIntValue(offset);
-    if (!o)
-      return std::nullopt;
-    offsets.push_back(*o);
-  }
-
-  // Static sizes (already implied by the result's static shape, but the sizes
-  // must match the result shape so the slice covers exactly the subview).
-  for (auto [size, dim] :
-       llvm::zip_equal(subView.getMixedSizes(), resType.getShape())) {
-    std::optional<int64_t> s = getConstantIntValue(size);
-    if (!s || *s != dim)
-      return std::nullopt;
-  }
-  return offsets;
-}
-
-namespace {
-
-/// Exposes a static, same-rank `memref.subview` as a sub-slice alias of a
-/// whole-buffer vector slot. Reads of the subview become
-/// `vector.extract_strided_slice` of the parent value; writes become
-/// `vector.insert_strided_slice` into the current reaching definition.
-struct SubViewOpAliasModel
-    : public PromotableAliaserInterface::ExternalModel<SubViewOpAliasModel,
-                                                       memref::SubViewOp> {
-  void getPromotableSlotAliases(Operation *op,
-                                OpOperand &aliasedSlotPointerOperand,
-                                const MemorySlot &parentSlot,
-                                SmallVectorImpl<MemorySlot> &newSlots) const {
-    auto subView = cast<memref::SubViewOp>(op);
-    if (aliasedSlotPointerOperand.get() != subView.getSource())
-      return;
-
-    // The parent slot must promote to a vector (whole-buffer promotion). A
-    // scalar (single-element) parent slot cannot be sliced.
-    auto parentVecType = dyn_cast<VectorType>(parentSlot.valueType);
-    if (!parentVecType)
-      return;
-
-    if (!getPromotableSubViewOffsets(subView))
-      return;
-
-    // The alias's value type is the sub-vector matching the subview's shape.
-    auto resType = cast<MemRefType>(subView.getResult().getType());
-    if (!VectorType::isValidElementType(resType.getElementType()))
-      return;
-    VectorType aliasVecType =
-        VectorType::get(resType.getShape(), resType.getElementType());
-    newSlots.push_back(MemorySlot{subView.getResult(), aliasVecType});
-  }
-
-  Value projectSlotValueToAliasValue(Operation *op,
-                                     OpOperand & /*aliasedSlotPointerOperand*/,
-                                     const MemorySlot & /*parentSlot*/,
-                                     const MemorySlot &aliasSlot,
-                                     Value slotValue,
-                                     OpBuilder &builder) const {
-    auto subView = cast<memref::SubViewOp>(op);
-    SmallVector<int64_t> offsets = *getPromotableSubViewOffsets(subView);
-    auto aliasVecType = cast<VectorType>(aliasSlot.valueType);
-    SmallVector<int64_t> strides(offsets.size(), 1);
-    return vector::ExtractStridedSliceOp::create(
-               builder, op->getLoc(), slotValue, offsets,
-               aliasVecType.getShape(), strides)
-        .getResult();
-  }
-
-  Value projectAliasValueToSlotValue(Operation *op,
-                                     OpOperand & /*aliasedSlotPointerOperand*/,
-                                     const MemorySlot & /*parentSlot*/,
-                                     const MemorySlot & /*aliasSlot*/,
-                                     Value aliasValue, Value reachingDef,
-                                     OpBuilder &builder) const {
-    auto subView = cast<memref::SubViewOp>(op);
-    SmallVector<int64_t> offsets = *getPromotableSubViewOffsets(subView);
-    SmallVector<int64_t> strides(offsets.size(), 1);
-    return vector::InsertStridedSliceOp::create(
-               builder, op->getLoc(), aliasValue, reachingDef, offsets, strides)
-        .getResult();
-  }
-};
-
-/// Companion `PromotableOpInterface` model: once the slot is promoted, the
-/// subview has no remaining memory uses and is erased.
-struct SubViewOpPromotableModel
-    : public PromotableOpInterface::ExternalModel<SubViewOpPromotableModel,
-                                                  memref::SubViewOp> {
-  bool canUsesBeRemoved(Operation *op,
-                        const SmallPtrSetImpl<OpOperand *> &blockingUses,
-                        SmallVectorImpl<OpOperand *> &newBlockingUses,
-                        const DataLayout &dataLayout) const {
-    // The subview result is itself a blocking use of the parent slot; its own
-    // users (the transfers) are resolved through the alias projections.
-    for (OpOperand &use : op->getResult(0).getUses())
-      newBlockingUses.push_back(&use);
-    return true;
-  }
-
-  DeletionKind
-  removeBlockingUses(Operation *op,
-                     const SmallPtrSetImpl<OpOperand *> &blockingUses,
-                     OpBuilder &builder) const {
-    return DeletionKind::Delete;
-  }
-};
-
-} // namespace
-
 //===----------------------------------------------------------------------===//
 //  Register external models
 //===----------------------------------------------------------------------===//
 
-void mlir::vector::registerMemorySlotOpInterfaceExternalModels(
-    DialectRegistry &registry) {
+void mlir::vector::registerMemorySlotExternalModels(DialectRegistry &registry) {
   registry.addExtension(+[](MLIRContext *ctx, vector::VectorDialect *dialect) {
     TransferReadOp::attachInterface<TransferReadOpMemOpModel>(*ctx);
     TransferWriteOp::attachInterface<TransferWriteOpMemOpModel>(*ctx);
   });
-  // The subview aliaser attaches to a MemRef op but lives here because the
-  // projections build Vector ops; Vector already depends on MemRef.
-  registry.addExtension(+[](MLIRContext *ctx, memref::MemRefDialect *dialect) {
-    memref::SubViewOp::attachInterface<SubViewOpAliasModel>(*ctx);
-    memref::SubViewOp::attachInterface<SubViewOpPromotableModel>(*ctx);
-  });
 }

diff  --git a/mlir/lib/RegisterAllDialects.cpp b/mlir/lib/RegisterAllDialects.cpp
index 11864144e843c..11005ab706cd3 100644
--- a/mlir/lib/RegisterAllDialects.cpp
+++ b/mlir/lib/RegisterAllDialects.cpp
@@ -59,6 +59,7 @@
 #include "mlir/Dialect/MemRef/IR/MemRefDialect.h"
 #include "mlir/Dialect/MemRef/IR/MemRefMemorySlot.h"
 #include "mlir/Dialect/MemRef/IR/ValueBoundsOpInterfaceImpl.h"
+#include "mlir/Dialect/MemRef/Transforms//MemorySlotOpInterfaceImpl.h"
 #include "mlir/Dialect/MemRef/Transforms/AllocationOpInterfaceImpl.h"
 #include "mlir/Dialect/MemRef/Transforms/BufferViewFlowOpInterfaceImpl.h"
 #include "mlir/Dialect/MemRef/Transforms/RuntimeOpVerification.h"
@@ -187,7 +188,8 @@ void mlir::registerAllDialects(DialectRegistry &registry) {
   memref::registerBufferViewFlowOpInterfaceExternalModels(registry);
   memref::registerRuntimeVerifiableOpInterfaceExternalModels(registry);
   memref::registerValueBoundsOpInterfaceExternalModels(registry);
-  memref::registerMemorySlotExternalModels(registry);
+  memref::registerDestructurableTypeExternalModels(registry);
+  memref::registerMemorySlotOpInterfaceExternalModels(registry);
   ml_program::registerBufferizableOpInterfaceExternalModels(registry);
   nvgpu::registerMemoryAccessOpInterfacesExternalModels(registry);
   scf::registerBufferDeallocationOpInterfaceExternalModels(registry);
@@ -205,7 +207,7 @@ void mlir::registerAllDialects(DialectRegistry &registry) {
   tosa::registerShardingInterfaceExternalModels(registry);
   vector::registerBufferizableOpInterfaceExternalModels(registry);
   vector::registerIndexedAccessOpInterfaceExternalModels(registry);
-  vector::registerMemorySlotOpInterfaceExternalModels(registry);
+  vector::registerMemorySlotExternalModels(registry);
   vector::registerSubsetOpInterfaceExternalModels(registry);
   vector::registerValueBoundsOpInterfaceExternalModels(registry);
   NVVM::registerNVVMTargetInterfaceExternalModels(registry);


        


More information about the Mlir-commits mailing list