[Mlir-commits] [mlir] [mlir][vector] Keep gather alignment when unrolling and lowering vector.mask (PR #221382)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri Sep 4 20:16:32 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Hung-Kuan Tseng (Tim096)

<details>
<summary>Changes</summary>

`UnrollGatherPattern` rebuilds a `vector.gather` per tile from the same
base and offsets, slicing only the index, mask and pass-through vectors,
and `MaskedGatherOpPattern` rebuilds the gather inside a `vector.mask`
with the mask of the region. Neither forwards the `alignment` attribute:

```mlir
%0 = vector.mask %m { vector.gather %base[%c0] [%idx], %all_true, %pt alignment = 8 : memref<64xf32>, vector<4xindex>, vector<4xi1>, vector<4xf32> into vector<4xf32> } : vector<4xi1> -> vector<4xf32>
// -lower-vector-mask today
%0 = vector.gather %base[%c0] [%idx], %m, %cst : memref<64xf32>, vector<4xindex>, vector<4xi1>, vector<4xf32> into vector<4xf32>
```

The rebuilt gathers access the same addresses, so the alignment still
holds. This passes it through the builder, the same way the gather
unrolling in `LowerVectorGather` already does.

The bufferization of `vector.gather`/`vector.scatter` rebuilds them too,
but the verifier rejects `alignment` on a tensor base, so there is
nothing to forward there.


---
Full diff: https://github.com/llvm/llvm-project/pull/221382.diff


4 Files Affected:

- (modified) mlir/lib/Dialect/Vector/Transforms/LowerVectorMask.cpp (+1-1) 
- (modified) mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp (+1-1) 
- (modified) mlir/test/Dialect/Vector/lower-vector-mask.mlir (+12) 
- (modified) mlir/test/Dialect/Vector/vector-transfer-unroll.mlir (+15) 


``````````diff
diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorMask.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorMask.cpp
index 7730c4e7c950a..3d631efc12cfa 100644
--- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorMask.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorMask.cpp
@@ -270,7 +270,7 @@ struct MaskedGatherOpPattern : public MaskOpRewritePattern<GatherOp> {
     rewriter.replaceOpWithNewOp<GatherOp>(
         maskingOp.getOperation(), gatherOp.getVectorType(), gatherOp.getBase(),
         gatherOp.getOffsets(), gatherOp.getIndices(), maskingOp.getMask(),
-        passthru);
+        passthru, gatherOp.getMaybeAlign());
     return success();
   }
 };
diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
index a95bfba0814bd..7b908fefa21de 100644
--- a/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/VectorUnroll.cpp
@@ -693,7 +693,7 @@ struct UnrollGatherPattern : public OpRewritePattern<vector::GatherOp> {
               strides);
       auto slicedGather = vector::GatherOp::create(
           rewriter, loc, targetType, gatherOp.getBase(), gatherOp.getOffsets(),
-          indexSubVec, maskSubVec, passThruSubVec);
+          indexSubVec, maskSubVec, passThruSubVec, gatherOp.getMaybeAlign());
 
       result = rewriter.createOrFold<vector::InsertStridedSliceOp>(
           loc, slicedGather, result, elementOffsets, strides);
diff --git a/mlir/test/Dialect/Vector/lower-vector-mask.mlir b/mlir/test/Dialect/Vector/lower-vector-mask.mlir
index a8a1164e2f762..fd6f3eea49f04 100644
--- a/mlir/test/Dialect/Vector/lower-vector-mask.mlir
+++ b/mlir/test/Dialect/Vector/lower-vector-mask.mlir
@@ -88,3 +88,15 @@ func.func @empty_vector_mask_with_return(%a : vector<8xf32>, %mask : vector<8xi1
   return %0 : vector<8xf32>
 }
 
+
+// -----
+
+// CHECK-LABEL:   func.func @vector_gather_alignment(
+//  CHECK-SAME:     %[[BASE:.*]]: memref<64xf32>, %[[IDX:.*]]: vector<4xindex>, %[[MASK:.*]]: vector<4xi1>,
+//       CHECK:     vector.gather %[[BASE]][%{{.*}}] [%[[IDX]]], %[[MASK]], %{{.*}} alignment = 8 : memref<64xf32>, vector<4xindex>, vector<4xi1>, vector<4xf32> into vector<4xf32>
+func.func @vector_gather_alignment(%base: memref<64xf32>, %idx: vector<4xindex>, %mask: vector<4xi1>, %pass_thru: vector<4xf32>) -> vector<4xf32> {
+  %c0 = arith.constant 0 : index
+  %all_true = arith.constant dense<true> : vector<4xi1>
+  %0 = vector.mask %mask { vector.gather %base[%c0] [%idx], %all_true, %pass_thru alignment = 8 : memref<64xf32>, vector<4xindex>, vector<4xi1>, vector<4xf32> into vector<4xf32> } : vector<4xi1> -> vector<4xf32>
+  return %0 : vector<4xf32>
+}
diff --git a/mlir/test/Dialect/Vector/vector-transfer-unroll.mlir b/mlir/test/Dialect/Vector/vector-transfer-unroll.mlir
index bfa76ecaf77f7..53f30ef6e7f35 100644
--- a/mlir/test/Dialect/Vector/vector-transfer-unroll.mlir
+++ b/mlir/test/Dialect/Vector/vector-transfer-unroll.mlir
@@ -416,3 +416,18 @@ func.func @transfer_write_unroll_dynamic_index(%mem : memref<4x4xf32>, %vec : ve
   vector.transfer_write %vec, %mem[%idx, %idx] : vector<4x2xf32>, memref<4x4xf32>
   return
 }
+
+// -----
+
+// ALL-LABEL: func @vector_gather_unroll_alignment(
+//       ALL:   vector.gather {{.*}} alignment = 8 : memref<?x?x?xf32>, vector<2x2xindex>, vector<2x2xi1>, vector<2x2xf32> into vector<2x2xf32>
+//       ALL:   vector.gather {{.*}} alignment = 8 : memref<?x?x?xf32>, vector<2x2xindex>, vector<2x2xi1>, vector<2x2xf32> into vector<2x2xf32>
+//   ALL-NOT:   vector.gather
+func.func @vector_gather_unroll_alignment(%mem : memref<?x?x?xf32>,
+                                          %indices : vector<2x4xindex>,
+                                          %mask : vector<2x4xi1>,
+                                          %pass_thru : vector<2x4xf32>) -> vector<2x4xf32> {
+  %c0 = arith.constant 0 : index
+  %res = vector.gather %mem[%c0, %c0, %c0] [%indices], %mask, %pass_thru alignment = 8 : memref<?x?x?xf32>, vector<2x4xindex>, vector<2x4xi1>, vector<2x4xf32> into vector<2x4xf32>
+  return %res : vector<2x4xf32>
+}

``````````

</details>


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


More information about the Mlir-commits mailing list