MLIR  22.0.0git
DivisionConverter.cpp
Go to the documentation of this file.
1 //===- DivisionConverter.cpp - Complex division conversion ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements functions for two different complex number division
10 // algorithms, the `algebraic formula` and `Smith's range reduction method`.
11 // These are used in two conversions: `ComplexToLLVM` and `ComplexToStandard`.
12 // When modifying the algorithms, both `ToLLVM` and `ToStandard` must be
13 // changed.
14 //
15 //===----------------------------------------------------------------------===//
16 
19 
20 using namespace mlir;
21 
23  ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm,
24  Value rhsRe, Value rhsIm, LLVM::FastmathFlagsAttr fmf, Value *resultRe,
25  Value *resultIm) {
26  Value rhsSqNorm = LLVM::FAddOp::create(
27  rewriter, loc, LLVM::FMulOp::create(rewriter, loc, rhsRe, rhsRe, fmf),
28  LLVM::FMulOp::create(rewriter, loc, rhsIm, rhsIm, fmf), fmf);
29 
30  Value realNumerator = LLVM::FAddOp::create(
31  rewriter, loc, LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsRe, fmf),
32  LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsIm, fmf), fmf);
33 
34  Value imagNumerator = LLVM::FSubOp::create(
35  rewriter, loc, LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsRe, fmf),
36  LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsIm, fmf), fmf);
37 
38  *resultRe =
39  LLVM::FDivOp::create(rewriter, loc, realNumerator, rhsSqNorm, fmf);
40  *resultIm =
41  LLVM::FDivOp::create(rewriter, loc, imagNumerator, rhsSqNorm, fmf);
42 }
43 
45  ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm,
46  Value rhsRe, Value rhsIm, arith::FastMathFlagsAttr fmf, Value *resultRe,
47  Value *resultIm) {
48  Value rhsSqNorm = arith::AddFOp::create(
49  rewriter, loc, arith::MulFOp::create(rewriter, loc, rhsRe, rhsRe, fmf),
50  arith::MulFOp::create(rewriter, loc, rhsIm, rhsIm, fmf), fmf);
51 
52  Value realNumerator = arith::AddFOp::create(
53  rewriter, loc, arith::MulFOp::create(rewriter, loc, lhsRe, rhsRe, fmf),
54  arith::MulFOp::create(rewriter, loc, lhsIm, rhsIm, fmf), fmf);
55  Value imagNumerator = arith::SubFOp::create(
56  rewriter, loc, arith::MulFOp::create(rewriter, loc, lhsIm, rhsRe, fmf),
57  arith::MulFOp::create(rewriter, loc, lhsRe, rhsIm, fmf), fmf);
58 
59  *resultRe =
60  arith::DivFOp::create(rewriter, loc, realNumerator, rhsSqNorm, fmf);
61  *resultIm =
62  arith::DivFOp::create(rewriter, loc, imagNumerator, rhsSqNorm, fmf);
63 }
64 
65 // Smith's algorithm to divide complex numbers. It is just a bit smarter
66 // way to compute the following algebraic formula:
67 // (lhsRe + lhsIm * i) / (rhsRe + rhsIm * i)
68 // = (lhsRe + lhsIm * i) (rhsRe - rhsIm * i) /
69 // ((rhsRe + rhsIm * i)(rhsRe - rhsIm * i))
70 // = ((lhsRe * rhsRe + lhsIm * rhsIm) +
71 // (lhsIm * rhsRe - lhsRe * rhsIm) * i) / ||rhs||^2
72 //
73 // Depending on whether |rhsRe| < |rhsIm| we compute either
74 // rhsRealImagRatio = rhsRe / rhsIm
75 // rhsRealImagDenom = rhsIm + rhsRe * rhsRealImagRatio
76 // resultRe = (lhsRe * rhsRealImagRatio + lhsIm) /
77 // rhsRealImagDenom
78 // resultIm = (lhsIm * rhsRealImagRatio - lhsRe) /
79 // rhsRealImagDenom
80 //
81 // or
82 //
83 // rhsImagRealRatio = rhsIm / rhsRe
84 // rhsImagRealDenom = rhsRe + rhsIm * rhsImagRealRatio
85 // resultRe = (lhsRe + lhsIm * rhsImagRealRatio) /
86 // rhsImagRealDenom
87 // resultIm = (lhsIm - lhsRe * rhsImagRealRatio) /
88 // rhsImagRealDenom
89 //
90 // See https://dl.acm.org/citation.cfm?id=368661 for more details.
91 
93  ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm,
94  Value rhsRe, Value rhsIm, LLVM::FastmathFlagsAttr fmf, Value *resultRe,
95  Value *resultIm) {
96  auto elementType = cast<FloatType>(rhsRe.getType());
97 
98  Value rhsRealImagRatio =
99  LLVM::FDivOp::create(rewriter, loc, rhsRe, rhsIm, fmf);
100  Value rhsRealImagDenom = LLVM::FAddOp::create(
101  rewriter, loc, rhsIm,
102  LLVM::FMulOp::create(rewriter, loc, rhsRealImagRatio, rhsRe, fmf), fmf);
103  Value realNumerator1 = LLVM::FAddOp::create(
104  rewriter, loc,
105  LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsRealImagRatio, fmf), lhsIm,
106  fmf);
107  Value resultReal1 = LLVM::FDivOp::create(rewriter, loc, realNumerator1,
108  rhsRealImagDenom, fmf);
109  Value imagNumerator1 = LLVM::FSubOp::create(
110  rewriter, loc,
111  LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsRealImagRatio, fmf), lhsRe,
112  fmf);
113  Value resultImag1 = LLVM::FDivOp::create(rewriter, loc, imagNumerator1,
114  rhsRealImagDenom, fmf);
115 
116  Value rhsImagRealRatio =
117  LLVM::FDivOp::create(rewriter, loc, rhsIm, rhsRe, fmf);
118  Value rhsImagRealDenom = LLVM::FAddOp::create(
119  rewriter, loc, rhsRe,
120  LLVM::FMulOp::create(rewriter, loc, rhsImagRealRatio, rhsIm, fmf), fmf);
121  Value realNumerator2 = LLVM::FAddOp::create(
122  rewriter, loc, lhsRe,
123  LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsImagRealRatio, fmf), fmf);
124  Value resultReal2 = LLVM::FDivOp::create(rewriter, loc, realNumerator2,
125  rhsImagRealDenom, fmf);
126  Value imagNumerator2 = LLVM::FSubOp::create(
127  rewriter, loc, lhsIm,
128  LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsImagRealRatio, fmf), fmf);
129  Value resultImag2 = LLVM::FDivOp::create(rewriter, loc, imagNumerator2,
130  rhsImagRealDenom, fmf);
131 
132  // Consider corner cases.
133  // Case 1. Zero denominator, numerator contains at most one NaN value.
134  Value zero = LLVM::ConstantOp::create(rewriter, loc, elementType,
135  rewriter.getZeroAttr(elementType));
136  Value rhsRealAbs = LLVM::FAbsOp::create(rewriter, loc, rhsRe, fmf);
137  Value rhsRealIsZero = LLVM::FCmpOp::create(
138  rewriter, loc, LLVM::FCmpPredicate::oeq, rhsRealAbs, zero);
139  Value rhsImagAbs = LLVM::FAbsOp::create(rewriter, loc, rhsIm, fmf);
140  Value rhsImagIsZero = LLVM::FCmpOp::create(
141  rewriter, loc, LLVM::FCmpPredicate::oeq, rhsImagAbs, zero);
142  Value lhsRealIsNotNaN = LLVM::FCmpOp::create(
143  rewriter, loc, LLVM::FCmpPredicate::ord, lhsRe, zero);
144  Value lhsImagIsNotNaN = LLVM::FCmpOp::create(
145  rewriter, loc, LLVM::FCmpPredicate::ord, lhsIm, zero);
146  Value lhsContainsNotNaNValue =
147  LLVM::OrOp::create(rewriter, loc, lhsRealIsNotNaN, lhsImagIsNotNaN);
148  Value resultIsInfinity = LLVM::AndOp::create(
149  rewriter, loc, lhsContainsNotNaNValue,
150  LLVM::AndOp::create(rewriter, loc, rhsRealIsZero, rhsImagIsZero));
151  Value inf = LLVM::ConstantOp::create(
152  rewriter, loc, elementType,
153  rewriter.getFloatAttr(elementType,
154  APFloat::getInf(elementType.getFloatSemantics())));
155  Value infWithSignOfrhsReal =
156  LLVM::CopySignOp::create(rewriter, loc, inf, rhsRe);
157  Value infinityResultReal =
158  LLVM::FMulOp::create(rewriter, loc, infWithSignOfrhsReal, lhsRe, fmf);
159  Value infinityResultImag =
160  LLVM::FMulOp::create(rewriter, loc, infWithSignOfrhsReal, lhsIm, fmf);
161 
162  // Case 2. Infinite numerator, finite denominator.
163  Value rhsRealFinite = LLVM::FCmpOp::create(
164  rewriter, loc, LLVM::FCmpPredicate::one, rhsRealAbs, inf);
165  Value rhsImagFinite = LLVM::FCmpOp::create(
166  rewriter, loc, LLVM::FCmpPredicate::one, rhsImagAbs, inf);
167  Value rhsFinite =
168  LLVM::AndOp::create(rewriter, loc, rhsRealFinite, rhsImagFinite);
169  Value lhsRealAbs = LLVM::FAbsOp::create(rewriter, loc, lhsRe, fmf);
170  Value lhsRealInfinite = LLVM::FCmpOp::create(
171  rewriter, loc, LLVM::FCmpPredicate::oeq, lhsRealAbs, inf);
172  Value lhsImagAbs = LLVM::FAbsOp::create(rewriter, loc, lhsIm, fmf);
173  Value lhsImagInfinite = LLVM::FCmpOp::create(
174  rewriter, loc, LLVM::FCmpPredicate::oeq, lhsImagAbs, inf);
175  Value lhsInfinite =
176  LLVM::OrOp::create(rewriter, loc, lhsRealInfinite, lhsImagInfinite);
177  Value infNumFiniteDenom =
178  LLVM::AndOp::create(rewriter, loc, lhsInfinite, rhsFinite);
179  Value one = LLVM::ConstantOp::create(rewriter, loc, elementType,
180  rewriter.getFloatAttr(elementType, 1));
181  Value lhsRealIsInfWithSign = LLVM::CopySignOp::create(
182  rewriter, loc,
183  LLVM::SelectOp::create(rewriter, loc, lhsRealInfinite, one, zero), lhsRe);
184  Value lhsImagIsInfWithSign = LLVM::CopySignOp::create(
185  rewriter, loc,
186  LLVM::SelectOp::create(rewriter, loc, lhsImagInfinite, one, zero), lhsIm);
187  Value lhsRealIsInfWithSignTimesrhsReal =
188  LLVM::FMulOp::create(rewriter, loc, lhsRealIsInfWithSign, rhsRe, fmf);
189  Value lhsImagIsInfWithSignTimesrhsImag =
190  LLVM::FMulOp::create(rewriter, loc, lhsImagIsInfWithSign, rhsIm, fmf);
191  Value resultReal3 = LLVM::FMulOp::create(
192  rewriter, loc, inf,
193  LLVM::FAddOp::create(rewriter, loc, lhsRealIsInfWithSignTimesrhsReal,
194  lhsImagIsInfWithSignTimesrhsImag, fmf),
195  fmf);
196  Value lhsRealIsInfWithSignTimesrhsImag =
197  LLVM::FMulOp::create(rewriter, loc, lhsRealIsInfWithSign, rhsIm, fmf);
198  Value lhsImagIsInfWithSignTimesrhsReal =
199  LLVM::FMulOp::create(rewriter, loc, lhsImagIsInfWithSign, rhsRe, fmf);
200  Value resultImag3 = LLVM::FMulOp::create(
201  rewriter, loc, inf,
202  LLVM::FSubOp::create(rewriter, loc, lhsImagIsInfWithSignTimesrhsReal,
203  lhsRealIsInfWithSignTimesrhsImag, fmf),
204  fmf);
205 
206  // Case 3: Finite numerator, infinite denominator.
207  Value lhsRealFinite = LLVM::FCmpOp::create(
208  rewriter, loc, LLVM::FCmpPredicate::one, lhsRealAbs, inf);
209  Value lhsImagFinite = LLVM::FCmpOp::create(
210  rewriter, loc, LLVM::FCmpPredicate::one, lhsImagAbs, inf);
211  Value lhsFinite =
212  LLVM::AndOp::create(rewriter, loc, lhsRealFinite, lhsImagFinite);
213  Value rhsRealInfinite = LLVM::FCmpOp::create(
214  rewriter, loc, LLVM::FCmpPredicate::oeq, rhsRealAbs, inf);
215  Value rhsImagInfinite = LLVM::FCmpOp::create(
216  rewriter, loc, LLVM::FCmpPredicate::oeq, rhsImagAbs, inf);
217  Value rhsInfinite =
218  LLVM::OrOp::create(rewriter, loc, rhsRealInfinite, rhsImagInfinite);
219  Value finiteNumInfiniteDenom =
220  LLVM::AndOp::create(rewriter, loc, lhsFinite, rhsInfinite);
221  Value rhsRealIsInfWithSign = LLVM::CopySignOp::create(
222  rewriter, loc,
223  LLVM::SelectOp::create(rewriter, loc, rhsRealInfinite, one, zero), rhsRe);
224  Value rhsImagIsInfWithSign = LLVM::CopySignOp::create(
225  rewriter, loc,
226  LLVM::SelectOp::create(rewriter, loc, rhsImagInfinite, one, zero), rhsIm);
227  Value rhsRealIsInfWithSignTimeslhsReal =
228  LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsRealIsInfWithSign, fmf);
229  Value rhsImagIsInfWithSignTimeslhsImag =
230  LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsImagIsInfWithSign, fmf);
231  Value resultReal4 = LLVM::FMulOp::create(
232  rewriter, loc, zero,
233  LLVM::FAddOp::create(rewriter, loc, rhsRealIsInfWithSignTimeslhsReal,
234  rhsImagIsInfWithSignTimeslhsImag, fmf),
235  fmf);
236  Value rhsRealIsInfWithSignTimeslhsImag =
237  LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsRealIsInfWithSign, fmf);
238  Value rhsImagIsInfWithSignTimeslhsReal =
239  LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsImagIsInfWithSign, fmf);
240  Value resultImag4 = LLVM::FMulOp::create(
241  rewriter, loc, zero,
242  LLVM::FSubOp::create(rewriter, loc, rhsRealIsInfWithSignTimeslhsImag,
243  rhsImagIsInfWithSignTimeslhsReal, fmf),
244  fmf);
245 
246  Value realAbsSmallerThanImagAbs = LLVM::FCmpOp::create(
247  rewriter, loc, LLVM::FCmpPredicate::olt, rhsRealAbs, rhsImagAbs);
248  Value resultReal5 = LLVM::SelectOp::create(
249  rewriter, loc, realAbsSmallerThanImagAbs, resultReal1, resultReal2);
250  Value resultImag5 = LLVM::SelectOp::create(
251  rewriter, loc, realAbsSmallerThanImagAbs, resultImag1, resultImag2);
252  Value resultRealSpecialCase3 = LLVM::SelectOp::create(
253  rewriter, loc, finiteNumInfiniteDenom, resultReal4, resultReal5);
254  Value resultImagSpecialCase3 = LLVM::SelectOp::create(
255  rewriter, loc, finiteNumInfiniteDenom, resultImag4, resultImag5);
256  Value resultRealSpecialCase2 = LLVM::SelectOp::create(
257  rewriter, loc, infNumFiniteDenom, resultReal3, resultRealSpecialCase3);
258  Value resultImagSpecialCase2 = LLVM::SelectOp::create(
259  rewriter, loc, infNumFiniteDenom, resultImag3, resultImagSpecialCase3);
260  Value resultRealSpecialCase1 =
261  LLVM::SelectOp::create(rewriter, loc, resultIsInfinity,
262  infinityResultReal, resultRealSpecialCase2);
263  Value resultImagSpecialCase1 =
264  LLVM::SelectOp::create(rewriter, loc, resultIsInfinity,
265  infinityResultImag, resultImagSpecialCase2);
266 
267  Value resultRealIsNaN = LLVM::FCmpOp::create(
268  rewriter, loc, LLVM::FCmpPredicate::uno, resultReal5, zero);
269  Value resultImagIsNaN = LLVM::FCmpOp::create(
270  rewriter, loc, LLVM::FCmpPredicate::uno, resultImag5, zero);
271  Value resultIsNaN =
272  LLVM::AndOp::create(rewriter, loc, resultRealIsNaN, resultImagIsNaN);
273 
274  *resultRe = LLVM::SelectOp::create(rewriter, loc, resultIsNaN,
275  resultRealSpecialCase1, resultReal5);
276  *resultIm = LLVM::SelectOp::create(rewriter, loc, resultIsNaN,
277  resultImagSpecialCase1, resultImag5);
278 }
279 
281  ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm,
282  Value rhsRe, Value rhsIm, arith::FastMathFlagsAttr fmf, Value *resultRe,
283  Value *resultIm) {
284  auto elementType = cast<FloatType>(rhsRe.getType());
285 
286  Value rhsRealImagRatio =
287  arith::DivFOp::create(rewriter, loc, rhsRe, rhsIm, fmf);
288  Value rhsRealImagDenom = arith::AddFOp::create(
289  rewriter, loc, rhsIm,
290  arith::MulFOp::create(rewriter, loc, rhsRealImagRatio, rhsRe, fmf), fmf);
291  Value realNumerator1 = arith::AddFOp::create(
292  rewriter, loc,
293  arith::MulFOp::create(rewriter, loc, lhsRe, rhsRealImagRatio, fmf), lhsIm,
294  fmf);
295  Value resultReal1 = arith::DivFOp::create(rewriter, loc, realNumerator1,
296  rhsRealImagDenom, fmf);
297  Value imagNumerator1 = arith::SubFOp::create(
298  rewriter, loc,
299  arith::MulFOp::create(rewriter, loc, lhsIm, rhsRealImagRatio, fmf), lhsRe,
300  fmf);
301  Value resultImag1 = arith::DivFOp::create(rewriter, loc, imagNumerator1,
302  rhsRealImagDenom, fmf);
303 
304  Value rhsImagRealRatio =
305  arith::DivFOp::create(rewriter, loc, rhsIm, rhsRe, fmf);
306  Value rhsImagRealDenom = arith::AddFOp::create(
307  rewriter, loc, rhsRe,
308  arith::MulFOp::create(rewriter, loc, rhsImagRealRatio, rhsIm, fmf), fmf);
309  Value realNumerator2 = arith::AddFOp::create(
310  rewriter, loc, lhsRe,
311  arith::MulFOp::create(rewriter, loc, lhsIm, rhsImagRealRatio, fmf), fmf);
312  Value resultReal2 = arith::DivFOp::create(rewriter, loc, realNumerator2,
313  rhsImagRealDenom, fmf);
314  Value imagNumerator2 = arith::SubFOp::create(
315  rewriter, loc, lhsIm,
316  arith::MulFOp::create(rewriter, loc, lhsRe, rhsImagRealRatio, fmf), fmf);
317  Value resultImag2 = arith::DivFOp::create(rewriter, loc, imagNumerator2,
318  rhsImagRealDenom, fmf);
319 
320  // Consider corner cases.
321  // Case 1. Zero denominator, numerator contains at most one NaN value.
322  Value zero = arith::ConstantOp::create(rewriter, loc, elementType,
323  rewriter.getZeroAttr(elementType));
324  Value rhsRealAbs = math::AbsFOp::create(rewriter, loc, rhsRe, fmf);
325  Value rhsRealIsZero = arith::CmpFOp::create(
326  rewriter, loc, arith::CmpFPredicate::OEQ, rhsRealAbs, zero);
327  Value rhsImagAbs = math::AbsFOp::create(rewriter, loc, rhsIm, fmf);
328  Value rhsImagIsZero = arith::CmpFOp::create(
329  rewriter, loc, arith::CmpFPredicate::OEQ, rhsImagAbs, zero);
330  Value lhsRealIsNotNaN = arith::CmpFOp::create(
331  rewriter, loc, arith::CmpFPredicate::ORD, lhsRe, zero);
332  Value lhsImagIsNotNaN = arith::CmpFOp::create(
333  rewriter, loc, arith::CmpFPredicate::ORD, lhsIm, zero);
334  Value lhsContainsNotNaNValue =
335  arith::OrIOp::create(rewriter, loc, lhsRealIsNotNaN, lhsImagIsNotNaN);
336  Value resultIsInfinity = arith::AndIOp::create(
337  rewriter, loc, lhsContainsNotNaNValue,
338  arith::AndIOp::create(rewriter, loc, rhsRealIsZero, rhsImagIsZero));
339  Value inf = arith::ConstantOp::create(
340  rewriter, loc, elementType,
341  rewriter.getFloatAttr(elementType,
342  APFloat::getInf(elementType.getFloatSemantics())));
343  Value infWithSignOfRhsReal =
344  math::CopySignOp::create(rewriter, loc, inf, rhsRe);
345  Value infinityResultReal =
346  arith::MulFOp::create(rewriter, loc, infWithSignOfRhsReal, lhsRe, fmf);
347  Value infinityResultImag =
348  arith::MulFOp::create(rewriter, loc, infWithSignOfRhsReal, lhsIm, fmf);
349 
350  // Case 2. Infinite numerator, finite denominator.
351  Value rhsRealFinite = arith::CmpFOp::create(
352  rewriter, loc, arith::CmpFPredicate::ONE, rhsRealAbs, inf);
353  Value rhsImagFinite = arith::CmpFOp::create(
354  rewriter, loc, arith::CmpFPredicate::ONE, rhsImagAbs, inf);
355  Value rhsFinite =
356  arith::AndIOp::create(rewriter, loc, rhsRealFinite, rhsImagFinite);
357  Value lhsRealAbs = math::AbsFOp::create(rewriter, loc, lhsRe, fmf);
358  Value lhsRealInfinite = arith::CmpFOp::create(
359  rewriter, loc, arith::CmpFPredicate::OEQ, lhsRealAbs, inf);
360  Value lhsImagAbs = math::AbsFOp::create(rewriter, loc, lhsIm, fmf);
361  Value lhsImagInfinite = arith::CmpFOp::create(
362  rewriter, loc, arith::CmpFPredicate::OEQ, lhsImagAbs, inf);
363  Value lhsInfinite =
364  arith::OrIOp::create(rewriter, loc, lhsRealInfinite, lhsImagInfinite);
365  Value infNumFiniteDenom =
366  arith::AndIOp::create(rewriter, loc, lhsInfinite, rhsFinite);
367  Value one = arith::ConstantOp::create(rewriter, loc, elementType,
368  rewriter.getFloatAttr(elementType, 1));
369  Value lhsRealIsInfWithSign = math::CopySignOp::create(
370  rewriter, loc,
371  arith::SelectOp::create(rewriter, loc, lhsRealInfinite, one, zero),
372  lhsRe);
373  Value lhsImagIsInfWithSign = math::CopySignOp::create(
374  rewriter, loc,
375  arith::SelectOp::create(rewriter, loc, lhsImagInfinite, one, zero),
376  lhsIm);
377  Value lhsRealIsInfWithSignTimesRhsReal =
378  arith::MulFOp::create(rewriter, loc, lhsRealIsInfWithSign, rhsRe, fmf);
379  Value lhsImagIsInfWithSignTimesRhsImag =
380  arith::MulFOp::create(rewriter, loc, lhsImagIsInfWithSign, rhsIm, fmf);
381  Value resultReal3 = arith::MulFOp::create(
382  rewriter, loc, inf,
383  arith::AddFOp::create(rewriter, loc, lhsRealIsInfWithSignTimesRhsReal,
384  lhsImagIsInfWithSignTimesRhsImag, fmf),
385  fmf);
386  Value lhsRealIsInfWithSignTimesRhsImag =
387  arith::MulFOp::create(rewriter, loc, lhsRealIsInfWithSign, rhsIm, fmf);
388  Value lhsImagIsInfWithSignTimesRhsReal =
389  arith::MulFOp::create(rewriter, loc, lhsImagIsInfWithSign, rhsRe, fmf);
390  Value resultImag3 = arith::MulFOp::create(
391  rewriter, loc, inf,
392  arith::SubFOp::create(rewriter, loc, lhsImagIsInfWithSignTimesRhsReal,
393  lhsRealIsInfWithSignTimesRhsImag, fmf),
394  fmf);
395 
396  // Case 3: Finite numerator, infinite denominator.
397  Value lhsRealFinite = arith::CmpFOp::create(
398  rewriter, loc, arith::CmpFPredicate::ONE, lhsRealAbs, inf);
399  Value lhsImagFinite = arith::CmpFOp::create(
400  rewriter, loc, arith::CmpFPredicate::ONE, lhsImagAbs, inf);
401  Value lhsFinite =
402  arith::AndIOp::create(rewriter, loc, lhsRealFinite, lhsImagFinite);
403  Value rhsRealInfinite = arith::CmpFOp::create(
404  rewriter, loc, arith::CmpFPredicate::OEQ, rhsRealAbs, inf);
405  Value rhsImagInfinite = arith::CmpFOp::create(
406  rewriter, loc, arith::CmpFPredicate::OEQ, rhsImagAbs, inf);
407  Value rhsInfinite =
408  arith::OrIOp::create(rewriter, loc, rhsRealInfinite, rhsImagInfinite);
409  Value finiteNumInfiniteDenom =
410  arith::AndIOp::create(rewriter, loc, lhsFinite, rhsInfinite);
411  Value rhsRealIsInfWithSign = math::CopySignOp::create(
412  rewriter, loc,
413  arith::SelectOp::create(rewriter, loc, rhsRealInfinite, one, zero),
414  rhsRe);
415  Value rhsImagIsInfWithSign = math::CopySignOp::create(
416  rewriter, loc,
417  arith::SelectOp::create(rewriter, loc, rhsImagInfinite, one, zero),
418  rhsIm);
419  Value rhsRealIsInfWithSignTimesLhsReal =
420  arith::MulFOp::create(rewriter, loc, lhsRe, rhsRealIsInfWithSign, fmf);
421  Value rhsImagIsInfWithSignTimesLhsImag =
422  arith::MulFOp::create(rewriter, loc, lhsIm, rhsImagIsInfWithSign, fmf);
423  Value resultReal4 = arith::MulFOp::create(
424  rewriter, loc, zero,
425  arith::AddFOp::create(rewriter, loc, rhsRealIsInfWithSignTimesLhsReal,
426  rhsImagIsInfWithSignTimesLhsImag, fmf),
427  fmf);
428  Value rhsRealIsInfWithSignTimesLhsImag =
429  arith::MulFOp::create(rewriter, loc, lhsIm, rhsRealIsInfWithSign, fmf);
430  Value rhsImagIsInfWithSignTimesLhsReal =
431  arith::MulFOp::create(rewriter, loc, lhsRe, rhsImagIsInfWithSign, fmf);
432  Value resultImag4 = arith::MulFOp::create(
433  rewriter, loc, zero,
434  arith::SubFOp::create(rewriter, loc, rhsRealIsInfWithSignTimesLhsImag,
435  rhsImagIsInfWithSignTimesLhsReal, fmf),
436  fmf);
437 
438  Value realAbsSmallerThanImagAbs = arith::CmpFOp::create(
439  rewriter, loc, arith::CmpFPredicate::OLT, rhsRealAbs, rhsImagAbs);
440  Value resultReal5 = arith::SelectOp::create(
441  rewriter, loc, realAbsSmallerThanImagAbs, resultReal1, resultReal2);
442  Value resultImag5 = arith::SelectOp::create(
443  rewriter, loc, realAbsSmallerThanImagAbs, resultImag1, resultImag2);
444  Value resultRealSpecialCase3 = arith::SelectOp::create(
445  rewriter, loc, finiteNumInfiniteDenom, resultReal4, resultReal5);
446  Value resultImagSpecialCase3 = arith::SelectOp::create(
447  rewriter, loc, finiteNumInfiniteDenom, resultImag4, resultImag5);
448  Value resultRealSpecialCase2 = arith::SelectOp::create(
449  rewriter, loc, infNumFiniteDenom, resultReal3, resultRealSpecialCase3);
450  Value resultImagSpecialCase2 = arith::SelectOp::create(
451  rewriter, loc, infNumFiniteDenom, resultImag3, resultImagSpecialCase3);
452  Value resultRealSpecialCase1 =
453  arith::SelectOp::create(rewriter, loc, resultIsInfinity,
454  infinityResultReal, resultRealSpecialCase2);
455  Value resultImagSpecialCase1 =
456  arith::SelectOp::create(rewriter, loc, resultIsInfinity,
457  infinityResultImag, resultImagSpecialCase2);
458 
459  Value resultRealIsNaN = arith::CmpFOp::create(
460  rewriter, loc, arith::CmpFPredicate::UNO, resultReal5, zero);
461  Value resultImagIsNaN = arith::CmpFOp::create(
462  rewriter, loc, arith::CmpFPredicate::UNO, resultImag5, zero);
463  Value resultIsNaN =
464  arith::AndIOp::create(rewriter, loc, resultRealIsNaN, resultImagIsNaN);
465 
466  *resultRe = arith::SelectOp::create(rewriter, loc, resultIsNaN,
467  resultRealSpecialCase1, resultReal5);
468  *resultIm = arith::SelectOp::create(rewriter, loc, resultIsNaN,
469  resultImagSpecialCase1, resultImag5);
470 }
FloatAttr getFloatAttr(Type type, double value)
Definition: Builders.cpp:253
TypedAttr getZeroAttr(Type type)
Definition: Builders.cpp:323
This class implements a pattern rewriter for use with ConversionPatterns.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:76
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
Type getType() const
Return the type of this value.
Definition: Value.h:105
void convertDivToLLVMUsingRangeReduction(ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm, Value rhsRe, Value rhsIm, LLVM::FastmathFlagsAttr fmf, Value *resultRe, Value *resultIm)
convert a complex division to the LLVM dialect using Smith's method
void convertDivToStandardUsingAlgebraic(ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm, Value rhsRe, Value rhsIm, arith::FastMathFlagsAttr fmf, Value *resultRe, Value *resultIm)
convert a complex division to the arith/math dialects using algebraic method
void convertDivToStandardUsingRangeReduction(ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm, Value rhsRe, Value rhsIm, arith::FastMathFlagsAttr fmf, Value *resultRe, Value *resultIm)
convert a complex division to the arith/math dialects using Smith's method
void convertDivToLLVMUsingAlgebraic(ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm, Value rhsRe, Value rhsIm, LLVM::FastmathFlagsAttr fmf, Value *resultRe, Value *resultIm)
convert a complex division to the LLVM dialect using algebraic method
Include the generated interface declarations.