diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLSLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLSLOps.td --- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLSLOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLSLOps.td @@ -261,10 +261,10 @@ let description = [{ The standard trigonometric tangent of x radians. - The operand x must be a scalar or vector whose component type is 16-bit or + 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 + Result Type and the type of x must be the same type. Results are computed per component. @@ -576,6 +576,36 @@ // ----- +def SPV_GLSLUMaxOp : SPV_GLSLBinaryArithmeticOp<"UMax", 41, SPV_Integer> { + let summary = "Return maximum of two unsigned integer operands"; + + let description = [{ + Result is y if x < y; otherwise result is x, where x and y are interpreted +as unsigned integers. + + Result Type and the type of x and y must both be integer scalar or integer + vector types. Result Type and operand types must have the same number of + components with the same component width. Results are computed per + component. + + + ``` + integer-scalar-vector-type ::= integer-type | + `vector<` integer-literal `x` integer-type `>` + smax-op ::= ssa-id `=` `spv.GLSL.UMax` ssa-use `:` + integer-scalar-vector-type + ``` + #### Example: + + ```mlir + %2 = spv.GLSL.UMax %0, %1 : i32 + %3 = spv.GLSL.UMax %0, %1 : vector<3xi16> + ``` + }]; +} + +// ----- + def SPV_GLSLSMaxOp : SPV_GLSLBinaryArithmeticOp<"SMax", 42, SPV_Integer> { let summary = "Return maximum of two signed integer operands"; @@ -637,6 +667,36 @@ // ----- +def SPV_GLSLUMinOp : SPV_GLSLBinaryArithmeticOp<"UMin", 38, SPV_Integer> { + let summary = "Return minimum of two unsigned integer operands"; + + let description = [{ + Result is y if y < x; otherwise result is x, where x and y are interpreted + as unsigned integers. + + Result Type and the type of x and y must both be integer scalar or integer + vector types. Result Type and operand types must have the same number of + components with the same component width. Results are computed per + component. + + + ``` + integer-scalar-vector-type ::= integer-type | + `vector<` integer-literal `x` integer-type `>` + smin-op ::= ssa-id `=` `spv.GLSL.UMin` ssa-use `:` + integer-scalar-vector-type + ``` + #### Example: + + ```mlir + %2 = spv.GLSL.UMin %0, %1 : i32 + %3 = spv.GLSL.UMin %0, %1 : vector<3xi16> + ``` + }]; +} + +// ----- + def SPV_GLSLSMinOp : SPV_GLSLBinaryArithmeticOp<"SMin", 39, SPV_Integer> { let summary = "Return minimum of two signed integer operands"; diff --git a/mlir/lib/Conversion/StandardToSPIRV/StandardToSPIRV.cpp b/mlir/lib/Conversion/StandardToSPIRV/StandardToSPIRV.cpp --- a/mlir/lib/Conversion/StandardToSPIRV/StandardToSPIRV.cpp +++ b/mlir/lib/Conversion/StandardToSPIRV/StandardToSPIRV.cpp @@ -889,6 +889,12 @@ UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, + UnaryAndBinaryOpPattern, + UnaryAndBinaryOpPattern, + UnaryAndBinaryOpPattern, + UnaryAndBinaryOpPattern, + UnaryAndBinaryOpPattern, + UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, diff --git a/mlir/test/Conversion/StandardToSPIRV/std-ops-to-spirv.mlir b/mlir/test/Conversion/StandardToSPIRV/std-ops-to-spirv.mlir --- a/mlir/test/Conversion/StandardToSPIRV/std-ops-to-spirv.mlir +++ b/mlir/test/Conversion/StandardToSPIRV/std-ops-to-spirv.mlir @@ -24,6 +24,14 @@ %4 = divi_unsigned %lhs, %rhs: i32 // CHECK: spv.UMod %{{.*}}, %{{.*}}: i32 %5 = remi_unsigned %lhs, %rhs: i32 + // CHECK: spv.GLSL.SMax %{{.*}}, %{{.*}}: i32 + %6 = maxsi %lhs, %rhs : i32 + // CHECK: spv.GLSL.UMax %{{.*}}, %{{.*}}: i32 + %7 = maxui %lhs, %rhs : i32 + // CHECK: spv.GLSL.SMin %{{.*}}, %{{.*}}: i32 + %8 = minsi %lhs, %rhs : i32 + // CHECK: spv.GLSL.UMin %{{.*}}, %{{.*}}: i32 + %9 = minui %lhs, %rhs : i32 return } @@ -67,6 +75,10 @@ %3 = divf %lhs, %rhs: f32 // CHECK: spv.FRem %{{.*}}, %{{.*}}: f32 %4 = remf %lhs, %rhs: f32 + // CHECK: spv.GLSL.FMax %{{.*}}, %{{.*}}: f32 + %5 = maxf %lhs, %rhs: f32 + // CHECK: spv.GLSL.FMin %{{.*}}, %{{.*}}: f32 + %6 = minf %lhs, %rhs: f32 return } diff --git a/mlir/test/Dialect/SPIRV/IR/glsl-ops.mlir b/mlir/test/Dialect/SPIRV/IR/glsl-ops.mlir --- a/mlir/test/Dialect/SPIRV/IR/glsl-ops.mlir +++ b/mlir/test/Dialect/SPIRV/IR/glsl-ops.mlir @@ -51,24 +51,42 @@ // ----- //===----------------------------------------------------------------------===// -// spv.GLSL.FMax +// spv.GLSL.{F|S|U}{Max|Min} //===----------------------------------------------------------------------===// -func @fmax(%arg0 : f32, %arg1 : f32) -> () { +func @fmaxmin(%arg0 : f32, %arg1 : f32) { // CHECK: spv.GLSL.FMax {{%.*}}, {{%.*}} : f32 - %2 = spv.GLSL.FMax %arg0, %arg1 : f32 + %1 = spv.GLSL.FMax %arg0, %arg1 : f32 + // CHECK: spv.GLSL.FMin {{%.*}}, {{%.*}} : f32 + %2 = spv.GLSL.FMin %arg0, %arg1 : f32 return } -func @fmaxvec(%arg0 : vector<3xf16>, %arg1 : vector<3xf16>) -> () { +func @fmaxminvec(%arg0 : vector<3xf16>, %arg1 : vector<3xf16>) { // CHECK: spv.GLSL.FMax {{%.*}}, {{%.*}} : vector<3xf16> - %2 = spv.GLSL.FMax %arg0, %arg1 : vector<3xf16> + %1 = spv.GLSL.FMax %arg0, %arg1 : vector<3xf16> + // CHECK: spv.GLSL.FMin {{%.*}}, {{%.*}} : vector<3xf16> + %2 = spv.GLSL.FMin %arg0, %arg1 : vector<3xf16> return } -func @fmaxf64(%arg0 : f64, %arg1 : f64) -> () { +func @fmaxminf64(%arg0 : f64, %arg1 : f64) { // CHECK: spv.GLSL.FMax {{%.*}}, {{%.*}} : f64 - %2 = spv.GLSL.FMax %arg0, %arg1 : f64 + %1 = spv.GLSL.FMax %arg0, %arg1 : f64 + // CHECK: spv.GLSL.FMin {{%.*}}, {{%.*}} : f64 + %2 = spv.GLSL.FMin %arg0, %arg1 : f64 + return +} + +func @iminmax(%arg0: i32, %arg1: i32) { + // CHECK: spv.GLSL.SMax {{%.*}}, {{%.*}} : i32 + %1 = spv.GLSL.SMax %arg0, %arg1 : i32 + // CHECK: spv.GLSL.UMax {{%.*}}, {{%.*}} : i32 + %2 = spv.GLSL.UMax %arg0, %arg1 : i32 + // CHECK: spv.GLSL.SMin {{%.*}}, {{%.*}} : i32 + %3 = spv.GLSL.SMin %arg0, %arg1 : i32 + // CHECK: spv.GLSL.UMin {{%.*}}, {{%.*}} : i32 + %4 = spv.GLSL.UMin %arg0, %arg1 : i32 return } diff --git a/mlir/test/Target/SPIRV/glsl-ops.mlir b/mlir/test/Target/SPIRV/glsl-ops.mlir --- a/mlir/test/Target/SPIRV/glsl-ops.mlir +++ b/mlir/test/Target/SPIRV/glsl-ops.mlir @@ -1,11 +1,9 @@ // RUN: mlir-translate -test-spirv-roundtrip %s | FileCheck %s spv.module Logical GLSL450 requires #spv.vce { - spv.func @fmul(%arg0 : f32, %arg1 : f32, %arg2 : i32) "None" { + spv.func @math(%arg0 : f32, %arg1 : f32, %arg2 : i32) "None" { // CHECK: {{%.*}} = spv.GLSL.Exp {{%.*}} : f32 %0 = spv.GLSL.Exp %arg0 : f32 - // CHECK: {{%.*}} = spv.GLSL.FMax {{%.*}}, {{%.*}} : f32 - %1 = spv.GLSL.FMax %arg0, %arg1 : f32 // CHECK: {{%.*}} = spv.GLSL.Sqrt {{%.*}} : f32 %2 = spv.GLSL.Sqrt %arg0 : f32 // CHECK: {{%.*}} = spv.GLSL.Cos {{%.*}} : f32 @@ -37,6 +35,23 @@ spv.Return } + spv.func @maxmin(%arg0 : f32, %arg1 : f32, %arg2 : i32, %arg3 : i32) "None" { + // CHECK: {{%.*}} = spv.GLSL.FMax {{%.*}}, {{%.*}} : f32 + %1 = spv.GLSL.FMax %arg0, %arg1 : f32 + // CHECK: {{%.*}} = spv.GLSL.SMax {{%.*}}, {{%.*}} : i32 + %2 = spv.GLSL.SMax %arg2, %arg3 : i32 + // CHECK: {{%.*}} = spv.GLSL.UMax {{%.*}}, {{%.*}} : i32 + %3 = spv.GLSL.UMax %arg2, %arg3 : i32 + + // CHECK: {{%.*}} = spv.GLSL.FMin {{%.*}}, {{%.*}} : f32 + %4 = spv.GLSL.FMin %arg0, %arg1 : f32 + // CHECK: {{%.*}} = spv.GLSL.SMin {{%.*}}, {{%.*}} : i32 + %5 = spv.GLSL.SMin %arg2, %arg3 : i32 + // CHECK: {{%.*}} = spv.GLSL.UMin {{%.*}}, {{%.*}} : i32 + %6 = spv.GLSL.UMin %arg2, %arg3 : i32 + spv.Return + } + spv.func @fclamp(%arg0 : f32, %arg1 : f32, %arg2 : f32) "None" { // CHECK: spv.GLSL.FClamp {{%[^,]*}}, {{%[^,]*}}, {{%[^,]*}} : f32 %13 = spv.GLSL.FClamp %arg0, %arg1, %arg2 : f32