diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td index f3f75240e5214..7ffe0c8da1cae 100644 --- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td @@ -1317,4 +1317,88 @@ def SPIRV_GLFractOp : SPIRV_GLUnaryArithmeticOp<"Fract", 10, SPIRV_Float> { }]; } +// ----- + +def SPIRV_GLPackHalf2x16Op : SPIRV_GLOp<"PackHalf2x16", 58, [Pure]> { + let summary = "Pack two-component vector of 32-bit floats into a 32-bit integer"; + + let description = [{ + Result is the unsigned integer obtained by converting the components of a + two-component floating-point vector to the 16-bit OpTypeFloat, and then packing + these two 16-bit integers into a 32-bit unsigned integer. The first vector + component specifies the 16 least-significant bits of the result; the second + component specifies the 16 most-significant bits. + + The RelaxedPrecision Decoration only affects the conversion step of the instruction. + + The v operand must be a vector of 2 components whose type is a 32-bit floating-point. + + Result Type must be a 32-bit integer type. + + #### Example: + + ```mlir + %1 = spirv.GL.PackHalf2x16 %0 : vector<2xf32> -> i32 + ``` + }]; + + let arguments = (ins + VectorOfLengthAndType<[2], [SPIRV_Float32]>:$operand + ); + + let results = (outs + SPIRV_Int32:$result + ); + + let assemblyFormat = [{ + attr-dict $operand `:` type($operand) `->` type($result) + }]; + + let hasVerifier = 0; +} + +// ----- + +def SPIRV_GLUnpackHalf2x16Op : SPIRV_GLOp<"UnpackHalf2x16", 62, [Pure]> { + let summary = "Unpack 32-bit integer into two-component vector of 32-bit floats"; + + let description = [{ + Result is the two-component floating-point vector with components obtained by + unpacking a 32-bit unsigned integer into a pair of 16-bit values, interpreting + those values as 16-bit floating-point numbers according to the OpenGL + Specification, and converting them to 32-bit floating-point values. Subnormal + numbers are either preserved or flushed to zero, consistently within an + implementation. + + The first component of the vector is obtained from the 16 least-significant bits + of v; the second component is obtained from the 16 most-significant bits of v. + + The RelaxedPrecision Decoration only affects the conversion step of the instruction. + + The v operand must be a scalar with 32-bit integer type. + + Result Type must be a vector of 2 components whose type is 32-bit floating point. + + #### Example: + + ```mlir + %1 = spirv.GL.UnpackHalf2x16 %0 : i32 -> vector<2xf32> + ``` + }]; + + let arguments = (ins + SPIRV_Int32:$operand + ); + + let results = (outs + VectorOfLengthAndType<[2], [SPIRV_Float32]>:$result + ); + + let assemblyFormat = [{ + attr-dict $operand `:` type($operand) `->` type($result) + }]; + + let hasVerifier = 0; +} + #endif // MLIR_DIALECT_SPIRV_IR_GL_OPS diff --git a/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir b/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir index 29beee5aea93c..fbcf2095dc608 100644 --- a/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir +++ b/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir @@ -815,3 +815,107 @@ func.func @exp2_invalid_type(%arg0 : i32) -> () { %0 = spirv.GL.Exp2 %arg0 : i32 return } + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.GL.PackHalf2x16 +//===----------------------------------------------------------------------===// + +func.func @pack_half_2x16(%arg0 : vector<2xf32>) -> () { + // CHECK: spirv.GL.PackHalf2x16 {{%.*}} : vector<2xf32> -> i32 + %0 = spirv.GL.PackHalf2x16 %arg0 : vector<2xf32> -> i32 + return +} + +// ----- + +func.func @pack_half_2x16_i16_output(%arg0 : vector<2xf32>) -> () { + // expected-error @+1 {{op result #0 must be Int32, but got 'i16'}} + %0 = spirv.GL.PackHalf2x16 %arg0 : vector<2xf32> -> i16 + return +} + +// ----- + +func.func @pack_half_2x16_wrong_vec_size(%arg0 : vector<3xf32>) -> () { + // expected-error @+1 {{op operand #0 must be vector of Float32 values of length 2, but got 'vector<3xf32>'}} + %0 = spirv.GL.PackHalf2x16 %arg0 : vector<3xf32> -> i32 + return +} + +// ----- + +func.func @pack_half_2x16_wrong_vec_type(%arg0 : vector<2xi32>) -> () { + // expected-error @+1 {{op operand #0 must be vector of Float32 values of length 2, but got 'vector<2xi32>'}} + %0 = spirv.GL.PackHalf2x16 %arg0 : vector<2xi32> -> i32 + return +} + +// ----- + +func.func @pack_half_2x16_scalar_in(%arg0 : f32) -> () { + // expected-error @+1 {{invalid kind of type specified: expected builtin.vector, but found 'f32'}} + %0 = spirv.GL.PackHalf2x16 %arg0 : f32 -> i32 + return +} + +// ----- + +func.func @unpack_half_2x16_vector_out(%arg0 : vector<2xf32>) -> () { + // expected-error @+1 {{invalid kind of type specified: expected builtin.integer, but found 'vector<2xf32>'}} + %0 = spirv.GL.UnpackHalf2x16 %arg0 : vector<2xf32> -> vector<2xi32> + return +} + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.GL.UnpackHalf2x16 +//===----------------------------------------------------------------------===// + +func.func @unpack_half_2x16(%arg0 : i32) -> () { + // CHECK: spirv.GL.UnpackHalf2x16 {{%.*}} : i32 -> vector<2xf32> + %0 = spirv.GL.UnpackHalf2x16 %arg0 : i32 -> vector<2xf32> + return +} + +// ----- + +func.func @unpack_half_2x16_i16_input(%arg0 : i16) -> () { + // expected-error @+1 {{op operand #0 must be Int32, but got 'i16'}} + %0 = spirv.GL.UnpackHalf2x16 %arg0 : i16 -> vector<2xf32> + return +} + +// ----- + +func.func @unpack_half_2x16_wrong_vec_size(%arg0 : i32) -> () { + // expected-error @+1 {{op result #0 must be vector of Float32 values of length 2, but got 'vector<3xf32>'}} + %0 = spirv.GL.UnpackHalf2x16 %arg0 : i32 -> vector<3xf32> + return +} + +// ----- + +func.func @unpack_half_2x16_wrong_vec_type(%arg0 : i32) -> () { + // expected-error @+1 {{op result #0 must be vector of Float32 values of length 2, but got 'vector<2xi32>'}} + %0 = spirv.GL.UnpackHalf2x16 %arg0 : i32 -> vector<2xi32> + return +} + +// ----- + +func.func @unpack_half_2x16_vec_in(%arg0 : vector<2xf32>) -> () { + // expected-error @+1 {{invalid kind of type specified: expected builtin.integer, but found 'vector<2xf32>'}} + %0 = spirv.GL.UnpackHalf2x16 %arg0 : vector<2xf32> -> vector<2xf32> + return +} + +// ----- + +func.func @unpack_half_2x16_scalar_out(%arg0 : i32) -> () { + // expected-error @+1 {{invalid kind of type specified: expected builtin.vector, but found 'f32'}} + %0 = spirv.GL.UnpackHalf2x16 %arg0 : i32 -> f32 + return +} diff --git a/mlir/test/Target/SPIRV/gl-ops.mlir b/mlir/test/Target/SPIRV/gl-ops.mlir index 3dee03345e9a1..e4a6c6fb5a34e 100644 --- a/mlir/test/Target/SPIRV/gl-ops.mlir +++ b/mlir/test/Target/SPIRV/gl-ops.mlir @@ -96,7 +96,7 @@ spirv.module Logical GLSL450 requires #spirv.vce { spirv.Return } -spirv.func @vector(%arg0 : f32, %arg1 : vector<3xf32>, %arg2 : vector<3xf32>) "None" { + spirv.func @vector(%arg0 : f32, %arg1 : vector<3xf32>, %arg2 : vector<3xf32>) "None" { // CHECK: {{%.*}} = spirv.GL.Cross {{%.*}}, {{%.*}} : vector<3xf32> %0 = spirv.GL.Cross %arg1, %arg2 : vector<3xf32> // CHECK: {{%.*}} = spirv.GL.Normalize {{%.*}} : f32 @@ -114,5 +114,11 @@ spirv.func @vector(%arg0 : f32, %arg1 : vector<3xf32>, %arg2 : vector<3xf32>) "N spirv.Return } - + spirv.func @pack_half_2x16(%arg0 : i32) "None" { + // CHECK: {{%.*}} = spirv.GL.UnpackHalf2x16 {{%.*}} : i32 -> vector<2xf32> + %0 = spirv.GL.UnpackHalf2x16 %arg0 : i32 -> vector<2xf32> + // CHECK: {{%.*}} = spirv.GL.PackHalf2x16 {{%.*}} : vector<2xf32> -> i32 + %1 = spirv.GL.PackHalf2x16 %0 : vector<2xf32> -> i32 + spirv.Return + } }