1d0cb0d30SAlexander Belyaev //===- ComplexToLLVM.cpp - conversion from Complex to LLVM dialect --------===//
2d0cb0d30SAlexander Belyaev //
3d0cb0d30SAlexander Belyaev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d0cb0d30SAlexander Belyaev // See https://llvm.org/LICENSE.txt for license information.
5d0cb0d30SAlexander Belyaev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d0cb0d30SAlexander Belyaev //
7d0cb0d30SAlexander Belyaev //===----------------------------------------------------------------------===//
8d0cb0d30SAlexander Belyaev 
9d0cb0d30SAlexander Belyaev #include "mlir/Conversion/ComplexToLLVM/ComplexToLLVM.h"
10d0cb0d30SAlexander Belyaev 
11d0cb0d30SAlexander Belyaev #include "../PassDetail.h"
12d0cb0d30SAlexander Belyaev #include "mlir/Dialect/Complex/IR/Complex.h"
13d0cb0d30SAlexander Belyaev #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
14d0cb0d30SAlexander Belyaev 
15d0cb0d30SAlexander Belyaev using namespace mlir;
16d0cb0d30SAlexander Belyaev using namespace mlir::LLVM;
17d0cb0d30SAlexander Belyaev 
18d0cb0d30SAlexander Belyaev namespace {
19d0cb0d30SAlexander Belyaev 
2011f4c58cSAlexander Belyaev struct AbsOpConversion : public ConvertOpToLLVMPattern<complex::AbsOp> {
2111f4c58cSAlexander Belyaev   using ConvertOpToLLVMPattern<complex::AbsOp>::ConvertOpToLLVMPattern;
2211f4c58cSAlexander Belyaev 
2311f4c58cSAlexander Belyaev   LogicalResult
2411f4c58cSAlexander Belyaev   matchAndRewrite(complex::AbsOp op, ArrayRef<Value> operands,
2511f4c58cSAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
2611f4c58cSAlexander Belyaev     complex::AbsOp::Adaptor transformed(operands);
2711f4c58cSAlexander Belyaev     auto loc = op.getLoc();
2811f4c58cSAlexander Belyaev 
2911f4c58cSAlexander Belyaev     ComplexStructBuilder complexStruct(transformed.complex());
3011f4c58cSAlexander Belyaev     Value real = complexStruct.real(rewriter, op.getLoc());
3111f4c58cSAlexander Belyaev     Value imag = complexStruct.imaginary(rewriter, op.getLoc());
3211f4c58cSAlexander Belyaev 
33038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
3411f4c58cSAlexander Belyaev     Value sqNorm = rewriter.create<LLVM::FAddOp>(
3511f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, real, real, fmf),
3611f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, imag, imag, fmf), fmf);
3711f4c58cSAlexander Belyaev 
3811f4c58cSAlexander Belyaev     rewriter.replaceOpWithNewOp<LLVM::SqrtOp>(op, sqNorm);
3911f4c58cSAlexander Belyaev     return success();
4011f4c58cSAlexander Belyaev   }
4111f4c58cSAlexander Belyaev };
4211f4c58cSAlexander Belyaev 
43d0cb0d30SAlexander Belyaev struct CreateOpConversion : public ConvertOpToLLVMPattern<complex::CreateOp> {
44d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::CreateOp>::ConvertOpToLLVMPattern;
45d0cb0d30SAlexander Belyaev 
46d0cb0d30SAlexander Belyaev   LogicalResult
47d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::CreateOp complexOp, ArrayRef<Value> operands,
48d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
49d0cb0d30SAlexander Belyaev     complex::CreateOp::Adaptor transformed(operands);
50d0cb0d30SAlexander Belyaev 
51d0cb0d30SAlexander Belyaev     // Pack real and imaginary part in a complex number struct.
52d0cb0d30SAlexander Belyaev     auto loc = complexOp.getLoc();
53d0cb0d30SAlexander Belyaev     auto structType = typeConverter->convertType(complexOp.getType());
54d0cb0d30SAlexander Belyaev     auto complexStruct = ComplexStructBuilder::undef(rewriter, loc, structType);
55d0cb0d30SAlexander Belyaev     complexStruct.setReal(rewriter, loc, transformed.real());
56d0cb0d30SAlexander Belyaev     complexStruct.setImaginary(rewriter, loc, transformed.imaginary());
57d0cb0d30SAlexander Belyaev 
58d0cb0d30SAlexander Belyaev     rewriter.replaceOp(complexOp, {complexStruct});
59d0cb0d30SAlexander Belyaev     return success();
60d0cb0d30SAlexander Belyaev   }
61d0cb0d30SAlexander Belyaev };
62d0cb0d30SAlexander Belyaev 
63d0cb0d30SAlexander Belyaev struct ReOpConversion : public ConvertOpToLLVMPattern<complex::ReOp> {
64d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::ReOp>::ConvertOpToLLVMPattern;
65d0cb0d30SAlexander Belyaev 
66d0cb0d30SAlexander Belyaev   LogicalResult
67d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::ReOp op, ArrayRef<Value> operands,
68d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
69d0cb0d30SAlexander Belyaev     complex::ReOp::Adaptor transformed(operands);
70d0cb0d30SAlexander Belyaev 
71d0cb0d30SAlexander Belyaev     // Extract real part from the complex number struct.
72d0cb0d30SAlexander Belyaev     ComplexStructBuilder complexStruct(transformed.complex());
73d0cb0d30SAlexander Belyaev     Value real = complexStruct.real(rewriter, op.getLoc());
74d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, real);
75d0cb0d30SAlexander Belyaev 
76d0cb0d30SAlexander Belyaev     return success();
77d0cb0d30SAlexander Belyaev   }
78d0cb0d30SAlexander Belyaev };
79d0cb0d30SAlexander Belyaev 
80d0cb0d30SAlexander Belyaev struct ImOpConversion : public ConvertOpToLLVMPattern<complex::ImOp> {
81d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::ImOp>::ConvertOpToLLVMPattern;
82d0cb0d30SAlexander Belyaev 
83d0cb0d30SAlexander Belyaev   LogicalResult
84d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::ImOp op, ArrayRef<Value> operands,
85d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
86d0cb0d30SAlexander Belyaev     complex::ImOp::Adaptor transformed(operands);
87d0cb0d30SAlexander Belyaev 
88d0cb0d30SAlexander Belyaev     // Extract imaginary part from the complex number struct.
89d0cb0d30SAlexander Belyaev     ComplexStructBuilder complexStruct(transformed.complex());
90d0cb0d30SAlexander Belyaev     Value imaginary = complexStruct.imaginary(rewriter, op.getLoc());
91d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, imaginary);
92d0cb0d30SAlexander Belyaev 
93d0cb0d30SAlexander Belyaev     return success();
94d0cb0d30SAlexander Belyaev   }
95d0cb0d30SAlexander Belyaev };
96d0cb0d30SAlexander Belyaev 
97d0cb0d30SAlexander Belyaev struct BinaryComplexOperands {
98d0cb0d30SAlexander Belyaev   std::complex<Value> lhs;
99d0cb0d30SAlexander Belyaev   std::complex<Value> rhs;
100d0cb0d30SAlexander Belyaev };
101d0cb0d30SAlexander Belyaev 
102d0cb0d30SAlexander Belyaev template <typename OpTy>
103d0cb0d30SAlexander Belyaev BinaryComplexOperands
104d0cb0d30SAlexander Belyaev unpackBinaryComplexOperands(OpTy op, ArrayRef<Value> operands,
105d0cb0d30SAlexander Belyaev                             ConversionPatternRewriter &rewriter) {
106d0cb0d30SAlexander Belyaev   auto loc = op.getLoc();
107d0cb0d30SAlexander Belyaev   typename OpTy::Adaptor transformed(operands);
108d0cb0d30SAlexander Belyaev 
109d0cb0d30SAlexander Belyaev   // Extract real and imaginary values from operands.
110d0cb0d30SAlexander Belyaev   BinaryComplexOperands unpacked;
111d0cb0d30SAlexander Belyaev   ComplexStructBuilder lhs(transformed.lhs());
112d0cb0d30SAlexander Belyaev   unpacked.lhs.real(lhs.real(rewriter, loc));
113d0cb0d30SAlexander Belyaev   unpacked.lhs.imag(lhs.imaginary(rewriter, loc));
114d0cb0d30SAlexander Belyaev   ComplexStructBuilder rhs(transformed.rhs());
115d0cb0d30SAlexander Belyaev   unpacked.rhs.real(rhs.real(rewriter, loc));
116d0cb0d30SAlexander Belyaev   unpacked.rhs.imag(rhs.imaginary(rewriter, loc));
117d0cb0d30SAlexander Belyaev 
118d0cb0d30SAlexander Belyaev   return unpacked;
119d0cb0d30SAlexander Belyaev }
120d0cb0d30SAlexander Belyaev 
121d0cb0d30SAlexander Belyaev struct AddOpConversion : public ConvertOpToLLVMPattern<complex::AddOp> {
122d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::AddOp>::ConvertOpToLLVMPattern;
123d0cb0d30SAlexander Belyaev 
124d0cb0d30SAlexander Belyaev   LogicalResult
125d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::AddOp op, ArrayRef<Value> operands,
126d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
127d0cb0d30SAlexander Belyaev     auto loc = op.getLoc();
128d0cb0d30SAlexander Belyaev     BinaryComplexOperands arg =
129d0cb0d30SAlexander Belyaev         unpackBinaryComplexOperands<complex::AddOp>(op, operands, rewriter);
130d0cb0d30SAlexander Belyaev 
131d0cb0d30SAlexander Belyaev     // Initialize complex number struct for result.
132d0cb0d30SAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
133d0cb0d30SAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
134d0cb0d30SAlexander Belyaev 
135d0cb0d30SAlexander Belyaev     // Emit IR to add complex numbers.
136038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
137d0cb0d30SAlexander Belyaev     Value real =
138d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FAddOp>(loc, arg.lhs.real(), arg.rhs.real(), fmf);
139d0cb0d30SAlexander Belyaev     Value imag =
140d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FAddOp>(loc, arg.lhs.imag(), arg.rhs.imag(), fmf);
141d0cb0d30SAlexander Belyaev     result.setReal(rewriter, loc, real);
142d0cb0d30SAlexander Belyaev     result.setImaginary(rewriter, loc, imag);
143d0cb0d30SAlexander Belyaev 
144d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, {result});
145d0cb0d30SAlexander Belyaev     return success();
146d0cb0d30SAlexander Belyaev   }
147d0cb0d30SAlexander Belyaev };
148d0cb0d30SAlexander Belyaev 
14911f4c58cSAlexander Belyaev struct DivOpConversion : public ConvertOpToLLVMPattern<complex::DivOp> {
15011f4c58cSAlexander Belyaev   using ConvertOpToLLVMPattern<complex::DivOp>::ConvertOpToLLVMPattern;
15111f4c58cSAlexander Belyaev 
15211f4c58cSAlexander Belyaev   LogicalResult
15311f4c58cSAlexander Belyaev   matchAndRewrite(complex::DivOp op, ArrayRef<Value> operands,
15411f4c58cSAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
15511f4c58cSAlexander Belyaev     auto loc = op.getLoc();
15611f4c58cSAlexander Belyaev     BinaryComplexOperands arg =
15711f4c58cSAlexander Belyaev         unpackBinaryComplexOperands<complex::DivOp>(op, operands, rewriter);
15811f4c58cSAlexander Belyaev 
15911f4c58cSAlexander Belyaev     // Initialize complex number struct for result.
16011f4c58cSAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
16111f4c58cSAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
16211f4c58cSAlexander Belyaev 
16311f4c58cSAlexander Belyaev     // Emit IR to add complex numbers.
164038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
16511f4c58cSAlexander Belyaev     Value rhsRe = arg.rhs.real();
16611f4c58cSAlexander Belyaev     Value rhsIm = arg.rhs.imag();
16711f4c58cSAlexander Belyaev     Value lhsRe = arg.lhs.real();
16811f4c58cSAlexander Belyaev     Value lhsIm = arg.lhs.imag();
16911f4c58cSAlexander Belyaev 
17011f4c58cSAlexander Belyaev     Value rhsSqNorm = rewriter.create<LLVM::FAddOp>(
17111f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, rhsRe, rhsRe, fmf),
17211f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, rhsIm, rhsIm, fmf), fmf);
17311f4c58cSAlexander Belyaev 
17411f4c58cSAlexander Belyaev     Value resultReal = rewriter.create<LLVM::FAddOp>(
17511f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, lhsRe, rhsRe, fmf),
17611f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, lhsIm, rhsIm, fmf), fmf);
17711f4c58cSAlexander Belyaev 
17811f4c58cSAlexander Belyaev     Value resultImag = rewriter.create<LLVM::FSubOp>(
17911f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, lhsIm, rhsRe, fmf),
18011f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, lhsRe, rhsIm, fmf), fmf);
18111f4c58cSAlexander Belyaev 
18211f4c58cSAlexander Belyaev     result.setReal(
18311f4c58cSAlexander Belyaev         rewriter, loc,
18411f4c58cSAlexander Belyaev         rewriter.create<LLVM::FDivOp>(loc, resultReal, rhsSqNorm, fmf));
18511f4c58cSAlexander Belyaev     result.setImaginary(
18611f4c58cSAlexander Belyaev         rewriter, loc,
18711f4c58cSAlexander Belyaev         rewriter.create<LLVM::FDivOp>(loc, resultImag, rhsSqNorm, fmf));
18811f4c58cSAlexander Belyaev 
18911f4c58cSAlexander Belyaev     rewriter.replaceOp(op, {result});
19011f4c58cSAlexander Belyaev     return success();
19111f4c58cSAlexander Belyaev   }
19211f4c58cSAlexander Belyaev };
19311f4c58cSAlexander Belyaev 
19411f4c58cSAlexander Belyaev struct MulOpConversion : public ConvertOpToLLVMPattern<complex::MulOp> {
19511f4c58cSAlexander Belyaev   using ConvertOpToLLVMPattern<complex::MulOp>::ConvertOpToLLVMPattern;
19611f4c58cSAlexander Belyaev 
19711f4c58cSAlexander Belyaev   LogicalResult
19811f4c58cSAlexander Belyaev   matchAndRewrite(complex::MulOp op, ArrayRef<Value> operands,
19911f4c58cSAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
20011f4c58cSAlexander Belyaev     auto loc = op.getLoc();
20111f4c58cSAlexander Belyaev     BinaryComplexOperands arg =
20211f4c58cSAlexander Belyaev         unpackBinaryComplexOperands<complex::MulOp>(op, operands, rewriter);
20311f4c58cSAlexander Belyaev 
20411f4c58cSAlexander Belyaev     // Initialize complex number struct for result.
20511f4c58cSAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
20611f4c58cSAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
20711f4c58cSAlexander Belyaev 
20811f4c58cSAlexander Belyaev     // Emit IR to add complex numbers.
209038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
21011f4c58cSAlexander Belyaev     Value rhsRe = arg.rhs.real();
21111f4c58cSAlexander Belyaev     Value rhsIm = arg.rhs.imag();
21211f4c58cSAlexander Belyaev     Value lhsRe = arg.lhs.real();
21311f4c58cSAlexander Belyaev     Value lhsIm = arg.lhs.imag();
21411f4c58cSAlexander Belyaev 
21511f4c58cSAlexander Belyaev     Value real = rewriter.create<LLVM::FSubOp>(
21611f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, rhsRe, lhsRe, fmf),
21711f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, rhsIm, lhsIm, fmf), fmf);
21811f4c58cSAlexander Belyaev 
21911f4c58cSAlexander Belyaev     Value imag = rewriter.create<LLVM::FAddOp>(
22011f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, lhsIm, rhsRe, fmf),
22111f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, lhsRe, rhsIm, fmf), fmf);
22211f4c58cSAlexander Belyaev 
22311f4c58cSAlexander Belyaev     result.setReal(rewriter, loc, real);
22411f4c58cSAlexander Belyaev     result.setImaginary(rewriter, loc, imag);
22511f4c58cSAlexander Belyaev 
22611f4c58cSAlexander Belyaev     rewriter.replaceOp(op, {result});
22711f4c58cSAlexander Belyaev     return success();
22811f4c58cSAlexander Belyaev   }
22911f4c58cSAlexander Belyaev };
23011f4c58cSAlexander Belyaev 
231d0cb0d30SAlexander Belyaev struct SubOpConversion : public ConvertOpToLLVMPattern<complex::SubOp> {
232d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::SubOp>::ConvertOpToLLVMPattern;
233d0cb0d30SAlexander Belyaev 
234d0cb0d30SAlexander Belyaev   LogicalResult
235d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::SubOp op, ArrayRef<Value> operands,
236d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
237d0cb0d30SAlexander Belyaev     auto loc = op.getLoc();
238d0cb0d30SAlexander Belyaev     BinaryComplexOperands arg =
239d0cb0d30SAlexander Belyaev         unpackBinaryComplexOperands<complex::SubOp>(op, operands, rewriter);
240d0cb0d30SAlexander Belyaev 
241d0cb0d30SAlexander Belyaev     // Initialize complex number struct for result.
242d0cb0d30SAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
243d0cb0d30SAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
244d0cb0d30SAlexander Belyaev 
245d0cb0d30SAlexander Belyaev     // Emit IR to substract complex numbers.
246038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
247d0cb0d30SAlexander Belyaev     Value real =
248d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FSubOp>(loc, arg.lhs.real(), arg.rhs.real(), fmf);
249d0cb0d30SAlexander Belyaev     Value imag =
250d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FSubOp>(loc, arg.lhs.imag(), arg.rhs.imag(), fmf);
251d0cb0d30SAlexander Belyaev     result.setReal(rewriter, loc, real);
252d0cb0d30SAlexander Belyaev     result.setImaginary(rewriter, loc, imag);
253d0cb0d30SAlexander Belyaev 
254d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, {result});
255d0cb0d30SAlexander Belyaev     return success();
256d0cb0d30SAlexander Belyaev   }
257d0cb0d30SAlexander Belyaev };
258d0cb0d30SAlexander Belyaev } // namespace
259d0cb0d30SAlexander Belyaev 
260d0cb0d30SAlexander Belyaev void mlir::populateComplexToLLVMConversionPatterns(
261*dc4e913bSChris Lattner     LLVMTypeConverter &converter, RewritePatternSet &patterns) {
262d0cb0d30SAlexander Belyaev   // clang-format off
263*dc4e913bSChris Lattner   patterns.add<
26411f4c58cSAlexander Belyaev       AbsOpConversion,
265d0cb0d30SAlexander Belyaev       AddOpConversion,
266d0cb0d30SAlexander Belyaev       CreateOpConversion,
26711f4c58cSAlexander Belyaev       DivOpConversion,
268d0cb0d30SAlexander Belyaev       ImOpConversion,
26911f4c58cSAlexander Belyaev       MulOpConversion,
270d0cb0d30SAlexander Belyaev       ReOpConversion,
271d0cb0d30SAlexander Belyaev       SubOpConversion
272d0cb0d30SAlexander Belyaev     >(converter);
273d0cb0d30SAlexander Belyaev   // clang-format on
274d0cb0d30SAlexander Belyaev }
275d0cb0d30SAlexander Belyaev 
276d0cb0d30SAlexander Belyaev namespace {
277d0cb0d30SAlexander Belyaev struct ConvertComplexToLLVMPass
278d0cb0d30SAlexander Belyaev     : public ConvertComplexToLLVMBase<ConvertComplexToLLVMPass> {
279d0cb0d30SAlexander Belyaev   void runOnOperation() override;
280d0cb0d30SAlexander Belyaev };
281d0cb0d30SAlexander Belyaev } // namespace
282d0cb0d30SAlexander Belyaev 
283d0cb0d30SAlexander Belyaev void ConvertComplexToLLVMPass::runOnOperation() {
284d0cb0d30SAlexander Belyaev   auto module = getOperation();
285d0cb0d30SAlexander Belyaev 
286d0cb0d30SAlexander Belyaev   // Convert to the LLVM IR dialect using the converter defined above.
287*dc4e913bSChris Lattner   RewritePatternSet patterns(&getContext());
288d0cb0d30SAlexander Belyaev   LLVMTypeConverter converter(&getContext());
289d0cb0d30SAlexander Belyaev   populateComplexToLLVMConversionPatterns(converter, patterns);
290d0cb0d30SAlexander Belyaev 
291d0cb0d30SAlexander Belyaev   LLVMConversionTarget target(getContext());
292d6be2773SAlex Zinenko   target.addLegalOp<ModuleOp, FuncOp>();
293d6be2773SAlex Zinenko   target.addLegalOp<LLVM::DialectCastOp>();
294d6be2773SAlex Zinenko   target.addIllegalDialect<complex::ComplexDialect>();
295d6be2773SAlex Zinenko   if (failed(applyPartialConversion(module, target, std::move(patterns))))
296d0cb0d30SAlexander Belyaev     signalPassFailure();
297d0cb0d30SAlexander Belyaev }
298d0cb0d30SAlexander Belyaev 
299d0cb0d30SAlexander Belyaev std::unique_ptr<OperationPass<ModuleOp>>
300d0cb0d30SAlexander Belyaev mlir::createConvertComplexToLLVMPass() {
301d0cb0d30SAlexander Belyaev   return std::make_unique<ConvertComplexToLLVMPass>();
302d0cb0d30SAlexander Belyaev }
303