[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