//===- KnownFPClassTest.cpp - KnownFPClass tests --------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/KnownFPClass.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/Support/KnownBits.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace {

static void expectConstant(const char *SemanticsName, const char *ValueName,
                           const fltSemantics &Semantics, APInt ValueBits,
                           FPClassTest PositiveClass, bool Negative) {
  if (Negative)
    ValueBits.setBit(Semantics.sizeInBits - 1);

  SCOPED_TRACE(testing::Message()
               << SemanticsName << ' ' << (Negative ? "negative " : "positive ")
               << ValueName);
  KnownFPClass Known =
      KnownFPClass::bitcast(Semantics, KnownBits::makeConstant(ValueBits));
  FPClassTest ExpectedClass =
      Negative ? llvm::fneg(PositiveClass) : PositiveClass;
  EXPECT_EQ(ExpectedClass, Known.getKnownFPClasses());
  EXPECT_EQ(Negative, Known.getSignBit());
}

TEST(KnownFPClassTest, BitcastExhaustiveIEEEHalf) {
  const fltSemantics &Semantics = APFloat::IEEEhalf();

  for (uint64_t RawBits = 0; RawBits != (1u << 16); ++RawBits) {
    APInt ValueBits(16, RawBits);
    KnownFPClass Known =
        KnownFPClass::bitcast(Semantics, KnownBits::makeConstant(ValueBits));
    KnownFPClass Expected(APFloat(Semantics, ValueBits));

    ASSERT_EQ(Expected.getKnownFPClasses(), Known.getKnownFPClasses())
        << RawBits;
    ASSERT_EQ(Expected.getSignBit(), Known.getSignBit()) << RawBits;
  }
}

TEST(KnownFPClassTest, BitcastConflict) {
  const fltSemantics &Semantics = APFloat::IEEEsingle();
  KnownBits Bits(Semantics.sizeInBits);
  Bits.setAllConflict();

  ASSERT_TRUE(Bits.hasConflict());
  KnownFPClass Known = KnownFPClass::bitcast(Semantics, Bits);
  EXPECT_EQ(fcAllFlags, Known.getKnownFPClasses());
  EXPECT_EQ(std::nullopt, Known.getSignBit());
}

TEST(KnownFPClassTest, BitcastPartialConflict) {
  const fltSemantics &Semantics = APFloat::IEEEsingle();
  KnownBits Bits(Semantics.sizeInBits);
  Bits.Zero.setAllBits();
  Bits.One.setBit(0);

  ASSERT_TRUE(Bits.hasConflict());
  KnownFPClass Known = KnownFPClass::bitcast(Semantics, Bits);
  EXPECT_EQ(fcAllFlags, Known.getKnownFPClasses());
  EXPECT_EQ(std::nullopt, Known.getSignBit());
}

TEST(KnownFPClassTest, BitcastConstant) {
  struct SemanticsCase {
    const char *Name;
    const fltSemantics *Semantics;
  };

  for (const SemanticsCase &TestCase :
       {SemanticsCase{"ieee_binary16", &APFloat::IEEEhalf()},
        SemanticsCase{"bfloat16", &APFloat::BFloat()},
        SemanticsCase{"ieee_binary32", &APFloat::IEEEsingle()},
        SemanticsCase{"ieee_binary64", &APFloat::IEEEdouble()},
        SemanticsCase{"ieee_binary128", &APFloat::IEEEquad()}}) {
    const fltSemantics &Semantics = *TestCase.Semantics;
    const unsigned BitWidth = Semantics.sizeInBits;
    const unsigned MantissaBits = Semantics.precision - 1;
    const APInt ExponentMask =
        APInt::getBitsSet(BitWidth, MantissaBits, BitWidth - 1);
    const APInt MantissaMask = APInt::getLowBitsSet(BitWidth, MantissaBits);
    const APInt QuietBit = APInt::getOneBitSet(BitWidth, MantissaBits - 1);

    for (bool Negative : {false, true}) {
      expectConstant(TestCase.Name, "0.0", Semantics, APInt::getZero(BitWidth),
                     fcPosZero, Negative);
      expectConstant(TestCase.Name, "min_subnormal", Semantics,
                     APInt(BitWidth, 1), fcPosSubnormal, Negative);
      expectConstant(TestCase.Name, "max_subnormal", Semantics, MantissaMask,
                     fcPosSubnormal, Negative);
      expectConstant(TestCase.Name, "min_normal", Semantics,
                     APInt::getOneBitSet(BitWidth, MantissaBits), fcPosNormal,
                     Negative);
      expectConstant(TestCase.Name, "1.0", Semantics,
                     APFloat::getOne(Semantics).bitcastToAPInt(), fcPosNormal,
                     Negative);
      expectConstant(TestCase.Name, "max_normal", Semantics,
                     APFloat::getLargest(Semantics).bitcastToAPInt(),
                     fcPosNormal, Negative);
      expectConstant(TestCase.Name, "inf", Semantics, ExponentMask, fcPosInf,
                     Negative);

      // An sNaN has a clear quiet bit and a non-zero payload.
      expectConstant(TestCase.Name, "snan_mostly_zero", Semantics,
                     ExponentMask | APInt(BitWidth, 1), fcSNan, Negative);

      // A qNaN has a set quiet bit. The remaining payload bits may be zero.
      expectConstant(TestCase.Name, "qnan_mostly_zero", Semantics,
                     ExponentMask | QuietBit, fcQNan, Negative);

      expectConstant(TestCase.Name, "snan_mostly_one", Semantics,
                     ExponentMask | (MantissaMask & ~QuietBit), fcSNan,
                     Negative);
      expectConstant(TestCase.Name, "qnan_mostly_one", Semantics,
                     ExponentMask | MantissaMask, fcQNan, Negative);
    }
  }
}

TEST(KnownFPClassTest, BitcastUnsupported) {
  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;
    }
  };

  for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
    APFloat::Semantics SemanticsKind = static_cast<APFloat::Semantics>(I);
    const fltSemantics &Semantics = APFloat::EnumToSemantics(SemanticsKind);

    for (const APInt &ValueBits : {APInt::getZero(Semantics.sizeInBits),
                                   APInt::getAllOnes(Semantics.sizeInBits)}) {
      SCOPED_TRACE(testing::Message()
                   << "Semantics = " << I << ", bits = " << ValueBits);
      KnownFPClass Known =
          KnownFPClass::bitcast(Semantics, KnownBits::makeConstant(ValueBits));
      if (IsSupported(Semantics)) {
        // We should be able to make at least one deduction for "Supported"
        // types.
        EXPECT_FALSE(Known.isUnknown());
      } else {
        EXPECT_TRUE(Known.isUnknown());
      }
    }
  }
}

TEST(KnownFPClassTest, ToKnownBitsUnsupported) {
  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;
    }
  };

  for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
    APFloat::Semantics SemanticsKind = static_cast<APFloat::Semantics>(I);
    const fltSemantics &Semantics = APFloat::EnumToSemantics(SemanticsKind);

    for (FPClassTest FPClass : {fcPosZero, fcPosNormal}) {
      SCOPED_TRACE(testing::Message()
                   << "Semantics = " << I << ", class = " << FPClass);
      KnownBits Known = KnownFPClass(FPClass, false).toKnownBits(Semantics);
      if (IsSupported(Semantics)) {
        // The following expectations are true for all "supported" types.
        EXPECT_TRUE(Known.isNonNegative());
        if (FPClass == fcPosZero)
          EXPECT_TRUE(Known.isZero());
      } else {
        EXPECT_TRUE(Known.isUnknown());
      }
    }
  }
}

} // end anonymous namespace
