//===- llvm/Support/KnownFPClass.h - Stores known fplcass -------*- C++ -*-===//
//
// 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 contains a class for representing known fpclasses used by
// computeKnownFPClass.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/KnownFPClass.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"

using namespace llvm;

KnownFPClass::KnownFPClass(const APFloat &C)
    : KnownFPClassesValue(C.classify()) {
  setSignBit(C.isNegative());
}

/// Return true if it's possible to assume IEEE treatment of input denormals in
/// \p F for \p Val.
static bool inputDenormalIsIEEE(DenormalMode Mode) {
  return Mode.Input == DenormalMode::IEEE;
}

static bool inputDenormalIsIEEEOrPosZero(DenormalMode Mode) {
  return Mode.Input == DenormalMode::IEEE ||
         Mode.Input == DenormalMode::PositiveZero;
}

bool KnownFPClass::isKnownNeverLogicalZero(DenormalMode Mode) const {
  return isKnownNeverZero() &&
         (isKnownNeverSubnormal() || inputDenormalIsIEEE(Mode));
}

bool KnownFPClass::isKnownNeverLogicalNegZero(DenormalMode Mode) const {
  return isKnownNeverNegZero() &&
         (isKnownNeverNegSubnormal() || inputDenormalIsIEEEOrPosZero(Mode));
}

bool KnownFPClass::isKnownNeverLogicalPosZero(DenormalMode Mode) const {
  if (!isKnownNeverPosZero())
    return false;

  // If we know there are no denormals, nothing can be flushed to zero.
  if (isKnownNeverSubnormal())
    return true;

  switch (Mode.Input) {
  case DenormalMode::IEEE:
    return true;
  case DenormalMode::PreserveSign:
    // Negative subnormal won't flush to +0
    return isKnownNeverPosSubnormal();
  case DenormalMode::PositiveZero:
  default:
    // Both positive and negative subnormal could flush to +0
    return false;
  }

  llvm_unreachable("covered switch over denormal mode");
}

void KnownFPClass::propagateDenormal(const KnownFPClass &Src,
                                     DenormalMode Mode) {
  setKnownFPClasses(Src.getKnownFPClasses());
  // If we aren't assuming the source can't be a zero, we don't have to check if
  // a denormal input could be flushed.
  if (!Src.isKnownNeverPosZero() && !Src.isKnownNeverNegZero())
    return;

  // If we know the input can't be a denormal, it can't be flushed to 0.
  if (Src.isKnownNeverSubnormal())
    return;

  if (!Src.isKnownNeverPosSubnormal() && Mode != DenormalMode::getIEEE())
    setKnownFPClasses(getKnownFPClasses() | fcPosZero);

  if (!Src.isKnownNeverNegSubnormal() && Mode != DenormalMode::getIEEE()) {
    if (Mode != DenormalMode::getPositiveZero())
      setKnownFPClasses(getKnownFPClasses() | fcNegZero);

    if (Mode.Input == DenormalMode::PositiveZero ||
        Mode.Output == DenormalMode::PositiveZero ||
        Mode.Input == DenormalMode::Dynamic ||
        Mode.Output == DenormalMode::Dynamic)
      setKnownFPClasses(getKnownFPClasses() | fcPosZero);
  }
}

KnownFPClass KnownFPClass::minMaxLike(const KnownFPClass &LHS_,
                                      const KnownFPClass &RHS_, MinMaxKind Kind,
                                      DenormalMode Mode) {
  KnownFPClass KnownLHS = LHS_;
  KnownFPClass KnownRHS = RHS_;

  bool NeverNaN = KnownLHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNaN();
  KnownFPClass Known = KnownLHS | KnownRHS;

  // If either operand is not NaN, the result is not NaN.
  if (NeverNaN &&
      (Kind == MinMaxKind::minnum || Kind == MinMaxKind::maxnum ||
       Kind == MinMaxKind::minimumnum || Kind == MinMaxKind::maximumnum))
    Known.knownNot(fcNan);

  if (Kind == MinMaxKind::maxnum || Kind == MinMaxKind::maximumnum) {
    if (KnownLHS.isKnownNeverNaN())
      Known.knownNot(orderedStrictlyLess(KnownLHS.getKnownFPClasses()));
    if (KnownRHS.isKnownNeverNaN())
      Known.knownNot(orderedStrictlyLess(KnownRHS.getKnownFPClasses()));
  } else if (Kind == MinMaxKind::maximum) {
    Known.knownNot(orderedStrictlyLess(KnownLHS.getKnownFPClasses()) |
                   orderedStrictlyLess(KnownRHS.getKnownFPClasses()));
  } else if (Kind == MinMaxKind::minnum || Kind == MinMaxKind::minimumnum) {
    if (KnownLHS.isKnownNeverNaN())
      Known.knownNot(orderedStrictlyGreater(KnownLHS.getKnownFPClasses()));
    if (KnownRHS.isKnownNeverNaN())
      Known.knownNot(orderedStrictlyGreater(KnownRHS.getKnownFPClasses()));
  } else if (Kind == MinMaxKind::minimum) {
    Known.knownNot(orderedStrictlyGreater(KnownLHS.getKnownFPClasses()) |
                   orderedStrictlyGreater(KnownRHS.getKnownFPClasses()));
  } else
    llvm_unreachable("unhandled intrinsic");

  // Fixup zero handling if denormals could be returned as a zero.
  //
  // As there's no spec for denormal flushing, be conservative with the
  // treatment of denormals that could be flushed to zero. For older
  // subtargets on AMDGPU the min/max instructions would not flush the
  // output and return the original value.
  //
  if ((Known.getKnownFPClasses() & fcZero) != fcNone &&
      !Known.isKnownNeverSubnormal()) {
    if (Mode != DenormalMode::getIEEE())
      Known.setKnownFPClasses(Known.getKnownFPClasses() | fcZero);
  }

  if (Known.isKnownNeverNaN()) {
    if (KnownLHS.getSignBit() && KnownRHS.getSignBit() &&
        *KnownLHS.getSignBit() == *KnownRHS.getSignBit()) {
      if (*KnownLHS.getSignBit())
        Known.signBitMustBeOne();
      else
        Known.signBitMustBeZero();
    } else if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::minimum ||
                Kind == MinMaxKind::maximumnum ||
                Kind == MinMaxKind::minimumnum) ||
               // FIXME: Should be using logical zero versions
               ((KnownLHS.isKnownNeverNegZero() ||
                 KnownRHS.isKnownNeverPosZero()) &&
                (KnownLHS.isKnownNeverPosZero() ||
                 KnownRHS.isKnownNeverNegZero()))) {
      // Don't take sign bit from NaN operands.
      if (!KnownLHS.isKnownNeverNaN())
        KnownLHS.setSignBit(std::nullopt);
      if (!KnownRHS.isKnownNeverNaN())
        KnownRHS.setSignBit(std::nullopt);
      if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::maximumnum ||
           Kind == MinMaxKind::maxnum) &&
          (KnownLHS.getSignBit() == false || KnownRHS.getSignBit() == false))
        Known.signBitMustBeZero();
      else if ((Kind == MinMaxKind::minimum || Kind == MinMaxKind::minimumnum ||
                Kind == MinMaxKind::minnum) &&
               (KnownLHS.getSignBit() == true || KnownRHS.getSignBit() == true))
        Known.signBitMustBeOne();
    }
  }

  return Known;
}

