[Mlir-commits] [mlir] [mlir][mem2reg] Promote whole-buffer memref to a vector SSA value (PR #211880)

Renato Golin llvmlistbot at llvm.org
Mon Jul 27 10:48:01 PDT 2026


================
@@ -0,0 +1,159 @@
+//===- 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Mem2Reg-related interfaces for Vector dialect
+// operations. It allows a memref that is only ever accessed as a whole buffer
+// through `vector.transfer_read`/`vector.transfer_write` to be promoted into a
+// single vector SSA value.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Vector/Transforms/MemorySlotOpInterfaceImpl.h"
+
+#include "mlir/Dialect/Utils/StaticValueUtils.h"
+#include "mlir/Dialect/Vector/IR/VectorOps.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/Interfaces/MemorySlotInterfaces.h"
+
+using namespace mlir;
+using namespace mlir::vector;
+
+//===----------------------------------------------------------------------===//
+//  Utilities
+//===----------------------------------------------------------------------===//
+
+/// Returns whether `xferOp` accesses exactly the whole contents of `slot`, so
+/// it can act as a plain whole-buffer load/store during Mem2Reg.
+template <typename TransferOpTy>
+static bool
+isWholeBufferTransfer(TransferOpTy xferOp, const MemorySlot &slot,
+                      const SmallPtrSetImpl<OpOperand *> &blockingUses) {
+  // The sole blocking use must be the slot pointer as the transfer's base.
+  if (blockingUses.size() != 1)
+    return false;
+  Value blockingUse = (*blockingUses.begin())->get();
+  if (blockingUse != slot.ptr || xferOp.getBase() != slot.ptr)
+    return false;
+
+  // Reject the tensor form (already implied, since slot pointers are memrefs).
+  if (!isa<MemRefType>(xferOp.getBase().getType()))
+    return false;
+
+  // Exact type match pins rank/extents/element type and rejects scalable
+  // vectors.
+  if (xferOp.getVectorType() != slot.elemType)
+    return false;
+
+  // Access must start at the buffer origin in every dimension.
+  for (Value index : xferOp.getIndices()) {
+    std::optional<int64_t> constIndex = getConstantIntValue(index);
+    if (!constIndex || *constIndex != 0)
+      return false;
+  }
+
+  // Identity map: no broadcast or transpose.
+  if (!xferOp.getPermutationMap().isIdentity())
+    return false;
+
+  // All dimensions in bounds: no out-of-buffer element, no padding.
+  if (xferOp.hasOutOfBoundsDim())
+    return false;
+
+  // A mask would make the access partial.
----------------
rengolin wrote:

```suggestion
  // A mask could make the access partial.
```

https://github.com/llvm/llvm-project/pull/211880


More information about the Mlir-commits mailing list