[Mlir-commits] [mlir] [mlir][SPIR-V] Add missing GL and CL extended-instruction ops (PR #203544)

Arseniy Obolenskiy llvmlistbot at llvm.org
Fri Jun 12 07:27:05 PDT 2026


https://github.com/aobolensk created https://github.com/llvm/llvm-project/pull/203544

- GLSL.std.450: Radians, Degrees, NMin, NMax, NClamp
- OpenCL.std: copysign, fdim, fmod, hypot, expm1, log1p

>From 4210bf497e6779d18b0ea229e9a58a2bd839029a Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 12 Jun 2026 16:24:17 +0200
Subject: [PATCH] [mlir][SPIR-V] Add missing GL and CL extended-instruction ops

- GLSL.std.450: Radians, Degrees, NMin, NMax, NClamp
- OpenCL.std: copysign, fdim, fmod, hypot, expm1, log1p
---
 .../mlir/Dialect/SPIRV/IR/SPIRVCLOps.td       | 130 ++++++++++++++++++
 .../mlir/Dialect/SPIRV/IR/SPIRVGLOps.td       | 125 +++++++++++++++++
 mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp        |  10 ++
 mlir/test/Dialect/SPIRV/IR/gl-ops.mlir        | 108 +++++++++++++++
 mlir/test/Dialect/SPIRV/IR/ocl-ops.mlir       | 120 ++++++++++++++++
 mlir/test/Target/SPIRV/gl-ops.mlir            |  15 ++
 mlir/test/Target/SPIRV/ocl-ops.mlir           |  12 ++
 7 files changed, 520 insertions(+)

diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCLOps.td
index 8972a03bedb2f..7c1ca28f728e9 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCLOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCLOps.td
@@ -319,6 +319,27 @@ def SPIRV_CLCeilOp : SPIRV_CLUnaryArithmeticOp<"ceil", 12, SPIRV_Float> {
 
 // -----
 
+def SPIRV_CLCopysignOp : SPIRV_CLBinaryArithmeticOp<"copysign", 13, SPIRV_Float> {
+  let summary = "Computes the value with the magnitude of x and the sign of y.";
+
+  let description = [{
+    Result Type, x and y must be floating-point or vector(2,3,4,8,16) of
+    floating-point values.
+
+    All of the operands, including the Result Type operand, must be of the
+    same type.
+
+    #### Example:
+
+    ```mlir
+    %2 = spirv.CL.copysign %0, %1 : f32
+    %3 = spirv.CL.copysign %0, %1 : vector<3xf16>
+    ```
+  }];
+}
+
+// -----
+
 def SPIRV_CLCosOp : SPIRV_CLUnaryArithmeticOp<"cos", 14, SPIRV_Float> {
   let summary = "Compute the cosine of x radians.";
 
@@ -472,6 +493,27 @@ def SPIRV_CLExp10Op : SPIRV_CLUnaryArithmeticOp<"exp10", 21, SPIRV_Float> {
 
 // -----
 
+def SPIRV_CLExpm1Op : SPIRV_CLUnaryArithmeticOp<"expm1", 22, SPIRV_Float> {
+  let summary = "Compute the base-e exponential of x minus 1.0.";
+
+  let description = [{
+    Result Type and x must be floating-point or vector(2,3,4,8,16) of
+    floating-point values.
+
+    All of the operands, including the Result Type operand,
+    must be of the same type.
+
+    #### Example:
+
+    ```mlir
+    %2 = spirv.CL.expm1 %0 : f32
+    %3 = spirv.CL.expm1 %1 : vector<3xf16>
+    ```
+  }];
+}
+
+// -----
+
 def SPIRV_CLFAbsOp : SPIRV_CLUnaryArithmeticOp<"fabs", 23, SPIRV_Float> {
   let summary = "Absolute value of operand";
 
@@ -541,6 +583,73 @@ def SPIRV_CLFMinOp : SPIRV_CLBinaryArithmeticOp<"fmin", 28, SPIRV_Float> {
 
 // -----
 
+def SPIRV_CLFdimOp : SPIRV_CLBinaryArithmeticOp<"fdim", 24, SPIRV_Float> {
+  let summary = "Compute the positive difference between x and y.";
+
+  let description = [{
+    Returns x - y if x > y, otherwise it returns +0.0.
+
+    Result Type, x and y must be floating-point or vector(2,3,4,8,16) of
+    floating-point values.
+
+    All of the operands, including the Result Type operand, must be of the
+    same type.
+
+    #### Example:
+
+    ```mlir
+    %2 = spirv.CL.fdim %0, %1 : f32
+    %3 = spirv.CL.fdim %0, %1 : vector<3xf16>
+    ```
+  }];
+}
+
+// -----
+
+def SPIRV_CLFmodOp : SPIRV_CLBinaryArithmeticOp<"fmod", 29, SPIRV_Float> {
+  let summary = [{
+    Modulus. Returns x - y * trunc(x / y), with the same sign as x.
+  }];
+
+  let description = [{
+    Result Type, x and y must be floating-point or vector(2,3,4,8,16) of
+    floating-point values.
+
+    All of the operands, including the Result Type operand, must be of the
+    same type.
+
+    #### Example:
+
+    ```mlir
+    %2 = spirv.CL.fmod %0, %1 : f32
+    %3 = spirv.CL.fmod %0, %1 : vector<3xf16>
+    ```
+  }];
+}
+
+// -----
+
+def SPIRV_CLHypotOp : SPIRV_CLBinaryArithmeticOp<"hypot", 32, SPIRV_Float> {
+  let summary = "Compute the square root of x^2 + y^2.";
+
+  let description = [{
+    Result Type, x and y must be floating-point or vector(2,3,4,8,16) of
+    floating-point values.
+
+    All of the operands, including the Result Type operand, must be of the
+    same type.
+
+    #### Example:
+
+    ```mlir
+    %2 = spirv.CL.hypot %0, %1 : f32
+    %3 = spirv.CL.hypot %0, %1 : vector<3xf16>
+    ```
+  }];
+}
+
+// -----
+
 def SPIRV_CLFloorOp : SPIRV_CLUnaryArithmeticOp<"floor", 25, SPIRV_Float> {
   let summary = [{
     Round x to the integral value using the round to negative infinity
@@ -696,6 +805,27 @@ def SPIRV_CLLog10Op : SPIRV_CLUnaryArithmeticOp<"log10", 39, SPIRV_Float> {
 
 // -----
 
+def SPIRV_CLLog1pOp : SPIRV_CLUnaryArithmeticOp<"log1p", 40, SPIRV_Float> {
+  let summary = "Compute the natural logarithm of x + 1.0.";
+
+  let description = [{
+    Result Type and x must be floating-point or vector(2,3,4,8,16) of
+    floating-point values.
+
+    All of the operands, including the Result Type operand, must be of the
+    same type.
+
+    #### Example:
+
+    ```mlir
+    %2 = spirv.CL.log1p %0 : f32
+    %3 = spirv.CL.log1p %1 : vector<3xf16>
+    ```
+  }];
+}
+
+// -----
+
 def SPIRV_CLMixOp : SPIRV_CLTernaryArithmeticOp<"mix", 99, SPIRV_Float> {
   let summary = "Returns the linear blend of x & y implemented as: x + (y - x) * a";
 
diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
index 83a3ff5c3adb0..e0b85e73cad99 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
@@ -887,6 +887,54 @@ def SPIRV_GLAtan2Op : SPIRV_GLBinaryArithmeticOp<"Atan2", 25, SPIRV_Float16or32>
 
 // -----
 
+def SPIRV_GLRadiansOp : SPIRV_GLUnaryArithmeticOp<"Radians", 11, SPIRV_Float16or32, [AlwaysSpeculatable]> {
+  let summary = "Convert a quantity in degrees to radians";
+
+  let description = [{
+    Result is the quantity in radians for the quantity x given in degrees, i.e.,
+    (π / 180) * x.
+
+    The operand x must be a scalar or vector whose component type is 16-bit or
+    32-bit floating-point.
+
+    Result Type and the type of x must be the same type. Results are computed
+    per component.
+
+    #### Example:
+
+    ```mlir
+    %2 = spirv.GL.Radians %0 : f32
+    %3 = spirv.GL.Radians %1 : vector<3xf16>
+    ```
+  }];
+}
+
+// -----
+
+def SPIRV_GLDegreesOp : SPIRV_GLUnaryArithmeticOp<"Degrees", 12, SPIRV_Float16or32, [AlwaysSpeculatable]> {
+  let summary = "Convert a quantity in radians to degrees";
+
+  let description = [{
+    Result is the quantity in degrees for the quantity x given in radians, i.e.,
+    (180 / π) * x.
+
+    The operand x must be a scalar or vector whose component type is 16-bit or
+    32-bit floating-point.
+
+    Result Type and the type of x must be the same type. Results are computed
+    per component.
+
+    #### Example:
+
+    ```mlir
+    %2 = spirv.GL.Degrees %0 : f32
+    %3 = spirv.GL.Degrees %1 : vector<3xf16>
+    ```
+  }];
+}
+
+// -----
+
 def SPIRV_GLExp2Op : SPIRV_GLUnaryArithmeticOp<"Exp2", 29, SPIRV_Float16or32, [AlwaysSpeculatable]> {
   let summary = "Result is 2 raised to the x power";
 
@@ -1033,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 119cdcf0fe4fa..ba6ac602c2453 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
@@ -1244,6 +1244,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 88593d54a6783..83483b22909e8 100644
--- a/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir
@@ -1214,3 +1214,111 @@ func.func @length_vec_out(%arg0 : vector<3xf32>) -> () {
   %0 = spirv.GL.Length %arg0 : vector<3xf32> -> vector<3xf32>
   return
 }
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.GL.Radians
+//===----------------------------------------------------------------------===//
+
+func.func @radians(%arg0 : f32) -> () {
+  // CHECK: spirv.GL.Radians {{%.*}} : f32
+  %2 = spirv.GL.Radians %arg0 : f32
+  return
+}
+
+func.func @radiansvec(%arg0 : vector<3xf16>) -> () {
+  // CHECK: spirv.GL.Radians {{%.*}} : vector<3xf16>
+  %2 = spirv.GL.Radians %arg0 : vector<3xf16>
+  return
+}
+
+// -----
+
+func.func @radians(%arg0 : i32) -> () {
+  // expected-error @+1 {{op operand #0 must be 16/32-bit float or fixed-length vector of 16/32-bit float values}}
+  %2 = spirv.GL.Radians %arg0 : i32
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.GL.Degrees
+//===----------------------------------------------------------------------===//
+
+func.func @degrees(%arg0 : f32) -> () {
+  // CHECK: spirv.GL.Degrees {{%.*}} : f32
+  %2 = spirv.GL.Degrees %arg0 : f32
+  return
+}
+
+func.func @degreesvec(%arg0 : vector<3xf16>) -> () {
+  // CHECK: spirv.GL.Degrees {{%.*}} : vector<3xf16>
+  %2 = spirv.GL.Degrees %arg0 : vector<3xf16>
+  return
+}
+
+// -----
+
+func.func @degrees(%arg0 : i32) -> () {
+  // expected-error @+1 {{op operand #0 must be 16/32-bit float or fixed-length vector of 16/32-bit float values}}
+  %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 @nclamp(%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/Dialect/SPIRV/IR/ocl-ops.mlir b/mlir/test/Dialect/SPIRV/IR/ocl-ops.mlir
index 997c36077b497..fb81372207bec 100644
--- a/mlir/test/Dialect/SPIRV/IR/ocl-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/ocl-ops.mlir
@@ -857,3 +857,123 @@ func.func @rootn_wrong_type_vec(%arg0 : vector<3xf32>, %arg1 : vector<2xi32>) ->
   %0 = spirv.CL.rootn %arg0, %arg1 : vector<3xf32>, vector<2xi32> -> vector<3xf32>
   return
 }
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.CL.copysign
+//===----------------------------------------------------------------------===//
+
+func.func @copysign(%arg0 : f32, %arg1 : f32) -> () {
+  // CHECK: spirv.CL.copysign {{%.*}}, {{%.*}} : f32
+  %2 = spirv.CL.copysign %arg0, %arg1 : f32
+  return
+}
+
+// -----
+
+func.func @copysign(%arg0 : vector<4xf16>, %arg1 : vector<4xf16>) -> () {
+  // CHECK: spirv.CL.copysign {{%.*}}, {{%.*}} : vector<4xf16>
+  %2 = spirv.CL.copysign %arg0, %arg1 : vector<4xf16>
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.CL.fdim
+//===----------------------------------------------------------------------===//
+
+func.func @fdim(%arg0 : f32, %arg1 : f32) -> () {
+  // CHECK: spirv.CL.fdim {{%.*}}, {{%.*}} : f32
+  %2 = spirv.CL.fdim %arg0, %arg1 : f32
+  return
+}
+
+// -----
+
+func.func @fdim(%arg0 : vector<4xf16>, %arg1 : vector<4xf16>) -> () {
+  // CHECK: spirv.CL.fdim {{%.*}}, {{%.*}} : vector<4xf16>
+  %2 = spirv.CL.fdim %arg0, %arg1 : vector<4xf16>
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.CL.fmod
+//===----------------------------------------------------------------------===//
+
+func.func @fmod(%arg0 : f32, %arg1 : f32) -> () {
+  // CHECK: spirv.CL.fmod {{%.*}}, {{%.*}} : f32
+  %2 = spirv.CL.fmod %arg0, %arg1 : f32
+  return
+}
+
+// -----
+
+func.func @fmod(%arg0 : vector<4xf16>, %arg1 : vector<4xf16>) -> () {
+  // CHECK: spirv.CL.fmod {{%.*}}, {{%.*}} : vector<4xf16>
+  %2 = spirv.CL.fmod %arg0, %arg1 : vector<4xf16>
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.CL.hypot
+//===----------------------------------------------------------------------===//
+
+func.func @hypot(%arg0 : f32, %arg1 : f32) -> () {
+  // CHECK: spirv.CL.hypot {{%.*}}, {{%.*}} : f32
+  %2 = spirv.CL.hypot %arg0, %arg1 : f32
+  return
+}
+
+// -----
+
+func.func @hypot(%arg0 : vector<4xf16>, %arg1 : vector<4xf16>) -> () {
+  // CHECK: spirv.CL.hypot {{%.*}}, {{%.*}} : vector<4xf16>
+  %2 = spirv.CL.hypot %arg0, %arg1 : vector<4xf16>
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.CL.expm1
+//===----------------------------------------------------------------------===//
+
+func.func @expm1(%arg0 : f32) -> () {
+  // CHECK: spirv.CL.expm1 {{%.*}} : f32
+  %2 = spirv.CL.expm1 %arg0 : f32
+  return
+}
+
+// -----
+
+func.func @expm1(%arg0 : vector<4xf16>) -> () {
+  // CHECK: spirv.CL.expm1 {{%.*}} : vector<4xf16>
+  %2 = spirv.CL.expm1 %arg0 : vector<4xf16>
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.CL.log1p
+//===----------------------------------------------------------------------===//
+
+func.func @log1p(%arg0 : f32) -> () {
+  // CHECK: spirv.CL.log1p {{%.*}} : f32
+  %2 = spirv.CL.log1p %arg0 : f32
+  return
+}
+
+// -----
+
+func.func @log1p(%arg0 : vector<4xf16>) -> () {
+  // CHECK: spirv.CL.log1p {{%.*}} : vector<4xf16>
+  %2 = spirv.CL.log1p %arg0 : vector<4xf16>
+  return
+}
diff --git a/mlir/test/Target/SPIRV/gl-ops.mlir b/mlir/test/Target/SPIRV/gl-ops.mlir
index f4dc4051818bf..bc17ff82cc441 100644
--- a/mlir/test/Target/SPIRV/gl-ops.mlir
+++ b/mlir/test/Target/SPIRV/gl-ops.mlir
@@ -55,6 +55,10 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage], []> {
     %21 = spirv.GL.Tanh %arg0 : f32
     // CHECK: {{%.*}} = spirv.GL.Exp2 {{%.*}} : f32
     %22 = spirv.GL.Exp2 %arg0 : f32
+    // CHECK: {{%.*}} = spirv.GL.Radians {{%.*}} : f32
+    %23 = spirv.GL.Radians %arg0 : f32
+    // CHECK: {{%.*}} = spirv.GL.Degrees {{%.*}} : f32
+    %24 = spirv.GL.Degrees %arg0 : f32
     spirv.Return
   }
 
@@ -72,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
   }
 
@@ -81,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
diff --git a/mlir/test/Target/SPIRV/ocl-ops.mlir b/mlir/test/Target/SPIRV/ocl-ops.mlir
index 71fed716aa360..dbade49d5bbdf 100644
--- a/mlir/test/Target/SPIRV/ocl-ops.mlir
+++ b/mlir/test/Target/SPIRV/ocl-ops.mlir
@@ -43,6 +43,18 @@ spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, Vec
     %11 = spirv.CL.trunc %arg0 : f32
     // CHECK: {{%.*}} = spirv.CL.cbrt {{%.*}} : f32
     %12 = spirv.CL.cbrt %arg0 : f32
+    // CHECK: {{%.*}} = spirv.CL.expm1 {{%.*}} : f32
+    %expm1 = spirv.CL.expm1 %arg0 : f32
+    // CHECK: {{%.*}} = spirv.CL.log1p {{%.*}} : f32
+    %log1p = spirv.CL.log1p %arg0 : f32
+    // CHECK: {{%.*}} = spirv.CL.copysign {{%.*}}, {{%.*}} : f32
+    %copysign = spirv.CL.copysign %arg0, %arg0 : f32
+    // CHECK: {{%.*}} = spirv.CL.fdim {{%.*}}, {{%.*}} : f32
+    %fdim = spirv.CL.fdim %arg0, %arg0 : f32
+    // CHECK: {{%.*}} = spirv.CL.fmod {{%.*}}, {{%.*}} : f32
+    %fmod = spirv.CL.fmod %arg0, %arg0 : f32
+    // CHECK: {{%.*}} = spirv.CL.hypot {{%.*}}, {{%.*}} : f32
+    %hypot = spirv.CL.hypot %arg0, %arg0 : f32
     spirv.Return
   }
 



More information about the Mlir-commits mailing list