[Mlir-commits] [mlir] Add examples for reinterpret_cast and subview operators to show their behavior in relation to their input memref underlying memory and view (PR #135244)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Apr 10 12:59:21 PDT 2025


https://github.com/ivangarcia44 created https://github.com/llvm/llvm-project/pull/135244

While working on #134845 I was trying to understand the difference of how the reinterpret_cast and subview operators see the input memref, but it was not clear to me.

I did a couple of experiments in which I learned that the subview takes into account the view of the input memref to create the view of the output memref, while the reinterpret_cast just uses the underlying memory of the input memref.

I thought it would help future readers to see these two experiements as examples in the documentation to quickly figure out the difference between these two operators.

>From 2dac9bb56ad2afd251a44296983687c5a1ce320c Mon Sep 17 00:00:00 2001
From: Ivan Garcia <igarcia at vdi-ah2ddp-178.dhcp.mathworks.com>
Date: Thu, 10 Apr 2025 15:52:31 -0400
Subject: [PATCH] Add examples for reinterpret_cast and subview operators to
 show their behavior in relation to their input memref underlying memory and
 view.

---
 .../mlir/Dialect/MemRef/IR/MemRefOps.td       | 102 +++++++++++++++++-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
index 3edc2433c85ea..909b5815ef89e 100644
--- a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
+++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
@@ -1331,7 +1331,7 @@ def MemRef_ReinterpretCastOp
   let description = [{
     Modify offset, sizes and strides of an unranked/ranked memref.
 
-    Example:
+    Example 1:
     ```mlir
     memref.reinterpret_cast %ranked to
       offset: [0],
@@ -1363,6 +1363,58 @@ def MemRef_ReinterpretCastOp
     %dst.sizes = %sizes
     %dst.strides = %strides
     ```
+
+    Example 2:
+
+    Consecutive `reinterpret_cast` operations on memref's with static dimensions.
+
+    We distinguish between *underlying memory* — the sequence of elements as
+    they appear in the contiguous memory of the memref — and the *view*, which refers to
+    the underlying memory interpreted according to specified offsets, sizes, and strides.
+
+    ```mlir
+    %result1 = memref.reinterpret_cast %arg0 to offset: [9], sizes: [4, 4], strides: [16, 2] : memref<8x8xf32, strided<[8, 1], offset: 0>> to memref<4x4xf32, strided<[16, 2], offset: 9>>
+
+    %result2 = memref.reinterpret_cast %result1 to offset: [0], sizes: [2, 2], strides: [4, 2] : memref<4x4xf32, strided<[16, 2], offset: 9>> to memref<2x2xf32, strided<[4, 2], offset: 0>>
+    ```
+
+    The input memref `%arg0` has the following view. The underlying memory consists
+    of a linear sequence of integers from 1 to 64:
+
+    ```mlir
+    [[1,  2,  3,  4,  5,  6,  7,  8],
+    [9,  10, 11, 12, 13, 14, 15, 16],
+    [17, 18, 19, 20, 21, 22, 23, 24],
+    [25, 26, 27, 28, 29, 30, 31, 32],
+    [33, 34, 35, 36, 37, 38, 39, 40],
+    [41, 42, 43, 44, 45, 46, 47, 48],
+    [49, 50, 51, 52, 53, 54, 55, 56],
+    [57, 58, 59, 60, 61, 62, 63, 64]]
+    ```
+
+    Following the first `reinterpret_cast`, the view of `%result1` is:
+
+    ```mlir
+    [[10, 12, 14, 16],
+    [26, 28, 30, 32],
+    [42, 44, 46, 48],
+    [58, 60, 62, 64]]
+    ```
+
+    Note: The offset and strides are relative to the underlying memory of `%arg0`.
+
+    The second `reinterpret_cast` results in the following view for `%result2`:
+
+    ```mlir
+    [[1, 3],
+    [5, 7]]
+    ```
+
+    It is important to observe that the offset and stride are relative to the base underlying
+    memory of the memref, starting at 1, not at 10 as seen in the output of `%result1`.
+    This behavior contrasts with the `subview` operator, where values are relative to the view of
+    the memref (refer to `subview` examples). Consequently, the second `reinterpret_cast` behaves
+    as if `%arg0` were passed directly as its argument.
   }];
 
   let arguments = (ins Arg<AnyRankedOrUnrankedMemRef, "", []>:$source,
@@ -1942,7 +1994,55 @@ def SubViewOp : MemRef_OpWithOffsetSizesAndStrides<"subview", [
     %1 = memref.subview %0[0, 0, 0] [8, 16, 4] [1, 1, 1]
         : memref<8x16x4xf32> to memref<8x16x4xf32>
     ```
+    Example 6:
+
+    Consecutive `subview` operations on memref's with static dimensions.
+
+    We distinguish between *underlying memory* — the sequence of elements as
+    they appear in the contiguous memory of the memref — and the *view*, which refers to
+    the underlying memory interpreted according to specified offsets, sizes, and strides.
+
+    ```mlir
+    %result1 = memref.subview %arg0[1, 1][4, 4][2, 2] : memref<8x8xf32, strided<[8, 1], offset: 0>> to memref<4x4xf32, strided<[16, 2], offset: 9>>
+
+    %result2 = memref.subview %result1[1, 1][2, 2][2, 2] : memref<4x4xf32, strided<[16, 2], offset: 9>> to memref<2x2xf32, strided<[32, 4], offset: 27>>
+    ```
+
+    The input memref `%arg0` has the following view. The underlying memory for this input
+    memref is a linear sequence of integers from 1 to 64:
+
+    ```mlir
+    [[1,  2,  3,  4,  5,  6,  7,  8],
+    [9,  10, 11, 12, 13, 14, 15, 16],
+    [17, 18, 19, 20, 21, 22, 23, 24],
+    [25, 26, 27, 28, 29, 30, 31, 32],
+    [33, 34, 35, 36, 37, 38, 39, 40],
+    [41, 42, 43, 44, 45, 46, 47, 48],
+    [49, 50, 51, 52, 53, 54, 55, 56],
+    [57, 58, 59, 60, 61, 62, 63, 64]]
+    ```
+
+    Following the first `subview`, the view of `%result1` is:
+
+    ```mlir
+    [[10, 12, 14, 16],
+    [26, 28, 30, 32],
+    [42, 44, 46, 48],
+    [58, 60, 62, 64]]
+    ```
+
+    Note: The offset and strides are relative to the memref view of `%arg0` (compare to the
+    corresponding `reinterpret_cast` example).
+
+    The second `subview` results in the following view for `%result2`:
+
+    ```mlir
+    [[28, 32],
+    [60, 64]]
+    ```
 
+    Unlike the `reinterpret_cast`, the values are relative to the view of the input memref
+    (`%result1` in this case) and not its underlying memory.
   }];
 
   let arguments = (ins AnyMemRef:$source,



More information about the Mlir-commits mailing list