[Mlir-commits] [mlir] aa673fa - [mlir][linalg] Fix rank-reducing insert_slice vectorization writing to wrong dims (#226490)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sat Oct 17 02:30:41 PDT 2026


Author: Dhairyashil R G
Date: 2026-10-17T15:00:35+05:30
New Revision: aa673fae32d57e8d9bd65dabc48eb361439aa55f

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

LOG: [mlir][linalg] Fix rank-reducing insert_slice vectorization writing to wrong dims (#226490)

Vectorizing a rank-reducing `tensor.insert_slice` took the vector shape
from the non-dropped result dims, but wrote the vector back with an
implied minor-identity permutation map, i.e. onto the trailing result
dims. When the dropped unit dims are not the trailing ones, those are
the wrong dims.

Inserting a `tensor<5xi32>` into `tensor<5x3xi32>` at `[0, 2] [5, 1] [1,
1]` fills column 2, one element per row. Vectorized, the write went
along dim 1, so only the first element landed and the other four were
discarded by the out-of-bounds check. With user-provided vector sizes
the write was masked with `dim(1) - index(0)` and stored past the end of
the row instead.

Fixed by passing a permutation map built from the non-dropped result
dims, and by making `createWriteOrMaskedWrite` use the dims that map
selects, both to decide whether a mask is needed and to size it: each
mask size is `dim - index` for that dim.

This also fixes the masked write for a dropped leading dim at a non-zero
offset. Each offset used to be subtracted from the wrong dim, so, for
example, a 4-row vector written from row 6 of an 8-row dim was left
unmasked.

Three of the four existing rank-reducing tests in insert-slice.mlir were
checking the old write; they now check the permutation map. New tests
cover the masked path, and a new integration test requires the
vectorized and un-vectorized forms to print the same result.

Part of #227821.
Related: #221293 (same bug; its stride check is still needed).

Context:
https://discourse.llvm.org/t/rfc-should-vector-transfer-read-write-keep-in-bounds-measurements-on-the-masking-alternative/91649

Assisted-by: Claude

Added: 
    mlir/test/Integration/Dialect/Linalg/CPU/vectorize-insert-slice-rank-reducing.mlir

Modified: 
    mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
    mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
    mlir/test/Dialect/Linalg/vectorization/insert-slice.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
index 8c0a2ce0b9ec1e..081a6220c85ccb 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
@@ -3079,9 +3079,20 @@ vectorizeAsInsertSliceOp(RewriterBase &rewriter, tensor::InsertSliceOp sliceOp,
   // Create write
   auto writeIndices =
       getValueOrCreateConstantIndexOp(rewriter, loc, sliceOp.getMixedOffsets());
-  Operation *write =
-      vector::createWriteOrMaskedWrite(rewriter, loc, read, sliceOp.getDest(),
-                                       writeIndices, inputVectorSizes.empty());
+  // For a rank-reducing slice the vector need not cover the trailing result
+  // dims, so state which result dim each vector dim writes to.
+  AffineMap writeMap;
+  if (sourceType.getRank() != resultType.getRank()) {
+    SmallVector<AffineExpr> exprs;
+    for (int64_t resultDim : resultDimsForSourceDims)
+      exprs.push_back(rewriter.getAffineDimExpr(resultDim));
+    writeMap = AffineMap::get(resultType.getRank(), /*symbolCount=*/0, exprs,
+                              rewriter.getContext());
+  }
+
+  Operation *write = vector::createWriteOrMaskedWrite(
+      rewriter, loc, read, sliceOp.getDest(), writeIndices,
+      inputVectorSizes.empty(), writeMap);
 
   // 4. Finalize
   newResults.push_back(write->getResult(0));

diff  --git a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
index bd889a82bdb59a..14a6571549897d 100644
--- a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
+++ b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp
@@ -584,37 +584,42 @@ Operation *vector::createWriteOrMaskedWrite(OpBuilder &builder, Location loc,
   if (useInBoundsInsteadOfMasking)
     return write;
 
+  // The dest dims written to are those the permutation map selects. A null map
+  // means a minor identity: the trailing dims.
+  AffineMap map = permutationMap
+                      ? permutationMap
+                      : AffineMap::getMinorIdentityMap(destRank, vecToStoreRank,
+                                                       builder.getContext());
+
   // Check if masking is needed. If not, exit.
-  if (llvm::equal(vecToStoreShape, destShape.take_back(vecToStoreRank)))
+  if (llvm::equal(vecToStoreShape, applyPermutationMap(map, destShape)))
     return write;
 
   // Compute the mask and mask the write Op.
-  auto writeMaskType = VectorType::get(vecToStoreShape, builder.getI1Type(),
-                                       vecToStoreType.getScalableDims());
+  VectorType writeMaskType = inferTransferOpMaskType(vecToStoreType, map);
 
   SmallVector<OpFoldResult> destSizes =
       isa<MemRefType>(dest.getType())
           ? memref::getMixedSizes(builder, loc, dest)
           : tensor::getMixedSizes(builder, loc, dest);
 
-  // Compute sizes for write-mask
+  // Compute sizes for write-mask: `dim - index` for each dest dim written to,
+  // in increasing order, as the mask dims are.
+  SmallVector<int64_t> writtenDims;
+  for (AffineExpr expr : map.getResults())
+    writtenDims.push_back(cast<AffineDimExpr>(expr).getPosition());
+  llvm::sort(writtenDims);
   SmallVector<OpFoldResult> maskSizes;
-  if (useDefaultWriteIdxs) {
-    maskSizes = SmallVector<OpFoldResult>(destSizes.end() - vecToStoreRank,
-                                          destSizes.end());
-  } else {
-    size_t 
diff  = destShape.size() - vecToStoreRank;
-    for (int64_t idx = 0; idx < vecToStoreRank; idx++) {
-      auto value =
-          getValueOrCreateConstantIndexOp(builder, loc, destSizes[
diff  + idx]);
-      auto neg =
-          builder.createOrFold<arith::SubIOp>(loc, value, writeIndices[idx]);
-      maskSizes.push_back(OpFoldResult(neg));
-    }
+  for (int64_t dim : writtenDims) {
+    Value size = getValueOrCreateConstantIndexOp(builder, loc, destSizes[dim]);
+    maskSizes.push_back(
+        builder.createOrFold<arith::SubIOp>(loc, size, writeIndices[dim]));
   }
 
-  if (isMaskTriviallyFoldable(maskSizes, writeIndices, destShape,
-                              vecToStoreShape))
+  // TODO: isMaskTriviallyFoldable checks the trailing dims against the leading
+  // indices. Make it use the dims that the map selects and their indices.
+  if (!permutationMap && isMaskTriviallyFoldable(maskSizes, writeIndices,
+                                                 destShape, vecToStoreShape))
     return write;
 
   Value maskForWrite =

diff  --git a/mlir/test/Dialect/Linalg/vectorization/insert-slice.mlir b/mlir/test/Dialect/Linalg/vectorization/insert-slice.mlir
index a73b4b8035adbf..319095f97e1513 100644
--- a/mlir/test/Dialect/Linalg/vectorization/insert-slice.mlir
+++ b/mlir/test/Dialect/Linalg/vectorization/insert-slice.mlir
@@ -97,13 +97,16 @@ func.func private @insert_slice_dynamic_src_dim_non_leading_unit_dim_dropped(
   return %res : tensor<8x1x4xi32>
 }
 
+// CHECK-DAG: #[[$MAP_0_2:.*]] = affine_map<(d0, d1, d2) -> (d0, d2)>
+
 // CHECK-LABEL:   func.func private @insert_slice_dynamic_src_dim_non_leading_unit_dim_dropped(
 // CHECK-SAME:      %[[SRC:.*]]: tensor<?x4xi32>,
 // CHECK-SAME:      %[[SIZE:.*]]: index) -> tensor<8x1x4xi32> {
 // CHECK-DAG:       %[[PAD:.*]] = arith.constant 0 : i32
 // CHECK:           %[[INIT:.*]] = linalg.fill ins(%[[PAD]] : i32) outs({{.*}} : tensor<8x1x4xi32>) -> tensor<8x1x4xi32>
 // CHECK:           %[[READ:.*]] = vector.transfer_read %[[SRC]][%{{.*}}, %{{.*}}], %[[PAD]] {{.*}} : tensor<?x4xi32>, vector<8x4xi32>
-// CHECK:           %[[RES:.*]] = vector.transfer_write %[[READ]], %[[INIT]][%{{.*}}, %{{.*}}, %{{.*}}] {{.*}} : vector<8x4xi32>, tensor<8x1x4xi32>
+// Dim 1 is dropped, so the source dims map to result dims 0 and 2.
+// CHECK:           %[[RES:.*]] = vector.transfer_write %[[READ]], %[[INIT]][%{{.*}}, %{{.*}}, %{{.*}}] {{.*}}permutation_map = #[[$MAP_0_2]]{{.*}} : vector<8x4xi32>, tensor<8x1x4xi32>
 // CHECK:           return %[[RES]] : tensor<8x1x4xi32>
 
  module attributes {transform.with_named_sequence} {
@@ -131,6 +134,8 @@ func.func private @insert_slice_dynamic_src_dim_leading_unit_dim_dropped(
 // CHECK-DAG:       %[[PAD:.*]] = arith.constant 0 : i32
 // CHECK:           %[[INIT:.*]] = linalg.fill ins(%[[PAD]] : i32) outs({{.*}} : tensor<1x8x4xi32>) -> tensor<1x8x4xi32>
 // CHECK:           %[[READ:.*]] = vector.transfer_read %[[SRC]][%{{.*}}, %{{.*}}], %[[PAD]] {{.*}} : tensor<?x4xi32>, vector<8x4xi32>
+// Dim 0 is dropped, so the source dims are already the trailing result dims.
+// CHECK-NOT:       permutation_map
 // CHECK:           %[[RES:.*]] = vector.transfer_write %[[READ]], %[[INIT]][%{{.*}}, %{{.*}}, %{{.*}}] {{.*}} : vector<8x4xi32>, tensor<1x8x4xi32>
 // CHECK:           return %[[RES]] : tensor<1x8x4xi32>
 
@@ -153,13 +158,16 @@ func.func private @insert_slice_dynamic_src_dim_trailing_unit_dim_dropped(
   return %res : tensor<8x4x1xi32>
 }
 
+// CHECK-DAG: #[[$MAP_0_1:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)>
+
 // CHECK-LABEL:   func.func private @insert_slice_dynamic_src_dim_trailing_unit_dim_dropped(
 // CHECK-SAME:      %[[SRC:.*]]: tensor<?x4xi32>,
 // CHECK-SAME:      %[[SIZE:.*]]: index) -> tensor<8x4x1xi32> {
 // CHECK-DAG:       %[[PAD:.*]] = arith.constant 0 : i32
 // CHECK:           %[[INIT:.*]] = linalg.fill ins(%[[PAD]] : i32) outs({{.*}} : tensor<8x4x1xi32>) -> tensor<8x4x1xi32>
 // CHECK:           %[[READ:.*]] = vector.transfer_read %[[SRC]][%{{.*}}, %{{.*}}], %[[PAD]] {{.*}} : tensor<?x4xi32>, vector<8x4xi32>
-// CHECK:           %[[RES:.*]] = vector.transfer_write %[[READ]], %[[INIT]][%{{.*}}, %{{.*}}, %{{.*}}] : vector<8x4xi32>, tensor<8x4x1xi32>
+// Dim 2 is dropped, so the source dims map to result dims 0 and 1.
+// CHECK:           %[[RES:.*]] = vector.transfer_write %[[READ]], %[[INIT]][%{{.*}}, %{{.*}}, %{{.*}}] {{.*}}permutation_map = #[[$MAP_0_1]]{{.*}} : vector<8x4xi32>, tensor<8x4x1xi32>
 // CHECK:           return %[[RES]] : tensor<8x4x1xi32>
 
  module attributes {transform.with_named_sequence} {
@@ -181,13 +189,16 @@ func.func private @insert_slice_dynamic_src_dim_leading_and_trailing_unit_dims_d
   return %res : tensor<1x8x4x1xi32>
 }
 
+// CHECK-DAG: #[[$MAP_1_2:.*]] = affine_map<(d0, d1, d2, d3) -> (d1, d2)>
+
 // CHECK-LABEL:   func.func private @insert_slice_dynamic_src_dim_leading_and_trailing_unit_dims_dropped(
 // CHECK-SAME:      %[[SRC:.*]]: tensor<?x4xi32>,
 // CHECK-SAME:      %[[SIZE:.*]]: index) -> tensor<1x8x4x1xi32> {
 // CHECK-DAG:       %[[PAD:.*]] = arith.constant 0 : i32
 // CHECK:           %[[INIT:.*]] = linalg.fill ins(%[[PAD]] : i32) outs({{.*}} : tensor<1x8x4x1xi32>) -> tensor<1x8x4x1xi32>
 // CHECK:           %[[READ:.*]] = vector.transfer_read %[[SRC]][%{{.*}}, %{{.*}}], %[[PAD]] {{.*}} : tensor<?x4xi32>, vector<8x4xi32>
-// CHECK:           %[[RES:.*]] = vector.transfer_write %[[READ]], %[[INIT]][%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : vector<8x4xi32>, tensor<1x8x4x1xi32>
+// Dims 0 and 3 are dropped, so the source dims map to result dims 1 and 2.
+// CHECK:           %[[RES:.*]] = vector.transfer_write %[[READ]], %[[INIT]][%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] {{.*}}permutation_map = #[[$MAP_1_2]]{{.*}} : vector<8x4xi32>, tensor<1x8x4x1xi32>
 // CHECK:           return %[[RES]] : tensor<1x8x4x1xi32>
 
  module attributes {transform.with_named_sequence} {
@@ -359,3 +370,88 @@ func.func private @insert_slice_non_zero_offset_for_dyn_dim(%source: tensor<?x3x
     transform.yield
   }
  }
+
+// -----
+
+/// Dim 1 is dropped, so the vector is written to result dims 0 and 2. Its shape
+/// (1x4) equals the trailing result dims (1x4), but result dim 0 is dynamic, so
+/// the write needs a mask. The mask sizes come from result dims 0 and 2.
+
+func.func private @insert_slice_non_leading_unit_dim_dropped_dynamic_dest_dim(
+    %source: tensor<?x4xi32>, %dest: tensor<?x1x4xi32>, %size: index, %offset: index) -> tensor<?x1x4xi32> {
+  %res = tensor.insert_slice %source into %dest[%offset, 0, 0] [%size, 1, 4] [1, 1, 1] : tensor<?x4xi32> into tensor<?x1x4xi32>
+  return %res : tensor<?x1x4xi32>
+}
+
+// CHECK-DAG: #[[$MAP_D0_D2:.*]] = affine_map<(d0, d1, d2) -> (d0, d2)>
+
+// CHECK-LABEL:   func.func private @insert_slice_non_leading_unit_dim_dropped_dynamic_dest_dim(
+// CHECK-SAME:      %[[SRC:.*]]: tensor<?x4xi32>,
+// CHECK-SAME:      %[[DEST:.*]]: tensor<?x1x4xi32>,
+// CHECK-SAME:      %[[SIZE:.*]]: index,
+// CHECK-SAME:      %[[OFFSET:.*]]: index) -> tensor<?x1x4xi32> {
+// CHECK:           %[[PAD:.*]] = arith.constant 0 : i32
+// CHECK:           %[[C_0:.*]] = arith.constant 0 : index
+// CHECK:           %[[C_0_1:.*]] = arith.constant 0 : index
+// CHECK:           %[[C_0_2:.*]] = arith.constant 0 : index
+// CHECK:           %[[SRC_DIM_0:.*]] = tensor.dim %[[SRC]], %[[C_0_2]] : tensor<?x4xi32>
+// CHECK:           %[[C_4:.*]] = arith.constant 4 : index
+// CHECK:           %[[MASK_READ:.*]] = vector.create_mask %[[SRC_DIM_0]], %[[C_4]] : vector<1x4xi1>
+// CHECK:           %[[READ:.*]] = vector.mask %[[MASK_READ]] { vector.transfer_read %[[SRC]][%[[C_0_1]], %[[C_0_1]]], %[[PAD]] {in_bounds = [true, true]} : tensor<?x4xi32>, vector<1x4xi32> } : vector<1x4xi1> -> vector<1x4xi32>
+// CHECK:           %[[C_0_3:.*]] = arith.constant 0 : index
+// CHECK:           %[[C_0_4:.*]] = arith.constant 0 : index
+// CHECK:           %[[C_0_5:.*]] = arith.constant 0 : index
+// CHECK:           %[[DEST_DIM_0:.*]] = tensor.dim %[[DEST]], %[[C_0_5]] : tensor<?x1x4xi32>
+// CHECK:           %[[SIZE_0:.*]] = arith.subi %[[DEST_DIM_0]], %[[OFFSET]] : index
+// CHECK:           %[[C_4_1:.*]] = arith.constant 4 : index
+// CHECK:           %[[MASK_WRITE:.*]] = vector.create_mask %[[SIZE_0]], %[[C_4_1]] : vector<1x4xi1>
+// CHECK:           %[[RES:.*]] = vector.mask %[[MASK_WRITE]] { vector.transfer_write %[[READ]], %[[DEST]][%[[OFFSET]], %[[C_0_3]], %[[C_0_4]]] {in_bounds = [true, true], permutation_map = #[[$MAP_D0_D2]]} : vector<1x4xi32>, tensor<?x1x4xi32> } : vector<1x4xi1> -> tensor<?x1x4xi32>
+// CHECK:           return %[[RES]] : tensor<?x1x4xi32>
+
+ module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
+    %0 = transform.structured.match ops{["tensor.insert_slice"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    transform.structured.vectorize %0 vector_sizes [1, 4] : !transform.any_op
+    transform.yield
+  }
+ }
+
+// -----
+
+/// The leading unit dim is dropped and the insert index for result dim 1 is
+/// != 0. The source has fewer dims than the result, so each mask size must be
+/// computed from the result dim and the index of that same dim (8 - 6, 8 - 0).
+
+func.func private @insert_slice_leading_unit_dim_dropped_non_zero_offset(
+    %source: tensor<2x2xi32>, %dest: tensor<1x8x8xi32>) -> tensor<1x8x8xi32> {
+  %res = tensor.insert_slice %source into %dest[0, 6, 0] [1, 2, 2] [1, 1, 1] : tensor<2x2xi32> into tensor<1x8x8xi32>
+  return %res : tensor<1x8x8xi32>
+}
+
+// CHECK-LABEL:   func.func private @insert_slice_leading_unit_dim_dropped_non_zero_offset(
+// CHECK-SAME:      %[[SRC:.*]]: tensor<2x2xi32>,
+// CHECK-SAME:      %[[DEST:.*]]: tensor<1x8x8xi32>) -> tensor<1x8x8xi32> {
+// CHECK:           %[[PAD:.*]] = arith.constant 0 : i32
+// CHECK:           %[[C_0:.*]] = arith.constant 0 : index
+// CHECK:           %[[C_0_1:.*]] = arith.constant 0 : index
+// CHECK:           %[[C_2:.*]] = arith.constant 2 : index
+// CHECK:           %[[C_2_1:.*]] = arith.constant 2 : index
+// CHECK:           %[[MASK_READ:.*]] = vector.create_mask %[[C_2]], %[[C_2_1]] : vector<4x2xi1>
+// CHECK:           %[[READ:.*]] = vector.mask %[[MASK_READ]] { vector.transfer_read %[[SRC]][%[[C_0_1]], %[[C_0_1]]], %[[PAD]] {in_bounds = [true, true]} : tensor<2x2xi32>, vector<4x2xi32> } : vector<4x2xi1> -> vector<4x2xi32>
+// CHECK:           %[[C_0_2:.*]] = arith.constant 0 : index
+// CHECK:           %[[C_6:.*]] = arith.constant 6 : index
+// CHECK:           %[[C_0_3:.*]] = arith.constant 0 : index
+// CHECK:           %[[C_8:.*]] = arith.constant 8 : index
+// CHECK:           %[[C_2_2:.*]] = arith.constant 2 : index
+// CHECK:           %[[C_8_1:.*]] = arith.constant 8 : index
+// CHECK:           %[[MASK_WRITE:.*]] = vector.create_mask %[[C_2_2]], %[[C_8_1]] : vector<4x2xi1>
+// CHECK:           %[[RES:.*]] = vector.mask %[[MASK_WRITE]] { vector.transfer_write %[[READ]], %[[DEST]][%[[C_0_2]], %[[C_6]], %[[C_0_3]]] {in_bounds = [true, true]} : vector<4x2xi32>, tensor<1x8x8xi32> } : vector<4x2xi1> -> tensor<1x8x8xi32>
+// CHECK:           return %[[RES]] : tensor<1x8x8xi32>
+
+ module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
+    %0 = transform.structured.match ops{["tensor.insert_slice"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+    transform.structured.vectorize %0 vector_sizes [4, 2] : !transform.any_op
+    transform.yield
+  }
+ }

diff  --git a/mlir/test/Integration/Dialect/Linalg/CPU/vectorize-insert-slice-rank-reducing.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/vectorize-insert-slice-rank-reducing.mlir
new file mode 100644
index 00000000000000..df4cf3729eab85
--- /dev/null
+++ b/mlir/test/Integration/Dialect/Linalg/CPU/vectorize-insert-slice-rank-reducing.mlir
@@ -0,0 +1,51 @@
+// DEFINE: %{entry_point} = main
+
+// DEFINE: %{vectorize} = mlir-opt -transform-interpreter
+// DEFINE: %{lower} = mlir-opt -one-shot-bufferize=bufferize-function-boundaries \
+// DEFINE:   -test-lower-to-llvm -test-transform-dialect-erase-schedule
+// DEFINE: %{run} = mlir-runner -e %{entry_point} -entry-point-result=void \
+// DEFINE:    -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils
+
+/// End-to-end test for vectorizing a rank-reducing tensor.insert_slice. Both
+/// runs use the same lowering and must print the same thing.
+
+/// _Without_ vectorization (reference)
+// RUN: %{lower} %s | %{run} | FileCheck %s
+
+/// _With_ vectorization
+// RUN: %{vectorize} %s | %{lower} | %{run} | FileCheck %s
+
+func.func @main() {
+  %pad = arith.constant 0 : i32
+  %src = arith.constant dense<[1, 2, 3, 4, 5]> : tensor<5xi32>
+  %empty = tensor.empty() : tensor<5x3xi32>
+  %init = linalg.fill ins(%pad : i32) outs(%empty : tensor<5x3xi32>) -> tensor<5x3xi32>
+
+  /// Dim 1 of the slice is dropped, so the source's only dim corresponds to
+  /// dim 0 of the result.
+  %res = tensor.insert_slice %src into %init[0, 2] [5, 1] [1, 1]
+    : tensor<5xi32> into tensor<5x3xi32>
+
+  %res_cast = tensor.cast %res : tensor<5x3xi32> to tensor<*xi32>
+
+  // CHECK: Unranked Memref base@ = 0x{{.*}} rank = 2 offset = 0 sizes = [5, 3] strides = [3, 1] data =
+  // CHECK-NEXT: [0,   0,   1]
+  // CHECK-NEXT: [0,   0,   2]
+  // CHECK-NEXT: [0,   0,   3]
+  // CHECK-NEXT: [0,   0,   4]
+  // CHECK-NEXT: [0,   0,   5]
+  call @printMemrefI32(%res_cast) : (tensor<*xi32>) -> ()
+
+  return
+}
+
+module @transforms attributes { transform.with_named_sequence } {
+  transform.named_sequence @__transform_main(%module: !transform.any_op {transform.readonly}) {
+    %slice = transform.structured.match ops{["tensor.insert_slice"]} in %module
+      : (!transform.any_op) -> !transform.any_op
+    transform.structured.vectorize %slice : !transform.any_op
+    transform.yield
+  }
+}
+
+func.func private @printMemrefI32(%ptr : tensor<*xi32>)


        


More information about the Mlir-commits mailing list