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