[Mlir-commits] [mlir] [mlir][vector] Implement IndexedAccessOpInterface for load, store, etc. (PR #196216)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Wed May 6 18:49:15 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Krzysztof Drewniak (krzysz00)
<details>
<summary>Changes</summary>
This commit adds simple (not trying to account for unit dimensions that could be cast away) implementations of IndexedAccessOpInterface to low-level vector operations like vector.load and vector.store, eliminating the need for the old-style code in FoldMemRefAliasOps.cpp. After this commit, it'll be possible to migrate all the other memref-rewriting passes (ExpandAddressComputation and FlattenMemRefs) to use the interface, taking a bunch of dialect dependencies off of memref/transforms.
Assisted-By: GPT 5.5 (pulled in old code, wrote some new tests)
---
Patch is 33.83 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/196216.diff
9 Files Affected:
- (modified) mlir/include/mlir/Dialect/MemRef/IR/MemoryAccessOpInterfaces.td (+5-1)
- (modified) mlir/include/mlir/Dialect/Vector/IR/VectorOps.td (+6)
- (added) mlir/include/mlir/Dialect/Vector/Transforms/IndexedAccessOpInterfaceImpl.h (+21)
- (modified) mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp (+13-318)
- (modified) mlir/lib/Dialect/Vector/IR/VectorOps.cpp (+4)
- (modified) mlir/lib/Dialect/Vector/Transforms/CMakeLists.txt (+1)
- (added) mlir/lib/Dialect/Vector/Transforms/IndexedAccessOpInterfaceImpl.cpp (+101)
- (modified) mlir/lib/RegisterAllDialects.cpp (+2)
- (modified) mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir (+124)
``````````diff
diff --git a/mlir/include/mlir/Dialect/MemRef/IR/MemoryAccessOpInterfaces.td b/mlir/include/mlir/Dialect/MemRef/IR/MemoryAccessOpInterfaces.td
index 7fc69b4fabca6..0f1ef521afc57 100644
--- a/mlir/include/mlir/Dialect/MemRef/IR/MemoryAccessOpInterfaces.td
+++ b/mlir/include/mlir/Dialect/MemRef/IR/MemoryAccessOpInterfaces.td
@@ -53,7 +53,11 @@ def IndexedAccessOpInterface : OpInterface<"IndexedAccessOpInterface"> {
InterfaceMethod<
/*desc=*/[{
Return the shape of the portion of the memref that is being accessed by
- this operation, if known, ignoring leading unit dimensions.
+ this operation, if known. This shape describes the access dimensions
+ whose strides are semantically important for this operation.
+ Implementations shall omit dimensions whose strides do not affect the
+ operation semantics. (In particular, if an operation will access one
+ element of the base memref, this method should return `{}`.)
Reindexing transformations may not modify the *strides* of the trailing
N dimensions, where N is the size returned value, and should ensure that
diff --git a/mlir/include/mlir/Dialect/Vector/IR/VectorOps.td b/mlir/include/mlir/Dialect/Vector/IR/VectorOps.td
index 8f4fa5ca6a844..28a8109cb59c0 100644
--- a/mlir/include/mlir/Dialect/Vector/IR/VectorOps.td
+++ b/mlir/include/mlir/Dialect/Vector/IR/VectorOps.td
@@ -1658,6 +1658,7 @@ def Vector_TransferWriteOp :
let hasVerifier = 1;
}
+// Promises IndexedAccessOpInterface.
def Vector_LoadOp : Vector_Op<"load", [
DeclareOpInterfaceMethods<VectorUnrollOpInterface, ["getShapeForUnroll"]>,
DeclareOpInterfaceMethods<MemorySpaceCastConsumerOpInterface>,
@@ -1776,6 +1777,7 @@ def Vector_LoadOp : Vector_Op<"load", [
"$base `[` $indices `]` attr-dict `:` type($base) `,` type($result)";
}
+// Promises IndexedAccessOpInterface.
def Vector_StoreOp : Vector_Op<"store", [
DeclareOpInterfaceMethods<VectorUnrollOpInterface, ["getShapeForUnroll"]>,
DeclareOpInterfaceMethods<MemorySpaceCastConsumerOpInterface>,
@@ -1883,6 +1885,7 @@ def Vector_StoreOp : Vector_Op<"store", [
"`:` type($base) `,` type($valueToStore)";
}
+// Promises IndexedAccessOpInterface.
def Vector_MaskedLoadOp :
Vector_Op<"maskedload", [
DeclareOpInterfaceMethods<MemorySpaceCastConsumerOpInterface>,
@@ -1978,6 +1981,7 @@ def Vector_MaskedLoadOp :
];
}
+// Promises IndexedAccessOpInterface.
def Vector_MaskedStoreOp :
Vector_Op<"maskedstore", [
DeclareOpInterfaceMethods<MemorySpaceCastConsumerOpInterface>,
@@ -2251,6 +2255,7 @@ def Vector_ScatterOp
}]>];
}
+// Promises IndexedAccessOpInterface.
def Vector_ExpandLoadOp :
Vector_Op<"expandload", [
DeclareOpInterfaceMethods<MemorySpaceCastConsumerOpInterface>,
@@ -2342,6 +2347,7 @@ def Vector_ExpandLoadOp :
];
}
+// Promises IndexedAccessOpInterface.
def Vector_CompressStoreOp :
Vector_Op<"compressstore", [
DeclareOpInterfaceMethods<MemorySpaceCastConsumerOpInterface>,
diff --git a/mlir/include/mlir/Dialect/Vector/Transforms/IndexedAccessOpInterfaceImpl.h b/mlir/include/mlir/Dialect/Vector/Transforms/IndexedAccessOpInterfaceImpl.h
new file mode 100644
index 0000000000000..57fe661ad81f0
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Vector/Transforms/IndexedAccessOpInterfaceImpl.h
@@ -0,0 +1,21 @@
+//===- IndexedAccessOpInterfaceImpl.h ---------------------------*- 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_VECTOR_TRANSFORMS_INDEXEDACCESSOPINTERFACEIMPL_H
+#define MLIR_DIALECT_VECTOR_TRANSFORMS_INDEXEDACCESSOPINTERFACEIMPL_H
+
+namespace mlir {
+
+class DialectRegistry;
+
+namespace vector {
+void registerIndexedAccessOpInterfaceExternalModels(DialectRegistry ®istry);
+} // namespace vector
+} // namespace mlir
+
+#endif // MLIR_DIALECT_VECTOR_TRANSFORMS_INDEXEDACCESSOPINTERFACEIMPL_H
diff --git a/mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp b/mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp
index e36ddfa063e11..de7662753d142 100644
--- a/mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp
+++ b/mlir/lib/Dialect/MemRef/Transforms/FoldMemRefAliasOps.cpp
@@ -25,7 +25,6 @@
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallBitVector.h"
-#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/Debug.h"
#include <cstdint>
@@ -52,6 +51,8 @@ hasTrivialReassociationSuffix(ArrayRef<ReassociationIndices> reassocs,
int64_t n) {
if (n <= 0)
return true;
+ if (n > static_cast<int64_t>(reassocs.size()))
+ return false;
return llvm::all_of(
reassocs.take_back(n),
[&](const ReassociationIndices &indices) { return indices.size() == 1; });
@@ -60,89 +61,17 @@ hasTrivialReassociationSuffix(ArrayRef<ReassociationIndices> reassocs,
static bool hasTrailingUnitStrides(memref::SubViewOp subview, int64_t n) {
if (n <= 0)
return true;
- return llvm::all_of(subview.getStaticStrides().take_back(n),
- [](int64_t s) { return s == 1; });
+ ArrayRef<int64_t> strides = subview.getStaticStrides();
+ if (n > static_cast<int64_t>(strides.size()))
+ return false;
+ return llvm::all_of(strides.take_back(n), [](int64_t s) { return s == 1; });
}
-/// Helpers to access the memref operand for each op.
-template <typename LoadOrStoreOpTy>
-static Value getMemRefOperand(LoadOrStoreOpTy op) {
- return op.getMemref();
-}
-
-static Value getMemRefOperand(vector::LoadOp op) { return op.getBase(); }
-
-static Value getMemRefOperand(vector::StoreOp op) { return op.getBase(); }
-
-static Value getMemRefOperand(vector::MaskedLoadOp op) { return op.getBase(); }
-
-static Value getMemRefOperand(vector::MaskedStoreOp op) { return op.getBase(); }
-
//===----------------------------------------------------------------------===//
// Patterns
//===----------------------------------------------------------------------===//
namespace {
-/// Merges subview operation with load/transferRead operation.
-template <typename OpTy>
-class LoadOpOfSubViewOpFolder final : public OpRewritePattern<OpTy> {
-public:
- using OpRewritePattern<OpTy>::OpRewritePattern;
-
- LogicalResult matchAndRewrite(OpTy loadOp,
- PatternRewriter &rewriter) const override;
-};
-
-/// Merges expand_shape operation with load/transferRead operation.
-template <typename OpTy>
-class LoadOpOfExpandShapeOpFolder final : public OpRewritePattern<OpTy> {
-public:
- using OpRewritePattern<OpTy>::OpRewritePattern;
-
- LogicalResult matchAndRewrite(OpTy loadOp,
- PatternRewriter &rewriter) const override;
-};
-
-/// Merges collapse_shape operation with load/transferRead operation.
-template <typename OpTy>
-class LoadOpOfCollapseShapeOpFolder final : public OpRewritePattern<OpTy> {
-public:
- using OpRewritePattern<OpTy>::OpRewritePattern;
-
- LogicalResult matchAndRewrite(OpTy loadOp,
- PatternRewriter &rewriter) const override;
-};
-
-/// Merges subview operation with store/transferWriteOp operation.
-template <typename OpTy>
-class StoreOpOfSubViewOpFolder final : public OpRewritePattern<OpTy> {
-public:
- using OpRewritePattern<OpTy>::OpRewritePattern;
-
- LogicalResult matchAndRewrite(OpTy storeOp,
- PatternRewriter &rewriter) const override;
-};
-
-/// Merges expand_shape operation with store/transferWriteOp operation.
-template <typename OpTy>
-class StoreOpOfExpandShapeOpFolder final : public OpRewritePattern<OpTy> {
-public:
- using OpRewritePattern<OpTy>::OpRewritePattern;
-
- LogicalResult matchAndRewrite(OpTy storeOp,
- PatternRewriter &rewriter) const override;
-};
-
-/// Merges collapse_shape operation with store/transferWriteOp operation.
-template <typename OpTy>
-class StoreOpOfCollapseShapeOpFolder final : public OpRewritePattern<OpTy> {
-public:
- using OpRewritePattern<OpTy>::OpRewritePattern;
-
- LogicalResult matchAndRewrite(OpTy storeOp,
- PatternRewriter &rewriter) const override;
-};
-
/// Folds subview(subview(x)) to a single subview(x).
class SubViewOfSubViewFolder : public OpRewritePattern<memref::SubViewOp> {
public:
@@ -286,226 +215,6 @@ struct TransferOpOfCollapseShapeOpFolder final
};
} // namespace
-static LogicalResult preconditionsFoldSubViewOp(RewriterBase &rewriter,
- Operation *op,
- memref::SubViewOp subviewOp) {
- return success();
-}
-
-template <typename OpTy>
-LogicalResult LoadOpOfSubViewOpFolder<OpTy>::matchAndRewrite(
- OpTy loadOp, PatternRewriter &rewriter) const {
- auto subViewOp =
- getMemRefOperand(loadOp).template getDefiningOp<memref::SubViewOp>();
-
- if (!subViewOp)
- return rewriter.notifyMatchFailure(loadOp, "not a subview producer");
-
- LogicalResult preconditionResult =
- preconditionsFoldSubViewOp(rewriter, loadOp, subViewOp);
- if (failed(preconditionResult))
- return preconditionResult;
-
- SmallVector<Value> sourceIndices;
- affine::resolveIndicesIntoOpWithOffsetsAndStrides(
- rewriter, loadOp.getLoc(), subViewOp.getMixedOffsets(),
- subViewOp.getMixedStrides(), subViewOp.getDroppedDims(),
- loadOp.getIndices(), sourceIndices);
-
- llvm::TypeSwitch<Operation *, void>(loadOp)
- .Case([&](memref::LoadOp op) {
- rewriter.replaceOpWithNewOp<memref::LoadOp>(
- loadOp, subViewOp.getSource(), sourceIndices, op.getNontemporal());
- })
- .Case([&](vector::LoadOp op) {
- rewriter.replaceOpWithNewOp<vector::LoadOp>(
- op, op.getType(), subViewOp.getSource(), sourceIndices);
- })
- .Case([&](vector::MaskedLoadOp op) {
- rewriter.replaceOpWithNewOp<vector::MaskedLoadOp>(
- op, op.getType(), subViewOp.getSource(), sourceIndices,
- op.getMask(), op.getPassThru());
- })
- .DefaultUnreachable("unexpected operation");
- return success();
-}
-
-template <typename OpTy>
-LogicalResult LoadOpOfExpandShapeOpFolder<OpTy>::matchAndRewrite(
- OpTy loadOp, PatternRewriter &rewriter) const {
- auto expandShapeOp =
- getMemRefOperand(loadOp).template getDefiningOp<memref::ExpandShapeOp>();
-
- if (!expandShapeOp)
- return failure();
-
- SmallVector<Value> sourceIndices;
- // memref.load guarantees that indexes start inbounds while the vector
- // operations don't. This impacts if our linearization is `disjoint`
- resolveSourceIndicesExpandShape(loadOp.getLoc(), rewriter, expandShapeOp,
- loadOp.getIndices(), sourceIndices,
- isa<memref::LoadOp>(loadOp.getOperation()));
-
- return llvm::TypeSwitch<Operation *, LogicalResult>(loadOp)
- .Case([&](memref::LoadOp op) {
- rewriter.replaceOpWithNewOp<memref::LoadOp>(
- loadOp, expandShapeOp.getViewSource(), sourceIndices,
- op.getNontemporal());
- return success();
- })
- .Case([&](vector::LoadOp op) {
- rewriter.replaceOpWithNewOp<vector::LoadOp>(
- op, op.getType(), expandShapeOp.getViewSource(), sourceIndices,
- op.getNontemporal());
- return success();
- })
- .Case([&](vector::MaskedLoadOp op) {
- rewriter.replaceOpWithNewOp<vector::MaskedLoadOp>(
- op, op.getType(), expandShapeOp.getViewSource(), sourceIndices,
- op.getMask(), op.getPassThru());
- return success();
- })
- .DefaultUnreachable("unexpected operation");
-}
-
-template <typename OpTy>
-LogicalResult LoadOpOfCollapseShapeOpFolder<OpTy>::matchAndRewrite(
- OpTy loadOp, PatternRewriter &rewriter) const {
- auto collapseShapeOp = getMemRefOperand(loadOp)
- .template getDefiningOp<memref::CollapseShapeOp>();
-
- if (!collapseShapeOp)
- return failure();
-
- SmallVector<Value> sourceIndices;
- resolveSourceIndicesCollapseShape(loadOp.getLoc(), rewriter, collapseShapeOp,
- loadOp.getIndices(), sourceIndices);
- llvm::TypeSwitch<Operation *, void>(loadOp)
- .Case([&](memref::LoadOp op) {
- rewriter.replaceOpWithNewOp<memref::LoadOp>(
- loadOp, collapseShapeOp.getViewSource(), sourceIndices,
- op.getNontemporal());
- })
- .Case([&](vector::LoadOp op) {
- rewriter.replaceOpWithNewOp<vector::LoadOp>(
- op, op.getType(), collapseShapeOp.getViewSource(), sourceIndices,
- op.getNontemporal());
- })
- .Case([&](vector::MaskedLoadOp op) {
- rewriter.replaceOpWithNewOp<vector::MaskedLoadOp>(
- op, op.getType(), collapseShapeOp.getViewSource(), sourceIndices,
- op.getMask(), op.getPassThru());
- })
- .DefaultUnreachable("unexpected operation");
- return success();
-}
-
-template <typename OpTy>
-LogicalResult StoreOpOfSubViewOpFolder<OpTy>::matchAndRewrite(
- OpTy storeOp, PatternRewriter &rewriter) const {
- auto subViewOp =
- getMemRefOperand(storeOp).template getDefiningOp<memref::SubViewOp>();
-
- if (!subViewOp)
- return rewriter.notifyMatchFailure(storeOp, "not a subview producer");
-
- LogicalResult preconditionResult =
- preconditionsFoldSubViewOp(rewriter, storeOp, subViewOp);
- if (failed(preconditionResult))
- return preconditionResult;
-
- SmallVector<Value> sourceIndices;
- affine::resolveIndicesIntoOpWithOffsetsAndStrides(
- rewriter, storeOp.getLoc(), subViewOp.getMixedOffsets(),
- subViewOp.getMixedStrides(), subViewOp.getDroppedDims(),
- storeOp.getIndices(), sourceIndices);
-
- llvm::TypeSwitch<Operation *, void>(storeOp)
- .Case([&](memref::StoreOp op) {
- rewriter.replaceOpWithNewOp<memref::StoreOp>(
- op, op.getValue(), subViewOp.getSource(), sourceIndices,
- op.getNontemporal());
- })
- .Case([&](vector::StoreOp op) {
- rewriter.replaceOpWithNewOp<vector::StoreOp>(
- op, op.getValueToStore(), subViewOp.getSource(), sourceIndices);
- })
- .Case([&](vector::MaskedStoreOp op) {
- rewriter.replaceOpWithNewOp<vector::MaskedStoreOp>(
- op, subViewOp.getSource(), sourceIndices, op.getMask(),
- op.getValueToStore());
- })
- .DefaultUnreachable("unexpected operation");
- return success();
-}
-
-template <typename OpTy>
-LogicalResult StoreOpOfExpandShapeOpFolder<OpTy>::matchAndRewrite(
- OpTy storeOp, PatternRewriter &rewriter) const {
- auto expandShapeOp =
- getMemRefOperand(storeOp).template getDefiningOp<memref::ExpandShapeOp>();
-
- if (!expandShapeOp)
- return failure();
-
- SmallVector<Value> sourceIndices;
- // memref.store guarantees that indexes start inbounds while the vector
- // operations don't. This impacts if our linearization is `disjoint`
- resolveSourceIndicesExpandShape(storeOp.getLoc(), rewriter, expandShapeOp,
- storeOp.getIndices(), sourceIndices,
- isa<memref::StoreOp>(storeOp.getOperation()));
- llvm::TypeSwitch<Operation *, void>(storeOp)
- .Case([&](memref::StoreOp op) {
- rewriter.replaceOpWithNewOp<memref::StoreOp>(
- storeOp, op.getValueToStore(), expandShapeOp.getViewSource(),
- sourceIndices, op.getNontemporal());
- })
- .Case([&](vector::StoreOp op) {
- rewriter.replaceOpWithNewOp<vector::StoreOp>(
- op, op.getValueToStore(), expandShapeOp.getViewSource(),
- sourceIndices, op.getNontemporal());
- })
- .Case([&](vector::MaskedStoreOp op) {
- rewriter.replaceOpWithNewOp<vector::MaskedStoreOp>(
- op, expandShapeOp.getViewSource(), sourceIndices, op.getMask(),
- op.getValueToStore());
- })
- .DefaultUnreachable("unexpected operation");
- return success();
-}
-
-template <typename OpTy>
-LogicalResult StoreOpOfCollapseShapeOpFolder<OpTy>::matchAndRewrite(
- OpTy storeOp, PatternRewriter &rewriter) const {
- auto collapseShapeOp = getMemRefOperand(storeOp)
- .template getDefiningOp<memref::CollapseShapeOp>();
-
- if (!collapseShapeOp)
- return failure();
-
- SmallVector<Value> sourceIndices;
- resolveSourceIndicesCollapseShape(storeOp.getLoc(), rewriter, collapseShapeOp,
- storeOp.getIndices(), sourceIndices);
- llvm::TypeSwitch<Operation *, void>(storeOp)
- .Case([&](memref::StoreOp op) {
- rewriter.replaceOpWithNewOp<memref::StoreOp>(
- storeOp, op.getValueToStore(), collapseShapeOp.getViewSource(),
- sourceIndices, op.getNontemporal());
- })
- .Case([&](vector::StoreOp op) {
- rewriter.replaceOpWithNewOp<vector::StoreOp>(
- op, op.getValueToStore(), collapseShapeOp.getViewSource(),
- sourceIndices, op.getNontemporal());
- })
- .Case([&](vector::MaskedStoreOp op) {
- rewriter.replaceOpWithNewOp<vector::MaskedStoreOp>(
- op, collapseShapeOp.getViewSource(), sourceIndices, op.getMask(),
- op.getValueToStore());
- })
- .DefaultUnreachable("unexpected operation");
- return success();
-}
-
LogicalResult
AccessOpOfSubViewOpFolder::matchAndRewrite(memref::IndexedAccessOpInterface op,
PatternRewriter &rewriter) const {
@@ -849,27 +558,13 @@ LogicalResult TransferOpOfCollapseShapeOpFolder::matchAndRewrite(
}
void memref::populateFoldMemRefAliasOpPatterns(RewritePatternSet &patterns) {
- patterns.add<
- // Interface-based patterns to which we will be migrating.
- AccessOpOfSubViewOpFolder, AccessOpOfExpandShapeOpFolder,
- AccessOpOfCollapseShapeOpFolder, IndexedMemCopyOpOfSubViewOpFolder,
- IndexedMemCopyOpOfExpandShapeOpFolder,
- IndexedMemCopyOpOfCollapseShapeOpFolder, TransferOpOfSubViewOpFolder,
- TransferOpOfExpandShapeOpFolder, TransferOpOfCollapseShapeOpFolder,
- // The old way of doing things. Don't add more of these.
- LoadOpOfSubViewOpFolder<vector::LoadOp>,
- LoadOpOfSubViewOpFolder<vector::MaskedLoadOp>,
- StoreOpOfSubViewOpFolder<vector::StoreOp>,
- StoreOpOfSubViewOpFolder<vector::MaskedStoreOp>,
- LoadOpOfExpandShapeOpFolder<vector::LoadOp>,
- LoadOpOfExpandShapeOpFolder<vector::MaskedLoadOp>,
- StoreOpOfExpandShapeOpFolder<vector::StoreOp>,
- StoreOpOfExpandShapeOpFolder<vector::MaskedStoreOp>,
- LoadOpOfCollapseShapeOpFolder<vector::LoadOp>,
- LoadOpOfCollapseShapeOpFolder<vector::MaskedLoadOp>,
- StoreOpOfCollapseShapeOpFolder<vector::StoreOp>,
- StoreOpOfCollapseShapeOpFolder<vector::MaskedStoreOp>,
- SubViewOfSubViewFolder>(patterns.getContext());
+ patterns
+ .add<AccessOpOfSubViewOpFolder, AccessOpOfExpandShapeOpFolder,
+ AccessOpOfCollapseShapeOpFolder, IndexedMemCopyOpOfSubViewOpFolder,
+ IndexedMemCopyOpOfExpandShapeOpFolder,
+ IndexedMemCopyOpOfCollapseShapeOpFolder, TransferOpOfSubViewOpFolder,
+ TransferOpOfExpandShapeOpFolder, TransferOpOfCollapseShapeOpFolder,
+ SubViewOfSubViewFolder>(patterns.getContext());
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
index 780b0cbb36120..51be1e4431e70 100644
--- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
+++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
@@ -19,6 +19,7 @@
#include "mlir/Dialect/Arith/Utils/Utils.h"
#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/Dialect/MemRef/IR/MemoryAccessOpInterfaces.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/UB/IR/UBMatchers.h"
#include "mlir/Dialect/Utils/IndexingUtils.h"
@@ -483,6 +484,9 @@ void VectorDialect::initialize() {
addInterfaces<Vector...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/196216
More information about the Mlir-commits
mailing list