blob: 14fbb9bf09545ffd2433090925c2c199af34261f [file] [log] [blame]
//===- 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<FloatType>(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<FloatType>(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);
}