KnownFPClass KnownFPClass::canonicalize(const KnownFPClass &KnownSrc,
                                        DenormalMode DenormMode) {
  KnownFPClass Known;

  // This is essentially a stronger form of
  // propagateCanonicalizingSrc. Other "canonicalizing" operations don't
  // actually have an IR canonicalization guarantee.

  // Canonicalize may flush denormals to zero, so we have to consider the
  // denormal mode to preserve known-not-0 knowledge.
  Known.setKnownFPClasses(KnownSrc.getKnownFPClasses() | fcZero | fcQNan);

  // Stronger version of propagateNaN
  // Canonicalize is guaranteed to quiet signaling nans.
  if (KnownSrc.isKnownNeverNaN())
    Known.knownNot(fcNan);
  else
    Known.knownNot(fcSNan);

  // FIXME: Missing check of IEEE like types.

  // If the parent function flushes denormals, the canonical output cannot be a
  // denormal.
  if (DenormMode == DenormalMode::getIEEE()) {
    if (KnownSrc.isKnownNever(fcPosZero))
      Known.knownNot(fcPosZero);
    if (KnownSrc.isKnownNever(fcNegZero))
      Known.knownNot(fcNegZero);
    return Known;
  }

  if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero())
    Known.knownNot(fcSubnormal);

  if (DenormMode == DenormalMode::getPreserveSign()) {
    if (KnownSrc.isKnownNever(fcPosZero | fcPosSubnormal))
      Known.knownNot(fcPosZero);
    if (KnownSrc.isKnownNever(fcNegZero | fcNegSubnormal))
      Known.knownNot(fcNegZero);
    return Known;
  }

  if (DenormMode.Input == DenormalMode::PositiveZero ||
      (DenormMode.Output == DenormalMode::PositiveZero &&
       DenormMode.Input == DenormalMode::IEEE)) {
    // -0.0 is not a subnormal and should not be flushed.
    if (KnownSrc.isKnownNever(fcNegZero))
      Known.knownNot(fcNegZero);

    if (KnownSrc.isKnownNever(fcPosZero | fcSubnormal))
      Known.knownNot(fcPosZero);
  }

  return Known;
}

