[Mlir-commits] [mlir] [mlir][SPIR-V] Lower arith.convertf to widen-then-narrow FConvert pair (PR #212817)

Arseniy Obolenskiy llvmlistbot at llvm.org
Mon Sep 21 05:56:17 PDT 2026


https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/212817

>From 1343e3829144961c66c73e58e6772d1092580ed9 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 29 Jul 2026 18:36:25 +0200
Subject: [PATCH 1/3] [mlir][SPIR-V] Lower arith.convertf to widen-then-narrow
 FConvert pair

spirv.FConvert requires differing component widths, so `f16<->bf16` casts must bridge through f32 rather than converting directly
---
 .../Conversion/ArithToSPIRV/ArithToSPIRV.cpp  | 50 +++++++++++++++++++
 .../ArithToSPIRV/arith-to-spirv.mlir          | 41 +++++++++++++++
 2 files changed, 91 insertions(+)

diff --git a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
index 614ac2b43b5f2..c65745e50fbb1 100644
--- a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
+++ b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
@@ -1068,6 +1068,55 @@ struct TypeCastingOpPattern final : public OpConversionPattern<Op> {
   }
 };
 
+//===----------------------------------------------------------------------===//
+// ConvertFOp
+//===----------------------------------------------------------------------===//
+
+/// Converts arith.convertf (same-bitwidth FP cast, e.g. f16 <-> bf16) to
+/// SPIR-V. spirv.FConvert requires differing component widths, so widen to
+/// f32 first and then narrow to the destination type.
+struct ConvertFOpPattern final : public OpConversionPattern<arith::ConvertFOp> {
+  using Base::Base;
+
+  LogicalResult
+  matchAndRewrite(arith::ConvertFOp op, OpAdaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    Type dstType = getTypeConverter()->convertType(op.getType());
+    if (!dstType)
+      return getTypeConversionFailure(rewriter, op);
+
+    if (dstType == adaptor.getIn().getType()) {
+      rewriter.replaceOp(op, adaptor.getIn());
+      return success();
+    }
+
+    Location loc = op.getLoc();
+    Type f32Type = Float32Type::get(rewriter.getContext());
+    if (auto vecType = dyn_cast<VectorType>(dstType))
+      f32Type = VectorType::get(vecType.getShape(), f32Type);
+
+    Value widened =
+        spirv::FConvertOp::create(rewriter, loc, f32Type, adaptor.getIn());
+
+    std::optional<spirv::FPRoundingMode> rm = std::nullopt;
+    if (arith::RoundingModeAttr roundingMode = op.getRoundingmodeAttr()) {
+      if (!(rm = convertArithRoundingModeToSPIRV(roundingMode.getValue())))
+        return rewriter.notifyMatchFailure(
+            op->getLoc(),
+            llvm::formatv("unsupported rounding mode '{0}'", roundingMode));
+    }
+
+    auto narrowed =
+        rewriter.replaceOpWithNewOp<spirv::FConvertOp>(op, dstType, widened);
+    if (rm) {
+      narrowed->setAttr(
+          getDecorationString(spirv::Decoration::FPRoundingMode),
+          spirv::FPRoundingModeAttr::get(rewriter.getContext(), *rm));
+    }
+    return success();
+  }
+};
+
 //===----------------------------------------------------------------------===//
 // CmpIOp
 //===----------------------------------------------------------------------===//
