//===- DivisionConverter.cpp - Complex division conversion ----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements functions for two different complex number division // algorithms, the `algebraic formula` and `Smith's range reduction method`. // These are used in two conversions: `ComplexToLLVM` and `ComplexToStandard`. // When modifying the algorithms, both `ToLLVM` and `ToStandard` must be // changed. // //===----------------------------------------------------------------------===// #include "mlir/Conversion/ComplexCommon/DivisionConverter.h" #include "mlir/Dialect/Math/IR/Math.h" using namespace mlir; void mlir::complex::convertDivToLLVMUsingAlgebraic( ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm, Value rhsRe, Value rhsIm, LLVM::FastmathFlagsAttr fmf, Value *resultRe, Value *resultIm) { Value rhsSqNorm = LLVM::FAddOp::create( rewriter, loc, LLVM::FMulOp::create(rewriter, loc, rhsRe, rhsRe, fmf), LLVM::FMulOp::create(rewriter, loc, rhsIm, rhsIm, fmf), fmf); Value realNumerator = LLVM::FAddOp::create( rewriter, loc, LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsRe, fmf), LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsIm, fmf), fmf); Value imagNumerator = LLVM::FSubOp::create( rewriter, loc, LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsRe, fmf), LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsIm, fmf), fmf); *resultRe = LLVM::FDivOp::create(rewriter, loc, realNumerator, rhsSqNorm, fmf); *resultIm = LLVM::FDivOp::create(rewriter, loc, imagNumerator, rhsSqNorm, fmf); } void mlir::complex::convertDivToStandardUsingAlgebraic( ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm, Value rhsRe, Value rhsIm, arith::FastMathFlagsAttr fmf, Value *resultRe, Value *resultIm) { Value rhsSqNorm = arith::AddFOp::create( rewriter, loc, arith::MulFOp::create(rewriter, loc, rhsRe, rhsRe, fmf), arith::MulFOp::create(rewriter, loc, rhsIm, rhsIm, fmf), fmf); Value realNumerator = arith::AddFOp::create( rewriter, loc, arith::MulFOp::create(rewriter, loc, lhsRe, rhsRe, fmf), arith::MulFOp::create(rewriter, loc, lhsIm, rhsIm, fmf), fmf); Value imagNumerator = arith::SubFOp::create( rewriter, loc, arith::MulFOp::create(rewriter, loc, lhsIm, rhsRe, fmf), arith::MulFOp::create(rewriter, loc, lhsRe, rhsIm, fmf), fmf); *resultRe = arith::DivFOp::create(rewriter, loc, realNumerator, rhsSqNorm, fmf); *resultIm = arith::DivFOp::create(rewriter, loc, imagNumerator, rhsSqNorm, fmf); } // Smith's algorithm to divide complex numbers. It is just a bit smarter // way to compute the following algebraic formula: // (lhsRe + lhsIm * i) / (rhsRe + rhsIm * i) // = (lhsRe + lhsIm * i) (rhsRe - rhsIm * i) / // ((rhsRe + rhsIm * i)(rhsRe - rhsIm * i)) // = ((lhsRe * rhsRe + lhsIm * rhsIm) + // (lhsIm * rhsRe - lhsRe * rhsIm) * i) / ||rhs||^2 // // Depending on whether |rhsRe| < |rhsIm| we compute either // rhsRealImagRatio = rhsRe / rhsIm // rhsRealImagDenom = rhsIm + rhsRe * rhsRealImagRatio // resultRe = (lhsRe * rhsRealImagRatio + lhsIm) / // rhsRealImagDenom // resultIm = (lhsIm * rhsRealImagRatio - lhsRe) / // rhsRealImagDenom // // or // // rhsImagRealRatio = rhsIm / rhsRe // rhsImagRealDenom = rhsRe + rhsIm * rhsImagRealRatio // resultRe = (lhsRe + lhsIm * rhsImagRealRatio) / // rhsImagRealDenom // resultIm = (lhsIm - lhsRe * rhsImagRealRatio) / // rhsImagRealDenom // // See https://dl.acm.org/citation.cfm?id=368661 for more details. void mlir::complex::convertDivToLLVMUsingRangeReduction( ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm, Value rhsRe, Value rhsIm, LLVM::FastmathFlagsAttr fmf, Value *resultRe, Value *resultIm) { auto elementType = cast(rhsRe.getType()); Value rhsRealImagRatio = LLVM::FDivOp::create(rewriter, loc, rhsRe, rhsIm, fmf); Value rhsRealImagDenom = LLVM::FAddOp::create( rewriter, loc, rhsIm, LLVM::FMulOp::create(rewriter, loc, rhsRealImagRatio, rhsRe, fmf), fmf); Value realNumerator1 = LLVM::FAddOp::create( rewriter, loc, LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsRealImagRatio, fmf), lhsIm, fmf); Value resultReal1 = LLVM::FDivOp::create(rewriter, loc, realNumerator1, rhsRealImagDenom, fmf); Value imagNumerator1 = LLVM::FSubOp::create( rewriter, loc, LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsRealImagRatio, fmf), lhsRe, fmf); Value resultImag1 = LLVM::FDivOp::create(rewriter, loc, imagNumerator1, rhsRealImagDenom, fmf); Value rhsImagRealRatio = LLVM::FDivOp::create(rewriter, loc, rhsIm, rhsRe, fmf); Value rhsImagRealDenom = LLVM::FAddOp::create( rewriter, loc, rhsRe, LLVM::FMulOp::create(rewriter, loc, rhsImagRealRatio, rhsIm, fmf), fmf); Value realNumerator2 = LLVM::FAddOp::create( rewriter, loc, lhsRe, LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsImagRealRatio, fmf), fmf); Value resultReal2 = LLVM::FDivOp::create(rewriter, loc, realNumerator2, rhsImagRealDenom, fmf); Value imagNumerator2 = LLVM::FSubOp::create( rewriter, loc, lhsIm, LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsImagRealRatio, fmf), fmf); Value resultImag2 = LLVM::FDivOp::create(rewriter, loc, imagNumerator2, rhsImagRealDenom, fmf); // Consider corner cases. // Case 1. Zero denominator, numerator contains at most one NaN value. Value zero = LLVM::ConstantOp::create(rewriter, loc, elementType, rewriter.getZeroAttr(elementType)); Value rhsRealAbs = LLVM::FAbsOp::create(rewriter, loc, rhsRe, fmf); Value rhsRealIsZero = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::oeq, rhsRealAbs, zero); Value rhsImagAbs = LLVM::FAbsOp::create(rewriter, loc, rhsIm, fmf); Value rhsImagIsZero = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::oeq, rhsImagAbs, zero); Value lhsRealIsNotNaN = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::ord, lhsRe, zero); Value lhsImagIsNotNaN = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::ord, lhsIm, zero); Value lhsContainsNotNaNValue = LLVM::OrOp::create(rewriter, loc, lhsRealIsNotNaN, lhsImagIsNotNaN); Value resultIsInfinity = LLVM::AndOp::create( rewriter, loc, lhsContainsNotNaNValue, LLVM::AndOp::create(rewriter, loc, rhsRealIsZero, rhsImagIsZero)); Value inf = LLVM::ConstantOp::create( rewriter, loc, elementType, rewriter.getFloatAttr(elementType, APFloat::getInf(elementType.getFloatSemantics()))); Value infWithSignOfrhsReal = LLVM::CopySignOp::create(rewriter, loc, inf, rhsRe); Value infinityResultReal = LLVM::FMulOp::create(rewriter, loc, infWithSignOfrhsReal, lhsRe, fmf); Value infinityResultImag = LLVM::FMulOp::create(rewriter, loc, infWithSignOfrhsReal, lhsIm, fmf); // Case 2. Infinite numerator, finite denominator. Value rhsRealFinite = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::one, rhsRealAbs, inf); Value rhsImagFinite = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::one, rhsImagAbs, inf); Value rhsFinite = LLVM::AndOp::create(rewriter, loc, rhsRealFinite, rhsImagFinite); Value lhsRealAbs = LLVM::FAbsOp::create(rewriter, loc, lhsRe, fmf); Value lhsRealInfinite = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::oeq, lhsRealAbs, inf); Value lhsImagAbs = LLVM::FAbsOp::create(rewriter, loc, lhsIm, fmf); Value lhsImagInfinite = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::oeq, lhsImagAbs, inf); Value lhsInfinite = LLVM::OrOp::create(rewriter, loc, lhsRealInfinite, lhsImagInfinite); Value infNumFiniteDenom = LLVM::AndOp::create(rewriter, loc, lhsInfinite, rhsFinite); Value one = LLVM::ConstantOp::create(rewriter, loc, elementType, rewriter.getFloatAttr(elementType, 1)); Value lhsRealIsInfWithSign = LLVM::CopySignOp::create( rewriter, loc, LLVM::SelectOp::create(rewriter, loc, lhsRealInfinite, one, zero), lhsRe); Value lhsImagIsInfWithSign = LLVM::CopySignOp::create( rewriter, loc, LLVM::SelectOp::create(rewriter, loc, lhsImagInfinite, one, zero), lhsIm); Value lhsRealIsInfWithSignTimesrhsReal = LLVM::FMulOp::create(rewriter, loc, lhsRealIsInfWithSign, rhsRe, fmf); Value lhsImagIsInfWithSignTimesrhsImag = LLVM::FMulOp::create(rewriter, loc, lhsImagIsInfWithSign, rhsIm, fmf); Value resultReal3 = LLVM::FMulOp::create( rewriter, loc, inf, LLVM::FAddOp::create(rewriter, loc, lhsRealIsInfWithSignTimesrhsReal, lhsImagIsInfWithSignTimesrhsImag, fmf), fmf); Value lhsRealIsInfWithSignTimesrhsImag = LLVM::FMulOp::create(rewriter, loc, lhsRealIsInfWithSign, rhsIm, fmf); Value lhsImagIsInfWithSignTimesrhsReal = LLVM::FMulOp::create(rewriter, loc, lhsImagIsInfWithSign, rhsRe, fmf); Value resultImag3 = LLVM::FMulOp::create( rewriter, loc, inf, LLVM::FSubOp::create(rewriter, loc, lhsImagIsInfWithSignTimesrhsReal, lhsRealIsInfWithSignTimesrhsImag, fmf), fmf); // Case 3: Finite numerator, infinite denominator. Value lhsRealFinite = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::one, lhsRealAbs, inf); Value lhsImagFinite = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::one, lhsImagAbs, inf); Value lhsFinite = LLVM::AndOp::create(rewriter, loc, lhsRealFinite, lhsImagFinite); Value rhsRealInfinite = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::oeq, rhsRealAbs, inf); Value rhsImagInfinite = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::oeq, rhsImagAbs, inf); Value rhsInfinite = LLVM::OrOp::create(rewriter, loc, rhsRealInfinite, rhsImagInfinite); Value finiteNumInfiniteDenom = LLVM::AndOp::create(rewriter, loc, lhsFinite, rhsInfinite); Value rhsRealIsInfWithSign = LLVM::CopySignOp::create( rewriter, loc, LLVM::SelectOp::create(rewriter, loc, rhsRealInfinite, one, zero), rhsRe); Value rhsImagIsInfWithSign = LLVM::CopySignOp::create( rewriter, loc, LLVM::SelectOp::create(rewriter, loc, rhsImagInfinite, one, zero), rhsIm); Value rhsRealIsInfWithSignTimeslhsReal = LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsRealIsInfWithSign, fmf); Value rhsImagIsInfWithSignTimeslhsImag = LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsImagIsInfWithSign, fmf); Value resultReal4 = LLVM::FMulOp::create( rewriter, loc, zero, LLVM::FAddOp::create(rewriter, loc, rhsRealIsInfWithSignTimeslhsReal, rhsImagIsInfWithSignTimeslhsImag, fmf), fmf); Value rhsRealIsInfWithSignTimeslhsImag = LLVM::FMulOp::create(rewriter, loc, lhsIm, rhsRealIsInfWithSign, fmf); Value rhsImagIsInfWithSignTimeslhsReal = LLVM::FMulOp::create(rewriter, loc, lhsRe, rhsImagIsInfWithSign, fmf); Value resultImag4 = LLVM::FMulOp::create( rewriter, loc, zero, LLVM::FSubOp::create(rewriter, loc, rhsRealIsInfWithSignTimeslhsImag, rhsImagIsInfWithSignTimeslhsReal, fmf), fmf); Value realAbsSmallerThanImagAbs = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::olt, rhsRealAbs, rhsImagAbs); Value resultReal5 = LLVM::SelectOp::create( rewriter, loc, realAbsSmallerThanImagAbs, resultReal1, resultReal2); Value resultImag5 = LLVM::SelectOp::create( rewriter, loc, realAbsSmallerThanImagAbs, resultImag1, resultImag2); Value resultRealSpecialCase3 = LLVM::SelectOp::create( rewriter, loc, finiteNumInfiniteDenom, resultReal4, resultReal5); Value resultImagSpecialCase3 = LLVM::SelectOp::create( rewriter, loc, finiteNumInfiniteDenom, resultImag4, resultImag5); Value resultRealSpecialCase2 = LLVM::SelectOp::create( rewriter, loc, infNumFiniteDenom, resultReal3, resultRealSpecialCase3); Value resultImagSpecialCase2 = LLVM::SelectOp::create( rewriter, loc, infNumFiniteDenom, resultImag3, resultImagSpecialCase3); Value resultRealSpecialCase1 = LLVM::SelectOp::create(rewriter, loc, resultIsInfinity, infinityResultReal, resultRealSpecialCase2); Value resultImagSpecialCase1 = LLVM::SelectOp::create(rewriter, loc, resultIsInfinity, infinityResultImag, resultImagSpecialCase2); Value resultRealIsNaN = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::uno, resultReal5, zero); Value resultImagIsNaN = LLVM::FCmpOp::create( rewriter, loc, LLVM::FCmpPredicate::uno, resultImag5, zero); Value resultIsNaN = LLVM::AndOp::create(rewriter, loc, resultRealIsNaN, resultImagIsNaN); *resultRe = LLVM::SelectOp::create(rewriter, loc, resultIsNaN, resultRealSpecialCase1, resultReal5); *resultIm = LLVM::SelectOp::create(rewriter, loc, resultIsNaN, resultImagSpecialCase1, resultImag5); } void mlir::complex::convertDivToStandardUsingRangeReduction( ConversionPatternRewriter &rewriter, Location loc, Value lhsRe, Value lhsIm, Value rhsRe, Value rhsIm, arith::FastMathFlagsAttr fmf, Value *resultRe, Value *resultIm) { auto elementType = cast(rhsRe.getType()); Value rhsRealImagRatio = arith::DivFOp::create(rewriter, loc, rhsRe, rhsIm, fmf); Value rhsRealImagDenom = arith::AddFOp::create( rewriter, loc, rhsIm, arith::MulFOp::create(rewriter, loc, rhsRealImagRatio, rhsRe, fmf), fmf); Value realNumerator1 = arith::AddFOp::create( rewriter, loc, arith::MulFOp::create(rewriter, loc, lhsRe, rhsRealImagRatio, fmf), lhsIm, fmf); Value resultReal1 = arith::DivFOp::create(rewriter, loc, realNumerator1, rhsRealImagDenom, fmf); Value imagNumerator1 = arith::SubFOp::create( rewriter, loc, arith::MulFOp::create(rewriter, loc, lhsIm, rhsRealImagRatio, fmf), lhsRe, fmf); Value resultImag1 = arith::DivFOp::create(rewriter, loc, imagNumerator1, rhsRealImagDenom, fmf); Value rhsImagRealRatio = arith::DivFOp::create(rewriter, loc, rhsIm, rhsRe, fmf); Value rhsImagRealDenom = arith::AddFOp::create( rewriter, loc, rhsRe, arith::MulFOp::create(rewriter, loc, rhsImagRealRatio, rhsIm, fmf), fmf); Value realNumerator2 = arith::AddFOp::create( rewriter, loc, lhsRe, arith::MulFOp::create(rewriter, loc, lhsIm, rhsImagRealRatio, fmf), fmf); Value resultReal2 = arith::DivFOp::create(rewriter, loc, realNumerator2, rhsImagRealDenom, fmf); Value imagNumerator2 = arith::SubFOp::create( rewriter, loc, lhsIm, arith::MulFOp::create(rewriter, loc, lhsRe, rhsImagRealRatio, fmf), fmf); Value resultImag2 = arith::DivFOp::create(rewriter, loc, imagNumerator2, rhsImagRealDenom, fmf); // Consider corner cases. // Case 1. Zero denominator, numerator contains at most one NaN value. Value zero = arith::ConstantOp::create(rewriter, loc, elementType, rewriter.getZeroAttr(elementType)); Value rhsRealAbs = math::AbsFOp::create(rewriter, loc, rhsRe, fmf); Value rhsRealIsZero = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::OEQ, rhsRealAbs, zero); Value rhsImagAbs = math::AbsFOp::create(rewriter, loc, rhsIm, fmf); Value rhsImagIsZero = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::OEQ, rhsImagAbs, zero); Value lhsRealIsNotNaN = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::ORD, lhsRe, zero); Value lhsImagIsNotNaN = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::ORD, lhsIm, zero); Value lhsContainsNotNaNValue = arith::OrIOp::create(rewriter, loc, lhsRealIsNotNaN, lhsImagIsNotNaN); Value resultIsInfinity = arith::AndIOp::create( rewriter, loc, lhsContainsNotNaNValue, arith::AndIOp::create(rewriter, loc, rhsRealIsZero, rhsImagIsZero)); Value inf = arith::ConstantOp::create( rewriter, loc, elementType, rewriter.getFloatAttr(elementType, APFloat::getInf(elementType.getFloatSemantics()))); Value infWithSignOfRhsReal = math::CopySignOp::create(rewriter, loc, inf, rhsRe); Value infinityResultReal = arith::MulFOp::create(rewriter, loc, infWithSignOfRhsReal, lhsRe, fmf); Value infinityResultImag = arith::MulFOp::create(rewriter, loc, infWithSignOfRhsReal, lhsIm, fmf); // Case 2. Infinite numerator, finite denominator. Value rhsRealFinite = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::ONE, rhsRealAbs, inf); Value rhsImagFinite = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::ONE, rhsImagAbs, inf); Value rhsFinite = arith::AndIOp::create(rewriter, loc, rhsRealFinite, rhsImagFinite); Value lhsRealAbs = math::AbsFOp::create(rewriter, loc, lhsRe, fmf); Value lhsRealInfinite = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::OEQ, lhsRealAbs, inf); Value lhsImagAbs = math::AbsFOp::create(rewriter, loc, lhsIm, fmf); Value lhsImagInfinite = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::OEQ, lhsImagAbs, inf); Value lhsInfinite = arith::OrIOp::create(rewriter, loc, lhsRealInfinite, lhsImagInfinite); Value infNumFiniteDenom = arith::AndIOp::create(rewriter, loc, lhsInfinite, rhsFinite); Value one = arith::ConstantOp::create(rewriter, loc, elementType, rewriter.getFloatAttr(elementType, 1)); Value lhsRealIsInfWithSign = math::CopySignOp::create( rewriter, loc, arith::SelectOp::create(rewriter, loc, lhsRealInfinite, one, zero), lhsRe); Value lhsImagIsInfWithSign = math::CopySignOp::create( rewriter, loc, arith::SelectOp::create(rewriter, loc, lhsImagInfinite, one, zero), lhsIm); Value lhsRealIsInfWithSignTimesRhsReal = arith::MulFOp::create(rewriter, loc, lhsRealIsInfWithSign, rhsRe, fmf); Value lhsImagIsInfWithSignTimesRhsImag = arith::MulFOp::create(rewriter, loc, lhsImagIsInfWithSign, rhsIm, fmf); Value resultReal3 = arith::MulFOp::create( rewriter, loc, inf, arith::AddFOp::create(rewriter, loc, lhsRealIsInfWithSignTimesRhsReal, lhsImagIsInfWithSignTimesRhsImag, fmf), fmf); Value lhsRealIsInfWithSignTimesRhsImag = arith::MulFOp::create(rewriter, loc, lhsRealIsInfWithSign, rhsIm, fmf); Value lhsImagIsInfWithSignTimesRhsReal = arith::MulFOp::create(rewriter, loc, lhsImagIsInfWithSign, rhsRe, fmf); Value resultImag3 = arith::MulFOp::create( rewriter, loc, inf, arith::SubFOp::create(rewriter, loc, lhsImagIsInfWithSignTimesRhsReal, lhsRealIsInfWithSignTimesRhsImag, fmf), fmf); // Case 3: Finite numerator, infinite denominator. Value lhsRealFinite = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::ONE, lhsRealAbs, inf); Value lhsImagFinite = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::ONE, lhsImagAbs, inf); Value lhsFinite = arith::AndIOp::create(rewriter, loc, lhsRealFinite, lhsImagFinite); Value rhsRealInfinite = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::OEQ, rhsRealAbs, inf); Value rhsImagInfinite = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::OEQ, rhsImagAbs, inf); Value rhsInfinite = arith::OrIOp::create(rewriter, loc, rhsRealInfinite, rhsImagInfinite); Value finiteNumInfiniteDenom = arith::AndIOp::create(rewriter, loc, lhsFinite, rhsInfinite); Value rhsRealIsInfWithSign = math::CopySignOp::create( rewriter, loc, arith::SelectOp::create(rewriter, loc, rhsRealInfinite, one, zero), rhsRe); Value rhsImagIsInfWithSign = math::CopySignOp::create( rewriter, loc, arith::SelectOp::create(rewriter, loc, rhsImagInfinite, one, zero), rhsIm); Value rhsRealIsInfWithSignTimesLhsReal = arith::MulFOp::create(rewriter, loc, lhsRe, rhsRealIsInfWithSign, fmf); Value rhsImagIsInfWithSignTimesLhsImag = arith::MulFOp::create(rewriter, loc, lhsIm, rhsImagIsInfWithSign, fmf); Value resultReal4 = arith::MulFOp::create( rewriter, loc, zero, arith::AddFOp::create(rewriter, loc, rhsRealIsInfWithSignTimesLhsReal, rhsImagIsInfWithSignTimesLhsImag, fmf), fmf); Value rhsRealIsInfWithSignTimesLhsImag = arith::MulFOp::create(rewriter, loc, lhsIm, rhsRealIsInfWithSign, fmf); Value rhsImagIsInfWithSignTimesLhsReal = arith::MulFOp::create(rewriter, loc, lhsRe, rhsImagIsInfWithSign, fmf); Value resultImag4 = arith::MulFOp::create( rewriter, loc, zero, arith::SubFOp::create(rewriter, loc, rhsRealIsInfWithSignTimesLhsImag, rhsImagIsInfWithSignTimesLhsReal, fmf), fmf); Value realAbsSmallerThanImagAbs = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::OLT, rhsRealAbs, rhsImagAbs); Value resultReal5 = arith::SelectOp::create( rewriter, loc, realAbsSmallerThanImagAbs, resultReal1, resultReal2); Value resultImag5 = arith::SelectOp::create( rewriter, loc, realAbsSmallerThanImagAbs, resultImag1, resultImag2); Value resultRealSpecialCase3 = arith::SelectOp::create( rewriter, loc, finiteNumInfiniteDenom, resultReal4, resultReal5); Value resultImagSpecialCase3 = arith::SelectOp::create( rewriter, loc, finiteNumInfiniteDenom, resultImag4, resultImag5); Value resultRealSpecialCase2 = arith::SelectOp::create( rewriter, loc, infNumFiniteDenom, resultReal3, resultRealSpecialCase3); Value resultImagSpecialCase2 = arith::SelectOp::create( rewriter, loc, infNumFiniteDenom, resultImag3, resultImagSpecialCase3); Value resultRealSpecialCase1 = arith::SelectOp::create(rewriter, loc, resultIsInfinity, infinityResultReal, resultRealSpecialCase2); Value resultImagSpecialCase1 = arith::SelectOp::create(rewriter, loc, resultIsInfinity, infinityResultImag, resultImagSpecialCase2); Value resultRealIsNaN = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::UNO, resultReal5, zero); Value resultImagIsNaN = arith::CmpFOp::create( rewriter, loc, arith::CmpFPredicate::UNO, resultImag5, zero); Value resultIsNaN = arith::AndIOp::create(rewriter, loc, resultRealIsNaN, resultImagIsNaN); *resultRe = arith::SelectOp::create(rewriter, loc, resultIsNaN, resultRealSpecialCase1, resultReal5); *resultIm = arith::SelectOp::create(rewriter, loc, resultIsNaN, resultImagSpecialCase1, resultImag5); }