KnownFPClass KnownFPClass::bitcast(const fltSemantics &FltSemantics,
                                   const KnownBits &Bits) {
  assert(FltSemantics.sizeInBits == Bits.getBitWidth() &&
         "Bitcast operand has incorrect bit width");
  KnownFPClass Known;

  // Conflicting known bits do not describe a concrete value. Return unknown.
  if (Bits.hasConflict())
    return Known;

  // Return unknown for types we have not validated.
  auto IsSupported = [](const fltSemantics &Semantics) {
    switch (APFloat::SemanticsToEnum(Semantics)) {
    case APFloatBase::S_IEEEhalf:
    case APFloatBase::S_BFloat:
    case APFloatBase::S_IEEEsingle:
    case APFloatBase::S_IEEEdouble:
    case APFloatBase::S_IEEEquad:
    case APFloatBase::S_x87DoubleExtended:
      return true;
    default:
      return false;
    }
  };
  if (!IsSupported(FltSemantics))
    return Known;

  // Transfer information from the sign bit.
  if (Bits.isNonNegative())
    Known.signBitMustBeZero();
  else if (Bits.isNegative())
    Known.signBitMustBeOne();

  if (APFloat::isIEEELikeFP(FltSemantics)) {
    const unsigned MantissaBits = FltSemantics.precision - 1;
    const APInt ExponentMask = APInt::getBitsSet(
        FltSemantics.sizeInBits, MantissaBits, FltSemantics.sizeInBits - 1);
    const APInt MantissaMask =
        APInt::getLowBitsSet(FltSemantics.sizeInBits, MantissaBits);

    const bool ExponentKnownAllZeros =
        (Bits.Zero & ExponentMask) == ExponentMask;
    const bool ExponentKnownAllOnes = (Bits.One & ExponentMask) == ExponentMask;
    const bool ExponentKnownNotAllZeros = !(Bits.One & ExponentMask).isZero();
    const bool ExponentKnownNotAllOnes = !(Bits.Zero & ExponentMask).isZero();

    const bool MantissaKnownAllZeros =
        (Bits.Zero & MantissaMask) == MantissaMask;
    const bool MantissaKnownNotAllZeros = !(Bits.One & MantissaMask).isZero();

    // Zero and subnormal require an exponent with all zero bits.
    if (ExponentKnownNotAllZeros)
      Known.knownNot(fcZero | fcSubnormal);

    // Infinity and NaN require an exponent with all one bits.
    if (ExponentKnownNotAllOnes)
      Known.knownNot(fcInf | fcNan);

    // Normal values have an exponent that is not all zeros or all ones.
    if (ExponentKnownAllZeros || ExponentKnownAllOnes)
      Known.knownNot(fcNormal);

    // Zero and infinity require a mantissa with all zero bits.
    if (MantissaKnownNotAllZeros)
      Known.knownNot(fcZero | fcInf);

    // Subnormal and NaN require a non-zero mantissa.
    if (MantissaKnownAllZeros)
      Known.knownNot(fcSubnormal | fcNan);

    const bool QuietBitKnownSet = Bits.One[MantissaBits - 1];
    const bool QuietBitKnownClear = Bits.Zero[MantissaBits - 1];

    if (QuietBitKnownSet)
      Known.knownNot(fcSNan);
    else if (QuietBitKnownClear)
      Known.knownNot(fcQNan);
  }

  return Known;
}

KnownBits KnownFPClass::toKnownBits(const fltSemantics &FltSemantics) const {
  KnownBits Known(FltSemantics.sizeInBits);
  const FPClassTest FPClasses = getKnownFPClasses();

  // Return unknown if poison.
  if (FPClasses == fcNone)
    return Known;

  // Return unknown for types we have not validated.
  auto IsSupported = [](const fltSemantics &Semantics) {
    switch (APFloat::SemanticsToEnum(Semantics)) {
    case APFloatBase::S_IEEEhalf:
    case APFloatBase::S_BFloat:
    case APFloatBase::S_IEEEsingle:
    case APFloatBase::S_IEEEdouble:
    case APFloatBase::S_IEEEquad:
    case APFloatBase::S_x87DoubleExtended:
      return true;
    default:
      return false;
    }
  };
  if (!IsSupported(FltSemantics))
    return Known;

  if (isKnownNever(fcNormal | fcSubnormal | fcNan)) {
    Known.setAllConflict();

    if (FPClasses & fcInf)
      Known = Known.intersectWith(KnownBits::makeConstant(
          APFloat::getInf(FltSemantics).bitcastToAPInt()));

    if (FPClasses & fcZero)
      Known = Known.intersectWith(
          KnownBits::makeConstant(APInt::getZero(FltSemantics.sizeInBits)));

    Known.Zero.clearSignBit();
    Known.One.clearSignBit();
  }

  if (std::optional<bool> Sign = getSignBit()) {
    if (*Sign)
      Known.makeNegative();
    else
      Known.makeNonNegative();
  }

  return Known;
}

// Handle known sign bit and nan cases for fadd.
static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS,
                              const KnownFPClass &KnownRHS, DenormalMode Mode) {
  KnownFPClass Known;

  // Adding positive and negative infinity produces NaN, but only if both
  // opposite-sign infinity combinations are possible.
  if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
      (KnownLHS.isKnownNever(fcPosInf) || KnownRHS.isKnownNever(fcNegInf)) &&
      (KnownLHS.isKnownNever(fcNegInf) || KnownRHS.isKnownNever(fcPosInf)))
    Known.knownNot(fcNan);

  if (KnownLHS.cannotBeOrderedLessThanZero() &&
      KnownRHS.cannotBeOrderedLessThanZero()) {
    Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);

    // This can't underflow if one of the operands is known normal.
    if (KnownLHS.isKnownNever(fcZero | fcPosSubnormal) ||
        KnownRHS.isKnownNever(fcZero | fcPosSubnormal))
      Known.knownNot(fcZero | fcPosSubnormal);
  }

  if (KnownLHS.cannotBeOrderedGreaterThanZero() &&
      KnownRHS.cannotBeOrderedGreaterThanZero()) {
    Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask);

    // This can't underflow if one of the operands is known normal.
    if (KnownLHS.isKnownNever(fcZero | fcNegSubnormal) ||
        KnownRHS.isKnownNever(fcZero | fcNegSubnormal))
      Known.knownNot(fcZero | fcNegSubnormal);
  }

  return Known;
}

KnownFPClass KnownFPClass::fadd(const KnownFPClass &KnownLHS,
                                const KnownFPClass &KnownRHS,
                                DenormalMode Mode) {
  KnownFPClass Known = fadd_impl(KnownLHS, KnownRHS, Mode);

  // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
  if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
       KnownRHS.isKnownNeverLogicalNegZero(Mode)) &&
      // Make sure output negative denormal can't flush to -0
      (Mode.Output == DenormalMode::IEEE ||
       Mode.Output == DenormalMode::PositiveZero))
    Known.knownNot(fcNegZero);

  Known.propagateNonSNaN(KnownLHS, KnownRHS);

  return Known;
}

