[Mlir-commits] [mlir] 57d9118 - [mlir][SPIR-V] Support SaturatedConversion serialization (#231622)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Oct 13 22:09:21 PDT 2026


Author: Alexander Shaposhnikov
Date: 2026-10-13T22:09:16-07:00
New Revision: 57d911854d22390aab3a4b893efd8bdc3bf7ea40

URL: https://github.com/llvm/llvm-project/commit/57d911854d22390aab3a4b893efd8bdc3bf7ea40
DIFF: https://github.com/llvm/llvm-project/commit/57d911854d22390aab3a4b893efd8bdc3bf7ea40.diff

LOG: [mlir][SPIR-V] Support SaturatedConversion serialization (#231622)

Handle SaturatedConversion as an operand-free decoration during SPIR-V
serialization and deserialization, represented by a unit attribute in
MLIR. This allows saturated integer conversions to round-trip instead of
failing with an unhandled decoration error.

Add round-trip coverage for scalar and vector saturated conversions,
including saturation combined with FPRoundingMode. Also extend rounding
mode coverage across floating-point conversion instructions.

Added: 
    

Modified: 
    mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
    mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
    mlir/test/Target/SPIRV/decorations.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
index 9df544d861767..00b51dc68bdcd 100644
--- a/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
+++ b/mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp
@@ -361,6 +361,7 @@ LogicalResult spirv::Deserializer::processDecoration(ArrayRef<uint32_t> words) {
   case spirv::Decoration::Patch:
   case spirv::Decoration::Coherent:
   case spirv::Decoration::Volatile:
+  case spirv::Decoration::SaturatedConversion:
     if (words.size() != 2) {
       return emitError(unknownLoc, "OpDecorate with ")
              << decorationName << " needs a single target <id>";

diff  --git a/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp b/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
index 3919c3ed5ec36..d22d198ee8c07 100644
--- a/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
+++ b/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp
@@ -416,6 +416,7 @@ LogicalResult Serializer::processDecorationAttr(Location loc, uint32_t resultID,
   case spirv::Decoration::Patch:
   case spirv::Decoration::Coherent:
   case spirv::Decoration::Volatile:
+  case spirv::Decoration::SaturatedConversion:
     // For unit attributes and decoration attributes, the args list
     // has no values so we do nothing.
     if (isa<UnitAttr, DecorationAttr>(attr))

diff  --git a/mlir/test/Target/SPIRV/decorations.mlir b/mlir/test/Target/SPIRV/decorations.mlir
index bbbe02b598244..2d3f256715caa 100644
--- a/mlir/test/Target/SPIRV/decorations.mlir
+++ b/mlir/test/Target/SPIRV/decorations.mlir
@@ -159,6 +159,66 @@ spirv.func @fp_rounding_mode(%arg: f32) -> f16 "None" {
 
 // -----
 
+spirv.module Logical OpenCL requires #spirv.vce<v1.0, [Kernel, Linkage, Float64], []> {
+spirv.func @f_convert_rounding_mode(%arg: f64) -> f32 "None" {
+  // CHECK: spirv.FConvert %{{.*}} {fp_rounding_mode = #spirv.fp_rounding_mode<RTZ>} : f64 to f32
+  %0 = spirv.FConvert %arg {fp_rounding_mode = #spirv.fp_rounding_mode<RTZ>} : f64 to f32
+  spirv.ReturnValue %0 : f32
+}
+spirv.func @convert_s_to_f_rounding_mode(%arg: i32) -> f32 "None" {
+  // CHECK: spirv.ConvertSToF %{{.*}} {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>} : i32 to f32
+  %0 = spirv.ConvertSToF %arg {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>} : i32 to f32
+  spirv.ReturnValue %0 : f32
+}
+spirv.func @convert_u_to_f_rounding_mode(%arg: vector<4xi32>) -> vector<4xf32> "None" {
+  // CHECK: spirv.ConvertUToF %{{.*}} {fp_rounding_mode = #spirv.fp_rounding_mode<RTP>} : vector<4xi32> to vector<4xf32>
+  %0 = spirv.ConvertUToF %arg {fp_rounding_mode = #spirv.fp_rounding_mode<RTP>} : vector<4xi32> to vector<4xf32>
+  spirv.ReturnValue %0 : vector<4xf32>
+}
+spirv.func @convert_f_to_s_rounding_mode(%arg: f32) -> i32 "None" {
+  // CHECK: spirv.ConvertFToS %{{.*}} {fp_rounding_mode = #spirv.fp_rounding_mode<RTN>} : f32 to i32
+  %0 = spirv.ConvertFToS %arg {fp_rounding_mode = #spirv.fp_rounding_mode<RTN>} : f32 to i32
+  spirv.ReturnValue %0 : i32
+}
+spirv.func @convert_f_to_u_rounding_mode(%arg: f32) -> i32 "None" {
+  // CHECK: spirv.ConvertFToU %{{.*}} {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>} : f32 to i32
+  %0 = spirv.ConvertFToU %arg {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>} : f32 to i32
+  spirv.ReturnValue %0 : i32
+}
+}
+
+// -----
+
+spirv.module Logical OpenCL requires #spirv.vce<v1.0, [Kernel, Linkage, Int8, Int64], []> {
+spirv.func @convert_f_to_s_saturated(%arg: f32) -> i32 "None" {
+  // CHECK: spirv.ConvertFToS %{{.*}} {saturated_conversion} : f32 to i32
+  %0 = spirv.ConvertFToS %arg {saturated_conversion} : f32 to i32
+  spirv.ReturnValue %0 : i32
+}
+spirv.func @convert_f_to_u_saturated(%arg: vector<4xf32>) -> vector<4xi32> "None" {
+  // CHECK: spirv.ConvertFToU %{{.*}} {saturated_conversion} : vector<4xf32> to vector<4xi32>
+  %0 = spirv.ConvertFToU %arg {saturated_conversion} : vector<4xf32> to vector<4xi32>
+  spirv.ReturnValue %0 : vector<4xi32>
+}
+spirv.func @s_convert_saturated(%arg: i64) -> i32 "None" {
+  // CHECK: spirv.SConvert %{{.*}} {saturated_conversion} : i64 to i32
+  %0 = spirv.SConvert %arg {saturated_conversion} : i64 to i32
+  spirv.ReturnValue %0 : i32
+}
+spirv.func @u_convert_saturated(%arg: i32) -> i8 "None" {
+  // CHECK: spirv.UConvert %{{.*}} {saturated_conversion} : i32 to i8
+  %0 = spirv.UConvert %arg {saturated_conversion} : i32 to i8
+  spirv.ReturnValue %0 : i8
+}
+spirv.func @convert_f_to_s_saturated_rounding_mode(%arg: f32) -> i32 "None" {
+  // CHECK: spirv.ConvertFToS %{{.*}} {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>, saturated_conversion} : f32 to i32
+  %0 = spirv.ConvertFToS %arg {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>, saturated_conversion} : f32 to i32
+  spirv.ReturnValue %0 : i32
+}
+}
+
+// -----
+
 spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage], []> {
   // CHECK: spirv.func @relaxed_precision_arg({{%.*}}: !spirv.ptr<f32, Function> {spirv.decoration = #spirv.decoration<RelaxedPrecision>}) "None" attributes {relaxed_precision} {
   spirv.func @relaxed_precision_arg(%arg0: !spirv.ptr<f32, Function> {spirv.decoration = #spirv.decoration<RelaxedPrecision>}) -> () "None" attributes {relaxed_precision} {


        


More information about the Mlir-commits mailing list