[Mlir-commits] [mlir] [mlir][gpu] Add `gpu.subgroup_uniform` op (PR	#157743)
    Fabian Mora 
    llvmlistbot at llvm.org
       
    Fri Sep 12 05:31:51 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)";
+}
----------------
fabianmcg wrote:
> Always the same thing: that breaks something fundamental about SSA. The same examples from the guideline applies: how is a transformation which seems harmless supposed to not break this verifier?
> Think of simple cases: the result of the assume is used in a scf.for loop with 2 iterations, I unroll the loop (the assume is outside of the loop), now loop-unrolling and boom...
Thank you for the explanation, that makes it clear, and I'm dropping the has one use proposal.
> I don't follow, can you expand? This looks to me exactly like how all the variant of "assume" in a dataflow context I've seen worked out: you tag an SSA Value and add information in the data low. How is it different from memref.assume for example?
I argue that `assume` semantics imply things about the operands, not the results. This works well with dataflow, the semantics are clear, and it is the model of `llvm.assume`.
Taking the case of `memref.assume`, or `gpu.subgroup_uniform`, the implication is on the result of the op, and not the operands. I claim these are not really compiler assumptions, as it's a new value with new information, you are not assuming anything on the previous value. Thus, their role is an active one, and have closer semantics to a `nop` cast.
(To be consistent, I'd argue `memref.assume_alignment`, should probably be called `memref.has_alignment`). So it's not really tagging, but creating a new value with added semantics.
Let's take a `memref.assume_alignment` that returns results and one that doesn't:
1.
```mlir
%1 = memref.assume_alignment %0, 8 : memref<4x4xf16>
%2 = memref.assume_alignment %0, 32 : memref<4x4xf16>
```
2.
```mlir
memref.assume_alignment %0, 8 : memref<4x4xf16>
memref.assume_alignment %0, 32 : memref<4x4xf16>
```
On 2, it's clear the assumption is on `%0`, so you could potentially combine those assumptions, and say `%0` has a `32` alignment.
On the other hand, on 1, I don't think one should combine them. They have different effects that should be scoped to the uses of each of the operations, thus they are more like value promotions.
Just to be clear, I'm not saying we can't have that, I'm saying that's not the description of the op.
However, since, it appears there's consensus on accepting assumes in such form, I'm not blocking the PR on this issue.
https://github.com/llvm/llvm-project/pull/157743
    
    
More information about the Mlir-commits
mailing list