KnownFPClass KnownFPClass::fadd_self(const KnownFPClass &KnownSrc,
                                     DenormalMode Mode) {
  KnownFPClass Known = fadd(KnownSrc, KnownSrc, Mode);

  // Doubling 0 will give the same 0.
  if (KnownSrc.isKnownNeverLogicalPosZero(Mode) &&
      (Mode.Output == DenormalMode::IEEE ||
       (Mode.Output == DenormalMode::PreserveSign &&
        KnownSrc.isKnownNeverPosSubnormal()) ||
       (Mode.Output == DenormalMode::PositiveZero &&
        KnownSrc.isKnownNeverSubnormal())))
    Known.knownNot(fcPosZero);

  return Known;
}

KnownFPClass KnownFPClass::fsub(const KnownFPClass &KnownLHS,
                                const KnownFPClass &KnownRHS,
                                DenormalMode Mode) {
  return fadd(KnownLHS, fneg(KnownRHS), Mode);
}

KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS,
                                const KnownFPClass &KnownRHS,
                                DenormalMode Mode) {
  KnownFPClass Known;

  Known.propagateNonSNaN(KnownLHS, KnownRHS);

  // +X * +Y or -X * -Y => +Q
  // +X * -Y or -X * +Y => -Q
  Known.propagateXorSign(KnownLHS, KnownRHS);

  // Inf * Y => Inf or NaN
  if (KnownLHS.isKnownAlways(fcInf | fcNan) ||
      KnownRHS.isKnownAlways(fcInf | fcNan))
    Known.knownNot(fcNormal | fcSubnormal | fcZero);

  // 0 * Y => 0 or NaN
  if (KnownRHS.isKnownAlways(fcZero | fcNan) ||
      KnownLHS.isKnownAlways(fcZero | fcNan))
    Known.knownNot(fcNormal | fcSubnormal | fcInf);

  if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
    return Known;

  // 0 * +/-inf => NaN
  if ((KnownRHS.isKnownNeverInfinity() ||
       KnownLHS.isKnownNeverLogicalZero(Mode)) &&
      (KnownLHS.isKnownNeverInfinity() ||
       KnownRHS.isKnownNeverLogicalZero(Mode)))
    Known.knownNot(fcNan);

  return Known;
}

// TODO: This generalizes to known ranges
KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS,
                                const APFloat &CRHS, DenormalMode Mode) {
  // Match denormal scaling pattern, similar to the case in ldexp. If the
  // constant's exponent is sufficiently large, the result cannot be subnormal.

  const fltSemantics &Flt = CRHS.getSemantics();
  unsigned Precision = APFloat::semanticsPrecision(Flt);
  const int MantissaBits = Precision - 1;

  int MinKnownExponent = ilogb(CRHS);
  bool CannotBeSubnormal = (MinKnownExponent >= MantissaBits);

  KnownFPClass Known = KnownFPClass::fmul(KnownLHS, KnownFPClass(CRHS), Mode);
  if (CannotBeSubnormal)
    Known.knownNot(fcSubnormal);

  // Multiply of values <= 1 cannot introduce overflow.
  if (KnownLHS.isKnownNever(fcInf)) {
    if (MinKnownExponent < 0)
      Known.knownNot(fcInf);
    else if (MinKnownExponent == 0 && CRHS.compareAbsoluteValue(APFloat::getOne(
                                          Flt)) == APFloat::cmpEqual)
      Known.knownNot(fcInf);
  }

  return Known;
}

KnownFPClass KnownFPClass::fdiv(const KnownFPClass &KnownLHS,
                                const KnownFPClass &KnownRHS,
                                DenormalMode Mode) {
  KnownFPClass Known;

  Known.propagateNonSNaN(KnownLHS, KnownRHS);

  // Only 0/0, Inf/Inf produce NaN.
  if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
      (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
      (KnownLHS.isKnownNeverLogicalZero(Mode) ||
       KnownRHS.isKnownNeverLogicalZero(Mode))) {
    Known.knownNot(fcNan);
  }

  //  X / -0.0 => -Inf (or NaN)
  // +X / +Y or -X / -Y => +Q
  // +X / -Y or -X / +Y => -Q
  Known.propagateXorSign(KnownLHS, KnownRHS);

  // Normal and subnormal results require two non-zero finite operands.
  if ((KnownLHS.isKnownNever(fcNegNormal | fcNegSubnormal) &&
       KnownRHS.isKnownNever(fcNegNormal | fcNegSubnormal)) ||
      (KnownLHS.isKnownNever(fcPosNormal | fcPosSubnormal) &&
       KnownRHS.isKnownNever(fcPosNormal | fcPosSubnormal)))
    Known.knownNot(fcNegNormal | fcNegSubnormal);
  if ((KnownLHS.isKnownNever(fcNegNormal | fcNegSubnormal) &&
       KnownRHS.isKnownNever(fcPosNormal | fcPosSubnormal)) ||
      (KnownLHS.isKnownNever(fcPosNormal | fcPosSubnormal) &&
       KnownRHS.isKnownNever(fcNegNormal | fcNegSubnormal)))
    Known.knownNot(fcPosNormal | fcPosSubnormal);

  // 0 / X => 0 or NaN
  if (KnownLHS.isKnownAlways(fcZero))
    Known.knownNot(fcSubnormal | fcNormal | fcInf);

  // X / 0 => NaN or Inf
  if (KnownRHS.isKnownAlways(fcZero))
    Known.knownNot(fcFinite);

  return Known;
}

KnownFPClass KnownFPClass::fdiv_self(const KnownFPClass &KnownSrc,
                                     DenormalMode Mode) {
  // X / X is always exactly 1.0 or a NaN.
  KnownFPClass Known(fcNan | fcPosNormal);

  Known.propagateNonSNaN(KnownSrc);

  if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
    Known.knownNot(fcNan);

  return Known;
}

