[Mlir-commits] [mlir] d0373ba - [mlir][SPIR-V] Add GL NMin, NMax and NClamp ops (#203878)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Jun 25 09:24:22 PDT 2026
Author: Arseniy Obolenskiy
Date: 2026-06-25T18:24:17+02:00
New Revision: d0373ba8b57bb2355cfed09ad4c15c315a36af8c
URL: https://github.com/llvm/llvm-project/commit/d0373ba8b57bb2355cfed09ad4c15c315a36af8c
DIFF: https://github.com/llvm/llvm-project/commit/d0373ba8b57bb2355cfed09ad4c15c315a36af8c.diff
LOG: [mlir][SPIR-V] Add GL NMin, NMax and NClamp ops (#203878)
Added:
Modified:
mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
mlir/test/Dialect/SPIRV/IR/gl-ops.mlir
mlir/test/Target/SPIRV/gl-ops.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
index dca21b6eedba0..e0b85e73cad99 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
@@ -1081,6 +1081,83 @@ def SPIRV_GLSClampOp : SPIRV_GLTernaryArithmeticOp<"SClamp", 45, SPIRV_Integer>
// -----
+def SPIRV_GLNMaxOp : SPIRV_GLBinaryArithmeticOp<"NMax", 80, SPIRV_Float, [AlwaysSpeculatable]> {
+ let summary = "Return maximum of two floating-point operands, NaN-aware";
+
+ let description = [{
+ Result is y if x < y; otherwise result is x, where x and y are interpreted
+ as floating-point. NMax considers a NaN argument as missing, so if one
+ operand is a NaN the result is the other operand. If both operands are NaNs,
+ the result is a NaN.
+
+ The operands must all be a scalar or vector whose component type is
+ floating-point.
+
+ Result Type and the type of all operands must be the same type. Results are
+ computed per component.
+
+ #### Example:
+
+ ```mlir
+ %2 = spirv.GL.NMax %0, %1 : f32
+ %3 = spirv.GL.NMax %0, %1 : vector<3xf16>
+ ```
+ }];
+}
+
+// -----
+
+def SPIRV_GLNMinOp : SPIRV_GLBinaryArithmeticOp<"NMin", 79, SPIRV_Float, [AlwaysSpeculatable]> {
+ let summary = "Return minimum of two floating-point operands, NaN-aware";
+
+ let description = [{
+ Result is y if y < x; otherwise result is x, where x and y are interpreted
+ as floating-point. NMin considers a NaN argument as missing, so if one
+ operand is a NaN the result is the other operand. If both operands are NaNs,
+ the result is a NaN.
+
+ The operands must all be a scalar or vector whose component type is
+ floating-point.
+
+ Result Type and the type of all operands must be the same type. Results are
+ computed per component.
+
+ #### Example:
+
+ ```mlir
+ %2 = spirv.GL.NMin %0, %1 : f32
+ %3 = spirv.GL.NMin %0, %1 : vector<3xf16>
+ ```
+ }];
+}
+
+// -----
+
+def SPIRV_GLNClampOp : SPIRV_GLTernaryArithmeticOp<"NClamp", 81, SPIRV_Float> {
+ let summary = "Clamp x between min and max values, NaN-aware";
+
+ let description = [{
+ Result is min(max(x, minVal), maxVal). The resulting value is poison if
+ minVal > maxVal. The semantics used by min() and max() are those of NMin
+ and NMax, so NaN arguments are considered missing.
+
+ The operands must all be a scalar or vector whose component type is
+ floating-point.
+
+ Result Type and the type of all operands must be the same type. Results are
+ computed per component.
+
+ #### Example:
+
+ ```mlir
+ %2 = spirv.GL.NClamp %x, %min, %max : f32
+ %3 = spirv.GL.NClamp %x, %min, %max : vector<3xf16>
+ ```
+ }];
+}
+
+// -----
+
def SPIRV_GLFmaOp : SPIRV_GLTernaryArithmeticOp<"Fma", 50, SPIRV_Float, [AlwaysSpeculatable]> {
let summary = "Computes a * b + c.";
diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
index 4cb6e6bbf6579..f699055b5502f 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
@@ -1284,6 +1284,16 @@ ParseResult spirv::GLSClampOp::parse(OpAsmParser &parser,
}
void spirv::GLSClampOp::print(OpAsmPrinter &p) { printOneResultOp(*this, p); }
+//===----------------------------------------------------------------------===//
+// spirv.GLNClampOp
+//===----------------------------------------------------------------------===//
+
+ParseResult spirv::GLNClampOp::parse(OpAsmParser &parser,
+ OperationState &result) {
+ return parseOneResultSameOperandTypeOp(parser, result);
+}
+void spirv::GLNClampOp::print(OpAsmPrinter &p) { printOneResultOp(*this, p); }
+
//===----------------------------------------------------------------------===//
// spirv.GLFmaOp
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir b/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir
index e8f15e30ba4ee..5665ae158d2e4 100644
--- a/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir
@@ -1266,3 +1266,57 @@ func.func @degrees(%arg0 : i32) -> () {
%2 = spirv.GL.Degrees %arg0 : i32
return
}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.GL.NMax
+//===----------------------------------------------------------------------===//
+
+func.func @nmax(%arg0 : f32, %arg1 : f32) {
+ // CHECK: spirv.GL.NMax {{%.*}}, {{%.*}} : f32
+ %0 = spirv.GL.NMax %arg0, %arg1 : f32
+ return
+}
+
+func.func @nmaxvec(%arg0 : vector<3xf16>, %arg1 : vector<3xf16>) {
+ // CHECK: spirv.GL.NMax {{%.*}}, {{%.*}} : vector<3xf16>
+ %0 = spirv.GL.NMax %arg0, %arg1 : vector<3xf16>
+ return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.GL.NMin
+//===----------------------------------------------------------------------===//
+
+func.func @nmin(%arg0 : f32, %arg1 : f32) {
+ // CHECK: spirv.GL.NMin {{%.*}}, {{%.*}} : f32
+ %0 = spirv.GL.NMin %arg0, %arg1 : f32
+ return
+}
+
+func.func @nminvec(%arg0 : vector<3xf16>, %arg1 : vector<3xf16>) {
+ // CHECK: spirv.GL.NMin {{%.*}}, {{%.*}} : vector<3xf16>
+ %0 = spirv.GL.NMin %arg0, %arg1 : vector<3xf16>
+ return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.GL.NClamp
+//===----------------------------------------------------------------------===//
+
+func.func @nclamp(%arg0 : f32, %min : f32, %max : f32) -> () {
+ // CHECK: spirv.GL.NClamp {{%[^,]*}}, {{%[^,]*}}, {{%[^,]*}} : f32
+ %2 = spirv.GL.NClamp %arg0, %min, %max : f32
+ return
+}
+
+func.func @nclampvec(%arg0 : vector<3xf32>, %min : vector<3xf32>, %max : vector<3xf32>) -> () {
+ // CHECK: spirv.GL.NClamp {{%[^,]*}}, {{%[^,]*}}, {{%[^,]*}} : vector<3xf32>
+ %2 = spirv.GL.NClamp %arg0, %min, %max : vector<3xf32>
+ return
+}
diff --git a/mlir/test/Target/SPIRV/gl-ops.mlir b/mlir/test/Target/SPIRV/gl-ops.mlir
index eac859ecf158e..bc17ff82cc441 100644
--- a/mlir/test/Target/SPIRV/gl-ops.mlir
+++ b/mlir/test/Target/SPIRV/gl-ops.mlir
@@ -76,6 +76,11 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage], []> {
%5 = spirv.GL.SMin %arg2, %arg3 : i32
// CHECK: {{%.*}} = spirv.GL.UMin {{%.*}}, {{%.*}} : i32
%6 = spirv.GL.UMin %arg2, %arg3 : i32
+
+ // CHECK: {{%.*}} = spirv.GL.NMax {{%.*}}, {{%.*}} : f32
+ %7 = spirv.GL.NMax %arg0, %arg1 : f32
+ // CHECK: {{%.*}} = spirv.GL.NMin {{%.*}}, {{%.*}} : f32
+ %8 = spirv.GL.NMin %arg0, %arg1 : f32
spirv.Return
}
@@ -85,6 +90,12 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage], []> {
spirv.Return
}
+ spirv.func @nclamp(%arg0 : f32, %arg1 : f32, %arg2 : f32) "None" {
+ // CHECK: spirv.GL.NClamp {{%[^,]*}}, {{%[^,]*}}, {{%[^,]*}} : f32
+ %13 = spirv.GL.NClamp %arg0, %arg1, %arg2 : f32
+ spirv.Return
+ }
+
spirv.func @uclamp(%arg0 : ui32, %arg1 : ui32, %arg2 : ui32) "None" {
// CHECK: spirv.GL.UClamp {{%[^,]*}}, {{%[^,]*}}, {{%[^,]*}} : i32
%13 = spirv.GL.UClamp %arg0, %arg1, %arg2 : ui32
More information about the Mlir-commits
mailing list