[Mlir-commits] [mlir] [mlir][gpu] Support `minimumnumf` and `maximumnumf` in GPU dialect (PR #226897)

Artem Gindinson llvmlistbot at llvm.org
Sun Sep 27 23:57:34 PDT 2026


https://github.com/AGindinson updated https://github.com/llvm/llvm-project/pull/226897

>From 383ca456e8dd2ba07df2214cdbaa66e481d3bdcb Mon Sep 17 00:00:00 2001
From: Artem Gindinson <gindinson at roofline.ai>
Date: Fri, 25 Sep 2026 15:24:44 +0000
Subject: [PATCH] [mlir][gpu] Support `minimumnumf` and `maximumnumf` in GPU
 dialect

Follow up on #221658. Add mirroring GPU reduction kinds and lower
through appropriate arith ops.

Assisted-by: Codex
---
 mlir/include/mlir/Dialect/GPU/IR/GPUOps.td    | 12 +++++--
 .../GPUToNVVM/LowerGpuOpsToNVVMOps.cpp        |  2 ++
 mlir/lib/Dialect/GPU/IR/GPUDialect.cpp        |  3 +-
 mlir/lib/Dialect/GPU/Utils/Utils.cpp          |  2 ++
 .../Dialect/GPU/all-reduce-minmaxnumf.mlir    | 21 ++++++++++++
 mlir/test/Dialect/GPU/invalid.mlir            | 32 +++++++++++++++++++
 .../Dialect/GPU/subgroup-reduce-lowering.mlir | 24 ++++++++++++++
 7 files changed, 92 insertions(+), 4 deletions(-)
 create mode 100644 mlir/test/Dialect/GPU/all-reduce-minmaxnumf.mlir

diff --git a/mlir/include/mlir/Dialect/GPU/IR/GPUOps.td b/mlir/include/mlir/Dialect/GPU/IR/GPUOps.td
index 2aa5219e904040..1b6c4ec26ab685 100644
--- a/mlir/include/mlir/Dialect/GPU/IR/GPUOps.td
+++ b/mlir/include/mlir/Dialect/GPU/IR/GPUOps.td
@@ -1151,6 +1151,10 @@ def GPU_AllReduceOpXor : I32EnumAttrCase<"XOR", 10, "xor">;
 def GPU_AllReduceOpMinimumF : I32EnumAttrCase<"MINIMUMF", 11, "minimumf">;
 // Follows the `arith.maximumf` semantics.
 def GPU_AllReduceOpMaximumF : I32EnumAttrCase<"MAXIMUMF", 12, "maximumf">;
+// Follows the `arith.minimumnumf` semantics.
+def GPU_AllReduceOpMinimumNumF : I32EnumAttrCase<"MINIMUMNUMF", 13, "minimumnumf">;
+// Follows the `arith.maximumnumf` semantics.
+def GPU_AllReduceOpMaximumNumF : I32EnumAttrCase<"MAXIMUMNUMF", 14, "maximumnumf">;
 
 def GPU_AllReduceOperation : I32EnumAttr<"AllReduceOperation",
     "built-in reduction operations supported by gpu.allreduce.",
@@ -1167,7 +1171,9 @@ def GPU_AllReduceOperation : I32EnumAttr<"AllReduceOperation",
       GPU_AllReduceOpOr,
       GPU_AllReduceOpXor,
       GPU_AllReduceOpMinimumF,
-      GPU_AllReduceOpMaximumF
+      GPU_AllReduceOpMaximumF,
+      GPU_AllReduceOpMinimumNumF,
+      GPU_AllReduceOpMaximumNumF
     ]>{
   let genSpecializedAttr = 0;
   let cppNamespace = "::mlir::gpu";
@@ -1202,7 +1208,7 @@ def GPU_AllReduceOp : GPU_Op<"all_reduce",
     *  Integer types: `add`, `mul`, `minui`, `minsi`, `maxui`, `maxsi`, `and`,
        `or`, `xor`
     *  Floating point types: `add`, `mul`, `minnumf`, `maxnumf`, `minimumf`,
-       `maximumf`
+       `maximumf`, `minimumnumf`, `maximumnumf`
 
     If `uniform` flag is set either none or all work items of a workgroup
     need to execute this op in convergence.
@@ -1259,7 +1265,7 @@ def GPU_SubgroupReduceOp : GPU_Op<"subgroup_reduce", [SameOperandsAndResultType,
     *  Integer types: `add`, `mul`, `minui`, `minsi`, `maxui`, `maxsi`, `and`,
        `or`, `xor`
     *  Floating point types: `add`, `mul`, `minnumf`, `maxnumf`, `minimumf`,
-       `maximumf`
+       `maximumf`, `minimumnumf`, `maximumnumf`
   }];
 
   let arguments = (ins
diff --git a/mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp b/mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp
index 10de345eb67128..ea776000d8190e 100644
--- a/mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp
+++ b/mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp
@@ -91,6 +91,8 @@ convertToNVVMReductionKind(gpu::AllReduceOperation mode) {
     return NVVM::ReductionKind::XOR;
   case gpu::AllReduceOperation::MINIMUMF:
   case gpu::AllReduceOperation::MAXIMUMF:
+  case gpu::AllReduceOperation::MINIMUMNUMF:
+  case gpu::AllReduceOperation::MAXIMUMNUMF:
     return std::nullopt;
   }
   return std::nullopt;
diff --git a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
index a39b43c9803eb9..4c29801c34220c 100644
--- a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
+++ b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
@@ -540,7 +540,8 @@ static LogicalResult verifyReduceOpAndType(gpu::AllReduceOperation opName,
                                            Type resType) {
   using Kind = gpu::AllReduceOperation;
   if (llvm::is_contained(
-          {Kind::MINNUMF, Kind::MAXNUMF, Kind::MINIMUMF, Kind::MAXIMUMF},
+          {Kind::MINNUMF, Kind::MAXNUMF, Kind::MINIMUMF, Kind::MAXIMUMF,
+           Kind::MINIMUMNUMF, Kind::MAXIMUMNUMF},
           opName)) {
     if (!isa<FloatType>(resType))
       return failure();
diff --git a/mlir/lib/Dialect/GPU/Utils/Utils.cpp b/mlir/lib/Dialect/GPU/Utils/Utils.cpp
index 1f09875b3e2732..8edd1ae904b6b9 100644
--- a/mlir/lib/Dialect/GPU/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/GPU/Utils/Utils.cpp
@@ -34,6 +34,8 @@ vector::CombiningKind convertReductionKind(gpu::AllReduceOperation mode) {
     MAP_CASE(XOR);
     MAP_CASE(MINIMUMF);
     MAP_CASE(MAXIMUMF);
+    MAP_CASE(MINIMUMNUMF);
+    MAP_CASE(MAXIMUMNUMF);
 
 #undef MAP_CASE
   }
diff --git a/mlir/test/Dialect/GPU/all-reduce-minmaxnumf.mlir b/mlir/test/Dialect/GPU/all-reduce-minmaxnumf.mlir
new file mode 100644
index 00000000000000..7ee88d38ffd4fa
--- /dev/null
+++ b/mlir/test/Dialect/GPU/all-reduce-minmaxnumf.mlir
@@ -0,0 +1,21 @@
+// RUN: mlir-opt --convert-gpu-to-nvvm %s | FileCheck %s
+
+gpu.module @kernels {
+  // CHECK-LABEL: llvm.func @minimum_number
+  // CHECK: llvm.intr.minimumnum
+  // CHECK: llvm.return
+  gpu.func @minimum_number(%arg0 : f32, %out : memref<f32>) kernel {
+    %result = gpu.all_reduce minimumnumf %arg0 uniform {} : (f32) -> f32
+    memref.store %result, %out[] : memref<f32>
+    gpu.return
+  }
+
+  // CHECK-LABEL: llvm.func @maximum_number
+  // CHECK: llvm.intr.maximumnum
+  // CHECK: llvm.return
+  gpu.func @maximum_number(%arg0 : f32, %out : memref<f32>) kernel {
+    %result = gpu.all_reduce maximumnumf %arg0 uniform {} : (f32) -> f32
+    memref.store %result, %out[] : memref<f32>
+    gpu.return
+  }
+}
diff --git a/mlir/test/Dialect/GPU/invalid.mlir b/mlir/test/Dialect/GPU/invalid.mlir
index 1b6d3a41d2bd09..7d352506209ffa 100644
--- a/mlir/test/Dialect/GPU/invalid.mlir
+++ b/mlir/test/Dialect/GPU/invalid.mlir
@@ -473,6 +473,22 @@ func.func @reduce_invalid_op_type_minimumf(%arg0 : i32) {
 
 // -----
 
+func.func @reduce_invalid_op_type_minimumnumf(%arg0 : i32) {
+  // expected-error at +1 {{`minimumnumf` reduction operation is not compatible with type 'i32'}}
+  %res = gpu.all_reduce minimumnumf %arg0 {} : (i32) -> (i32)
+  return
+}
+
+// -----
+
+func.func @reduce_invalid_op_type_maximumnumf(%arg0 : i32) {
+  // expected-error at +1 {{`maximumnumf` reduction operation is not compatible with type 'i32'}}
+  %res = gpu.all_reduce maximumnumf %arg0 {} : (i32) -> (i32)
+  return
+}
+
+// -----
+
 func.func @reduce_invalid_op_type_maximumf(%arg0 : i32) {
   // expected-error at +1 {{`maximumf` reduction operation is not compatible with type 'i32'}}
   %res = gpu.all_reduce maximumf %arg0 {} : (i32) -> (i32)
@@ -546,6 +562,22 @@ func.func @subgroup_reduce_invalid_op_type_maxnumf(%arg0 : i32) {
 
 // -----
 
+func.func @subgroup_reduce_invalid_op_type_minimumnumf(%arg0 : i32) {
+  // expected-error at +1 {{`minimumnumf` reduction operation is not compatible with type 'i32'}}
+  %res = gpu.subgroup_reduce minimumnumf %arg0 : (i32) -> (i32)
+  return
+}
+
+// -----
+
+func.func @subgroup_reduce_invalid_op_type_maximumnumf(%arg0 : vector<2xi32>) {
+  // expected-error at +1 {{`maximumnumf` reduction operation is not compatible with type 'vector<2xi32>'}}
+  %res = gpu.subgroup_reduce maximumnumf %arg0 : (vector<2xi32>) -> vector<2xi32>
+  return
+}
+
+// -----
+
 func.func @reduce_incorrect_region_arguments(%arg0 : f32) {
   // expected-error at +1 {{expected two region arguments}}
   %res = gpu.all_reduce %arg0 {
diff --git a/mlir/test/Dialect/GPU/subgroup-reduce-lowering.mlir b/mlir/test/Dialect/GPU/subgroup-reduce-lowering.mlir
index ed69a60de85bc2..4d9fa23c3c2e1b 100644
--- a/mlir/test/Dialect/GPU/subgroup-reduce-lowering.mlir
+++ b/mlir/test/Dialect/GPU/subgroup-reduce-lowering.mlir
@@ -20,6 +20,30 @@
 // CHECK-GFX10: gpu.module @kernels {
 gpu.module @kernels {
 
+  // CHECK-SUB-LABEL: gpu.func @minimum_number
+  // CHECK-SUB: gpu.subgroup_reduce minimumnumf
+  // CHECK-SHFL-LABEL: gpu.func @minimum_number
+  // CHECK-SHFL: arith.minimumnumf
+  // CHECK-GFX-LABEL: gpu.func @minimum_number
+  // CHECK-GFX: arith.minimumnumf
+  gpu.func @minimum_number(%arg0: f32) kernel {
+    %result = gpu.subgroup_reduce minimumnumf %arg0 : (f32) -> f32
+    "test.consume"(%result) : (f32) -> ()
+    gpu.return
+  }
+
+  // CHECK-SUB-LABEL: gpu.func @maximum_number
+  // CHECK-SUB: gpu.subgroup_reduce maximumnumf
+  // CHECK-SHFL-LABEL: gpu.func @maximum_number
+  // CHECK-SHFL: arith.maximumnumf
+  // CHECK-GFX-LABEL: gpu.func @maximum_number
+  // CHECK-GFX: arith.maximumnumf
+  gpu.func @maximum_number(%arg0: vector<2xf32>) kernel {
+    %result = gpu.subgroup_reduce maximumnumf %arg0 : (vector<2xf32>) -> vector<2xf32>
+    "test.consume"(%result) : (vector<2xf32>) -> ()
+    gpu.return
+  }
+
   // CHECK-SUB-LABEL:  gpu.func @kernel0(
   // CHECK-SUB-SAME:     %[[ARG0:.+]]: vector<5xf16>)
   //



More information about the Mlir-commits mailing list