KnownFPClass KnownFPClass::frem(const KnownFPClass &KnownLHS,
                                const KnownFPClass &KnownRHS,
                                DenormalMode Mode) {
  KnownFPClass Known;

  Known.knownNot(fcInf);

  // Inf REM x and x REM 0 produce NaN.
  if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
      KnownLHS.isKnownNeverInfinity() &&
      KnownRHS.isKnownNeverLogicalZero(Mode)) {
    Known.knownNot(fcNan);
  }

  // The sign for frem is the same as the first operand.
  if (KnownLHS.cannotBeOrderedLessThanZero())
    Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
  if (KnownLHS.cannotBeOrderedGreaterThanZero())
    Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask);

  // See if we can be more aggressive about the sign of 0.
  if (KnownLHS.isKnownNever(fcNegative))
    Known.knownNot(fcNegative);
  if (KnownLHS.isKnownNever(fcPositive))
    Known.knownNot(fcPositive);

  return Known;
}

KnownFPClass KnownFPClass::frem_self(const KnownFPClass &KnownSrc,
                                     DenormalMode Mode) {
  // X % X is always exactly [+-]0.0 or a NaN.
  KnownFPClass Known(fcNan | fcZero);

  if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
    Known.knownNot(fcNan);
  else if (KnownSrc.isKnownNever(fcSNan))
    Known.knownNot(fcSNan);

  return Known;
}

KnownFPClass KnownFPClass::fma(const KnownFPClass &KnownLHS,
                               const KnownFPClass &KnownRHS,
                               const KnownFPClass &KnownAddend,
                               DenormalMode Mode) {
  KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);

  // FMA differs from the base fmul + fadd handling only in the treatment of -0
  // results.
  //
  // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
  // unlike for a separate fadd.
  KnownFPClass Known = fadd_impl(Mul, KnownAddend, Mode);

  // propagateNonSNaN for 3 arguments.
  if (KnownLHS.isKnownNever(fcSNan) && KnownRHS.isKnownNever(fcSNan) &&
      KnownAddend.isKnownNever(fcSNan))
    Known.knownNot(fcSNan);

  return Known;
}

KnownFPClass KnownFPClass::fma_square(const KnownFPClass &KnownSquared,
                                      const KnownFPClass &KnownAddend,
                                      DenormalMode Mode) {
  KnownFPClass Squared = square(KnownSquared, Mode);
  KnownFPClass Known = fadd_impl(Squared, KnownAddend, Mode);

  // Since we know the squared input must be positive, the add of opposite sign
  // infinities nan hazard only applies for negative inf.
  //
  // TODO: Alternatively to proving addend is not -inf, we could know Squared is
  // not pinf. Other than the degenerate always-subnormal input case, we can't
  // prove that without a known range.
  if (KnownAddend.isKnownNever(fcNegInf | fcNan) && Squared.isKnownNever(fcNan))
    Known.knownNot(fcNan);

  Known.propagateNonSNaN(KnownSquared, KnownAddend);

  return Known;
}

KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;
  Known.knownNot(fcNegative);

  Known.propagateNonNaN(KnownSrc);

  if (KnownSrc.cannotBeOrderedLessThanZero()) {
    // If the source is positive this cannot underflow.
    Known.knownNot(fcPosZero);

    // Cannot introduce denormal values.
    Known.knownNot(fcPosSubnormal);
  }

  // If the source is negative, this cannot overflow to infinity.
  if (KnownSrc.cannotBeOrderedGreaterThanZero())
    Known.knownNot(fcPosInf);

  return Known;
}

void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
                                              DenormalMode Mode) {
  propagateDenormal(Src, Mode);
  propagateNonNaN(Src);
}

KnownFPClass KnownFPClass::log(const KnownFPClass &KnownSrc,
                               DenormalMode Mode) {
  KnownFPClass Known;
  Known.knownNot(fcNegZero | fcSubnormal);

  Known.propagateNonSNaN(KnownSrc);

  if (KnownSrc.isKnownNeverPosInfinity())
    Known.knownNot(fcPosInf);

  if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
    Known.knownNot(fcNan);

  if (KnownSrc.isKnownNeverLogicalZero(Mode))
    Known.knownNot(fcNegInf);

  return Known;
}

KnownFPClass KnownFPClass::sqrt(const KnownFPClass &KnownSrc,
                                DenormalMode Mode) {
  KnownFPClass Known;
  Known.knownNot(fcPosSubnormal);

  if (KnownSrc.isKnownNeverPosInfinity())
    Known.knownNot(fcPosInf);

  Known.propagateNonSNaN(KnownSrc);

  // Any negative value besides -0 returns a nan.
  if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
    Known.knownNot(fcNan);

  // The only negative value that can be returned is -0 for -0 inputs.
  Known.knownNot(fcNegInf | fcNegSubnormal | fcNegNormal);

  // If the input denormal mode could be PreserveSign, a negative
  // subnormal input could produce a negative zero output.
  if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
    Known.knownNot(fcNegZero);

  return Known;
}

KnownFPClass KnownFPClass::sin(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;

  Known.propagateNonSNaN(KnownSrc);

  // Return NaN on infinite inputs.
  Known.knownNot(fcInf);
  if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
    Known.knownNot(fcNan);

  return Known;
}

KnownFPClass KnownFPClass::cos(const KnownFPClass &KnownSrc) {
  return sin(KnownSrc);
}

