[Mlir-commits] [mlir] [mlir][vector] Keep store attributes when sinking a broadcast into vector.store (PR #221383)

Hung-Kuan Tseng llvmlistbot at llvm.org
Fri Sep 4 20:19:22 PDT 2026


https://github.com/Tim096 created https://github.com/llvm/llvm-project/pull/221383

`StoreOpFromBroadcast` rebuilds a one-element `vector.store` of a
broadcast as a `vector.store` or `memref.store` of the broadcast source,
at the same base and indices, but does not forward `nontemporal` or
`alignment`:

```mlir
%0 = vector.broadcast %v : f32 to vector<1xf32>
vector.store %0, %mem[%i] alignment = 16 nontemporal = true : memref<?xf32>, vector<1xf32>
// sink patterns today
memref.store %v, %mem[%i] : memref<?xf32>
```

The rebuilt store writes the same address, so both attributes still
hold. This passes them through the builders. Same shape of fix as
#221319 for `vector.linearize`.


>From 7f333326e7b07ab2c6799aa4998c8ce5bca28026 Mon Sep 17 00:00:00 2001
From: Hung-Kuan Tseng <tseng.tim096 at gmail.com>
Date: Sat, 5 Sep 2026 11:18:32 +0800
Subject: [PATCH] [mlir][vector] Keep store attributes when sinking a broadcast
 into vector.store

`StoreOpFromBroadcast` rebuilds a one-element `vector.store` of a
broadcast as a `vector.store` or `memref.store` of the broadcast source,
at the same base and indices, but does not forward `nontemporal` or
`alignment`. The rebuilt store writes the same address, so both still
hold. Pass them through the builders.
---
 .../Vector/Transforms/VectorTransforms.cpp     |  6 ++++--
 mlir/test/Dialect/Vector/vector-sink.mlir      | 18 ++++++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp
index 123caf2c11b83..04ea7fbbe441b 100644
--- a/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp
@@ -1351,9 +1351,11 @@ class StoreOpFromBroadcast final : public OpRewritePattern<vector::StoreOp> {
     ValueRange indices = op.getIndices();
 
     if (isa<VectorType>(source.getType())) {
-      rewriter.replaceOpWithNewOp<vector::StoreOp>(op, source, base, indices);
+      rewriter.replaceOpWithNewOp<vector::StoreOp>(
+          op, source, base, indices, op.getNontemporal(), op.getMaybeAlign());
     } else {
-      rewriter.replaceOpWithNewOp<memref::StoreOp>(op, source, base, indices);
+      rewriter.replaceOpWithNewOp<memref::StoreOp>(
+          op, source, base, indices, op.getNontemporal(), op.getMaybeAlign());
     }
     rewriter.eraseOp(broadcast);
     return success();
diff --git a/mlir/test/Dialect/Vector/vector-sink.mlir b/mlir/test/Dialect/Vector/vector-sink.mlir
index ac1e4fa1ea1cf..466befa908618 100644
--- a/mlir/test/Dialect/Vector/vector-sink.mlir
+++ b/mlir/test/Dialect/Vector/vector-sink.mlir
@@ -931,6 +931,24 @@ func.func @store_broadcast_1d_to_2d(%arg0: memref<?x?xf32>, %arg1: index, %arg2:
   return
 }
 
+// CHECK-LABEL: @store_broadcast_attrs
+//  CHECK-SAME:   (%[[ARG0:.*]]: memref<?xf32>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: f32)
+func.func @store_broadcast_attrs(%arg0: memref<?xf32>, %arg1: index, %arg2: f32) {
+// CHECK:   memref.store %[[ARG2]], %[[ARG0]][%[[ARG1]]] alignment(16) nontemporal(true) : memref<?xf32>
+  %0 = vector.broadcast %arg2 : f32 to vector<1xf32>
+  vector.store %0, %arg0[%arg1] alignment = 16 nontemporal = true : memref<?xf32>, vector<1xf32>
+  return
+}
+
+// CHECK-LABEL: @store_broadcast_1d_to_2d_attrs
+//  CHECK-SAME:   (%[[ARG0:.*]]: memref<?x?xf32>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: vector<1xf32>)
+func.func @store_broadcast_1d_to_2d_attrs(%arg0: memref<?x?xf32>, %arg1: index, %arg2: index, %arg3: vector<1xf32>) {
+// CHECK:   vector.store %[[ARG3]], %[[ARG0]][%[[ARG1]], %[[ARG2]]] alignment = 16 nontemporal = true : memref<?x?xf32>, vector<1xf32>
+  %0 = vector.broadcast %arg3 : vector<1xf32> to vector<1x1xf32>
+  vector.store %0, %arg0[%arg1, %arg2] alignment = 16 nontemporal = true : memref<?x?xf32>, vector<1x1xf32>
+  return
+}
+
 // CHECK-LABEL: @negative_store_scalable
 //  CHECK-SAME:   (%[[ARG0:.*]]: memref<?xf32>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: f32)
 func.func @negative_store_scalable(%arg0: memref<?xf32>, %arg1: index, %arg2: f32) {



More information about the Mlir-commits mailing list