@@ -1500,6 +1549,7 @@ void mlir::arith::populateArithToSPIRVPatterns(
     TypeCastingOpPattern<arith::ExtFOp, spirv::FConvertOp>,
     TruncIPattern, TruncII1Pattern,
     TypeCastingOpPattern<arith::TruncFOp, spirv::FConvertOp>,
+    ConvertFOpPattern,
     IntToFPPattern<arith::UIToFPOp, spirv::ConvertUToFOp, false>,
     BoolToValuePattern<arith::UIToFPOp>,
     IntToFPPattern<arith::SIToFPOp, spirv::ConvertSToFOp, true>,
diff --git a/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir b/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
index 4cef06992727b..1dcccbad41455 100644
--- a/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
+++ b/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
@@ -1158,6 +1158,47 @@ func.func @fptosi2(%arg0 : f16) -> i16 {
 
 // -----
 
+module attributes {
+  spirv.target_env = #spirv.target_env<
+    #spirv.vce<v1.0, [Float16, BFloat16TypeKHR], [SPV_KHR_bfloat16]>, #spirv.resource_limits<>>
+} {
+
+// CHECK-LABEL: @convertf_f16_to_bf16
+func.func @convertf_f16_to_bf16(%arg0 : f16) -> bf16 {
+  // CHECK: %[[WIDE:.+]] = spirv.FConvert %{{.*}} : f16 to f32
+  // CHECK: spirv.FConvert %[[WIDE]] : f32 to bf16
+  %0 = arith.convertf %arg0 : f16 to bf16
+  return %0 : bf16
+}
+
+// CHECK-LABEL: @convertf_bf16_to_f16
+func.func @convertf_bf16_to_f16(%arg0 : bf16) -> f16 {
+  // CHECK: %[[WIDE:.+]] = spirv.FConvert %{{.*}} : bf16 to f32
+  // CHECK: spirv.FConvert %[[WIDE]] : f32 to f16
+  %0 = arith.convertf %arg0 : bf16 to f16
+  return %0 : f16
+}
+
+// CHECK-LABEL: @convertf_vector_f16_to_bf16
+func.func @convertf_vector_f16_to_bf16(%arg0 : vector<4xf16>) -> vector<4xbf16> {
+  // CHECK: %[[WIDE:.+]] = spirv.FConvert %{{.*}} : vector<4xf16> to vector<4xf32>
+  // CHECK: spirv.FConvert %[[WIDE]] : vector<4xf32> to vector<4xbf16>
+  %0 = arith.convertf %arg0 : vector<4xf16> to vector<4xbf16>
+  return %0 : vector<4xbf16>
+}
+
+// CHECK-LABEL: @convertf_rounding_mode
+func.func @convertf_rounding_mode(%arg0 : f16) -> bf16 {
+  // CHECK: %[[WIDE:.+]] = spirv.FConvert %{{.*}} : f16 to f32
+  // CHECK: spirv.FConvert %[[WIDE]] {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>} : f32 to bf16
+  %0 = arith.convertf %arg0 to_nearest_even : f16 to bf16
+  return %0 : bf16
+}
+
+} // end module
+
+// -----
+
 // Checks that cast types will be adjusted when missing special capabilities for
 // certain non-32-bit scalar types.
 module attributes {

>From b180ff0ce52bfa7005f1358c7717ff20afdf71c8 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 21 Sep 2026 14:01:21 +0200
Subject: [PATCH 2/3] address comments

---
 .../mlir/Dialect/SPIRV/IR/SPIRVCastOps.td     |  4 +-
 .../Conversion/ArithToSPIRV/ArithToSPIRV.cpp  | 17 ++-----
 mlir/lib/Dialect/SPIRV/IR/CastOps.cpp         | 44 +++++++++++++++----
 .../ArithToSPIRV/arith-to-spirv.mlir          | 12 ++---
 mlir/test/Dialect/SPIRV/IR/cast-ops.mlir      | 10 ++++-
 mlir/test/Target/SPIRV/cast-ops.mlir          |  7 ++-
 6 files changed, 60 insertions(+), 34 deletions(-)

diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
index a434764750a56..7a85a386900f0 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
@@ -204,8 +204,8 @@ def SPIRV_FConvertOp : SPIRV_CastOp<"FConvert",
     Result Type must be a scalar or vector of floating-point type.
 
     Float Value must be a scalar or vector of floating-point type.  It must
-    have the same number of components as Result Type.  The component width
-    cannot equal the component width in Result Type.
+    have the same number of components as Result Type.  The component type
+    must not equal the component type in Result Type.
 
     Results are computed per component.
 
diff --git a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
index 1a4042065568a..7c2bc5fca63a4 100644
--- a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
+++ b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
@@ -1075,8 +1075,7 @@ struct TypeCastingOpPattern final : public OpConversionPattern<Op> {
 //===----------------------------------------------------------------------===//
 
 /// Converts arith.convertf (same-bitwidth FP cast, e.g. f16 <-> bf16) to
-/// SPIR-V. spirv.FConvert requires differing component widths, so widen to
-/// f32 first and then narrow to the destination type.
+/// spirv.FConvert.
 struct ConvertFOpPattern final : public OpConversionPattern<arith::ConvertFOp> {
   using Base::Base;
 
@@ -1092,14 +1091,6 @@ struct ConvertFOpPattern final : public OpConversionPattern<arith::ConvertFOp> {
       return success();
     }
 
-    Location loc = op.getLoc();
-    Type f32Type = Float32Type::get(rewriter.getContext());
-    if (auto vecType = dyn_cast<VectorType>(dstType))
-      f32Type = VectorType::get(vecType.getShape(), f32Type);
-
-    Value widened =
-        spirv::FConvertOp::create(rewriter, loc, f32Type, adaptor.getIn());
-
     std::optional<spirv::FPRoundingMode> rm = std::nullopt;
     if (arith::RoundingModeAttr roundingMode = op.getRoundingmodeAttr()) {
       if (!(rm = convertArithRoundingModeToSPIRV(roundingMode.getValue())))
@@ -1108,10 +1099,10 @@ struct ConvertFOpPattern final : public OpConversionPattern<arith::ConvertFOp> {
             llvm::formatv("unsupported rounding mode '{0}'", roundingMode));
     }
 
-    auto narrowed =
-        rewriter.replaceOpWithNewOp<spirv::FConvertOp>(op, dstType, widened);
+    auto converted = rewriter.replaceOpWithNewOp<spirv::FConvertOp>(
+        op, dstType, adaptor.getIn());
     if (rm) {
-      narrowed->setAttr(
+      converted->setAttr(
           getDecorationString(spirv::Decoration::FPRoundingMode),
           spirv::FPRoundingModeAttr::get(rewriter.getContext(), *rm));
     }
diff --git a/mlir/lib/Dialect/SPIRV/IR/CastOps.cpp b/mlir/lib/Dialect/SPIRV/IR/CastOps.cpp
index e8bbb8016baf6..309ccfea31a8f 100644
--- a/mlir/lib/Dialect/SPIRV/IR/CastOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/CastOps.cpp
@@ -21,13 +21,8 @@ using namespace mlir::spirv::AttrNames;
 
 namespace mlir::spirv {
 
-static LogicalResult verifyCastOp(Operation *op,
-                                  bool requireSameBitWidth = true,
-                                  bool skipBitWidthCheck = false) {
-  // Some CastOps have no limit on bit widths for result and operand type.
-  if (skipBitWidthCheck)
-    return success();
-
+static FailureOr<std::pair<Type, Type>>
+getCastOpOperandAndResultElementType(Operation *op) {
   Type operandType = op->getOperand(0).getType();
   Type resultType = op->getResult(0).getType();
 
@@ -50,7 +45,23 @@ static LogicalResult verifyCastOp(Operation *op,
           });
 
   if (!operandElemTy || !resultElemTy)
-    return op->emitOpError("incompatible operand and result types");
+    return op->emitOpError("incompatible operand and result types"), failure();
+
+  return TypePair{operandElemTy, resultElemTy};
+}
+
+static LogicalResult verifyCastOp(Operation *op,
+                                  bool requireSameBitWidth = true,
+                                  bool skipBitWidthCheck = false) {
+  // Some CastOps have no limit on bit widths for result and operand type.
+  if (skipBitWidthCheck)
+    return success();
+
+  FailureOr<std::pair<Type, Type>> elemTypes =
+      getCastOpOperandAndResultElementType(op);
+  if (failed(elemTypes))
+    return failure();
+  auto [operandElemTy, resultElemTy] = *elemTypes;
 
   unsigned operandTypeBitWidth = operandElemTy.getIntOrFloatBitWidth();
   unsigned resultTypeBitWidth = resultElemTy.getIntOrFloatBitWidth();
@@ -304,7 +315,22 @@ LogicalResult ConvertUToFOp::verify() {
 //===----------------------------------------------------------------------===//
 
 LogicalResult spirv::FConvertOp::verify() {
-  return verifyCastOp(*this, /*requireSameBitWidth=*/false);
+  // The SPIR-V spec requires the component type to differ, not the bit
+  // width: "The component type must not equal the component type in Result
+  // Type." (OpFConvert, section 3.42.11). This allows converting between
+  // same-width encodings such as f16 and bf16.
+  FailureOr<std::pair<Type, Type>> elemTypes =
+      getCastOpOperandAndResultElementType(*this);
+  if (failed(elemTypes))
+    return failure();
+  auto [operandElemTy, resultElemTy] = *elemTypes;
+
+  if (operandElemTy == resultElemTy) {
+    return emitOpError("expected different component types for operand type "
+                       "and result type, but provided ")
+           << operandElemTy << " and " << resultElemTy;
+  }
+  return success();
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir b/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
index 1dcccbad41455..123dc08031311 100644
--- a/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
+++ b/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
@@ -1165,32 +1165,28 @@ module attributes {
 
 // CHECK-LABEL: @convertf_f16_to_bf16
 func.func @convertf_f16_to_bf16(%arg0 : f16) -> bf16 {
-  // CHECK: %[[WIDE:.+]] = spirv.FConvert %{{.*}} : f16 to f32
-  // CHECK: spirv.FConvert %[[WIDE]] : f32 to bf16
+  // CHECK: spirv.FConvert %{{.*}} : f16 to bf16
   %0 = arith.convertf %arg0 : f16 to bf16
   return %0 : bf16
 }
 
 // CHECK-LABEL: @convertf_bf16_to_f16
 func.func @convertf_bf16_to_f16(%arg0 : bf16) -> f16 {
-  // CHECK: %[[WIDE:.+]] = spirv.FConvert %{{.*}} : bf16 to f32
-  // CHECK: spirv.FConvert %[[WIDE]] : f32 to f16
+  // CHECK: spirv.FConvert %{{.*}} : bf16 to f16
   %0 = arith.convertf %arg0 : bf16 to f16
   return %0 : f16
 }
 
 // CHECK-LABEL: @convertf_vector_f16_to_bf16
 func.func @convertf_vector_f16_to_bf16(%arg0 : vector<4xf16>) -> vector<4xbf16> {
-  // CHECK: %[[WIDE:.+]] = spirv.FConvert %{{.*}} : vector<4xf16> to vector<4xf32>
-  // CHECK: spirv.FConvert %[[WIDE]] : vector<4xf32> to vector<4xbf16>
+  // CHECK: spirv.FConvert %{{.*}} : vector<4xf16> to vector<4xbf16>
   %0 = arith.convertf %arg0 : vector<4xf16> to vector<4xbf16>
   return %0 : vector<4xbf16>
 }
 
 // CHECK-LABEL: @convertf_rounding_mode
 func.func @convertf_rounding_mode(%arg0 : f16) -> bf16 {
-  // CHECK: %[[WIDE:.+]] = spirv.FConvert %{{.*}} : f16 to f32
-  // CHECK: spirv.FConvert %[[WIDE]] {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>} : f32 to bf16
+  // CHECK: spirv.FConvert %{{.*}} {fp_rounding_mode = #spirv.fp_rounding_mode<RTE>} : f16 to bf16
   %0 = arith.convertf %arg0 to_nearest_even : f16 to bf16
   return %0 : bf16
 }
diff --git a/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir b/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
index 2bd992979e2ab..e5ea675a1f243 100644
--- a/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
@@ -309,7 +309,7 @@ func.func @f_convert_coop_matrix(%arg0 : !spirv.coopmatrix<8x16xf32, Subgroup, M
 // -----
 
 func.func @f_convert_vector(%arg0 : f32) -> f32 {
-  // expected-error @+1 {{expected the different bit widths for operand type and result type, but provided 'f32' and 'f32'}}
+  // expected-error @+1 {{expected different component types for operand type and result type, but provided 'f32' and 'f32'}}
   %0 = spirv.FConvert %arg0 : f32 to f32
   spirv.ReturnValue %0 : f32
 }
@@ -324,6 +324,14 @@ func.func @f_convert_bf16_to_f32_scalar(%arg0 : bf16) -> f32 {
 
 // -----
 
+func.func @f_convert_f16_to_bf16_scalar(%arg0 : f16) -> bf16 {
+  // CHECK: {{%.*}} = spirv.FConvert {{%.*}} : f16 to bf16
+  %0 = spirv.FConvert %arg0 : f16 to bf16
+  spirv.ReturnValue %0 : bf16
+}
+
+// -----
+
 func.func @f_convert_f32_to_bf16_vector(%arg0 : vector<3xf32>) -> vector<3xbf16> {
   // CHECK: {{%.*}} = spirv.FConvert {{%.*}} : vector<3xf32> to vector<3xbf16>
   %0 = spirv.FConvert %arg0 : vector<3xf32> to vector<3xbf16>
diff --git a/mlir/test/Target/SPIRV/cast-ops.mlir b/mlir/test/Target/SPIRV/cast-ops.mlir
index 317264d37b8c8..b058c2cebda2f 100644
--- a/mlir/test/Target/SPIRV/cast-ops.mlir
+++ b/mlir/test/Target/SPIRV/cast-ops.mlir
@@ -29,7 +29,7 @@ spirv.module Logical Vulkan requires #spirv.vce<v1.6, [Shader, Linkage, Cooperat
 
 // -----
 
-spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage, BFloat16TypeKHR, Float64, Int64], [SPV_KHR_bfloat16]> {
+spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage, BFloat16TypeKHR, Float16, Float64, Int64], [SPV_KHR_bfloat16]> {
   spirv.func @convert_f_to_s(%arg0 : f32) -> i32 "None" {
     // CHECK: {{%.*}} = spirv.ConvertFToS {{%.*}} : f32 to i32
     %0 = spirv.ConvertFToS %arg0 : f32 to i32
@@ -105,6 +105,11 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage, BFloat1
     %0 = spirv.FConvert %arg0 : bf16 to f32
     spirv.ReturnValue %0 : f32
   }
+  spirv.func @convert_f16_to_bf16(%arg0 : f16) -> bf16 "None" {
+    // CHECK: {{%.*}} = spirv.FConvert {{%.*}} : f16 to bf16
+    %0 = spirv.FConvert %arg0 : f16 to bf16
+    spirv.ReturnValue %0 : bf16
+  }
   spirv.func @s_convert(%arg0 : i32) -> i64 "None" {
     // CHECK: {{%.*}} = spirv.SConvert {{%.*}} : i32 to i64
     %0 = spirv.SConvert %arg0 : i32 to i64

>From e4a5eb33631f5f8989858ae9f0cbc1a50e614d18 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 21 Sep 2026 14:56:03 +0200
Subject: [PATCH 3/3] simplification

---
 .../Conversion/ArithToSPIRV/ArithToSPIRV.cpp  | 42 +------------------
 mlir/lib/Dialect/SPIRV/IR/CastOps.cpp         |  6 ++-
 2 files changed, 5 insertions(+), 43 deletions(-)

diff --git a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
index 7c2bc5fca63a4..40c0ac7064fdb 100644
--- a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
+++ b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
@@ -1070,46 +1070,6 @@ struct TypeCastingOpPattern final : public OpConversionPattern<Op> {
   }
 };
 
-//===----------------------------------------------------------------------===//
-// ConvertFOp
-//===----------------------------------------------------------------------===//
-
-/// Converts arith.convertf (same-bitwidth FP cast, e.g. f16 <-> bf16) to
-/// spirv.FConvert.
-struct ConvertFOpPattern final : public OpConversionPattern<arith::ConvertFOp> {
-  using Base::Base;
-
-  LogicalResult
-  matchAndRewrite(arith::ConvertFOp op, OpAdaptor adaptor,
-                  ConversionPatternRewriter &rewriter) const override {
-    Type dstType = getTypeConverter()->convertType(op.getType());
-    if (!dstType)
-      return getTypeConversionFailure(rewriter, op);
-
-    if (dstType == adaptor.getIn().getType()) {
-      rewriter.replaceOp(op, adaptor.getIn());
-      return success();
-    }
-
-    std::optional<spirv::FPRoundingMode> rm = std::nullopt;
-    if (arith::RoundingModeAttr roundingMode = op.getRoundingmodeAttr()) {
-      if (!(rm = convertArithRoundingModeToSPIRV(roundingMode.getValue())))
-        return rewriter.notifyMatchFailure(
-            op->getLoc(),
-            llvm::formatv("unsupported rounding mode '{0}'", roundingMode));
-    }
-
-    auto converted = rewriter.replaceOpWithNewOp<spirv::FConvertOp>(
-        op, dstType, adaptor.getIn());
-    if (rm) {
-      converted->setAttr(
-          getDecorationString(spirv::Decoration::FPRoundingMode),
-          spirv::FPRoundingModeAttr::get(rewriter.getContext(), *rm));
-    }
-    return success();
-  }
-};
-
 //===----------------------------------------------------------------------===//
 // CmpIOp
 //===----------------------------------------------------------------------===//
@@ -1542,7 +1502,7 @@ void mlir::arith::populateArithToSPIRVPatterns(
     TypeCastingOpPattern<arith::ExtFOp, spirv::FConvertOp>,
     TruncIPattern, TruncII1Pattern,
     TypeCastingOpPattern<arith::TruncFOp, spirv::FConvertOp>,
-    ConvertFOpPattern,
+    TypeCastingOpPattern<arith::ConvertFOp, spirv::FConvertOp>,
     IntToFPPattern<arith::UIToFPOp, spirv::ConvertUToFOp, false>,
     BoolToValuePattern<arith::UIToFPOp>,
     IntToFPPattern<arith::SIToFPOp, spirv::ConvertSToFOp, true>,
diff --git a/mlir/lib/Dialect/SPIRV/IR/CastOps.cpp b/mlir/lib/Dialect/SPIRV/IR/CastOps.cpp
index 309ccfea31a8f..5884afca0fe77 100644
--- a/mlir/lib/Dialect/SPIRV/IR/CastOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/CastOps.cpp
@@ -44,8 +44,10 @@ getCastOpOperandAndResultElementType(Operation *op) {
             return {operandType, resultType};
           });
 
-  if (!operandElemTy || !resultElemTy)
-    return op->emitOpError("incompatible operand and result types"), failure();
+  if (!operandElemTy || !resultElemTy) {
+    op->emitOpError("incompatible operand and result types");
+    return failure();
+  }
 
   return TypePair{operandElemTy, resultElemTy};
 }



More information about the Mlir-commits mailing list