KnownFPClass KnownFPClass::tan(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;

  // tan never returns Inf (tan(+-Inf) = NaN; tan(finite) = finite).
  Known.knownNot(fcInf);

  Known.propagateNonSNaN(KnownSrc);

  // NaN propagates. tan(+-Inf) is NaN.
  if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
    Known.knownNot(fcNan);

  return Known;
}

KnownFPClass KnownFPClass::sinh(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;

  // sinh is sign-preserving: sinh(x) < 0 iff x < 0.
  if (KnownSrc.isKnownNever(fcNegative))
    Known.knownNot(fcNegative);

  Known.propagateNonNaN(KnownSrc);

  return Known;
}

KnownFPClass KnownFPClass::cosh(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;

  // cosh(x) >= 1 for all real x; cosh(+-Inf) = +Inf. Never negative,
  // zero, or subnormal.
  Known.knownNot(fcNegative | fcZero | fcSubnormal);

  Known.propagateNonNaN(KnownSrc);

  return Known;
}

KnownFPClass KnownFPClass::tanh(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;

  // tanh is bounded to (-1, 1), never Inf.
  Known.knownNot(fcInf);

  // tanh is sign-preserving: tanh(x) < 0 iff x < 0.
  if (KnownSrc.isKnownNever(fcNegative))
    Known.knownNot(fcNegative);

  Known.propagateNonNaN(KnownSrc);

  return Known;
}

KnownFPClass KnownFPClass::asin(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;

  // asin is bounded to [-pi/2, pi/2], never Inf.
  Known.knownNot(fcInf);

  Known.propagateNonSNaN(KnownSrc);

  // asin is sign-preserving for finite arguments.
  if (KnownSrc.isKnownNever(fcNegFinite))
    Known.knownNot(fcNegFinite);

  // NaN propagates. asin(x) is also NaN for |x| > 1, so we cannot rule
  // out NaN without knowing the source is in [-1, 1].
  return Known;
}

KnownFPClass KnownFPClass::acos(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;

  // acos(x) is bounded to [0, pi] for -1 <= x <= 1, and is never negative,
  // infinite, or subnormal. The smallest non-zero value occurs when x is
  // close to 1.0, where acos(x) can be approximated by sqrt(2 * (1 - x)).
  // Since sqrt cannot produce a subnormal result, we can conclude that
  // acos(x) will also never produce a subnormal result.
  Known.knownNot(fcNegative | fcInf | fcSubnormal);

  // acos(x) == +0.0 iff x == +1.0
  if (KnownSrc.isKnownNever(fcPosNormal))
    Known.knownNot(fcZero);

  Known.propagateNonSNaN(KnownSrc);

  // NaN propagates. acos(x) is also NaN for |x| > 1, so we cannot rule
  // out NaN without knowing the source is in [-1, 1].
  return Known;
}

KnownFPClass KnownFPClass::atan(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;

  // atan is bounded to (-pi/2, pi/2), never Inf. atan(+-Inf) = +-pi/2 (finite).
  Known.knownNot(fcInf);

  // atan is sign-preserving: atan(x) < 0 iff x < 0.
  if (KnownSrc.isKnownNever(fcNegative))
    Known.knownNot(fcNegative);

  Known.propagateNonNaN(KnownSrc);

  return Known;
}

KnownFPClass KnownFPClass::atan2(const KnownFPClass &KnownY,
                                 const KnownFPClass &KnownX,
                                 DenormalMode Mode) {
  KnownFPClass Known;

  // Even though these deductions are correct, we are ignoring the following
  // potentially erroneous cases:
  //   * atan2(y, inf) is not subnormal
  //   * atan2(inf, x) is not zero or subnormal

  // atan2 result is in (-pi, pi], never Inf.
  Known.knownNot(fcInf);

  Known.propagateNonNaN(KnownY, KnownX);

  // Negative subnormals could be treated like positive zero.
  const bool XCannotHavePositiveInput = KnownX.isKnownNever(fcPositive) &&
                                        KnownX.isKnownNeverLogicalPosZero(Mode);
  const bool YCannotHavePositiveInput = KnownY.isKnownNever(fcPositive) &&
                                        KnownY.isKnownNeverLogicalPosZero(Mode);

  // If x <= -0.0, then |atan2(y, x)| >= pi/2
  if (XCannotHavePositiveInput)
    Known.knownNot(fcZero | fcSubnormal);

  // If y >= +0.0, then atan2(y, x) >= +0.0
  if (KnownY.isKnownNever(fcNegative))
    Known.knownNot(fcNegative);

  // If y <= -0.0, then atan2(y, x) <= -0.0
  // We do this deduction last in case we were able to rule out a negative
  // subnormal result earlier.
  if (YCannotHavePositiveInput) {
    Known.knownNot(fcPosSubnormal | fcPosNormal | fcPosInf);
    // Negative subnormal results can flush to +0.0.
    if (Known.isKnownNever(fcNegSubnormal) || !Mode.outputsMayBePositiveZero())
      Known.knownNot(fcPosZero);
  }

  return Known;
}

KnownFPClass KnownFPClass::fpext(const KnownFPClass &KnownSrc,
                                 const fltSemantics &DstTy,
                                 const fltSemantics &SrcTy) {
  // Infinity, nan and zero propagate from source.
  KnownFPClass Known = KnownSrc;

  // All subnormal inputs should be in the normal range in the result type.
  if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy)) {
    if (Known.getKnownFPClasses() & fcPosSubnormal)
      Known.setKnownFPClasses(Known.getKnownFPClasses() | fcPosNormal);
    if (Known.getKnownFPClasses() & fcNegSubnormal)
      Known.setKnownFPClasses(Known.getKnownFPClasses() | fcNegNormal);
    Known.knownNot(fcSubnormal);
  }

  // Sign bit of a nan isn't guaranteed.
  if (!Known.isKnownNeverNaN())
    Known.setSignBit(std::nullopt);

  return Known;
}

