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
17#include "mlir/Conversion/ComplexCommon/DivisionConverter.h"
18#include "mlir/Dialect/Math/IR/Math.h"
19
20using namespace mlir;
21
22void mlir::complex::convertDivToLLVMUsingAlgebraic(
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
42void mlir::complex::convertDivToStandardUsingAlgebraic(
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
90void mlir::complex::convertDivToLLVMUsingRangeReduction(
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
274void mlir::complex::convertDivToStandardUsingRangeReduction(
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}
457

source code of mlir/lib/Conversion/ComplexCommon/DivisionConverter.cpp