[Mlir-commits] [mlir] [mlir][spirv] Add definition for GL Pack/UnpackSnorm4x8 (PR #174574)

Igor Wodiany llvmlistbot at llvm.org
Tue Jan 6 03:55:10 PST 2026


https://github.com/IgWod-IMG created https://github.com/llvm/llvm-project/pull/174574

None

>From f3229867f053cd7915555cde2490e84130b501f6 Mon Sep 17 00:00:00 2001
From: Igor Wodiany <igor.wodiany at imgtec.com>
Date: Tue, 6 Jan 2026 11:33:48 +0000
Subject: [PATCH] [mlir][spirv] Add definition for GL Pack/UnpackSnorm4x8

---
 .../mlir/Dialect/SPIRV/IR/SPIRVGLOps.td       |  93 +++++++++++++++
 mlir/test/Dialect/SPIRV/IR/gl-ops.mlir        | 110 +++++++++++++++++-
 mlir/test/Target/SPIRV/gl-ops.mlir            |   8 ++
 3 files changed, 208 insertions(+), 3 deletions(-)

diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
index 8c4da9b2dce18..01fe12a4660af 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVGLOps.td
@@ -1476,4 +1476,97 @@ def SPIRV_GLUnpackHalf2x16Op : SPIRV_GLOp<"UnpackHalf2x16", 62, [Pure]> {
   let hasVerifier = 0;
 }
 
+// -----
+
+def SPIRV_GLPackSnorm4x8Op : SPIRV_GLOp<"PackSnorm4x8", 54, [Pure]> {
+  let summary = "Pack four-component vector of normalized 32-bit floats into a 32-bit integer";
+
+  let description = [{
+    First, converts each component of the normalized floating-point value v into
+    8-bit integer values. These are then packed into the result.
+
+    The conversion for component c of v to fixed point is done as follows:
+
+    ```
+    round(clamp(c, -1, +1) * 127.0)
+    ```
+
+    The RelaxedPrecision Decoration only affects the conversion step of the instruction.
+
+    The first component of the vector is written to the least significant bits of the
+    output; the last component is written to the most significant bits.
+
+    The v operand must be a vector of 4 components whose type is a 32-bit floating-point.
+
+    Result Type must be a 32-bit integer type.
+
+    #### Example:
+
+    ```mlir
+    %0 = spirv.GL.PackSnorm4x8 %1 : vector<4xf32> -> i32
+    ```
+  }];
+
+  let arguments = (ins
+    VectorOfLengthAndType<[4], [SPIRV_Float32]>:$operand
+  );
+
+  let results = (outs
+    SPIRV_Int32:$result
+  );
+
+  let assemblyFormat = [{
+    attr-dict $operand `:` type($operand) `->` type($result)
+  }];
+
+  let hasVerifier = 0;
+}
+
+
+// -----
+
+def SPIRV_GLUnpackSnorm4x8Op : SPIRV_GLOp<"UnpackSnorm4x8", 63, [Pure]> {
+  let summary = "Unpack 32-bit integer into four-component vector of normalized 32-bit floats";
+
+  let description = [{
+    First, unpacks a single 32-bit unsigned integer p into four 8-bit signed integers.
+    Then, each component is converted to a normalized floating-point value to generate
+    the result. The conversion for unpacked fixed-point value f to floating point is
+    done as follows:
+
+    ```
+    clamp(f / 127.0, -1, +1)
+    ```
+
+    The first component of the result is extracted from the least significant bits of the
+    input; the last component is extracted from the most significant bits.
+
+    The RelaxedPrecision Decoration only affects the conversion step of the instruction.
+
+    The p operand must be a scalar with 32-bit integer type.
+
+    Result Type must be a vector of 4 components whose type is 32-bit floating point.
+
+    #### Example:
+
+    ```mlir
+    %0 = spirv.GL.UnpackSnorm4x8 %1 : i32 -> vector<4xf32>
+    ```
+  }];
+
+  let arguments = (ins
+    SPIRV_Int32:$operand
+  );
+
+  let results = (outs
+    VectorOfLengthAndType<[4], [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 fd8a2ffbbddf9..bab12b183faf1 100644
--- a/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/gl-ops.mlir
@@ -943,9 +943,9 @@ func.func @pack_half_2x16_scalar_in(%arg0 : f32) -> () {
 
 // -----
 
-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>
+func.func @pack_half_2x16_vector_out(%arg0 : vector<2xf32>) -> () {
+  // expected-error @+1 {{invalid kind of type specified: expected builtin.integer, but found 'vector<2xi32>'}}
+  %0 = spirv.GL.PackHalf2x16 %arg0 : vector<2xf32> -> vector<2xi32>
   return
 }
 
@@ -1003,6 +1003,110 @@ func.func @unpack_half_2x16_scalar_out(%arg0 : i32) -> () {
 
 // -----
 
+//===----------------------------------------------------------------------===//
+// spirv.GL.PackSnorm4x8
+//===----------------------------------------------------------------------===//
+
+func.func @pack_snorm_4x8(%arg0 : vector<4xf32>) -> () {
+  // CHECK: spirv.GL.PackSnorm4x8 {{%.*}} : vector<4xf32> -> i32
+  %0 = spirv.GL.PackSnorm4x8 %arg0 : vector<4xf32> -> i32
+  return
+}
+
+// -----
+
+func.func @pack_snorm_4x8_i16_output(%arg0 : vector<4xf32>) -> () {
+  // expected-error @+1 {{op result #0 must be Int32, but got 'i16'}}
+  %0 = spirv.GL.PackSnorm4x8 %arg0 : vector<4xf32> -> i16
+  return
+}
+
+// -----
+
+func.func @pack_snorm_4x8_wrong_vec_size(%arg0 : vector<3xf32>) -> () {
+  // expected-error @+1 {{op operand #0 must be vector of Float32 values of length 4, but got 'vector<3xf32>'}}
+  %0 = spirv.GL.PackSnorm4x8 %arg0 : vector<3xf32> -> i32
+  return
+}
+
+// -----
+
+func.func @pack_snorm_4x8_wrong_vec_type(%arg0 : vector<4xi32>) -> () {
+  // expected-error @+1 {{op operand #0 must be vector of Float32 values of length 4, but got 'vector<4xi32>'}}
+  %0 = spirv.GL.PackSnorm4x8 %arg0 : vector<4xi32> -> i32
+  return
+}
+
+// -----
+
+func.func @pack_snorm_4x8_scalar_in(%arg0 : f32) -> () {
+  // expected-error @+1 {{invalid kind of type specified: expected builtin.vector, but found 'f32'}}
+  %0 = spirv.GL.PackSnorm4x8 %arg0 : f32 -> i32
+  return
+}
+
+// -----
+
+func.func @pack_snorm_4x8_vector_out(%arg0 : vector<4xf32>) -> () {
+  // expected-error @+1 {{invalid kind of type specified: expected builtin.integer, but found 'vector<4xi32>'}}
+  %0 = spirv.GL.PackSnorm4x8 %arg0 : vector<4xf32> -> vector<4xi32>
+  return
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.GL.UnpackSnorm4x8
+//===----------------------------------------------------------------------===//
+
+func.func @unpack_snorm_4x8(%arg0 : i32) -> () {
+  // CHECK: spirv.GL.UnpackSnorm4x8 {{%.*}} : i32 -> vector<4xf32>
+  %0 = spirv.GL.UnpackSnorm4x8 %arg0 : i32 -> vector<4xf32>
+  return
+}
+
+// -----
+
+func.func @unpack_snorm_4x8_i16_input(%arg0 : i16) -> () {
+  // expected-error @+1 {{op operand #0 must be Int32, but got 'i16'}}
+  %0 = spirv.GL.UnpackSnorm4x8 %arg0 : i16 -> vector<4xf32>
+  return
+}
+
+// -----
+
+func.func @unpack_snorm_4x8_wrong_vec_size(%arg0 : i32) -> () {
+  // expected-error @+1 {{op result #0 must be vector of Float32 values of length 4, but got 'vector<3xf32>'}}
+  %0 = spirv.GL.UnpackSnorm4x8 %arg0 : i32 -> vector<3xf32>
+  return
+}
+
+// -----
+
+func.func @unpack_snorm_4x8_wrong_vec_type(%arg0 : i32) -> () {
+  // expected-error @+1 {{op result #0 must be vector of Float32 values of length 4, but got 'vector<4xi32>'}}
+  %0 = spirv.GL.UnpackSnorm4x8 %arg0 : i32 -> vector<4xi32>
+  return
+}
+
+// -----
+
+func.func @unpack_snorm_4x8_vec_in(%arg0 : vector<4xf32>) -> () {
+  // expected-error @+1 {{invalid kind of type specified: expected builtin.integer, but found 'vector<4xf32>'}}
+  %0 = spirv.GL.UnpackSnorm4x8 %arg0 : vector<4xf32> -> vector<4xf32>
+  return
+}
+
+// -----
+
+func.func @unpack_snorm_4x8_scalar_out(%arg0 : i32) -> () {
+  // expected-error @+1 {{invalid kind of type specified: expected builtin.vector, but found 'f32'}}
+  %0 = spirv.GL.UnpackSnorm4x8 %arg0 : i32 -> f32
+  return
+}
+
+// -----
+
 //===----------------------------------------------------------------------===//
 // spirv.GL.Length
 //===----------------------------------------------------------------------===//
diff --git a/mlir/test/Target/SPIRV/gl-ops.mlir b/mlir/test/Target/SPIRV/gl-ops.mlir
index 3c661f88e90d2..3255044770159 100644
--- a/mlir/test/Target/SPIRV/gl-ops.mlir
+++ b/mlir/test/Target/SPIRV/gl-ops.mlir
@@ -147,4 +147,12 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage], []> {
     %1 = spirv.GL.PackHalf2x16 %0 : vector<2xf32> -> i32
     spirv.Return
   }
+
+  spirv.func @pack_snorm_4x8(%arg0 : i32) "None" {
+    // CHECK: {{%.*}} = spirv.GL.UnpackSnorm4x8 {{%.*}} : i32 -> vector<4xf32>
+    %0 = spirv.GL.UnpackSnorm4x8 %arg0 : i32 -> vector<4xf32>
+    // CHECK: {{%.*}} = spirv.GL.PackSnorm4x8 {{%.*}} : vector<4xf32> -> i32
+    %1 = spirv.GL.PackSnorm4x8 %0 : vector<4xf32> -> i32
+    spirv.Return
+  }
 }



More information about the Mlir-commits mailing list