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