[Mlir-commits] [mlir] 2fe7826 - [mlir][SPIR-V] Add ComplexToSPIRV lowering for complex.sign (#216722)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Wed Oct 14 03:33:10 PDT 2026
Author: Arseniy Obolenskiy
Date: 2026-10-14T12:33:04+02:00
New Revision: 2fe78267078428c0b0c9ae8379d78cf93606759e
URL: https://github.com/llvm/llvm-project/commit/2fe78267078428c0b0c9ae8379d78cf93606759e
DIFF: https://github.com/llvm/llvm-project/commit/2fe78267078428c0b0c9ae8379d78cf93606759e.diff
LOG: [mlir][SPIR-V] Add ComplexToSPIRV lowering for complex.sign (#216722)
Computes complex.sign as z / abs(z), using a component-wise spirv.Select
to pick a zero result when z is zero without requiring SPIR-V 1.4 (a
vector-result Select would need a scalar condition paired with a
composite result, which is only legal from 1.4 on)
Added:
Modified:
mlir/lib/Conversion/ComplexToSPIRV/ComplexToSPIRV.cpp
mlir/test/Conversion/ComplexToSPIRV/complex-to-spirv.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Conversion/ComplexToSPIRV/ComplexToSPIRV.cpp b/mlir/lib/Conversion/ComplexToSPIRV/ComplexToSPIRV.cpp
index 884df06a4e705..e57d6d922e5ba 100644
--- a/mlir/lib/Conversion/ComplexToSPIRV/ComplexToSPIRV.cpp
+++ b/mlir/lib/Conversion/ComplexToSPIRV/ComplexToSPIRV.cpp
@@ -25,6 +25,12 @@ using namespace mlir;
//===----------------------------------------------------------------------===//
namespace {
+/// Creates a scalar floating-point constant of the given value.
+Value createFPConstant(OpBuilder &builder, Location loc, Type type,
+ double value) {
+ return spirv::ConstantOp::create(
+ builder, loc, type, builder.getFloatAttr(cast<FloatType>(type), value));
+}
struct ConstantOpPattern final : OpConversionPattern<complex::ConstantOp> {
using Base::Base;
@@ -309,6 +315,60 @@ struct AngleOpPattern final : OpConversionPattern<complex::AngleOp> {
}
};
+/// Computes complex.sign as z / abs(z), selecting a zero result when z is
+/// zero to avoid a division by zero. abs(z) is computed as
+/// max * sqrt(1 + (min / max)^2) to avoid overflow in squaring.
+template <typename SqrtOp, typename FAbsOp, typename FMaxOp, typename FMinOp>
+struct SignOpPattern final : OpConversionPattern<complex::SignOp> {
+ using OpConversionPattern<complex::SignOp>::OpConversionPattern;
+
+ LogicalResult
+ matchAndRewrite(complex::SignOp op, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ Type spirvType =
+ this->getTypeConverter()->convertType(op.getResult().getType());
+ if (!spirvType)
+ return rewriter.notifyMatchFailure(op, "unable to convert result type");
+
+ Location loc = op.getLoc();
+ Value complexVal = adaptor.getComplex();
+
+ Value re =
+ spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
+ Value im =
+ spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
+
+ Value absRe = FAbsOp::create(rewriter, loc, re);
+ Value absIm = FAbsOp::create(rewriter, loc, im);
+ Value max = FMaxOp::create(rewriter, loc, absRe, absIm);
+ Value min = FMinOp::create(rewriter, loc, absRe, absIm);
+ Value ratio = spirv::FDivOp::create(rewriter, loc, min, max);
+ Value ratioSq = spirv::FMulOp::create(rewriter, loc, ratio, ratio);
+ Value one = createFPConstant(rewriter, loc, re.getType(), 1.0);
+ Value ratioSqPlusOne = spirv::FAddOp::create(rewriter, loc, ratioSq, one);
+ Value sqrt = SqrtOp::create(rewriter, loc, ratioSqPlusOne);
+ Value abs = spirv::FMulOp::create(rewriter, loc, max, sqrt);
+
+ Value signRe = spirv::FDivOp::create(rewriter, loc, re, abs);
+ Value signIm = spirv::FDivOp::create(rewriter, loc, im, abs);
+
+ Value zero = createFPConstant(rewriter, loc, re.getType(), 0.0);
+ Value reIsZero = spirv::FOrdEqualOp::create(rewriter, loc, re, zero);
+ Value imIsZero = spirv::FOrdEqualOp::create(rewriter, loc, im, zero);
+ Value isZero =
+ spirv::LogicalAndOp::create(rewriter, loc, reIsZero, imIsZero);
+
+ // Select per component: spirv.Select with a scalar condition and a
+ // composite result requires SPIR-V 1.4, so operate on scalars here and
+ // assemble the result afterwards.
+ Value resultRe = spirv::SelectOp::create(rewriter, loc, isZero, re, signRe);
+ Value resultIm = spirv::SelectOp::create(rewriter, loc, isZero, im, signIm);
+
+ rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
+ op, spirvType, llvm::ArrayRef<Value>{resultRe, resultIm});
+ return success();
+ }
+};
} // namespace
//===----------------------------------------------------------------------===//
@@ -331,6 +391,9 @@ void mlir::populateComplexToSPIRVPatterns(
NegationOpPattern<complex::NegOp, /*NegateReal=*/true>,
NegationOpPattern<complex::ConjOp, /*NegateReal=*/false>,
AbsOpPattern<spirv::GLSqrtOp>, AbsOpPattern<spirv::CLSqrtOp>,
- AngleOpPattern<spirv::GLAtan2Op>, AngleOpPattern<spirv::CLAtan2Op>>(
- typeConverter, context);
+ AngleOpPattern<spirv::GLAtan2Op>, AngleOpPattern<spirv::CLAtan2Op>,
+ SignOpPattern<spirv::GLSqrtOp, spirv::GLFAbsOp, spirv::GLFMaxOp,
+ spirv::GLFMinOp>,
+ SignOpPattern<spirv::CLSqrtOp, spirv::CLFAbsOp, spirv::CLFMaxOp,
+ spirv::CLFMinOp>>(typeConverter, context);
}
diff --git a/mlir/test/Conversion/ComplexToSPIRV/complex-to-spirv.mlir b/mlir/test/Conversion/ComplexToSPIRV/complex-to-spirv.mlir
index e060c1c0ad44a..1b39062ab985a 100644
--- a/mlir/test/Conversion/ComplexToSPIRV/complex-to-spirv.mlir
+++ b/mlir/test/Conversion/ComplexToSPIRV/complex-to-spirv.mlir
@@ -268,3 +268,35 @@ func.func @complex_angle_opencl(%arg: complex<f32>) -> f32 {
// CHECK: spirv.CL.atan2
}
+
+// -----
+
+func.func @complex_sign(%arg: complex<f32>) -> complex<f32> {
+ %sign = complex.sign %arg : complex<f32>
+ return %sign : complex<f32>
+}
+
+// CHECK-LABEL: func.func @complex_sign
+// CHECK-SAME: %[[ARG:.+]]: complex<f32>
+// CHECK: %[[V:.+]] = builtin.unrealized_conversion_cast %[[ARG]] : complex<f32> to vector<2xf32>
+// CHECK: %[[RE:.+]] = spirv.CompositeExtract %[[V]][0 : i32] : vector<2xf32>
+// CHECK: %[[IM:.+]] = spirv.CompositeExtract %[[V]][1 : i32] : vector<2xf32>
+// CHECK: %[[ABSRE:.+]] = spirv.GL.FAbs %[[RE]] : f32
+// CHECK: %[[ABSIM:.+]] = spirv.GL.FAbs %[[IM]] : f32
+// CHECK: %[[MAX:.+]] = spirv.GL.FMax %[[ABSRE]], %[[ABSIM]] : f32
+// CHECK: %[[MIN:.+]] = spirv.GL.FMin %[[ABSRE]], %[[ABSIM]] : f32
+// CHECK: %[[RATIO:.+]] = spirv.FDiv %[[MIN]], %[[MAX]] : f32
+// CHECK: %[[RATIOSQ:.+]] = spirv.FMul %[[RATIO]], %[[RATIO]] : f32
+// CHECK: %[[ONE:.+]] = spirv.Constant 1.000000e+00 : f32
+// CHECK: %[[SUM:.+]] = spirv.FAdd %[[RATIOSQ]], %[[ONE]] : f32
+// CHECK: %[[SQRT:.+]] = spirv.GL.Sqrt %[[SUM]] : f32
+// CHECK: %[[ABS:.+]] = spirv.FMul %[[MAX]], %[[SQRT]] : f32
+// CHECK: %[[SIGNRE:.+]] = spirv.FDiv %[[RE]], %[[ABS]] : f32
+// CHECK: %[[SIGNIM:.+]] = spirv.FDiv %[[IM]], %[[ABS]] : f32
+// CHECK: %[[ZERO:.+]] = spirv.Constant 0.000000e+00 : f32
+// CHECK: %[[REZ:.+]] = spirv.FOrdEqual %[[RE]], %[[ZERO]] : f32
+// CHECK: %[[IMZ:.+]] = spirv.FOrdEqual %[[IM]], %[[ZERO]] : f32
+// CHECK: %[[ISZERO:.+]] = spirv.LogicalAnd %[[REZ]], %[[IMZ]] : i1
+// CHECK: %[[SELRE:.+]] = spirv.Select %[[ISZERO]], %[[RE]], %[[SIGNRE]] : i1, f32
+// CHECK: %[[SELIM:.+]] = spirv.Select %[[ISZERO]], %[[IM]], %[[SIGNIM]] : i1, f32
+// CHECK: %[[RESULT:.+]] = spirv.CompositeConstruct %[[SELRE]], %[[SELIM]] : (f32, f32) -> vector<2xf32>
More information about the Mlir-commits
mailing list