[Mlir-commits] [mlir] [mlir][gpu] Add `gpu.subgroup_uniform` op (PR #157743)

Mehdi Amini llvmlistbot at llvm.org
Fri Sep 12 06:17:10 PDT 2025


================
@@ -3255,4 +3255,37 @@ def GPU_SubgroupBroadcastOp : GPU_Op<"subgroup_broadcast",
   let hasVerifier = 1;
 }
 
+def GPU_SubgroupUniformOp : GPU_Op<"subgroup_uniform",
+    [Pure, AllTypesMatch<["result", "src"]>,
+    DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>] #
+    ElementwiseMappable.traits>,
+  Arguments<(ins AnyType:$src)> {
+  let summary = "Assumes value is unform across the lanes in subgroup";
+  let description = [{
+    The "subgroup_uniform" op assumes that the value is uniform across all lanes
+    in a subgroup. This means that all active lanes in the subgroup are expected
+    to have the same value.
+
+    This op can be used to inform the compiler that a value is uniform across
+    the subgroup, enabling optimizations. The result is poison if the value
+    is not actually uniform.
+
+    This op is functionally no-op as no valid program should change its
+    semantics if this op is removed. Backends can choose to ignore it or do
+    some optimizations (e.g. put value into scalar registers).
+
+    This op can be freely speculated across structured control flow as parent
+    active mask is always superset of current mask and if can hoist input
+    calculation you can hoist the operation itself as well.
+
+    Example:
+
+    ```mlir
+    %1 = gpu.subgroup_uniform %0 : f32
+    ```
+  }];
+  let results = (outs AnyType:$result);
+  let assemblyFormat = "$src attr-dict `:` type($result)";
+}
----------------
joker-eph wrote:

>I argue that assume semantics imply things about the operands, not the results. This works well with dataflow, the semantics are clear
 
I don't see the argument here? You seem to be repeatingly making claims that I don't understand the rationale behind and I don't see much explanation on the fundamentals behind it.


> and it is the model of llvm.assume.

Actually no: `llvm.assume` is **not** dataflow based, it a path-sensitive representation. You want to add information about a condition at a specific point, which is at-odd with the properties you'd want from a "dataflow based" approach.


> . I claim these are not really compiler assumptions

How so? We encode an assumption on a value, I don't quite see why this makes it "not a compiler assumption". You're identifying yourself later that the operation is a "nop": it's only effect is on the compiler itself, as a metadata that is inserted in the dataflow. 

> On the other hand, on 1, I don't think one should combine them.

Right, one probably shouldn't: the assumption is dataflow based instead of path-based.
This is in line with the deferred UB provided by poison here. 
You could be smart and combine some of these **if** you reach a point where you're using a value in a context where it creates UB to violate the assumption.
Basically from a:

```
%1 = memref.assume_alignment %0, 8 : memref<4x4xf16>
```

which isn't an immediate UB when violated, you can generate later:

```
memref.assume_alignment %0, 32 : memref<4x4xf16>
```

at a point where %1 is used in a manner that triggers UB.

This dataflow vs path sensitivity, alongside with deferred UB is pretty key to understand the design space hre.


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


More information about the Mlir-commits mailing list