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"
1275e5f0aaSAlex Zinenko #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
1375e5f0aaSAlex Zinenko #include "mlir/Conversion/LLVMCommon/Pattern.h"
14a54f4eaeSMogball #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
15d0cb0d30SAlexander Belyaev #include "mlir/Dialect/Complex/IR/Complex.h"
16d0cb0d30SAlexander Belyaev #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
17d0cb0d30SAlexander Belyaev 
18d0cb0d30SAlexander Belyaev using namespace mlir;
19d0cb0d30SAlexander Belyaev using namespace mlir::LLVM;
20d0cb0d30SAlexander Belyaev 
21b5d847b1SAlex Zinenko //===----------------------------------------------------------------------===//
22b5d847b1SAlex Zinenko // ComplexStructBuilder implementation.
23b5d847b1SAlex Zinenko //===----------------------------------------------------------------------===//
24b5d847b1SAlex Zinenko 
25b5d847b1SAlex Zinenko static constexpr unsigned kRealPosInComplexNumberStruct = 0;
26b5d847b1SAlex Zinenko static constexpr unsigned kImaginaryPosInComplexNumberStruct = 1;
27b5d847b1SAlex Zinenko 
undef(OpBuilder & builder,Location loc,Type type)28b5d847b1SAlex Zinenko ComplexStructBuilder ComplexStructBuilder::undef(OpBuilder &builder,
29b5d847b1SAlex Zinenko                                                  Location loc, Type type) {
30b5d847b1SAlex Zinenko   Value val = builder.create<LLVM::UndefOp>(loc, type);
31b5d847b1SAlex Zinenko   return ComplexStructBuilder(val);
32b5d847b1SAlex Zinenko }
33b5d847b1SAlex Zinenko 
setReal(OpBuilder & builder,Location loc,Value real)34b5d847b1SAlex Zinenko void ComplexStructBuilder::setReal(OpBuilder &builder, Location loc,
35b5d847b1SAlex Zinenko                                    Value real) {
36b5d847b1SAlex Zinenko   setPtr(builder, loc, kRealPosInComplexNumberStruct, real);
37b5d847b1SAlex Zinenko }
38b5d847b1SAlex Zinenko 
real(OpBuilder & builder,Location loc)39b5d847b1SAlex Zinenko Value ComplexStructBuilder::real(OpBuilder &builder, Location loc) {
40b5d847b1SAlex Zinenko   return extractPtr(builder, loc, kRealPosInComplexNumberStruct);
41b5d847b1SAlex Zinenko }
42b5d847b1SAlex Zinenko 
setImaginary(OpBuilder & builder,Location loc,Value imaginary)43b5d847b1SAlex Zinenko void ComplexStructBuilder::setImaginary(OpBuilder &builder, Location loc,
44b5d847b1SAlex Zinenko                                         Value imaginary) {
45b5d847b1SAlex Zinenko   setPtr(builder, loc, kImaginaryPosInComplexNumberStruct, imaginary);
46b5d847b1SAlex Zinenko }
47b5d847b1SAlex Zinenko 
imaginary(OpBuilder & builder,Location loc)48b5d847b1SAlex Zinenko Value ComplexStructBuilder::imaginary(OpBuilder &builder, Location loc) {
49b5d847b1SAlex Zinenko   return extractPtr(builder, loc, kImaginaryPosInComplexNumberStruct);
50b5d847b1SAlex Zinenko }
51b5d847b1SAlex Zinenko 
52b5d847b1SAlex Zinenko //===----------------------------------------------------------------------===//
53b5d847b1SAlex Zinenko // Conversion patterns.
54b5d847b1SAlex Zinenko //===----------------------------------------------------------------------===//
55b5d847b1SAlex Zinenko 
56d0cb0d30SAlexander Belyaev namespace {
57d0cb0d30SAlexander Belyaev 
5811f4c58cSAlexander Belyaev struct AbsOpConversion : public ConvertOpToLLVMPattern<complex::AbsOp> {
5911f4c58cSAlexander Belyaev   using ConvertOpToLLVMPattern<complex::AbsOp>::ConvertOpToLLVMPattern;
6011f4c58cSAlexander Belyaev 
6111f4c58cSAlexander Belyaev   LogicalResult
matchAndRewrite__anone1f7db290111::AbsOpConversion62ef976337SRiver Riddle   matchAndRewrite(complex::AbsOp op, OpAdaptor adaptor,
6311f4c58cSAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
6411f4c58cSAlexander Belyaev     auto loc = op.getLoc();
6511f4c58cSAlexander Belyaev 
66c0342a2dSJacques Pienaar     ComplexStructBuilder complexStruct(adaptor.getComplex());
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 
80608cc6b1SBenjamin Kramer struct ConstantOpLowering : public ConvertOpToLLVMPattern<complex::ConstantOp> {
81608cc6b1SBenjamin Kramer   using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern;
82608cc6b1SBenjamin Kramer 
83608cc6b1SBenjamin Kramer   LogicalResult
matchAndRewrite__anone1f7db290111::ConstantOpLowering84608cc6b1SBenjamin Kramer   matchAndRewrite(complex::ConstantOp op, OpAdaptor adaptor,
85608cc6b1SBenjamin Kramer                   ConversionPatternRewriter &rewriter) const override {
86608cc6b1SBenjamin Kramer     return LLVM::detail::oneToOneRewrite(
87608cc6b1SBenjamin Kramer         op, LLVM::ConstantOp::getOperationName(), adaptor.getOperands(),
88608cc6b1SBenjamin Kramer         *getTypeConverter(), rewriter);
89608cc6b1SBenjamin Kramer   }
90608cc6b1SBenjamin Kramer };
91608cc6b1SBenjamin Kramer 
92d0cb0d30SAlexander Belyaev struct CreateOpConversion : public ConvertOpToLLVMPattern<complex::CreateOp> {
93d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::CreateOp>::ConvertOpToLLVMPattern;
94d0cb0d30SAlexander Belyaev 
95d0cb0d30SAlexander Belyaev   LogicalResult
matchAndRewrite__anone1f7db290111::CreateOpConversion96ef976337SRiver Riddle   matchAndRewrite(complex::CreateOp complexOp, OpAdaptor adaptor,
97d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
98d0cb0d30SAlexander Belyaev     // Pack real and imaginary part in a complex number struct.
99d0cb0d30SAlexander Belyaev     auto loc = complexOp.getLoc();
100d0cb0d30SAlexander Belyaev     auto structType = typeConverter->convertType(complexOp.getType());
101d0cb0d30SAlexander Belyaev     auto complexStruct = ComplexStructBuilder::undef(rewriter, loc, structType);
102c0342a2dSJacques Pienaar     complexStruct.setReal(rewriter, loc, adaptor.getReal());
103c0342a2dSJacques Pienaar     complexStruct.setImaginary(rewriter, loc, adaptor.getImaginary());
104d0cb0d30SAlexander Belyaev 
105d0cb0d30SAlexander Belyaev     rewriter.replaceOp(complexOp, {complexStruct});
106d0cb0d30SAlexander Belyaev     return success();
107d0cb0d30SAlexander Belyaev   }
108d0cb0d30SAlexander Belyaev };
109d0cb0d30SAlexander Belyaev 
110d0cb0d30SAlexander Belyaev struct ReOpConversion : public ConvertOpToLLVMPattern<complex::ReOp> {
111d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::ReOp>::ConvertOpToLLVMPattern;
112d0cb0d30SAlexander Belyaev 
113d0cb0d30SAlexander Belyaev   LogicalResult
matchAndRewrite__anone1f7db290111::ReOpConversion114ef976337SRiver Riddle   matchAndRewrite(complex::ReOp op, OpAdaptor adaptor,
115d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
116d0cb0d30SAlexander Belyaev     // Extract real part from the complex number struct.
117c0342a2dSJacques Pienaar     ComplexStructBuilder complexStruct(adaptor.getComplex());
118d0cb0d30SAlexander Belyaev     Value real = complexStruct.real(rewriter, op.getLoc());
119d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, real);
120d0cb0d30SAlexander Belyaev 
121d0cb0d30SAlexander Belyaev     return success();
122d0cb0d30SAlexander Belyaev   }
123d0cb0d30SAlexander Belyaev };
124d0cb0d30SAlexander Belyaev 
125d0cb0d30SAlexander Belyaev struct ImOpConversion : public ConvertOpToLLVMPattern<complex::ImOp> {
126d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::ImOp>::ConvertOpToLLVMPattern;
127d0cb0d30SAlexander Belyaev 
128d0cb0d30SAlexander Belyaev   LogicalResult
matchAndRewrite__anone1f7db290111::ImOpConversion129ef976337SRiver Riddle   matchAndRewrite(complex::ImOp op, OpAdaptor adaptor,
130d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
131d0cb0d30SAlexander Belyaev     // Extract imaginary part from the complex number struct.
132c0342a2dSJacques Pienaar     ComplexStructBuilder complexStruct(adaptor.getComplex());
133d0cb0d30SAlexander Belyaev     Value imaginary = complexStruct.imaginary(rewriter, op.getLoc());
134d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, imaginary);
135d0cb0d30SAlexander Belyaev 
136d0cb0d30SAlexander Belyaev     return success();
137d0cb0d30SAlexander Belyaev   }
138d0cb0d30SAlexander Belyaev };
139d0cb0d30SAlexander Belyaev 
140d0cb0d30SAlexander Belyaev struct BinaryComplexOperands {
141d0cb0d30SAlexander Belyaev   std::complex<Value> lhs;
142d0cb0d30SAlexander Belyaev   std::complex<Value> rhs;
143d0cb0d30SAlexander Belyaev };
144d0cb0d30SAlexander Belyaev 
145d0cb0d30SAlexander Belyaev template <typename OpTy>
146d0cb0d30SAlexander Belyaev BinaryComplexOperands
unpackBinaryComplexOperands(OpTy op,typename OpTy::Adaptor adaptor,ConversionPatternRewriter & rewriter)147ef976337SRiver Riddle unpackBinaryComplexOperands(OpTy op, typename OpTy::Adaptor adaptor,
148d0cb0d30SAlexander Belyaev                             ConversionPatternRewriter &rewriter) {
149d0cb0d30SAlexander Belyaev   auto loc = op.getLoc();
150d0cb0d30SAlexander Belyaev 
151d0cb0d30SAlexander Belyaev   // Extract real and imaginary values from operands.
152d0cb0d30SAlexander Belyaev   BinaryComplexOperands unpacked;
153c0342a2dSJacques Pienaar   ComplexStructBuilder lhs(adaptor.getLhs());
154d0cb0d30SAlexander Belyaev   unpacked.lhs.real(lhs.real(rewriter, loc));
155d0cb0d30SAlexander Belyaev   unpacked.lhs.imag(lhs.imaginary(rewriter, loc));
156c0342a2dSJacques Pienaar   ComplexStructBuilder rhs(adaptor.getRhs());
157d0cb0d30SAlexander Belyaev   unpacked.rhs.real(rhs.real(rewriter, loc));
158d0cb0d30SAlexander Belyaev   unpacked.rhs.imag(rhs.imaginary(rewriter, loc));
159d0cb0d30SAlexander Belyaev 
160d0cb0d30SAlexander Belyaev   return unpacked;
161d0cb0d30SAlexander Belyaev }
162d0cb0d30SAlexander Belyaev 
163d0cb0d30SAlexander Belyaev struct AddOpConversion : public ConvertOpToLLVMPattern<complex::AddOp> {
164d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::AddOp>::ConvertOpToLLVMPattern;
165d0cb0d30SAlexander Belyaev 
166d0cb0d30SAlexander Belyaev   LogicalResult
matchAndRewrite__anone1f7db290111::AddOpConversion167ef976337SRiver Riddle   matchAndRewrite(complex::AddOp op, OpAdaptor adaptor,
168d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
169d0cb0d30SAlexander Belyaev     auto loc = op.getLoc();
170d0cb0d30SAlexander Belyaev     BinaryComplexOperands arg =
171ef976337SRiver Riddle         unpackBinaryComplexOperands<complex::AddOp>(op, adaptor, rewriter);
172d0cb0d30SAlexander Belyaev 
173d0cb0d30SAlexander Belyaev     // Initialize complex number struct for result.
174d0cb0d30SAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
175d0cb0d30SAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
176d0cb0d30SAlexander Belyaev 
177d0cb0d30SAlexander Belyaev     // Emit IR to add complex numbers.
178038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
179d0cb0d30SAlexander Belyaev     Value real =
180d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FAddOp>(loc, arg.lhs.real(), arg.rhs.real(), fmf);
181d0cb0d30SAlexander Belyaev     Value imag =
182d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FAddOp>(loc, arg.lhs.imag(), arg.rhs.imag(), fmf);
183d0cb0d30SAlexander Belyaev     result.setReal(rewriter, loc, real);
184d0cb0d30SAlexander Belyaev     result.setImaginary(rewriter, loc, imag);
185d0cb0d30SAlexander Belyaev 
186d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, {result});
187d0cb0d30SAlexander Belyaev     return success();
188d0cb0d30SAlexander Belyaev   }
189d0cb0d30SAlexander Belyaev };
190d0cb0d30SAlexander Belyaev 
19111f4c58cSAlexander Belyaev struct DivOpConversion : public ConvertOpToLLVMPattern<complex::DivOp> {
19211f4c58cSAlexander Belyaev   using ConvertOpToLLVMPattern<complex::DivOp>::ConvertOpToLLVMPattern;
19311f4c58cSAlexander Belyaev 
19411f4c58cSAlexander Belyaev   LogicalResult
matchAndRewrite__anone1f7db290111::DivOpConversion195ef976337SRiver Riddle   matchAndRewrite(complex::DivOp op, OpAdaptor adaptor,
19611f4c58cSAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
19711f4c58cSAlexander Belyaev     auto loc = op.getLoc();
19811f4c58cSAlexander Belyaev     BinaryComplexOperands arg =
199ef976337SRiver Riddle         unpackBinaryComplexOperands<complex::DivOp>(op, adaptor, rewriter);
20011f4c58cSAlexander Belyaev 
20111f4c58cSAlexander Belyaev     // Initialize complex number struct for result.
20211f4c58cSAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
20311f4c58cSAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
20411f4c58cSAlexander Belyaev 
20511f4c58cSAlexander Belyaev     // Emit IR to add complex numbers.
206038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
20711f4c58cSAlexander Belyaev     Value rhsRe = arg.rhs.real();
20811f4c58cSAlexander Belyaev     Value rhsIm = arg.rhs.imag();
20911f4c58cSAlexander Belyaev     Value lhsRe = arg.lhs.real();
21011f4c58cSAlexander Belyaev     Value lhsIm = arg.lhs.imag();
21111f4c58cSAlexander Belyaev 
21211f4c58cSAlexander Belyaev     Value rhsSqNorm = rewriter.create<LLVM::FAddOp>(
21311f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, rhsRe, rhsRe, fmf),
21411f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, rhsIm, rhsIm, fmf), fmf);
21511f4c58cSAlexander Belyaev 
21611f4c58cSAlexander Belyaev     Value resultReal = rewriter.create<LLVM::FAddOp>(
21711f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, lhsRe, rhsRe, fmf),
21811f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, lhsIm, rhsIm, fmf), fmf);
21911f4c58cSAlexander Belyaev 
22011f4c58cSAlexander Belyaev     Value resultImag = rewriter.create<LLVM::FSubOp>(
22111f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, lhsIm, rhsRe, fmf),
22211f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, lhsRe, rhsIm, fmf), fmf);
22311f4c58cSAlexander Belyaev 
22411f4c58cSAlexander Belyaev     result.setReal(
22511f4c58cSAlexander Belyaev         rewriter, loc,
22611f4c58cSAlexander Belyaev         rewriter.create<LLVM::FDivOp>(loc, resultReal, rhsSqNorm, fmf));
22711f4c58cSAlexander Belyaev     result.setImaginary(
22811f4c58cSAlexander Belyaev         rewriter, loc,
22911f4c58cSAlexander Belyaev         rewriter.create<LLVM::FDivOp>(loc, resultImag, rhsSqNorm, fmf));
23011f4c58cSAlexander Belyaev 
23111f4c58cSAlexander Belyaev     rewriter.replaceOp(op, {result});
23211f4c58cSAlexander Belyaev     return success();
23311f4c58cSAlexander Belyaev   }
23411f4c58cSAlexander Belyaev };
23511f4c58cSAlexander Belyaev 
23611f4c58cSAlexander Belyaev struct MulOpConversion : public ConvertOpToLLVMPattern<complex::MulOp> {
23711f4c58cSAlexander Belyaev   using ConvertOpToLLVMPattern<complex::MulOp>::ConvertOpToLLVMPattern;
23811f4c58cSAlexander Belyaev 
23911f4c58cSAlexander Belyaev   LogicalResult
matchAndRewrite__anone1f7db290111::MulOpConversion240ef976337SRiver Riddle   matchAndRewrite(complex::MulOp op, OpAdaptor adaptor,
24111f4c58cSAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
24211f4c58cSAlexander Belyaev     auto loc = op.getLoc();
24311f4c58cSAlexander Belyaev     BinaryComplexOperands arg =
244ef976337SRiver Riddle         unpackBinaryComplexOperands<complex::MulOp>(op, adaptor, rewriter);
24511f4c58cSAlexander Belyaev 
24611f4c58cSAlexander Belyaev     // Initialize complex number struct for result.
24711f4c58cSAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
24811f4c58cSAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
24911f4c58cSAlexander Belyaev 
25011f4c58cSAlexander Belyaev     // Emit IR to add complex numbers.
251038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
25211f4c58cSAlexander Belyaev     Value rhsRe = arg.rhs.real();
25311f4c58cSAlexander Belyaev     Value rhsIm = arg.rhs.imag();
25411f4c58cSAlexander Belyaev     Value lhsRe = arg.lhs.real();
25511f4c58cSAlexander Belyaev     Value lhsIm = arg.lhs.imag();
25611f4c58cSAlexander Belyaev 
25711f4c58cSAlexander Belyaev     Value real = rewriter.create<LLVM::FSubOp>(
25811f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, rhsRe, lhsRe, fmf),
25911f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, rhsIm, lhsIm, fmf), fmf);
26011f4c58cSAlexander Belyaev 
26111f4c58cSAlexander Belyaev     Value imag = rewriter.create<LLVM::FAddOp>(
26211f4c58cSAlexander Belyaev         loc, rewriter.create<LLVM::FMulOp>(loc, lhsIm, rhsRe, fmf),
26311f4c58cSAlexander Belyaev         rewriter.create<LLVM::FMulOp>(loc, lhsRe, rhsIm, fmf), fmf);
26411f4c58cSAlexander Belyaev 
26511f4c58cSAlexander Belyaev     result.setReal(rewriter, loc, real);
26611f4c58cSAlexander Belyaev     result.setImaginary(rewriter, loc, imag);
26711f4c58cSAlexander Belyaev 
26811f4c58cSAlexander Belyaev     rewriter.replaceOp(op, {result});
26911f4c58cSAlexander Belyaev     return success();
27011f4c58cSAlexander Belyaev   }
27111f4c58cSAlexander Belyaev };
27211f4c58cSAlexander Belyaev 
273d0cb0d30SAlexander Belyaev struct SubOpConversion : public ConvertOpToLLVMPattern<complex::SubOp> {
274d0cb0d30SAlexander Belyaev   using ConvertOpToLLVMPattern<complex::SubOp>::ConvertOpToLLVMPattern;
275d0cb0d30SAlexander Belyaev 
276d0cb0d30SAlexander Belyaev   LogicalResult
matchAndRewrite__anone1f7db290111::SubOpConversion277ef976337SRiver Riddle   matchAndRewrite(complex::SubOp op, OpAdaptor adaptor,
278d0cb0d30SAlexander Belyaev                   ConversionPatternRewriter &rewriter) const override {
279d0cb0d30SAlexander Belyaev     auto loc = op.getLoc();
280d0cb0d30SAlexander Belyaev     BinaryComplexOperands arg =
281ef976337SRiver Riddle         unpackBinaryComplexOperands<complex::SubOp>(op, adaptor, rewriter);
282d0cb0d30SAlexander Belyaev 
283d0cb0d30SAlexander Belyaev     // Initialize complex number struct for result.
284d0cb0d30SAlexander Belyaev     auto structType = typeConverter->convertType(op.getType());
285d0cb0d30SAlexander Belyaev     auto result = ComplexStructBuilder::undef(rewriter, loc, structType);
286d0cb0d30SAlexander Belyaev 
287d0cb0d30SAlexander Belyaev     // Emit IR to substract complex numbers.
288038f2a33SMehdi Amini     auto fmf = LLVM::FMFAttr::get(op.getContext(), {});
289d0cb0d30SAlexander Belyaev     Value real =
290d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FSubOp>(loc, arg.lhs.real(), arg.rhs.real(), fmf);
291d0cb0d30SAlexander Belyaev     Value imag =
292d0cb0d30SAlexander Belyaev         rewriter.create<LLVM::FSubOp>(loc, arg.lhs.imag(), arg.rhs.imag(), fmf);
293d0cb0d30SAlexander Belyaev     result.setReal(rewriter, loc, real);
294d0cb0d30SAlexander Belyaev     result.setImaginary(rewriter, loc, imag);
295d0cb0d30SAlexander Belyaev 
296d0cb0d30SAlexander Belyaev     rewriter.replaceOp(op, {result});
297d0cb0d30SAlexander Belyaev     return success();
298d0cb0d30SAlexander Belyaev   }
299d0cb0d30SAlexander Belyaev };
300d0cb0d30SAlexander Belyaev } // namespace
301d0cb0d30SAlexander Belyaev 
populateComplexToLLVMConversionPatterns(LLVMTypeConverter & converter,RewritePatternSet & patterns)302d0cb0d30SAlexander Belyaev void mlir::populateComplexToLLVMConversionPatterns(
303dc4e913bSChris Lattner     LLVMTypeConverter &converter, RewritePatternSet &patterns) {
304d0cb0d30SAlexander Belyaev   // clang-format off
305dc4e913bSChris Lattner   patterns.add<
30611f4c58cSAlexander Belyaev       AbsOpConversion,
307d0cb0d30SAlexander Belyaev       AddOpConversion,
308608cc6b1SBenjamin Kramer       ConstantOpLowering,
309d0cb0d30SAlexander Belyaev       CreateOpConversion,
31011f4c58cSAlexander Belyaev       DivOpConversion,
311d0cb0d30SAlexander Belyaev       ImOpConversion,
31211f4c58cSAlexander Belyaev       MulOpConversion,
313d0cb0d30SAlexander Belyaev       ReOpConversion,
314d0cb0d30SAlexander Belyaev       SubOpConversion
315d0cb0d30SAlexander Belyaev     >(converter);
316d0cb0d30SAlexander Belyaev   // clang-format on
317d0cb0d30SAlexander Belyaev }
318d0cb0d30SAlexander Belyaev 
319d0cb0d30SAlexander Belyaev namespace {
320d0cb0d30SAlexander Belyaev struct ConvertComplexToLLVMPass
321d0cb0d30SAlexander Belyaev     : public ConvertComplexToLLVMBase<ConvertComplexToLLVMPass> {
322d0cb0d30SAlexander Belyaev   void runOnOperation() override;
323d0cb0d30SAlexander Belyaev };
324d0cb0d30SAlexander Belyaev } // namespace
325d0cb0d30SAlexander Belyaev 
runOnOperation()326d0cb0d30SAlexander Belyaev void ConvertComplexToLLVMPass::runOnOperation() {
327d0cb0d30SAlexander Belyaev   // Convert to the LLVM IR dialect using the converter defined above.
328dc4e913bSChris Lattner   RewritePatternSet patterns(&getContext());
329d0cb0d30SAlexander Belyaev   LLVMTypeConverter converter(&getContext());
330d0cb0d30SAlexander Belyaev   populateComplexToLLVMConversionPatterns(converter, patterns);
331d0cb0d30SAlexander Belyaev 
332d0cb0d30SAlexander Belyaev   LLVMConversionTarget target(getContext());
333d6be2773SAlex Zinenko   target.addIllegalDialect<complex::ComplexDialect>();
334*f05b0afaSRiver Riddle   if (failed(
335*f05b0afaSRiver Riddle           applyPartialConversion(getOperation(), target, std::move(patterns))))
336d0cb0d30SAlexander Belyaev     signalPassFailure();
337d0cb0d30SAlexander Belyaev }
338d0cb0d30SAlexander Belyaev 
createConvertComplexToLLVMPass()339*f05b0afaSRiver Riddle std::unique_ptr<Pass> mlir::createConvertComplexToLLVMPass() {
340d0cb0d30SAlexander Belyaev   return std::make_unique<ConvertComplexToLLVMPass>();
341d0cb0d30SAlexander Belyaev }
342