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"
12*75e5f0aaSAlex Zinenko #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
13*75e5f0aaSAlex Zinenko #include "mlir/Conversion/LLVMCommon/Pattern.h"
14d0cb0d30SAlexander Belyaev #include "mlir/Dialect/Complex/IR/Complex.h"
15d0cb0d30SAlexander Belyaev #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
16d0cb0d30SAlexander Belyaev 
17d0cb0d30SAlexander Belyaev using namespace mlir;
18d0cb0d30SAlexander Belyaev using namespace mlir::LLVM;
19d0cb0d30SAlexander Belyaev 
20b5d847b1SAlex Zinenko //===----------------------------------------------------------------------===//
21b5d847b1SAlex Zinenko // ComplexStructBuilder implementation.
22b5d847b1SAlex Zinenko //===----------------------------------------------------------------------===//
23b5d847b1SAlex Zinenko 
24b5d847b1SAlex Zinenko static constexpr unsigned kRealPosInComplexNumberStruct = 0;
25b5d847b1SAlex Zinenko static constexpr unsigned kImaginaryPosInComplexNumberStruct = 1;
26b5d847b1SAlex Zinenko 
27b5d847b1SAlex Zinenko ComplexStructBuilder ComplexStructBuilder::undef(OpBuilder &builder,
28b5d847b1SAlex Zinenko                                                  Location loc, Type type) {
29b5d847b1SAlex Zinenko   Value val = builder.create<LLVM::UndefOp>(loc, type);
30b5d847b1SAlex Zinenko   return ComplexStructBuilder(val);
31b5d847b1SAlex Zinenko }
32b5d847b1SAlex Zinenko 
33b5d847b1SAlex Zinenko void ComplexStructBuilder::setReal(OpBuilder &builder, Location loc,
34b5d847b1SAlex Zinenko                                    Value real) {
35b5d847b1SAlex Zinenko   setPtr(builder, loc, kRealPosInComplexNumberStruct, real);
36b5d847b1SAlex Zinenko }
37b5d847b1SAlex Zinenko 
38b5d847b1SAlex Zinenko Value ComplexStructBuilder::real(OpBuilder &builder, Location loc) {
39b5d847b1SAlex Zinenko   return extractPtr(builder, loc, kRealPosInComplexNumberStruct);
40b5d847b1SAlex Zinenko }
41b5d847b1SAlex Zinenko 
42b5d847b1SAlex Zinenko void ComplexStructBuilder::setImaginary(OpBuilder &builder, Location loc,
43b5d847b1SAlex Zinenko                                         Value imaginary) {
44b5d847b1SAlex Zinenko   setPtr(builder, loc, kImaginaryPosInComplexNumberStruct, imaginary);
45b5d847b1SAlex Zinenko }
46b5d847b1SAlex Zinenko 
47b5d847b1SAlex Zinenko Value ComplexStructBuilder::imaginary(OpBuilder &builder, Location loc) {
48b5d847b1SAlex Zinenko   return extractPtr(builder, loc, kImaginaryPosInComplexNumberStruct);
49b5d847b1SAlex Zinenko }
50b5d847b1SAlex Zinenko 
51b5d847b1SAlex Zinenko //===----------------------------------------------------------------------===//
52b5d847b1SAlex Zinenko // Conversion patterns.
53b5d847b1SAlex Zinenko //===----------------------------------------------------------------------===//
54b5d847b1SAlex Zinenko 
55d0cb0d30SAlexander Belyaev namespace {
56d0cb0d30SAlexander Belyaev 
5711f4c58cSAlexander Belyaev struct AbsOpConversion : public ConvertOpToLLVMPattern<complex::AbsOp> {
5811f4c58cSAlexander Belyaev   using ConvertOpToLLVMPattern<complex::AbsOp>::ConvertOpToLLVMPattern;
5911f4c58cSAlexander Belyaev 
6011f4c58cSAlexander Belyaev   LogicalResult
6111f4c58cSAlexander Belyaev   matchAndRewrite(complex::AbsOp op, ArrayRef<Value> operands,
6211f4c58cSAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
6311f4c58cSAlexander Belyaev     complex::AbsOp::Adaptor transformed(operands);
6411f4c58cSAlexander Belyaev     auto loc = op.getLoc();
6511f4c58cSAlexander Belyaev 
6611f4c58cSAlexander Belyaev     ComplexStructBuilder complexStruct(transformed.complex());
6711f4c58cSAlexander Belyaev     Value real = complexStruct.real(rewriter, op.getLoc());
6811f4c58cSAlexander Belyaev     Value imag = complexStruct.imaginary(rewriter, op.getLoc());
6911f4c58cSAlexander Belyaev 
70038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
7111f4c58cSAlexander Belyaev     Value sqNorm = rewriter.create<LLVM::FAddOp>(
7211f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, real, real, fmf),
7311f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, imag, imag, fmf), fmf);
7411f4c58cSAlexander Belyaev 
7511f4c58cSAlexander Belyaev     rewriter.replaceOpWithNewOp<LLVM::SqrtOp>(op, sqNorm);
7611f4c58cSAlexander Belyaev     return success();
7711f4c58cSAlexander Belyaev   }
7811f4c58cSAlexander Belyaev };
7911f4c58cSAlexander Belyaev 
80d0cb0d30SAlexander Belyaev struct CreateOpConversion : public ConvertOpToLLVMPattern<complex::CreateOp> {
81d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::CreateOp>::ConvertOpToLLVMPattern;
82d0cb0d30SAlexander Belyaev 
83d0cb0d30SAlexander Belyaev   LogicalResult
84d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::CreateOp complexOp, ArrayRef<Value> operands,
85d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
86d0cb0d30SAlexander Belyaev     complex::CreateOp::Adaptor transformed(operands);
87d0cb0d30SAlexander Belyaev 
88d0cb0d30SAlexander Belyaev     // Pack real and imaginary part in a complex number struct.
89d0cb0d30SAlexander Belyaev     auto loc = complexOp.getLoc();
90d0cb0d30SAlexander Belyaev     auto structType = typeConverter->convertType(complexOp.getType());
91d0cb0d30SAlexander Belyaev     auto complexStruct = ComplexStructBuilder::undef(rewriter, loc, structType);
92d0cb0d30SAlexander Belyaev     complexStruct.setReal(rewriter, loc, transformed.real());
93d0cb0d30SAlexander Belyaev     complexStruct.setImaginary(rewriter, loc, transformed.imaginary());
94d0cb0d30SAlexander Belyaev 
95d0cb0d30SAlexander Belyaev     rewriter.replaceOp(complexOp, {complexStruct});
96d0cb0d30SAlexander Belyaev     return success();
97d0cb0d30SAlexander Belyaev   }
98d0cb0d30SAlexander Belyaev };
99d0cb0d30SAlexander Belyaev 
100d0cb0d30SAlexander Belyaev struct ReOpConversion : public ConvertOpToLLVMPattern<complex::ReOp> {
101d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::ReOp>::ConvertOpToLLVMPattern;
102d0cb0d30SAlexander Belyaev 
103d0cb0d30SAlexander Belyaev   LogicalResult
104d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::ReOp op, ArrayRef<Value> operands,
105d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
106d0cb0d30SAlexander Belyaev     complex::ReOp::Adaptor transformed(operands);
107d0cb0d30SAlexander Belyaev 
108d0cb0d30SAlexander Belyaev     // Extract real part from the complex number struct.
109d0cb0d30SAlexander Belyaev     ComplexStructBuilder complexStruct(transformed.complex());
110d0cb0d30SAlexander Belyaev     Value real = complexStruct.real(rewriter, op.getLoc());
111d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, real);
112d0cb0d30SAlexander Belyaev 
113d0cb0d30SAlexander Belyaev     return success();
114d0cb0d30SAlexander Belyaev   }
115d0cb0d30SAlexander Belyaev };
116d0cb0d30SAlexander Belyaev 
117d0cb0d30SAlexander Belyaev struct ImOpConversion : public ConvertOpToLLVMPattern<complex::ImOp> {
118d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::ImOp>::ConvertOpToLLVMPattern;
119d0cb0d30SAlexander Belyaev 
120d0cb0d30SAlexander Belyaev   LogicalResult
121d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::ImOp op, ArrayRef<Value> operands,
122d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
123d0cb0d30SAlexander Belyaev     complex::ImOp::Adaptor transformed(operands);
124d0cb0d30SAlexander Belyaev 
125d0cb0d30SAlexander Belyaev     // Extract imaginary part from the complex number struct.
126d0cb0d30SAlexander Belyaev     ComplexStructBuilder complexStruct(transformed.complex());
127d0cb0d30SAlexander Belyaev     Value imaginary = complexStruct.imaginary(rewriter, op.getLoc());
128d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, imaginary);
129d0cb0d30SAlexander Belyaev 
130d0cb0d30SAlexander Belyaev     return success();
131d0cb0d30SAlexander Belyaev   }
132d0cb0d30SAlexander Belyaev };
133d0cb0d30SAlexander Belyaev 
134d0cb0d30SAlexander Belyaev struct BinaryComplexOperands {
135d0cb0d30SAlexander Belyaev   std::complex<Value> lhs;
136d0cb0d30SAlexander Belyaev   std::complex<Value> rhs;
137d0cb0d30SAlexander Belyaev };
138d0cb0d30SAlexander Belyaev 
139d0cb0d30SAlexander Belyaev template <typename OpTy>
140d0cb0d30SAlexander Belyaev BinaryComplexOperands
141d0cb0d30SAlexander Belyaev unpackBinaryComplexOperands(OpTy op, ArrayRef<Value> operands,
142d0cb0d30SAlexander Belyaev                             ConversionPatternRewriter &rewriter) {
143d0cb0d30SAlexander Belyaev   auto loc = op.getLoc();
144d0cb0d30SAlexander Belyaev   typename OpTy::Adaptor transformed(operands);
145d0cb0d30SAlexander Belyaev 
146d0cb0d30SAlexander Belyaev   // Extract real and imaginary values from operands.
147d0cb0d30SAlexander Belyaev   BinaryComplexOperands unpacked;
148d0cb0d30SAlexander Belyaev   ComplexStructBuilder lhs(transformed.lhs());
149d0cb0d30SAlexander Belyaev   unpacked.lhs.real(lhs.real(rewriter, loc));
150d0cb0d30SAlexander Belyaev   unpacked.lhs.imag(lhs.imaginary(rewriter, loc));
151d0cb0d30SAlexander Belyaev   ComplexStructBuilder rhs(transformed.rhs());
152d0cb0d30SAlexander Belyaev   unpacked.rhs.real(rhs.real(rewriter, loc));
153d0cb0d30SAlexander Belyaev   unpacked.rhs.imag(rhs.imaginary(rewriter, loc));
154d0cb0d30SAlexander Belyaev 
155d0cb0d30SAlexander Belyaev   return unpacked;
156d0cb0d30SAlexander Belyaev }
157d0cb0d30SAlexander Belyaev 
158d0cb0d30SAlexander Belyaev struct AddOpConversion : public ConvertOpToLLVMPattern<complex::AddOp> {
159d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::AddOp>::ConvertOpToLLVMPattern;
160d0cb0d30SAlexander Belyaev 
161d0cb0d30SAlexander Belyaev   LogicalResult
162d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::AddOp op, ArrayRef<Value> operands,
163d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
164d0cb0d30SAlexander Belyaev     auto loc = op.getLoc();
165d0cb0d30SAlexander Belyaev     BinaryComplexOperands arg =
166d0cb0d30SAlexander Belyaev         unpackBinaryComplexOperands<complex::AddOp>(op, operands, rewriter);
167d0cb0d30SAlexander Belyaev 
168d0cb0d30SAlexander Belyaev     // Initialize complex number struct for result.
169d0cb0d30SAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
170d0cb0d30SAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
171d0cb0d30SAlexander Belyaev 
172d0cb0d30SAlexander Belyaev     // Emit IR to add complex numbers.
173038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
174d0cb0d30SAlexander Belyaev     Value real =
175d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FAddOp>(loc, arg.lhs.real(), arg.rhs.real(), fmf);
176d0cb0d30SAlexander Belyaev     Value imag =
177d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FAddOp>(loc, arg.lhs.imag(), arg.rhs.imag(), fmf);
178d0cb0d30SAlexander Belyaev     result.setReal(rewriter, loc, real);
179d0cb0d30SAlexander Belyaev     result.setImaginary(rewriter, loc, imag);
180d0cb0d30SAlexander Belyaev 
181d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, {result});
182d0cb0d30SAlexander Belyaev     return success();
183d0cb0d30SAlexander Belyaev   }
184d0cb0d30SAlexander Belyaev };
185d0cb0d30SAlexander Belyaev 
18611f4c58cSAlexander Belyaev struct DivOpConversion : public ConvertOpToLLVMPattern<complex::DivOp> {
18711f4c58cSAlexander Belyaev   using ConvertOpToLLVMPattern<complex::DivOp>::ConvertOpToLLVMPattern;
18811f4c58cSAlexander Belyaev 
18911f4c58cSAlexander Belyaev   LogicalResult
19011f4c58cSAlexander Belyaev   matchAndRewrite(complex::DivOp op, ArrayRef<Value> operands,
19111f4c58cSAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
19211f4c58cSAlexander Belyaev     auto loc = op.getLoc();
19311f4c58cSAlexander Belyaev     BinaryComplexOperands arg =
19411f4c58cSAlexander Belyaev         unpackBinaryComplexOperands<complex::DivOp>(op, operands, rewriter);
19511f4c58cSAlexander Belyaev 
19611f4c58cSAlexander Belyaev     // Initialize complex number struct for result.
19711f4c58cSAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
19811f4c58cSAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
19911f4c58cSAlexander Belyaev 
20011f4c58cSAlexander Belyaev     // Emit IR to add complex numbers.
201038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
20211f4c58cSAlexander Belyaev     Value rhsRe = arg.rhs.real();
20311f4c58cSAlexander Belyaev     Value rhsIm = arg.rhs.imag();
20411f4c58cSAlexander Belyaev     Value lhsRe = arg.lhs.real();
20511f4c58cSAlexander Belyaev     Value lhsIm = arg.lhs.imag();
20611f4c58cSAlexander Belyaev 
20711f4c58cSAlexander Belyaev     Value rhsSqNorm = rewriter.create<LLVM::FAddOp>(
20811f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, rhsRe, rhsRe, fmf),
20911f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, rhsIm, rhsIm, fmf), fmf);
21011f4c58cSAlexander Belyaev 
21111f4c58cSAlexander Belyaev     Value resultReal = rewriter.create<LLVM::FAddOp>(
21211f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, lhsRe, rhsRe, fmf),
21311f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, lhsIm, rhsIm, fmf), fmf);
21411f4c58cSAlexander Belyaev 
21511f4c58cSAlexander Belyaev     Value resultImag = rewriter.create<LLVM::FSubOp>(
21611f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, lhsIm, rhsRe, fmf),
21711f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, lhsRe, rhsIm, fmf), fmf);
21811f4c58cSAlexander Belyaev 
21911f4c58cSAlexander Belyaev     result.setReal(
22011f4c58cSAlexander Belyaev         rewriter, loc,
22111f4c58cSAlexander Belyaev         rewriter.create<LLVM::FDivOp>(loc, resultReal, rhsSqNorm, fmf));
22211f4c58cSAlexander Belyaev     result.setImaginary(
22311f4c58cSAlexander Belyaev         rewriter, loc,
22411f4c58cSAlexander Belyaev         rewriter.create<LLVM::FDivOp>(loc, resultImag, rhsSqNorm, fmf));
22511f4c58cSAlexander Belyaev 
22611f4c58cSAlexander Belyaev     rewriter.replaceOp(op, {result});
22711f4c58cSAlexander Belyaev     return success();
22811f4c58cSAlexander Belyaev   }
22911f4c58cSAlexander Belyaev };
23011f4c58cSAlexander Belyaev 
23111f4c58cSAlexander Belyaev struct MulOpConversion : public ConvertOpToLLVMPattern<complex::MulOp> {
23211f4c58cSAlexander Belyaev   using ConvertOpToLLVMPattern<complex::MulOp>::ConvertOpToLLVMPattern;
23311f4c58cSAlexander Belyaev 
23411f4c58cSAlexander Belyaev   LogicalResult
23511f4c58cSAlexander Belyaev   matchAndRewrite(complex::MulOp op, ArrayRef<Value> operands,
23611f4c58cSAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
23711f4c58cSAlexander Belyaev     auto loc = op.getLoc();
23811f4c58cSAlexander Belyaev     BinaryComplexOperands arg =
23911f4c58cSAlexander Belyaev         unpackBinaryComplexOperands<complex::MulOp>(op, operands, rewriter);
24011f4c58cSAlexander Belyaev 
24111f4c58cSAlexander Belyaev     // Initialize complex number struct for result.
24211f4c58cSAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
24311f4c58cSAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
24411f4c58cSAlexander Belyaev 
24511f4c58cSAlexander Belyaev     // Emit IR to add complex numbers.
246038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
24711f4c58cSAlexander Belyaev     Value rhsRe = arg.rhs.real();
24811f4c58cSAlexander Belyaev     Value rhsIm = arg.rhs.imag();
24911f4c58cSAlexander Belyaev     Value lhsRe = arg.lhs.real();
25011f4c58cSAlexander Belyaev     Value lhsIm = arg.lhs.imag();
25111f4c58cSAlexander Belyaev 
25211f4c58cSAlexander Belyaev     Value real = rewriter.create<LLVM::FSubOp>(
25311f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, rhsRe, lhsRe, fmf),
25411f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, rhsIm, lhsIm, fmf), fmf);
25511f4c58cSAlexander Belyaev 
25611f4c58cSAlexander Belyaev     Value imag = rewriter.create<LLVM::FAddOp>(
25711f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, lhsIm, rhsRe, fmf),
25811f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, lhsRe, rhsIm, fmf), fmf);
25911f4c58cSAlexander Belyaev 
26011f4c58cSAlexander Belyaev     result.setReal(rewriter, loc, real);
26111f4c58cSAlexander Belyaev     result.setImaginary(rewriter, loc, imag);
26211f4c58cSAlexander Belyaev 
26311f4c58cSAlexander Belyaev     rewriter.replaceOp(op, {result});
26411f4c58cSAlexander Belyaev     return success();
26511f4c58cSAlexander Belyaev   }
26611f4c58cSAlexander Belyaev };
26711f4c58cSAlexander Belyaev 
268d0cb0d30SAlexander Belyaev struct SubOpConversion : public ConvertOpToLLVMPattern<complex::SubOp> {
269d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::SubOp>::ConvertOpToLLVMPattern;
270d0cb0d30SAlexander Belyaev 
271d0cb0d30SAlexander Belyaev   LogicalResult
272d0cb0d30SAlexander Belyaev   matchAndRewrite(complex::SubOp op, ArrayRef<Value> operands,
273d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
274d0cb0d30SAlexander Belyaev     auto loc = op.getLoc();
275d0cb0d30SAlexander Belyaev     BinaryComplexOperands arg =
276d0cb0d30SAlexander Belyaev         unpackBinaryComplexOperands<complex::SubOp>(op, operands, rewriter);
277d0cb0d30SAlexander Belyaev 
278d0cb0d30SAlexander Belyaev     // Initialize complex number struct for result.
279d0cb0d30SAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
280d0cb0d30SAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
281d0cb0d30SAlexander Belyaev 
282d0cb0d30SAlexander Belyaev     // Emit IR to substract complex numbers.
283038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
284d0cb0d30SAlexander Belyaev     Value real =
285d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FSubOp>(loc, arg.lhs.real(), arg.rhs.real(), fmf);
286d0cb0d30SAlexander Belyaev     Value imag =
287d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FSubOp>(loc, arg.lhs.imag(), arg.rhs.imag(), fmf);
288d0cb0d30SAlexander Belyaev     result.setReal(rewriter, loc, real);
289d0cb0d30SAlexander Belyaev     result.setImaginary(rewriter, loc, imag);
290d0cb0d30SAlexander Belyaev 
291d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, {result});
292d0cb0d30SAlexander Belyaev     return success();
293d0cb0d30SAlexander Belyaev   }
294d0cb0d30SAlexander Belyaev };
295d0cb0d30SAlexander Belyaev } // namespace
296d0cb0d30SAlexander Belyaev 
297d0cb0d30SAlexander Belyaev void mlir::populateComplexToLLVMConversionPatterns(
298dc4e913bSChris Lattner     LLVMTypeConverter &converter, RewritePatternSet &patterns) {
299d0cb0d30SAlexander Belyaev   // clang-format off
300dc4e913bSChris Lattner   patterns.add<
30111f4c58cSAlexander Belyaev       AbsOpConversion,
302d0cb0d30SAlexander Belyaev       AddOpConversion,
303d0cb0d30SAlexander Belyaev       CreateOpConversion,
30411f4c58cSAlexander Belyaev       DivOpConversion,
305d0cb0d30SAlexander Belyaev       ImOpConversion,
30611f4c58cSAlexander Belyaev       MulOpConversion,
307d0cb0d30SAlexander Belyaev       ReOpConversion,
308d0cb0d30SAlexander Belyaev       SubOpConversion
309d0cb0d30SAlexander Belyaev     >(converter);
310d0cb0d30SAlexander Belyaev   // clang-format on
311d0cb0d30SAlexander Belyaev }
312d0cb0d30SAlexander Belyaev 
313d0cb0d30SAlexander Belyaev namespace {
314d0cb0d30SAlexander Belyaev struct ConvertComplexToLLVMPass
315d0cb0d30SAlexander Belyaev     : public ConvertComplexToLLVMBase<ConvertComplexToLLVMPass> {
316d0cb0d30SAlexander Belyaev   void runOnOperation() override;
317d0cb0d30SAlexander Belyaev };
318d0cb0d30SAlexander Belyaev } // namespace
319d0cb0d30SAlexander Belyaev 
320d0cb0d30SAlexander Belyaev void ConvertComplexToLLVMPass::runOnOperation() {
321d0cb0d30SAlexander Belyaev   auto module = getOperation();
322d0cb0d30SAlexander Belyaev 
323d0cb0d30SAlexander Belyaev   // Convert to the LLVM IR dialect using the converter defined above.
324dc4e913bSChris Lattner   RewritePatternSet patterns(&getContext());
325d0cb0d30SAlexander Belyaev   LLVMTypeConverter converter(&getContext());
326d0cb0d30SAlexander Belyaev   populateComplexToLLVMConversionPatterns(converter, patterns);
327d0cb0d30SAlexander Belyaev 
328d0cb0d30SAlexander Belyaev   LLVMConversionTarget target(getContext());
329d6be2773SAlex Zinenko   target.addLegalOp<ModuleOp, FuncOp>();
330d6be2773SAlex Zinenko   target.addLegalOp<LLVM::DialectCastOp>();
331d6be2773SAlex Zinenko   target.addIllegalDialect<complex::ComplexDialect>();
332d6be2773SAlex Zinenko   if (failed(applyPartialConversion(module, target, std::move(patterns))))
333d0cb0d30SAlexander Belyaev     signalPassFailure();
334d0cb0d30SAlexander Belyaev }
335d0cb0d30SAlexander Belyaev 
336d0cb0d30SAlexander Belyaev std::unique_ptr<OperationPass<ModuleOp>>
337d0cb0d30SAlexander Belyaev mlir::createConvertComplexToLLVMPass() {
338d0cb0d30SAlexander Belyaev   return std::make_unique<ConvertComplexToLLVMPass>();
339d0cb0d30SAlexander Belyaev }
340