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