[Mlir-commits] [mlir] [mlir][GPU] Add ValueBoundsOphinterface to gpu.subgroup_broadcast (PR #183848)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Feb 27 14:02:14 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-gpu
Author: Krzysztof Drewniak (krzysz00)
<details>
<summary>Changes</summary>
This commit adds an ValueBoundsOpInterface to gpu.subgroup_broadcast, matching its integer range interface implementation, so that affine analysis can peek through subgroup broadcast ops.
---
Full diff: https://github.com/llvm/llvm-project/pull/183848.diff
2 Files Affected:
- (modified) mlir/lib/Dialect/GPU/IR/ValueBoundsOpInterfaceImpl.cpp (+23)
- (modified) mlir/test/Dialect/GPU/value-bounds-op-interface-impl.mlir (+38)
``````````diff
diff --git a/mlir/lib/Dialect/GPU/IR/ValueBoundsOpInterfaceImpl.cpp b/mlir/lib/Dialect/GPU/IR/ValueBoundsOpInterfaceImpl.cpp
index 3bb7082daa5a0..c978aefe3f655 100644
--- a/mlir/lib/Dialect/GPU/IR/ValueBoundsOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/GPU/IR/ValueBoundsOpInterfaceImpl.cpp
@@ -40,6 +40,28 @@ struct GpuIdOpInterface
}
};
+/// Implement ValueBoundsOpInterface on subgroup broadcast operations to
+/// indicate that such a broadcast does not modify the ranges of the values in
+/// question. Handles shaped types just in case one wants to broadcast a memref
+/// descriptor.
+struct SubgroupBroadcastOpInterface
+ : public ValueBoundsOpInterface::ExternalModel<SubgroupBroadcastOpInterface,
+ SubgroupBroadcastOp> {
+ void populateBoundsForIndexValue(Operation *op, Value value,
+ ValueBoundsConstraintSet &cstr) const {
+ auto broadcastOp = cast<SubgroupBroadcastOp>(op);
+ assert(value == broadcastOp.getResult() && "invalid value");
+ cstr.bound(value) == cstr.getExpr(broadcastOp.getSrc());
+ }
+
+ void populateBoundsForShapedValueDim(Operation *op, Value value, int64_t dim,
+ ValueBoundsConstraintSet &cstr) const {
+ auto broadcastOp = cast<SubgroupBroadcastOp>(op);
+ assert(value == broadcastOp.getResult() && "invalid value");
+ cstr.bound(value)[dim] == cstr.getExpr(broadcastOp.getSrc(), dim);
+ }
+};
+
struct GpuLaunchOpInterface
: public ValueBoundsOpInterface::ExternalModel<GpuLaunchOpInterface,
LaunchOp> {
@@ -110,5 +132,6 @@ void mlir::gpu::registerValueBoundsOpInterfaceExternalModels(
#undef REGISTER
LaunchOp::attachInterface<GpuLaunchOpInterface>(*ctx);
+ SubgroupBroadcastOp::attachInterface<SubgroupBroadcastOpInterface>(*ctx);
});
}
diff --git a/mlir/test/Dialect/GPU/value-bounds-op-interface-impl.mlir b/mlir/test/Dialect/GPU/value-bounds-op-interface-impl.mlir
index 6facf1e22aab9..d6a2e17e19704 100644
--- a/mlir/test/Dialect/GPU/value-bounds-op-interface-impl.mlir
+++ b/mlir/test/Dialect/GPU/value-bounds-op-interface-impl.mlir
@@ -157,3 +157,41 @@ module attributes {gpu.container_module} {
}
}
}
+
+// -----
+
+// CHECK-LABEL: func @subgroup_broadcast
+module attributes {gpu.container_module} {
+ gpu.module @gpu_module {
+ gpu.func @subgroup_broadcast(%arg0 : index) kernel {
+ %lane = arith.constant 1 : i32
+
+ %bcast = gpu.subgroup_broadcast %arg0, specific_lane %lane : index
+ // expected-remark @below{{true}}
+ "test.compare"(%bcast, %arg0) {cmp = "EQ"} : (index, index) -> ()
+
+ %bcast2 = gpu.subgroup_broadcast %arg0, first_active_lane : index
+ // expected-remark @below{{true}}
+ "test.compare"(%bcast2, %arg0) {cmp = "EQ"} : (index, index) -> ()
+ gpu.return
+ }
+ }
+}
+
+// -----
+
+// CHECK-LABEL: func @subgroup_broadcast_shaped
+module attributes {gpu.container_module} {
+ gpu.module @gpu_module {
+ gpu.func @subgroup_broadcast_shaped(%arg0 : memref<?xf32>) kernel {
+ %c0 = arith.constant 0 : index
+
+ %bcast = gpu.subgroup_broadcast %arg0, first_active_lane : memref<?xf32>
+ %bdim = memref.dim %bcast, %c0 : memref<?xf32>
+ %dim = memref.dim %arg0, %c0 : memref<?xf32>
+ // expected-remark @below{{true}}
+ "test.compare"(%bdim, %dim) {cmp = "EQ"} : (index, index) -> ()
+ gpu.return
+ }
+ }
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/183848
More information about the Mlir-commits
mailing list