471 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements functions for two different complex number division10// 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 be13// 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 = 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 44void mlir::complex::convertDivToStandardUsingAlgebraic(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 smarter66// 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||^272//73// Depending on whether |rhsRe| < |rhsIm| we compute either74// rhsRealImagRatio = rhsRe / rhsIm75// rhsRealImagDenom = rhsIm + rhsRe * rhsRealImagRatio76// resultRe = (lhsRe * rhsRealImagRatio + lhsIm) /77// rhsRealImagDenom78// resultIm = (lhsIm * rhsRealImagRatio - lhsRe) /79// rhsRealImagDenom80//81// or82//83// rhsImagRealRatio = rhsIm / rhsRe84// rhsImagRealDenom = rhsRe + rhsIm * rhsImagRealRatio85// resultRe = (lhsRe + lhsIm * rhsImagRealRatio) /86// rhsImagRealDenom87// resultIm = (lhsIm - lhsRe * rhsImagRealRatio) /88// rhsImagRealDenom89//90// See https://dl.acm.org/citation.cfm?id=368661 for more details.91 92void mlir::complex::convertDivToLLVMUsingRangeReduction(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 280void mlir::complex::convertDivToStandardUsingRangeReduction(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}471