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
20using 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}
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.