KnownFPClass KnownFPClass::fptrunc(const KnownFPClass &KnownSrc) {
  KnownFPClass Known;

  // Sign should be preserved
  // TODO: Handle cannot be ordered greater than zero
  if (KnownSrc.cannotBeOrderedLessThanZero())
    Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);

  Known.propagateNonNaN(KnownSrc);

  // Infinity needs a range check.
  return Known;
}

KnownFPClass KnownFPClass::roundToIntegral(const KnownFPClass &KnownSrc,
                                           bool IsTrunc,
                                           bool IsMultiUnitFPType) {
  KnownFPClass Known;

  // Integer results cannot be subnormal.
  Known.knownNot(fcSubnormal);

  Known.propagateNonNaN(KnownSrc);

  // Pass through infinities, except PPC_FP128 is a special case for
  // intrinsics other than trunc.
  if (IsTrunc || !IsMultiUnitFPType) {
    if (KnownSrc.isKnownNeverPosInfinity())
      Known.knownNot(fcPosInf);
    if (KnownSrc.isKnownNeverNegInfinity())
      Known.knownNot(fcNegInf);
  }

  // Negative round ups to 0 produce -0
  if (KnownSrc.isKnownNever(fcPosFinite))
    Known.knownNot(fcPosFinite);
  if (KnownSrc.isKnownNever(fcNegFinite))
    Known.knownNot(fcNegFinite);

  return Known;
}

KnownFPClass KnownFPClass::frexp_mant(const KnownFPClass &KnownSrc,
                                      DenormalMode Mode) {
  KnownFPClass Known;
  Known.knownNot(fcSubnormal);

  if (KnownSrc.isKnownNever(fcNegative))
    Known.knownNot(fcNegative);
  else {
    if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
      Known.knownNot(fcNegZero);
    if (KnownSrc.isKnownNever(fcNegInf))
      Known.knownNot(fcNegInf);
  }

  if (KnownSrc.isKnownNever(fcPositive))
    Known.knownNot(fcPositive);
  else {
    if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
      Known.knownNot(fcPosZero);
    if (KnownSrc.isKnownNever(fcPosInf))
      Known.knownNot(fcPosInf);
  }

  Known.propagateNonNaN(KnownSrc);
  return Known;
}

KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
                                 const APInt &ConstantRangeExpMin,
                                 const APInt &ConstantRangeExpMax,
                                 const fltSemantics &Flt, DenormalMode Mode) {
  KnownFPClass Known;
  Known.propagateNonNaN(KnownSrc);

  // Sign is preserved, but underflows may produce zeroes.
  if (KnownSrc.isKnownNever(fcNegative))
    Known.knownNot(fcNegative);
  else if (KnownSrc.cannotBeOrderedLessThanZero())
    Known.knownNot(OrderedLessThanZeroMask);

  if (KnownSrc.isKnownNever(fcPositive))
    Known.knownNot(fcPositive);
  else if (KnownSrc.cannotBeOrderedGreaterThanZero())
    Known.knownNot(OrderedGreaterThanZeroMask);

  unsigned Precision = APFloat::semanticsPrecision(Flt);
  const int MantissaBits = Precision - 1;
  if (ConstantRangeExpMin.sge(MantissaBits))
    Known.knownNot(fcSubnormal);

  if (ConstantRangeExpMin.isZero() && ConstantRangeExpMax.isZero()) {
    // ldexp(x, 0) -> x, so propagate everything.
    Known.propagateCanonicalizingSrc(KnownSrc, Mode);
  } else if (ConstantRangeExpMax.isNonPositive()) {
    // If we know the power is <= 0, can't introduce inf
    if (KnownSrc.isKnownNeverPosInfinity())
      Known.knownNot(fcPosInf);
    if (KnownSrc.isKnownNeverNegInfinity())
      Known.knownNot(fcNegInf);
  } else if (ConstantRangeExpMin.isNonNegative()) {
    // If we know the power is >= 0, can't introduce subnormal or zero
    if (KnownSrc.isKnownNeverPosSubnormal())
      Known.knownNot(fcPosSubnormal);
    if (KnownSrc.isKnownNeverNegSubnormal())
      Known.knownNot(fcNegSubnormal);
    if (KnownSrc.isKnownNeverLogicalPosZero(Mode))
      Known.knownNot(fcPosZero);
    if (KnownSrc.isKnownNeverLogicalNegZero(Mode))
      Known.knownNot(fcNegZero);
  }

  return Known;
}

KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
                                 const KnownBits &ExpBits,
                                 const fltSemantics &Flt, DenormalMode Mode) {
  return ldexp(KnownSrc, ExpBits.getSignedMinValue(),
               ExpBits.getSignedMaxValue(), Flt, Mode);
}

