[Mlir-commits] [mlir] [mlir][SPIR-V] Accept spec constants for GroupNonUniform cluster size (PR #214408)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Aug 5 23:35:18 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-spirv

Author: Arseniy Obolenskiy (aobolensk)

<details>
<summary>Changes</summary>

The SPIR-V spec requires ClusterSize to come from a constant instruction, which includes OpSpecConstant

The verifiers only accepted spirv.Constant, rejecting valid modules that size subgroup clusters with a tunable spec constant

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


2 Files Affected:

- (modified) mlir/lib/Dialect/SPIRV/IR/GroupOps.cpp (+12-7) 
- (modified) mlir/test/Dialect/SPIRV/IR/non-uniform-ops.mlir (+26) 


``````````diff
diff --git a/mlir/lib/Dialect/SPIRV/IR/GroupOps.cpp b/mlir/lib/Dialect/SPIRV/IR/GroupOps.cpp
index fe6f00e9e5bca..6a206f03a62b7 100644
--- a/mlir/lib/Dialect/SPIRV/IR/GroupOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/GroupOps.cpp
@@ -33,14 +33,16 @@ static LogicalResult verifyGroupNonUniformArithmeticOp(Operation *groupOp) {
                                 "'ClusteredReduce' group operation");
   if (groupOp->getNumOperands() > 1) {
     Operation *sizeOp = groupOp->getOperand(1).getDefiningOp();
-    int32_t clusterSize = 0;
 
-    // TODO: support specialization constant here.
-    if (failed(extractValueFromConstOp(sizeOp, clusterSize)))
+    // SPIR-V spec: "ClusterSize must come from a constant instruction",
+    // which includes both a normal constant and a specialization constant.
+    if (!isa_and_present<spirv::ConstantOp, spirv::ReferenceOfOp>(sizeOp))
       return groupOp->emitOpError(
           "cluster size operand must come from a constant op");
 
-    if (!llvm::isPowerOf2_32(clusterSize))
+    int32_t clusterSize = 0;
+    if (succeeded(extractValueFromConstOp(sizeOp, clusterSize)) &&
+        !llvm::isPowerOf2_32(clusterSize))
       return groupOp->emitOpError(
           "cluster size operand must be a power of two");
   }
@@ -242,12 +244,15 @@ LogicalResult GroupNonUniformLogicalXorOp::verify() {
 LogicalResult GroupNonUniformRotateKHROp::verify() {
   if (Value clusterSizeVal = getClusterSize()) {
     mlir::Operation *defOp = clusterSizeVal.getDefiningOp();
-    int32_t clusterSize = 0;
 
-    if (failed(extractValueFromConstOp(defOp, clusterSize)))
+    // SPIR-V spec: "ClusterSize must come from a constant instruction",
+    // which includes both a normal constant and a specialization constant.
+    if (!isa_and_present<spirv::ConstantOp, spirv::ReferenceOfOp>(defOp))
       return emitOpError("cluster size operand must come from a constant op");
 
-    if (!llvm::isPowerOf2_32(clusterSize))
+    int32_t clusterSize = 0;
+    if (succeeded(extractValueFromConstOp(defOp, clusterSize)) &&
+        !llvm::isPowerOf2_32(clusterSize))
       return emitOpError("cluster size operand must be a power of two");
   }
 
diff --git a/mlir/test/Dialect/SPIRV/IR/non-uniform-ops.mlir b/mlir/test/Dialect/SPIRV/IR/non-uniform-ops.mlir
index 9c927331a08b4..0ce076a27ed4b 100644
--- a/mlir/test/Dialect/SPIRV/IR/non-uniform-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/non-uniform-ops.mlir
@@ -312,6 +312,19 @@ func.func @group_non_uniform_iadd_clustered_reduce(%val: vector<2xi32>) -> vecto
 
 // -----
 
+spirv.module Logical GLSL450 {
+  spirv.SpecConstant @cluster_size = 4 : i32
+  // CHECK-LABEL: @group_non_uniform_iadd_clustered_reduce_spec_const
+  spirv.func @group_non_uniform_iadd_clustered_reduce_spec_const(%val: vector<2xi32>) -> vector<2xi32> "None" {
+    %size = spirv.mlir.referenceof @cluster_size : i32
+    // CHECK: %{{.+}} = spirv.GroupNonUniformIAdd <Subgroup> <ClusteredReduce> %{{.+}} cluster_size(%{{.+}}) : vector<2xi32>, i32 -> vector<2xi32>
+    %0 = spirv.GroupNonUniformIAdd <Subgroup> <ClusteredReduce> %val cluster_size(%size) : vector<2xi32>, i32 -> vector<2xi32>
+    spirv.ReturnValue %0 : vector<2xi32>
+  }
+}
+
+// -----
+
 func.func @group_non_uniform_iadd_reduce(%val: i32) -> i32 {
   // expected-error @+1 {{execution_scope must be 'Subgroup'}}
   %0 = spirv.GroupNonUniformIAdd <Device> <Reduce> %val : i32 -> i32
@@ -775,6 +788,19 @@ func.func @group_non_uniform_rotate_khr(%val: f32, %delta: i32) -> f32 {
 
 // -----
 
+spirv.module Logical GLSL450 {
+  spirv.SpecConstant @cluster_size = 4 : i32
+  // CHECK-LABEL: @group_non_uniform_rotate_khr_spec_const
+  spirv.func @group_non_uniform_rotate_khr_spec_const(%val: f32, %delta: i32) -> f32 "None" {
+    %size = spirv.mlir.referenceof @cluster_size : i32
+    // CHECK: %{{.+}} = spirv.GroupNonUniformRotateKHR <Workgroup> %{{.+}} : f32, i32, i32 -> f32
+    %0 = spirv.GroupNonUniformRotateKHR <Workgroup> %val, %delta, cluster_size(%size) : f32, i32, i32 -> f32
+    spirv.ReturnValue %0 : f32
+  }
+}
+
+// -----
+
 func.func @group_non_uniform_rotate_khr(%val: f32, %delta: i32) -> f32 {
   %four = spirv.Constant 4 : i32
   // expected-error @+1 {{execution_scope must be 'Workgroup' or 'Subgroup'}}

``````````

</details>


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


More information about the Mlir-commits mailing list