brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.1 KiB · 14fbb9b Raw
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