KnownFPClass KnownFPClass::pow(const KnownFPClass &KnownLHS,
                               const KnownFPClass &KnownRHS) {
  KnownFPClass Known;

  Known.propagateNonSNaN(KnownLHS, KnownRHS);

  // pow may return NaN if one of the arguments is NaN. NaN may be produced from
  // a non-zero-finite-negative base and a non-integer exponent.
  if (KnownLHS.isKnownNever(fcNan | fcNegNormal | fcNegSubnormal) &&
      KnownRHS.isKnownNeverNaN())
    Known.knownNot(fcNan);

  // We could rule out negative and subnormal results when exponent is known to
  // never be a normal value, but having either argument being known to never be
  // normal is unlikely and not worth considering.

  // Only a negative base raised to an odd power returns a negative value.
  if (KnownLHS.isKnownNever(fcNegative)) {
    Known.knownNot(fcNegative);
  } else if (KnownLHS.isKnownNever(fcNegNormal | fcNegSubnormal)) {
    Known.knownNot(fcNegNormal | fcNegSubnormal);
    // See if we can also rule out -0.0 or -inf.
    // Here at least one of -0.0 or -inf is a possible base.

    // pow(-0.0, odd-positive) = -0.0
    // pow(-inf, odd-negative) = -0.0
    if ((KnownLHS.isKnownNever(fcNegZero) ||
         KnownRHS.isKnownNever(fcPosNormal)) &&
        (KnownLHS.isKnownNever(fcNegInf) || KnownRHS.isKnownNever(fcNegNormal)))
      Known.knownNot(fcNegZero);

    // pow(-0.0, odd-negative) = -inf
    // pow(-inf, odd-positive) = -inf
    if ((KnownLHS.isKnownNever(fcNegZero) ||
         KnownRHS.isKnownNever(fcNegNormal)) &&
        (KnownLHS.isKnownNever(fcNegInf) || KnownRHS.isKnownNever(fcPosNormal)))
      Known.knownNot(fcNegInf);
  }

  return Known;
}

KnownFPClass KnownFPClass::powi(const KnownFPClass &KnownSrc,
                                const KnownBits &ExponentKnownBits) {
  KnownFPClass Known;
  Known.propagateNonNaN(KnownSrc);

  if (ExponentKnownBits.isZero()) {
    // powi(QNaN, 0) returns 1.0, and powi(SNaN, 0) may non-deterministically
    // return 1.0 or a NaN.
    if (KnownSrc.isKnownNever(fcSNan)) {
      Known.knownNot(~fcPosNormal);
      return Known;
    }

    Known.knownNot(~(fcPosNormal | fcNan));
    return Known;
  }

  // Given that exp is an integer, here are the
  // ways that powi can return a negative value:
  //
  //   powi(x, exp)    --> negative if exp is odd and x is negative.
  //   powi(-0, exp)   --> -inf if exp is negative odd.
  //   powi(-0, exp)   --> -0 if exp is positive odd.
  //   powi(-inf, exp) --> -0 if exp is negative odd.
  //   powi(-inf, exp) --> -inf if exp is positive odd.
  if (KnownSrc.isKnownNever(fcNegative) || ExponentKnownBits.isEven()) {
    Known.knownNot(fcNegative);
  } else if (KnownSrc.isKnownNever(fcNegNormal | fcNegSubnormal)) {
    Known.knownNot(fcNegNormal | fcNegSubnormal);
    // See if we can also rule out -0.0 or -inf.
    // Here at least one of -0.0 or -inf is a possible base.

    // We already know that ExponentKnownBits.isEven() is false here.
    const bool IsKnownNeverOddPositive = ExponentKnownBits.isNegative();
    const bool IsKnownNeverOddNegative = ExponentKnownBits.isNonNegative();

    // powi(-0.0, odd-positive) = -0.0
    // powi(-inf, odd-negative) = -0.0
    if ((KnownSrc.isKnownNever(fcNegZero) || IsKnownNeverOddPositive) &&
        (KnownSrc.isKnownNever(fcNegInf) || IsKnownNeverOddNegative))
      Known.knownNot(fcNegZero);

    // powi(-0.0, odd-negative) = -inf
    // powi(-inf, odd-positive) = -inf
    if ((KnownSrc.isKnownNever(fcNegZero) || IsKnownNeverOddNegative) &&
        (KnownSrc.isKnownNever(fcNegInf) || IsKnownNeverOddPositive))
      Known.knownNot(fcNegInf);
  }

  // powi(x, exp) --> inf
  // when:
  //   * powi(inf, exp), exp > 0
  //   * powi(+/-0, exp), exp < 0
  //   * powi(finite, exp), |exp| > 1
  //   * powi(subnormal, -1)
  // TODO:
  //   1. This simple all or nothing approach. We can do better
  //      and cover sign/parity and exp > 1 vs exp < -1 separately.
  //   2. powi(0/nan, exp), exp > 0 can be refinable
  //      to fcNan | fcZero | fcPosNormal.
  {
    APInt MinExp = ExponentKnownBits.getSignedMinValue();
    APInt MaxExp = ExponentKnownBits.getSignedMaxValue();

    // powi(inf, exp), exp > 0
    bool MayInfSrc =
        !KnownSrc.isKnownNever(fcInf) && MaxExp.isStrictlyPositive();

    // powi(+/-0, exp), exp < 0
    bool MayDivByZero = !KnownSrc.isKnownNever(fcZero) && MinExp.isNegative();

    // powi(finite, exp), |exp| > 1
    bool MayFinite = !KnownSrc.isKnownNever(fcNormal | fcSubnormal);
    bool MayAbsExpGT1 = MinExp.slt(-1) || MaxExp.sgt(1);
    bool MayFiniteOverflow = MayFinite && MayAbsExpGT1;

    // powi(subnormal, -1)
    bool MayBeNegOne = ExponentKnownBits.Zero.isZero();
    bool MaySubnormInv = !KnownSrc.isKnownNever(fcSubnormal) && MayBeNegOne;

    if (!MayInfSrc && !MayDivByZero && !MayFiniteOverflow && !MaySubnormInv)
      Known.knownNot(fcInf);
  }

  return Known;
}
