[mlir][spirv] Add ops and patterns for lowering standard max/min ops

Reviewed By: ThomasRaoux

Differential Revision: https://reviews.llvm.org/D111143
This commit is contained in:
Lei Zhang
2021-10-05 13:56:20 -04:00
parent cc1d13f997
commit 7a89444cd9
5 changed files with 123 additions and 12 deletions

View File

@@ -261,10 +261,10 @@ def SPV_GLSLTanOp : SPV_GLSLUnaryArithmeticOp<"Tan", 15, SPV_Float16or32> {
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.
<!-- End of AutoGen section -->
@@ -576,6 +576,36 @@ def SPV_GLSLFMaxOp : SPV_GLSLBinaryArithmeticOp<"FMax", 40, SPV_Float> {
// -----
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.
<!-- End of AutoGen section -->
```
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_GLSLFMinOp : SPV_GLSLBinaryArithmeticOp<"FMin", 37, SPV_Float> {
// -----
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.
<!-- End of AutoGen section -->
```
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";

View File

@@ -889,6 +889,12 @@ void populateStandardToSPIRVPatterns(SPIRVTypeConverter &typeConverter,
UnaryAndBinaryOpPattern<CeilFOp, spirv::GLSLCeilOp>,
UnaryAndBinaryOpPattern<DivFOp, spirv::FDivOp>,
UnaryAndBinaryOpPattern<FloorFOp, spirv::GLSLFloorOp>,
UnaryAndBinaryOpPattern<MaxFOp, spirv::GLSLFMaxOp>,
UnaryAndBinaryOpPattern<MaxSIOp, spirv::GLSLSMaxOp>,
UnaryAndBinaryOpPattern<MaxUIOp, spirv::GLSLUMaxOp>,
UnaryAndBinaryOpPattern<MinFOp, spirv::GLSLFMinOp>,
UnaryAndBinaryOpPattern<MinSIOp, spirv::GLSLSMinOp>,
UnaryAndBinaryOpPattern<MinUIOp, spirv::GLSLUMinOp>,
UnaryAndBinaryOpPattern<MulFOp, spirv::FMulOp>,
UnaryAndBinaryOpPattern<MulIOp, spirv::IMulOp>,
UnaryAndBinaryOpPattern<NegFOp, spirv::FNegateOp>,

View File

@@ -24,6 +24,14 @@ func @int32_scalar(%lhs: i32, %rhs: i32) {
%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 @@ func @float32_binary_scalar(%lhs: f32, %rhs: f32) {
%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
}

View File

@@ -51,24 +51,42 @@ func @exp(%arg0 : i32) -> () {
// -----
//===----------------------------------------------------------------------===//
// 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
}

View File

@@ -1,11 +1,9 @@
// RUN: mlir-translate -test-spirv-roundtrip %s | FileCheck %s
spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
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.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
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