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 location: loc, args: rewriter.create<LLVM::FMulOp>(location: loc, args&: rhsRe, args&: rhsRe, args&: fmf),
28 args: rewriter.create<LLVM::FMulOp>(location: loc, args&: rhsIm, args&: rhsIm, args&: fmf), args&: fmf);
29
30 Value realNumerator = rewriter.create<LLVM::FAddOp>(
31 location: loc, args: rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsRe, args&: rhsRe, args&: fmf),
32 args: rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsIm, args&: rhsIm, args&: fmf), args&: fmf);
33
34 Value imagNumerator = rewriter.create<LLVM::FSubOp>(
35 location: loc, args: rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsIm, args&: rhsRe, args&: fmf),
36 args: rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsRe, args&: rhsIm, args&: fmf), args&: fmf);
37
38 *resultRe = rewriter.create<LLVM::FDivOp>(location: loc, args&: realNumerator, args&: rhsSqNorm, args&: fmf);
39 *resultIm = rewriter.create<LLVM::FDivOp>(location: loc, args&: imagNumerator, args&: rhsSqNorm, args&: 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 location: loc, args: rewriter.create<arith::MulFOp>(location: loc, args&: rhsRe, args&: rhsRe, args&: fmf),
48 args: rewriter.create<arith::MulFOp>(location: loc, args&: rhsIm, args&: rhsIm, args&: fmf), args&: fmf);
49
50 Value realNumerator = rewriter.create<arith::AddFOp>(
51 location: loc, args: rewriter.create<arith::MulFOp>(location: loc, args&: lhsRe, args&: rhsRe, args&: fmf),
52 args: rewriter.create<arith::MulFOp>(location: loc, args&: lhsIm, args&: rhsIm, args&: fmf), args&: fmf);
53 Value imagNumerator = rewriter.create<arith::SubFOp>(
54 location: loc, args: rewriter.create<arith::MulFOp>(location: loc, args&: lhsIm, args&: rhsRe, args&: fmf),
55 args: rewriter.create<arith::MulFOp>(location: loc, args&: lhsRe, args&: rhsIm, args&: fmf), args&: fmf);
56
57 *resultRe =
58 rewriter.create<arith::DivFOp>(location: loc, args&: realNumerator, args&: rhsSqNorm, args&: fmf);
59 *resultIm =
60 rewriter.create<arith::DivFOp>(location: loc, args&: imagNumerator, args&: rhsSqNorm, args&: 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>(Val: rhsRe.getType());
95
96 Value rhsRealImagRatio =
97 rewriter.create<LLVM::FDivOp>(location: loc, args&: rhsRe, args&: rhsIm, args&: fmf);
98 Value rhsRealImagDenom = rewriter.create<LLVM::FAddOp>(
99 location: loc, args&: rhsIm,
100 args: rewriter.create<LLVM::FMulOp>(location: loc, args&: rhsRealImagRatio, args&: rhsRe, args&: fmf), args&: fmf);
101 Value realNumerator1 = rewriter.create<LLVM::FAddOp>(
102 location: loc, args: rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsRe, args&: rhsRealImagRatio, args&: fmf),
103 args&: lhsIm, args&: fmf);
104 Value resultReal1 =
105 rewriter.create<LLVM::FDivOp>(location: loc, args&: realNumerator1, args&: rhsRealImagDenom, args&: fmf);
106 Value imagNumerator1 = rewriter.create<LLVM::FSubOp>(
107 location: loc, args: rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsIm, args&: rhsRealImagRatio, args&: fmf),
108 args&: lhsRe, args&: fmf);
109 Value resultImag1 =
110 rewriter.create<LLVM::FDivOp>(location: loc, args&: imagNumerator1, args&: rhsRealImagDenom, args&: fmf);
111
112 Value rhsImagRealRatio =
113 rewriter.create<LLVM::FDivOp>(location: loc, args&: rhsIm, args&: rhsRe, args&: fmf);
114 Value rhsImagRealDenom = rewriter.create<LLVM::FAddOp>(
115 location: loc, args&: rhsRe,
116 args: rewriter.create<LLVM::FMulOp>(location: loc, args&: rhsImagRealRatio, args&: rhsIm, args&: fmf), args&: fmf);
117 Value realNumerator2 = rewriter.create<LLVM::FAddOp>(
118 location: loc, args&: lhsRe,
119 args: rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsIm, args&: rhsImagRealRatio, args&: fmf), args&: fmf);
120 Value resultReal2 =
121 rewriter.create<LLVM::FDivOp>(location: loc, args&: realNumerator2, args&: rhsImagRealDenom, args&: fmf);
122 Value imagNumerator2 = rewriter.create<LLVM::FSubOp>(
123 location: loc, args&: lhsIm,
124 args: rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsRe, args&: rhsImagRealRatio, args&: fmf), args&: fmf);
125 Value resultImag2 =
126 rewriter.create<LLVM::FDivOp>(location: loc, args&: imagNumerator2, args&: rhsImagRealDenom, args&: 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 location: loc, args&: elementType, args: rewriter.getZeroAttr(type: elementType));
132 Value rhsRealAbs = rewriter.create<LLVM::FAbsOp>(location: loc, args&: rhsRe, args&: fmf);
133 Value rhsRealIsZero = rewriter.create<LLVM::FCmpOp>(
134 location: loc, args: LLVM::FCmpPredicate::oeq, args&: rhsRealAbs, args&: zero);
135 Value rhsImagAbs = rewriter.create<LLVM::FAbsOp>(location: loc, args&: rhsIm, args&: fmf);
136 Value rhsImagIsZero = rewriter.create<LLVM::FCmpOp>(
137 location: loc, args: LLVM::FCmpPredicate::oeq, args&: rhsImagAbs, args&: zero);
138 Value lhsRealIsNotNaN =
139 rewriter.create<LLVM::FCmpOp>(location: loc, args: LLVM::FCmpPredicate::ord, args&: lhsRe, args&: zero);
140 Value lhsImagIsNotNaN =
141 rewriter.create<LLVM::FCmpOp>(location: loc, args: LLVM::FCmpPredicate::ord, args&: lhsIm, args&: zero);
142 Value lhsContainsNotNaNValue =
143 rewriter.create<LLVM::OrOp>(location: loc, args&: lhsRealIsNotNaN, args&: lhsImagIsNotNaN);
144 Value resultIsInfinity = rewriter.create<LLVM::AndOp>(
145 location: loc, args&: lhsContainsNotNaNValue,
146 args: rewriter.create<LLVM::AndOp>(location: loc, args&: rhsRealIsZero, args&: rhsImagIsZero));
147 Value inf = rewriter.create<LLVM::ConstantOp>(
148 location: loc, args&: elementType,
149 args: rewriter.getFloatAttr(type: elementType,
150 value: APFloat::getInf(Sem: elementType.getFloatSemantics())));
151 Value infWithSignOfrhsReal =
152 rewriter.create<LLVM::CopySignOp>(location: loc, args&: inf, args&: rhsRe);
153 Value infinityResultReal =
154 rewriter.create<LLVM::FMulOp>(location: loc, args&: infWithSignOfrhsReal, args&: lhsRe, args&: fmf);
155 Value infinityResultImag =
156 rewriter.create<LLVM::FMulOp>(location: loc, args&: infWithSignOfrhsReal, args&: lhsIm, args&: fmf);
157
158 // Case 2. Infinite numerator, finite denominator.
159 Value rhsRealFinite = rewriter.create<LLVM::FCmpOp>(
160 location: loc, args: LLVM::FCmpPredicate::one, args&: rhsRealAbs, args&: inf);
161 Value rhsImagFinite = rewriter.create<LLVM::FCmpOp>(
162 location: loc, args: LLVM::FCmpPredicate::one, args&: rhsImagAbs, args&: inf);
163 Value rhsFinite =
164 rewriter.create<LLVM::AndOp>(location: loc, args&: rhsRealFinite, args&: rhsImagFinite);
165 Value lhsRealAbs = rewriter.create<LLVM::FAbsOp>(location: loc, args&: lhsRe, args&: fmf);
166 Value lhsRealInfinite = rewriter.create<LLVM::FCmpOp>(
167 location: loc, args: LLVM::FCmpPredicate::oeq, args&: lhsRealAbs, args&: inf);
168 Value lhsImagAbs = rewriter.create<LLVM::FAbsOp>(location: loc, args&: lhsIm, args&: fmf);
169 Value lhsImagInfinite = rewriter.create<LLVM::FCmpOp>(
170 location: loc, args: LLVM::FCmpPredicate::oeq, args&: lhsImagAbs, args&: inf);
171 Value lhsInfinite =
172 rewriter.create<LLVM::OrOp>(location: loc, args&: lhsRealInfinite, args&: lhsImagInfinite);
173 Value infNumFiniteDenom =
174 rewriter.create<LLVM::AndOp>(location: loc, args&: lhsInfinite, args&: rhsFinite);
175 Value one = rewriter.create<LLVM::ConstantOp>(
176 location: loc, args&: elementType, args: rewriter.getFloatAttr(type: elementType, value: 1));
177 Value lhsRealIsInfWithSign = rewriter.create<LLVM::CopySignOp>(
178 location: loc, args: rewriter.create<LLVM::SelectOp>(location: loc, args&: lhsRealInfinite, args&: one, args&: zero),
179 args&: lhsRe);
180 Value lhsImagIsInfWithSign = rewriter.create<LLVM::CopySignOp>(
181 location: loc, args: rewriter.create<LLVM::SelectOp>(location: loc, args&: lhsImagInfinite, args&: one, args&: zero),
182 args&: lhsIm);
183 Value lhsRealIsInfWithSignTimesrhsReal =
184 rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsRealIsInfWithSign, args&: rhsRe, args&: fmf);
185 Value lhsImagIsInfWithSignTimesrhsImag =
186 rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsImagIsInfWithSign, args&: rhsIm, args&: fmf);
187 Value resultReal3 = rewriter.create<LLVM::FMulOp>(
188 location: loc, args&: inf,
189 args: rewriter.create<LLVM::FAddOp>(location: loc, args&: lhsRealIsInfWithSignTimesrhsReal,
190 args&: lhsImagIsInfWithSignTimesrhsImag, args&: fmf),
191 args&: fmf);
192 Value lhsRealIsInfWithSignTimesrhsImag =
193 rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsRealIsInfWithSign, args&: rhsIm, args&: fmf);
194 Value lhsImagIsInfWithSignTimesrhsReal =
195 rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsImagIsInfWithSign, args&: rhsRe, args&: fmf);
196 Value resultImag3 = rewriter.create<LLVM::FMulOp>(
197 location: loc, args&: inf,
198 args: rewriter.create<LLVM::FSubOp>(location: loc, args&: lhsImagIsInfWithSignTimesrhsReal,
199 args&: lhsRealIsInfWithSignTimesrhsImag, args&: fmf),
200 args&: fmf);
201
202 // Case 3: Finite numerator, infinite denominator.
203 Value lhsRealFinite = rewriter.create<LLVM::FCmpOp>(
204 location: loc, args: LLVM::FCmpPredicate::one, args&: lhsRealAbs, args&: inf);
205 Value lhsImagFinite = rewriter.create<LLVM::FCmpOp>(
206 location: loc, args: LLVM::FCmpPredicate::one, args&: lhsImagAbs, args&: inf);
207 Value lhsFinite =
208 rewriter.create<LLVM::AndOp>(location: loc, args&: lhsRealFinite, args&: lhsImagFinite);
209 Value rhsRealInfinite = rewriter.create<LLVM::FCmpOp>(
210 location: loc, args: LLVM::FCmpPredicate::oeq, args&: rhsRealAbs, args&: inf);
211 Value rhsImagInfinite = rewriter.create<LLVM::FCmpOp>(
212 location: loc, args: LLVM::FCmpPredicate::oeq, args&: rhsImagAbs, args&: inf);
213 Value rhsInfinite =
214 rewriter.create<LLVM::OrOp>(location: loc, args&: rhsRealInfinite, args&: rhsImagInfinite);
215 Value finiteNumInfiniteDenom =
216 rewriter.create<LLVM::AndOp>(location: loc, args&: lhsFinite, args&: rhsInfinite);
217 Value rhsRealIsInfWithSign = rewriter.create<LLVM::CopySignOp>(
218 location: loc, args: rewriter.create<LLVM::SelectOp>(location: loc, args&: rhsRealInfinite, args&: one, args&: zero),
219 args&: rhsRe);
220 Value rhsImagIsInfWithSign = rewriter.create<LLVM::CopySignOp>(
221 location: loc, args: rewriter.create<LLVM::SelectOp>(location: loc, args&: rhsImagInfinite, args&: one, args&: zero),
222 args&: rhsIm);
223 Value rhsRealIsInfWithSignTimeslhsReal =
224 rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsRe, args&: rhsRealIsInfWithSign, args&: fmf);
225 Value rhsImagIsInfWithSignTimeslhsImag =
226 rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsIm, args&: rhsImagIsInfWithSign, args&: fmf);
227 Value resultReal4 = rewriter.create<LLVM::FMulOp>(
228 location: loc, args&: zero,
229 args: rewriter.create<LLVM::FAddOp>(location: loc, args&: rhsRealIsInfWithSignTimeslhsReal,
230 args&: rhsImagIsInfWithSignTimeslhsImag, args&: fmf),
231 args&: fmf);
232 Value rhsRealIsInfWithSignTimeslhsImag =
233 rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsIm, args&: rhsRealIsInfWithSign, args&: fmf);
234 Value rhsImagIsInfWithSignTimeslhsReal =
235 rewriter.create<LLVM::FMulOp>(location: loc, args&: lhsRe, args&: rhsImagIsInfWithSign, args&: fmf);
236 Value resultImag4 = rewriter.create<LLVM::FMulOp>(
237 location: loc, args&: zero,
238 args: rewriter.create<LLVM::FSubOp>(location: loc, args&: rhsRealIsInfWithSignTimeslhsImag,
239 args&: rhsImagIsInfWithSignTimeslhsReal, args&: fmf),
240 args&: fmf);
241
242 Value realAbsSmallerThanImagAbs = rewriter.create<LLVM::FCmpOp>(
243 location: loc, args: LLVM::FCmpPredicate::olt, args&: rhsRealAbs, args&: rhsImagAbs);
244 Value resultReal5 = rewriter.create<LLVM::SelectOp>(
245 location: loc, args&: realAbsSmallerThanImagAbs, args&: resultReal1, args&: resultReal2);
246 Value resultImag5 = rewriter.create<LLVM::SelectOp>(
247 location: loc, args&: realAbsSmallerThanImagAbs, args&: resultImag1, args&: resultImag2);
248 Value resultRealSpecialCase3 = rewriter.create<LLVM::SelectOp>(
249 location: loc, args&: finiteNumInfiniteDenom, args&: resultReal4, args&: resultReal5);
250 Value resultImagSpecialCase3 = rewriter.create<LLVM::SelectOp>(
251 location: loc, args&: finiteNumInfiniteDenom, args&: resultImag4, args&: resultImag5);
252 Value resultRealSpecialCase2 = rewriter.create<LLVM::SelectOp>(
253 location: loc, args&: infNumFiniteDenom, args&: resultReal3, args&: resultRealSpecialCase3);
254 Value resultImagSpecialCase2 = rewriter.create<LLVM::SelectOp>(
255 location: loc, args&: infNumFiniteDenom, args&: resultImag3, args&: resultImagSpecialCase3);
256 Value resultRealSpecialCase1 = rewriter.create<LLVM::SelectOp>(
257 location: loc, args&: resultIsInfinity, args&: infinityResultReal, args&: resultRealSpecialCase2);
258 Value resultImagSpecialCase1 = rewriter.create<LLVM::SelectOp>(
259 location: loc, args&: resultIsInfinity, args&: infinityResultImag, args&: resultImagSpecialCase2);
260
261 Value resultRealIsNaN = rewriter.create<LLVM::FCmpOp>(
262 location: loc, args: LLVM::FCmpPredicate::uno, args&: resultReal5, args&: zero);
263 Value resultImagIsNaN = rewriter.create<LLVM::FCmpOp>(
264 location: loc, args: LLVM::FCmpPredicate::uno, args&: resultImag5, args&: zero);
265 Value resultIsNaN =
266 rewriter.create<LLVM::AndOp>(location: loc, args&: resultRealIsNaN, args&: resultImagIsNaN);
267
268 *resultRe = rewriter.create<LLVM::SelectOp>(
269 location: loc, args&: resultIsNaN, args&: resultRealSpecialCase1, args&: resultReal5);
270 *resultIm = rewriter.create<LLVM::SelectOp>(
271 location: loc, args&: resultIsNaN, args&: resultImagSpecialCase1, args&: 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>(Val: rhsRe.getType());
279
280 Value rhsRealImagRatio =
281 rewriter.create<arith::DivFOp>(location: loc, args&: rhsRe, args&: rhsIm, args&: fmf);
282 Value rhsRealImagDenom = rewriter.create<arith::AddFOp>(
283 location: loc, args&: rhsIm,
284 args: rewriter.create<arith::MulFOp>(location: loc, args&: rhsRealImagRatio, args&: rhsRe, args&: fmf), args&: fmf);
285 Value realNumerator1 = rewriter.create<arith::AddFOp>(
286 location: loc, args: rewriter.create<arith::MulFOp>(location: loc, args&: lhsRe, args&: rhsRealImagRatio, args&: fmf),
287 args&: lhsIm, args&: fmf);
288 Value resultReal1 = rewriter.create<arith::DivFOp>(location: loc, args&: realNumerator1,
289 args&: rhsRealImagDenom, args&: fmf);
290 Value imagNumerator1 = rewriter.create<arith::SubFOp>(
291 location: loc, args: rewriter.create<arith::MulFOp>(location: loc, args&: lhsIm, args&: rhsRealImagRatio, args&: fmf),
292 args&: lhsRe, args&: fmf);
293 Value resultImag1 = rewriter.create<arith::DivFOp>(location: loc, args&: imagNumerator1,
294 args&: rhsRealImagDenom, args&: fmf);
295
296 Value rhsImagRealRatio =
297 rewriter.create<arith::DivFOp>(location: loc, args&: rhsIm, args&: rhsRe, args&: fmf);
298 Value rhsImagRealDenom = rewriter.create<arith::AddFOp>(
299 location: loc, args&: rhsRe,
300 args: rewriter.create<arith::MulFOp>(location: loc, args&: rhsImagRealRatio, args&: rhsIm, args&: fmf), args&: fmf);
301 Value realNumerator2 = rewriter.create<arith::AddFOp>(
302 location: loc, args&: lhsRe,
303 args: rewriter.create<arith::MulFOp>(location: loc, args&: lhsIm, args&: rhsImagRealRatio, args&: fmf), args&: fmf);
304 Value resultReal2 = rewriter.create<arith::DivFOp>(location: loc, args&: realNumerator2,
305 args&: rhsImagRealDenom, args&: fmf);
306 Value imagNumerator2 = rewriter.create<arith::SubFOp>(
307 location: loc, args&: lhsIm,
308 args: rewriter.create<arith::MulFOp>(location: loc, args&: lhsRe, args&: rhsImagRealRatio, args&: fmf), args&: fmf);
309 Value resultImag2 = rewriter.create<arith::DivFOp>(location: loc, args&: imagNumerator2,
310 args&: rhsImagRealDenom, args&: 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 location: loc, args&: elementType, args: rewriter.getZeroAttr(type: elementType));
316 Value rhsRealAbs = rewriter.create<math::AbsFOp>(location: loc, args&: rhsRe, args&: fmf);
317 Value rhsRealIsZero = rewriter.create<arith::CmpFOp>(
318 location: loc, args: arith::CmpFPredicate::OEQ, args&: rhsRealAbs, args&: zero);
319 Value rhsImagAbs = rewriter.create<math::AbsFOp>(location: loc, args&: rhsIm, args&: fmf);
320 Value rhsImagIsZero = rewriter.create<arith::CmpFOp>(
321 location: loc, args: arith::CmpFPredicate::OEQ, args&: rhsImagAbs, args&: zero);
322 Value lhsRealIsNotNaN = rewriter.create<arith::CmpFOp>(
323 location: loc, args: arith::CmpFPredicate::ORD, args&: lhsRe, args&: zero);
324 Value lhsImagIsNotNaN = rewriter.create<arith::CmpFOp>(
325 location: loc, args: arith::CmpFPredicate::ORD, args&: lhsIm, args&: zero);
326 Value lhsContainsNotNaNValue =
327 rewriter.create<arith::OrIOp>(location: loc, args&: lhsRealIsNotNaN, args&: lhsImagIsNotNaN);
328 Value resultIsInfinity = rewriter.create<arith::AndIOp>(
329 location: loc, args&: lhsContainsNotNaNValue,
330 args: rewriter.create<arith::AndIOp>(location: loc, args&: rhsRealIsZero, args&: rhsImagIsZero));
331 Value inf = rewriter.create<arith::ConstantOp>(
332 location: loc, args&: elementType,
333 args: rewriter.getFloatAttr(type: elementType,
334 value: APFloat::getInf(Sem: elementType.getFloatSemantics())));
335 Value infWithSignOfRhsReal =
336 rewriter.create<math::CopySignOp>(location: loc, args&: inf, args&: rhsRe);
337 Value infinityResultReal =
338 rewriter.create<arith::MulFOp>(location: loc, args&: infWithSignOfRhsReal, args&: lhsRe, args&: fmf);
339 Value infinityResultImag =
340 rewriter.create<arith::MulFOp>(location: loc, args&: infWithSignOfRhsReal, args&: lhsIm, args&: fmf);
341
342 // Case 2. Infinite numerator, finite denominator.
343 Value rhsRealFinite = rewriter.create<arith::CmpFOp>(
344 location: loc, args: arith::CmpFPredicate::ONE, args&: rhsRealAbs, args&: inf);
345 Value rhsImagFinite = rewriter.create<arith::CmpFOp>(
346 location: loc, args: arith::CmpFPredicate::ONE, args&: rhsImagAbs, args&: inf);
347 Value rhsFinite =
348 rewriter.create<arith::AndIOp>(location: loc, args&: rhsRealFinite, args&: rhsImagFinite);
349 Value lhsRealAbs = rewriter.create<math::AbsFOp>(location: loc, args&: lhsRe, args&: fmf);
350 Value lhsRealInfinite = rewriter.create<arith::CmpFOp>(
351 location: loc, args: arith::CmpFPredicate::OEQ, args&: lhsRealAbs, args&: inf);
352 Value lhsImagAbs = rewriter.create<math::AbsFOp>(location: loc, args&: lhsIm, args&: fmf);
353 Value lhsImagInfinite = rewriter.create<arith::CmpFOp>(
354 location: loc, args: arith::CmpFPredicate::OEQ, args&: lhsImagAbs, args&: inf);
355 Value lhsInfinite =
356 rewriter.create<arith::OrIOp>(location: loc, args&: lhsRealInfinite, args&: lhsImagInfinite);
357 Value infNumFiniteDenom =
358 rewriter.create<arith::AndIOp>(location: loc, args&: lhsInfinite, args&: rhsFinite);
359 Value one = rewriter.create<arith::ConstantOp>(
360 location: loc, args&: elementType, args: rewriter.getFloatAttr(type: elementType, value: 1));
361 Value lhsRealIsInfWithSign = rewriter.create<math::CopySignOp>(
362 location: loc, args: rewriter.create<arith::SelectOp>(location: loc, args&: lhsRealInfinite, args&: one, args&: zero),
363 args&: lhsRe);
364 Value lhsImagIsInfWithSign = rewriter.create<math::CopySignOp>(
365 location: loc, args: rewriter.create<arith::SelectOp>(location: loc, args&: lhsImagInfinite, args&: one, args&: zero),
366 args&: lhsIm);
367 Value lhsRealIsInfWithSignTimesRhsReal =
368 rewriter.create<arith::MulFOp>(location: loc, args&: lhsRealIsInfWithSign, args&: rhsRe, args&: fmf);
369 Value lhsImagIsInfWithSignTimesRhsImag =
370 rewriter.create<arith::MulFOp>(location: loc, args&: lhsImagIsInfWithSign, args&: rhsIm, args&: fmf);
371 Value resultReal3 = rewriter.create<arith::MulFOp>(
372 location: loc, args&: inf,
373 args: rewriter.create<arith::AddFOp>(location: loc, args&: lhsRealIsInfWithSignTimesRhsReal,
374 args&: lhsImagIsInfWithSignTimesRhsImag, args&: fmf),
375 args&: fmf);
376 Value lhsRealIsInfWithSignTimesRhsImag =
377 rewriter.create<arith::MulFOp>(location: loc, args&: lhsRealIsInfWithSign, args&: rhsIm, args&: fmf);
378 Value lhsImagIsInfWithSignTimesRhsReal =
379 rewriter.create<arith::MulFOp>(location: loc, args&: lhsImagIsInfWithSign, args&: rhsRe, args&: fmf);
380 Value resultImag3 = rewriter.create<arith::MulFOp>(
381 location: loc, args&: inf,
382 args: rewriter.create<arith::SubFOp>(location: loc, args&: lhsImagIsInfWithSignTimesRhsReal,
383 args&: lhsRealIsInfWithSignTimesRhsImag, args&: fmf),
384 args&: fmf);
385
386 // Case 3: Finite numerator, infinite denominator.
387 Value lhsRealFinite = rewriter.create<arith::CmpFOp>(
388 location: loc, args: arith::CmpFPredicate::ONE, args&: lhsRealAbs, args&: inf);
389 Value lhsImagFinite = rewriter.create<arith::CmpFOp>(
390 location: loc, args: arith::CmpFPredicate::ONE, args&: lhsImagAbs, args&: inf);
391 Value lhsFinite =
392 rewriter.create<arith::AndIOp>(location: loc, args&: lhsRealFinite, args&: lhsImagFinite);
393 Value rhsRealInfinite = rewriter.create<arith::CmpFOp>(
394 location: loc, args: arith::CmpFPredicate::OEQ, args&: rhsRealAbs, args&: inf);
395 Value rhsImagInfinite = rewriter.create<arith::CmpFOp>(
396 location: loc, args: arith::CmpFPredicate::OEQ, args&: rhsImagAbs, args&: inf);
397 Value rhsInfinite =
398 rewriter.create<arith::OrIOp>(location: loc, args&: rhsRealInfinite, args&: rhsImagInfinite);
399 Value finiteNumInfiniteDenom =
400 rewriter.create<arith::AndIOp>(location: loc, args&: lhsFinite, args&: rhsInfinite);
401 Value rhsRealIsInfWithSign = rewriter.create<math::CopySignOp>(
402 location: loc, args: rewriter.create<arith::SelectOp>(location: loc, args&: rhsRealInfinite, args&: one, args&: zero),
403 args&: rhsRe);
404 Value rhsImagIsInfWithSign = rewriter.create<math::CopySignOp>(
405 location: loc, args: rewriter.create<arith::SelectOp>(location: loc, args&: rhsImagInfinite, args&: one, args&: zero),
406 args&: rhsIm);
407 Value rhsRealIsInfWithSignTimesLhsReal =
408 rewriter.create<arith::MulFOp>(location: loc, args&: lhsRe, args&: rhsRealIsInfWithSign, args&: fmf);
409 Value rhsImagIsInfWithSignTimesLhsImag =
410 rewriter.create<arith::MulFOp>(location: loc, args&: lhsIm, args&: rhsImagIsInfWithSign, args&: fmf);
411 Value resultReal4 = rewriter.create<arith::MulFOp>(
412 location: loc, args&: zero,
413 args: rewriter.create<arith::AddFOp>(location: loc, args&: rhsRealIsInfWithSignTimesLhsReal,
414 args&: rhsImagIsInfWithSignTimesLhsImag, args&: fmf),
415 args&: fmf);
416 Value rhsRealIsInfWithSignTimesLhsImag =
417 rewriter.create<arith::MulFOp>(location: loc, args&: lhsIm, args&: rhsRealIsInfWithSign, args&: fmf);
418 Value rhsImagIsInfWithSignTimesLhsReal =
419 rewriter.create<arith::MulFOp>(location: loc, args&: lhsRe, args&: rhsImagIsInfWithSign, args&: fmf);
420 Value resultImag4 = rewriter.create<arith::MulFOp>(
421 location: loc, args&: zero,
422 args: rewriter.create<arith::SubFOp>(location: loc, args&: rhsRealIsInfWithSignTimesLhsImag,
423 args&: rhsImagIsInfWithSignTimesLhsReal, args&: fmf),
424 args&: fmf);
425
426 Value realAbsSmallerThanImagAbs = rewriter.create<arith::CmpFOp>(
427 location: loc, args: arith::CmpFPredicate::OLT, args&: rhsRealAbs, args&: rhsImagAbs);
428 Value resultReal5 = rewriter.create<arith::SelectOp>(
429 location: loc, args&: realAbsSmallerThanImagAbs, args&: resultReal1, args&: resultReal2);
430 Value resultImag5 = rewriter.create<arith::SelectOp>(
431 location: loc, args&: realAbsSmallerThanImagAbs, args&: resultImag1, args&: resultImag2);
432 Value resultRealSpecialCase3 = rewriter.create<arith::SelectOp>(
433 location: loc, args&: finiteNumInfiniteDenom, args&: resultReal4, args&: resultReal5);
434 Value resultImagSpecialCase3 = rewriter.create<arith::SelectOp>(
435 location: loc, args&: finiteNumInfiniteDenom, args&: resultImag4, args&: resultImag5);
436 Value resultRealSpecialCase2 = rewriter.create<arith::SelectOp>(
437 location: loc, args&: infNumFiniteDenom, args&: resultReal3, args&: resultRealSpecialCase3);
438 Value resultImagSpecialCase2 = rewriter.create<arith::SelectOp>(
439 location: loc, args&: infNumFiniteDenom, args&: resultImag3, args&: resultImagSpecialCase3);
440 Value resultRealSpecialCase1 = rewriter.create<arith::SelectOp>(
441 location: loc, args&: resultIsInfinity, args&: infinityResultReal, args&: resultRealSpecialCase2);
442 Value resultImagSpecialCase1 = rewriter.create<arith::SelectOp>(
443 location: loc, args&: resultIsInfinity, args&: infinityResultImag, args&: resultImagSpecialCase2);
444
445 Value resultRealIsNaN = rewriter.create<arith::CmpFOp>(
446 location: loc, args: arith::CmpFPredicate::UNO, args&: resultReal5, args&: zero);
447 Value resultImagIsNaN = rewriter.create<arith::CmpFOp>(
448 location: loc, args: arith::CmpFPredicate::UNO, args&: resultImag5, args&: zero);
449 Value resultIsNaN =
450 rewriter.create<arith::AndIOp>(location: loc, args&: resultRealIsNaN, args&: resultImagIsNaN);
451
452 *resultRe = rewriter.create<arith::SelectOp>(
453 location: loc, args&: resultIsNaN, args&: resultRealSpecialCase1, args&: resultReal5);
454 *resultIm = rewriter.create<arith::SelectOp>(
455 location: loc, args&: resultIsNaN, args&: resultImagSpecialCase1, args&: resultImag5);
456}
457

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