1fa824dc0SYingwei Zheng //===- ConstantRangeTest.cpp - ConstantRange tests ------------------------===// 2fa824dc0SYingwei Zheng // 3fa824dc0SYingwei Zheng // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fa824dc0SYingwei Zheng // See https://llvm.org/LICENSE.txt for license information. 5fa824dc0SYingwei Zheng // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fa824dc0SYingwei Zheng // 7fa824dc0SYingwei Zheng //===----------------------------------------------------------------------===// 8fa824dc0SYingwei Zheng 9fa824dc0SYingwei Zheng #include "llvm/IR/ConstantFPRange.h" 10fa824dc0SYingwei Zheng #include "llvm/IR/Instructions.h" 11fa824dc0SYingwei Zheng #include "llvm/IR/Operator.h" 12fa824dc0SYingwei Zheng #include "gtest/gtest.h" 13fa824dc0SYingwei Zheng 14fa824dc0SYingwei Zheng using namespace llvm; 15fa824dc0SYingwei Zheng 16fa824dc0SYingwei Zheng namespace { 17fa824dc0SYingwei Zheng 18fa824dc0SYingwei Zheng class ConstantFPRangeTest : public ::testing::Test { 19fa824dc0SYingwei Zheng protected: 20fa824dc0SYingwei Zheng static const fltSemantics &Sem; 21fa824dc0SYingwei Zheng static ConstantFPRange Full; 22fa824dc0SYingwei Zheng static ConstantFPRange Empty; 23fa824dc0SYingwei Zheng static ConstantFPRange Finite; 24fa824dc0SYingwei Zheng static ConstantFPRange One; 25fa824dc0SYingwei Zheng static ConstantFPRange PosZero; 26fa824dc0SYingwei Zheng static ConstantFPRange NegZero; 27fa824dc0SYingwei Zheng static ConstantFPRange Zero; 28fa824dc0SYingwei Zheng static ConstantFPRange PosInf; 29fa824dc0SYingwei Zheng static ConstantFPRange NegInf; 30fa824dc0SYingwei Zheng static ConstantFPRange Denormal; 31fa824dc0SYingwei Zheng static ConstantFPRange NaN; 32fa824dc0SYingwei Zheng static ConstantFPRange SNaN; 33fa824dc0SYingwei Zheng static ConstantFPRange QNaN; 34fa824dc0SYingwei Zheng static ConstantFPRange Some; 35fa824dc0SYingwei Zheng static ConstantFPRange SomePos; 36fa824dc0SYingwei Zheng static ConstantFPRange SomeNeg; 37fa824dc0SYingwei Zheng }; 38fa824dc0SYingwei Zheng 39fa824dc0SYingwei Zheng const fltSemantics &ConstantFPRangeTest::Sem = APFloat::IEEEdouble(); 40fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::Full = 41fa824dc0SYingwei Zheng ConstantFPRange::getFull(APFloat::IEEEdouble()); 42fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::Empty = 43fa824dc0SYingwei Zheng ConstantFPRange::getEmpty(APFloat::IEEEdouble()); 44fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::Finite = 45fa824dc0SYingwei Zheng ConstantFPRange::getFinite(APFloat::IEEEdouble()); 46fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::One = ConstantFPRange(APFloat(1.0)); 47fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::PosZero = ConstantFPRange( 48fa824dc0SYingwei Zheng APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/false)); 49fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::NegZero = 50fa824dc0SYingwei Zheng ConstantFPRange(APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/true)); 51fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::Zero = ConstantFPRange::getNonNaN( 52fa824dc0SYingwei Zheng APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/true), 53fa824dc0SYingwei Zheng APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/false)); 54fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::Denormal = 55fa824dc0SYingwei Zheng ConstantFPRange(APFloat::getSmallest(APFloat::IEEEdouble())); 56fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::PosInf = 57fa824dc0SYingwei Zheng ConstantFPRange(APFloat::getInf(APFloat::IEEEdouble(), /*Negative=*/false)); 58fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::NegInf = 59fa824dc0SYingwei Zheng ConstantFPRange(APFloat::getInf(APFloat::IEEEdouble(), /*Negative=*/true)); 60fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::NaN = ConstantFPRange::getNaNOnly( 61fa824dc0SYingwei Zheng APFloat::IEEEdouble(), /*MayBeQNaN=*/true, /*MayBeSNaN=*/true); 62fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::SNaN = 63fa824dc0SYingwei Zheng ConstantFPRange(APFloat::getSNaN(APFloat::IEEEdouble())); 64fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::QNaN = 65fa824dc0SYingwei Zheng ConstantFPRange(APFloat::getQNaN(APFloat::IEEEdouble())); 66fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::Some = 67fa824dc0SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(3.0)); 68fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::SomePos = ConstantFPRange::getNonNaN( 69fa824dc0SYingwei Zheng APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/false), APFloat(3.0)); 70fa824dc0SYingwei Zheng ConstantFPRange ConstantFPRangeTest::SomeNeg = ConstantFPRange::getNonNaN( 71fa824dc0SYingwei Zheng APFloat(-3.0), APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/true)); 72fa824dc0SYingwei Zheng 73fa824dc0SYingwei Zheng static void strictNext(APFloat &V) { 74fa824dc0SYingwei Zheng // Note: nextUp(+/-0) is smallest. 75fa824dc0SYingwei Zheng if (V.isNegZero()) 76fa824dc0SYingwei Zheng V = APFloat::getZero(V.getSemantics(), /*Negative=*/false); 77fa824dc0SYingwei Zheng else 78fa824dc0SYingwei Zheng V.next(/*nextDown=*/false); 79fa824dc0SYingwei Zheng } 80fa824dc0SYingwei Zheng 81fa824dc0SYingwei Zheng template <typename Fn> 82fa824dc0SYingwei Zheng static void EnumerateConstantFPRangesImpl(Fn TestFn, bool Exhaustive, 83fa824dc0SYingwei Zheng bool MayBeQNaN, bool MayBeSNaN) { 84fa824dc0SYingwei Zheng const fltSemantics &Sem = APFloat::Float8E4M3(); 85fa824dc0SYingwei Zheng APFloat PosInf = APFloat::getInf(Sem, /*Negative=*/false); 86fa824dc0SYingwei Zheng APFloat NegInf = APFloat::getInf(Sem, /*Negative=*/true); 87fa824dc0SYingwei Zheng TestFn(ConstantFPRange(PosInf, NegInf, MayBeQNaN, MayBeSNaN)); 88fa824dc0SYingwei Zheng 89fa824dc0SYingwei Zheng if (!Exhaustive) { 90fa824dc0SYingwei Zheng SmallVector<APFloat, 36> Values; 91fa824dc0SYingwei Zheng Values.push_back(APFloat::getInf(Sem, /*Negative=*/true)); 92fa824dc0SYingwei Zheng Values.push_back(APFloat::getLargest(Sem, /*Negative=*/true)); 93fa824dc0SYingwei Zheng unsigned BitWidth = APFloat::semanticsSizeInBits(Sem); 94fa824dc0SYingwei Zheng unsigned Exponents = APFloat::semanticsMaxExponent(Sem) - 95fa824dc0SYingwei Zheng APFloat::semanticsMinExponent(Sem) + 3; 96fa824dc0SYingwei Zheng unsigned MantissaBits = APFloat::semanticsPrecision(Sem) - 1; 97fa824dc0SYingwei Zheng // Add -2^(max exponent), -2^(max exponent-1), ..., -2^(min exponent) 98fa824dc0SYingwei Zheng for (unsigned M = Exponents - 2; M != 0; --M) 99fa824dc0SYingwei Zheng Values.push_back( 100fa824dc0SYingwei Zheng APFloat(Sem, APInt(BitWidth, (M + Exponents) << MantissaBits))); 101fa824dc0SYingwei Zheng Values.push_back(APFloat::getSmallest(Sem, /*Negative=*/true)); 102fa824dc0SYingwei Zheng Values.push_back(APFloat::getZero(Sem, /*Negative=*/true)); 103fa824dc0SYingwei Zheng size_t E = Values.size(); 104fa824dc0SYingwei Zheng for (size_t I = 1; I <= E; ++I) 105fa824dc0SYingwei Zheng Values.push_back(-Values[E - I]); 106fa824dc0SYingwei Zheng for (size_t I = 0; I != Values.size(); ++I) 107fa824dc0SYingwei Zheng for (size_t J = I; J != Values.size(); ++J) 108fa824dc0SYingwei Zheng TestFn(ConstantFPRange(Values[I], Values[J], MayBeQNaN, MayBeSNaN)); 109fa824dc0SYingwei Zheng return; 110fa824dc0SYingwei Zheng } 111fa824dc0SYingwei Zheng 112fa824dc0SYingwei Zheng auto Next = [&](APFloat &V) { 113fa824dc0SYingwei Zheng if (V.isPosInfinity()) 114fa824dc0SYingwei Zheng return false; 115fa824dc0SYingwei Zheng strictNext(V); 116fa824dc0SYingwei Zheng return true; 117fa824dc0SYingwei Zheng }; 118fa824dc0SYingwei Zheng 119fa824dc0SYingwei Zheng APFloat Lower = NegInf; 120fa824dc0SYingwei Zheng do { 121fa824dc0SYingwei Zheng APFloat Upper = Lower; 122fa824dc0SYingwei Zheng do { 123fa824dc0SYingwei Zheng TestFn(ConstantFPRange(Lower, Upper, MayBeQNaN, MayBeSNaN)); 124fa824dc0SYingwei Zheng } while (Next(Upper)); 125fa824dc0SYingwei Zheng } while (Next(Lower)); 126fa824dc0SYingwei Zheng } 127fa824dc0SYingwei Zheng 128fa824dc0SYingwei Zheng template <typename Fn> 129fa824dc0SYingwei Zheng static void EnumerateConstantFPRanges(Fn TestFn, bool Exhaustive) { 130fa824dc0SYingwei Zheng EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/false, 131fa824dc0SYingwei Zheng /*MayBeSNaN=*/false); 132fa824dc0SYingwei Zheng EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/false, 133fa824dc0SYingwei Zheng /*MayBeSNaN=*/true); 134fa824dc0SYingwei Zheng EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/true, 135fa824dc0SYingwei Zheng /*MayBeSNaN=*/false); 136fa824dc0SYingwei Zheng EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/true, 137fa824dc0SYingwei Zheng /*MayBeSNaN=*/true); 138fa824dc0SYingwei Zheng } 139fa824dc0SYingwei Zheng 140fa824dc0SYingwei Zheng template <typename Fn> 141fa824dc0SYingwei Zheng static void EnumerateTwoInterestingConstantFPRanges(Fn TestFn, 142fa824dc0SYingwei Zheng bool Exhaustive) { 143fa824dc0SYingwei Zheng EnumerateConstantFPRanges( 144fa824dc0SYingwei Zheng [&](const ConstantFPRange &CR1) { 145fa824dc0SYingwei Zheng EnumerateConstantFPRanges( 146fa824dc0SYingwei Zheng [&](const ConstantFPRange &CR2) { TestFn(CR1, CR2); }, Exhaustive); 147fa824dc0SYingwei Zheng }, 148fa824dc0SYingwei Zheng Exhaustive); 149fa824dc0SYingwei Zheng } 150fa824dc0SYingwei Zheng 151fa824dc0SYingwei Zheng template <typename Fn> 152fa824dc0SYingwei Zheng static void EnumerateValuesInConstantFPRange(const ConstantFPRange &CR, 153856774ddSYingwei Zheng Fn TestFn, bool IgnoreNaNPayload) { 154fa824dc0SYingwei Zheng const fltSemantics &Sem = CR.getSemantics(); 155856774ddSYingwei Zheng if (IgnoreNaNPayload) { 156856774ddSYingwei Zheng if (CR.containsSNaN()) { 157856774ddSYingwei Zheng TestFn(APFloat::getSNaN(Sem, false)); 158856774ddSYingwei Zheng TestFn(APFloat::getSNaN(Sem, true)); 159856774ddSYingwei Zheng } 160856774ddSYingwei Zheng if (CR.containsQNaN()) { 161856774ddSYingwei Zheng TestFn(APFloat::getQNaN(Sem, false)); 162856774ddSYingwei Zheng TestFn(APFloat::getQNaN(Sem, true)); 163856774ddSYingwei Zheng } 164856774ddSYingwei Zheng if (CR.isNaNOnly()) 165856774ddSYingwei Zheng return; 166856774ddSYingwei Zheng APFloat Lower = CR.getLower(); 167856774ddSYingwei Zheng const APFloat &Upper = CR.getUpper(); 168856774ddSYingwei Zheng auto Next = [&](APFloat &V) { 169856774ddSYingwei Zheng if (V.bitwiseIsEqual(Upper)) 170856774ddSYingwei Zheng return false; 171856774ddSYingwei Zheng strictNext(V); 172856774ddSYingwei Zheng return true; 173856774ddSYingwei Zheng }; 174856774ddSYingwei Zheng do 175856774ddSYingwei Zheng TestFn(Lower); 176856774ddSYingwei Zheng while (Next(Lower)); 177856774ddSYingwei Zheng } else { 178fa824dc0SYingwei Zheng unsigned Bits = APFloat::semanticsSizeInBits(Sem); 179fa824dc0SYingwei Zheng assert(Bits < 32 && "Too many bits"); 180fa824dc0SYingwei Zheng for (unsigned I = 0, E = (1U << Bits) - 1; I != E; ++I) { 181fa824dc0SYingwei Zheng APFloat V(Sem, APInt(Bits, I)); 182fa824dc0SYingwei Zheng if (CR.contains(V)) 183fa824dc0SYingwei Zheng TestFn(V); 184fa824dc0SYingwei Zheng } 185fa824dc0SYingwei Zheng } 186856774ddSYingwei Zheng } 187fa824dc0SYingwei Zheng 18858673622SYingwei Zheng template <typename Fn> 189856774ddSYingwei Zheng static bool AnyOfValueInConstantFPRange(const ConstantFPRange &CR, Fn TestFn, 190856774ddSYingwei Zheng bool IgnoreNaNPayload) { 19158673622SYingwei Zheng const fltSemantics &Sem = CR.getSemantics(); 192856774ddSYingwei Zheng if (IgnoreNaNPayload) { 193856774ddSYingwei Zheng if (CR.containsSNaN()) { 194856774ddSYingwei Zheng if (TestFn(APFloat::getSNaN(Sem, false))) 195856774ddSYingwei Zheng return true; 196856774ddSYingwei Zheng if (TestFn(APFloat::getSNaN(Sem, true))) 197856774ddSYingwei Zheng return true; 198856774ddSYingwei Zheng } 199856774ddSYingwei Zheng if (CR.containsQNaN()) { 200856774ddSYingwei Zheng if (TestFn(APFloat::getQNaN(Sem, false))) 201856774ddSYingwei Zheng return true; 202856774ddSYingwei Zheng if (TestFn(APFloat::getQNaN(Sem, true))) 203856774ddSYingwei Zheng return true; 204856774ddSYingwei Zheng } 205856774ddSYingwei Zheng if (CR.isNaNOnly()) 206856774ddSYingwei Zheng return false; 207856774ddSYingwei Zheng APFloat Lower = CR.getLower(); 208856774ddSYingwei Zheng const APFloat &Upper = CR.getUpper(); 209856774ddSYingwei Zheng auto Next = [&](APFloat &V) { 210856774ddSYingwei Zheng if (V.bitwiseIsEqual(Upper)) 211856774ddSYingwei Zheng return false; 212856774ddSYingwei Zheng strictNext(V); 213856774ddSYingwei Zheng return true; 214856774ddSYingwei Zheng }; 215856774ddSYingwei Zheng do { 216856774ddSYingwei Zheng if (TestFn(Lower)) 217856774ddSYingwei Zheng return true; 218856774ddSYingwei Zheng } while (Next(Lower)); 219856774ddSYingwei Zheng } else { 22058673622SYingwei Zheng unsigned Bits = APFloat::semanticsSizeInBits(Sem); 22158673622SYingwei Zheng assert(Bits < 32 && "Too many bits"); 22258673622SYingwei Zheng for (unsigned I = 0, E = (1U << Bits) - 1; I != E; ++I) { 22358673622SYingwei Zheng APFloat V(Sem, APInt(Bits, I)); 22458673622SYingwei Zheng if (CR.contains(V) && TestFn(V)) 22558673622SYingwei Zheng return true; 22658673622SYingwei Zheng } 227856774ddSYingwei Zheng } 22858673622SYingwei Zheng return false; 22958673622SYingwei Zheng } 23058673622SYingwei Zheng 231fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, Basics) { 232fa824dc0SYingwei Zheng EXPECT_TRUE(Full.isFullSet()); 233fa824dc0SYingwei Zheng EXPECT_FALSE(Full.isEmptySet()); 234fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(APFloat::getNaN(Sem))); 235fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(APFloat::getInf(Sem, /*Negative=*/false))); 236fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(APFloat::getInf(Sem, /*Negative=*/true))); 237fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(APFloat::getZero(Sem, /*Negative=*/false))); 238fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(APFloat::getZero(Sem, /*Negative=*/true))); 239fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(APFloat::getSmallest(Sem))); 240fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(APFloat(2.0))); 241fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(Full)); 242fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(Empty)); 243fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(Finite)); 244fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(Zero)); 245fa824dc0SYingwei Zheng EXPECT_TRUE(Full.contains(Some)); 246fa824dc0SYingwei Zheng 247fa824dc0SYingwei Zheng EXPECT_FALSE(Empty.isFullSet()); 248fa824dc0SYingwei Zheng EXPECT_TRUE(Empty.isEmptySet()); 249fa824dc0SYingwei Zheng EXPECT_FALSE(Empty.contains(APFloat::getNaN(Sem))); 250fa824dc0SYingwei Zheng EXPECT_FALSE(Empty.contains(APFloat::getInf(Sem, /*Negative=*/false))); 251fa824dc0SYingwei Zheng EXPECT_FALSE(Empty.contains(APFloat::getZero(Sem, /*Negative=*/true))); 252fa824dc0SYingwei Zheng EXPECT_FALSE(Empty.contains(APFloat(2.0))); 253fa824dc0SYingwei Zheng EXPECT_TRUE(Empty.contains(Empty)); 254fa824dc0SYingwei Zheng 255fa824dc0SYingwei Zheng EXPECT_FALSE(Finite.isFullSet()); 256fa824dc0SYingwei Zheng EXPECT_FALSE(Finite.isEmptySet()); 257fa824dc0SYingwei Zheng EXPECT_FALSE(Finite.contains(APFloat::getNaN(Sem))); 258fa824dc0SYingwei Zheng EXPECT_FALSE(Finite.contains(APFloat::getInf(Sem, /*Negative=*/false))); 259fa824dc0SYingwei Zheng EXPECT_FALSE(Finite.contains(APFloat::getInf(Sem, /*Negative=*/true))); 260fa824dc0SYingwei Zheng EXPECT_TRUE(Finite.contains(APFloat::getLargest(Sem, /*Negative=*/false))); 261fa824dc0SYingwei Zheng EXPECT_TRUE(Finite.contains(APFloat::getLargest(Sem, /*Negative=*/true))); 262fa824dc0SYingwei Zheng EXPECT_TRUE(Finite.contains(Finite)); 263fa824dc0SYingwei Zheng EXPECT_TRUE(Finite.contains(Some)); 264fa824dc0SYingwei Zheng EXPECT_TRUE(Finite.contains(Denormal)); 265fa824dc0SYingwei Zheng EXPECT_TRUE(Finite.contains(Zero)); 266fa824dc0SYingwei Zheng EXPECT_FALSE(Finite.contains(PosInf)); 267fa824dc0SYingwei Zheng EXPECT_FALSE(Finite.contains(NaN)); 268fa824dc0SYingwei Zheng 269fa824dc0SYingwei Zheng EXPECT_TRUE(One.contains(APFloat(1.0))); 270fa824dc0SYingwei Zheng EXPECT_FALSE(One.contains(APFloat(1.1))); 271fa824dc0SYingwei Zheng 272fa824dc0SYingwei Zheng EXPECT_TRUE(PosZero.contains(APFloat::getZero(Sem, /*Negative=*/false))); 273fa824dc0SYingwei Zheng EXPECT_FALSE(PosZero.contains(APFloat::getZero(Sem, /*Negative=*/true))); 274fa824dc0SYingwei Zheng EXPECT_TRUE(NegZero.contains(APFloat::getZero(Sem, /*Negative=*/true))); 275fa824dc0SYingwei Zheng EXPECT_FALSE(NegZero.contains(APFloat::getZero(Sem, /*Negative=*/false))); 276fa824dc0SYingwei Zheng EXPECT_TRUE(Zero.contains(PosZero)); 277fa824dc0SYingwei Zheng EXPECT_TRUE(Zero.contains(NegZero)); 278fa824dc0SYingwei Zheng EXPECT_TRUE(Denormal.contains(APFloat::getSmallest(Sem))); 279fa824dc0SYingwei Zheng EXPECT_FALSE(Denormal.contains(APFloat::getSmallestNormalized(Sem))); 280fa824dc0SYingwei Zheng EXPECT_TRUE(PosInf.contains(APFloat::getInf(Sem, /*Negative=*/false))); 281fa824dc0SYingwei Zheng EXPECT_TRUE(NegInf.contains(APFloat::getInf(Sem, /*Negative=*/true))); 282fa824dc0SYingwei Zheng EXPECT_TRUE(NaN.contains(APFloat::getQNaN(Sem))); 283fa824dc0SYingwei Zheng EXPECT_TRUE(NaN.contains(APFloat::getSNaN(Sem))); 284fa824dc0SYingwei Zheng EXPECT_TRUE(NaN.contains(SNaN)); 285fa824dc0SYingwei Zheng EXPECT_TRUE(NaN.contains(QNaN)); 286fa824dc0SYingwei Zheng 287fa824dc0SYingwei Zheng EXPECT_TRUE(Some.contains(APFloat(3.0))); 288fa824dc0SYingwei Zheng EXPECT_TRUE(Some.contains(APFloat(-3.0))); 289fa824dc0SYingwei Zheng EXPECT_FALSE(Some.contains(APFloat(4.0))); 290fa824dc0SYingwei Zheng APFloat Next1(3.0); 291fa824dc0SYingwei Zheng Next1.next(/*nextDown=*/true); 292fa824dc0SYingwei Zheng EXPECT_TRUE(Some.contains(Next1)); 293fa824dc0SYingwei Zheng APFloat Next2(3.0); 294fa824dc0SYingwei Zheng Next2.next(/*nextDown=*/false); 295fa824dc0SYingwei Zheng EXPECT_FALSE(Some.contains(Next2)); 296fa824dc0SYingwei Zheng EXPECT_TRUE(Some.contains(Zero)); 297fa824dc0SYingwei Zheng EXPECT_TRUE(Some.contains(Some)); 298fa824dc0SYingwei Zheng EXPECT_TRUE(Some.contains(One)); 299fa824dc0SYingwei Zheng EXPECT_FALSE(Some.contains(NaN)); 300fa824dc0SYingwei Zheng EXPECT_FALSE(Some.contains(PosInf)); 301fa824dc0SYingwei Zheng EXPECT_TRUE(SomePos.contains(APFloat(3.0))); 302fa824dc0SYingwei Zheng EXPECT_FALSE(SomeNeg.contains(APFloat(3.0))); 303fa824dc0SYingwei Zheng EXPECT_TRUE(SomeNeg.contains(APFloat(-3.0))); 304fa824dc0SYingwei Zheng EXPECT_FALSE(SomePos.contains(APFloat(-3.0))); 305fa824dc0SYingwei Zheng EXPECT_TRUE(Some.contains(SomePos)); 306fa824dc0SYingwei Zheng EXPECT_TRUE(Some.contains(SomeNeg)); 307fa824dc0SYingwei Zheng } 308fa824dc0SYingwei Zheng 309fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, Equality) { 310fa824dc0SYingwei Zheng EXPECT_EQ(Full, Full); 311fa824dc0SYingwei Zheng EXPECT_EQ(Empty, Empty); 312fa824dc0SYingwei Zheng EXPECT_EQ(One, One); 313fa824dc0SYingwei Zheng EXPECT_EQ(Some, Some); 314fa824dc0SYingwei Zheng EXPECT_NE(Full, Empty); 315fa824dc0SYingwei Zheng EXPECT_NE(Zero, PosZero); 316fa824dc0SYingwei Zheng EXPECT_NE(One, NaN); 317fa824dc0SYingwei Zheng EXPECT_NE(Some, One); 318fa824dc0SYingwei Zheng EXPECT_NE(SNaN, QNaN); 319fa824dc0SYingwei Zheng } 320fa824dc0SYingwei Zheng 321fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, SingleElement) { 322fa824dc0SYingwei Zheng EXPECT_EQ(Full.getSingleElement(), static_cast<APFloat *>(nullptr)); 323fa824dc0SYingwei Zheng EXPECT_EQ(Empty.getSingleElement(), static_cast<APFloat *>(nullptr)); 324fa824dc0SYingwei Zheng EXPECT_EQ(Finite.getSingleElement(), static_cast<APFloat *>(nullptr)); 325fa824dc0SYingwei Zheng EXPECT_EQ(Zero.getSingleElement(), static_cast<APFloat *>(nullptr)); 326fa824dc0SYingwei Zheng EXPECT_EQ(NaN.getSingleElement(), static_cast<APFloat *>(nullptr)); 327fa824dc0SYingwei Zheng EXPECT_EQ(SNaN.getSingleElement(), static_cast<APFloat *>(nullptr)); 328fa824dc0SYingwei Zheng EXPECT_EQ(QNaN.getSingleElement(), static_cast<APFloat *>(nullptr)); 329fa824dc0SYingwei Zheng 330fa824dc0SYingwei Zheng EXPECT_EQ(*One.getSingleElement(), APFloat(1.0)); 331fa824dc0SYingwei Zheng EXPECT_EQ(*PosZero.getSingleElement(), APFloat::getZero(Sem)); 332fa824dc0SYingwei Zheng EXPECT_EQ(*PosInf.getSingleElement(), APFloat::getInf(Sem)); 3334db10561SYingwei Zheng ConstantFPRange PosZeroOrNaN = PosZero.unionWith(NaN); 3344db10561SYingwei Zheng EXPECT_EQ(*PosZeroOrNaN.getSingleElement(/*ExcludesNaN=*/true), 3354db10561SYingwei Zheng APFloat::getZero(Sem)); 336fa824dc0SYingwei Zheng 337fa824dc0SYingwei Zheng EXPECT_FALSE(Full.isSingleElement()); 338fa824dc0SYingwei Zheng EXPECT_FALSE(Empty.isSingleElement()); 339fa824dc0SYingwei Zheng EXPECT_TRUE(One.isSingleElement()); 340fa824dc0SYingwei Zheng EXPECT_FALSE(Some.isSingleElement()); 341fa824dc0SYingwei Zheng EXPECT_FALSE(Zero.isSingleElement()); 3424db10561SYingwei Zheng EXPECT_TRUE(PosZeroOrNaN.isSingleElement(/*ExcludesNaN=*/true)); 343fa824dc0SYingwei Zheng } 344fa824dc0SYingwei Zheng 345fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, ExhaustivelyEnumerate) { 346fa824dc0SYingwei Zheng constexpr unsigned NNaNValues = (1 << 8) - 2 * ((1 << 3) - 1); 347fa824dc0SYingwei Zheng constexpr unsigned Expected = 4 * ((NNaNValues + 1) * NNaNValues / 2 + 1); 348fa824dc0SYingwei Zheng unsigned Count = 0; 349fa824dc0SYingwei Zheng EnumerateConstantFPRanges([&](const ConstantFPRange &) { ++Count; }, 350fa824dc0SYingwei Zheng /*Exhaustive=*/true); 351fa824dc0SYingwei Zheng EXPECT_EQ(Expected, Count); 352fa824dc0SYingwei Zheng } 353fa824dc0SYingwei Zheng 354fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, Enumerate) { 355fa824dc0SYingwei Zheng constexpr unsigned NNaNValues = 2 * ((1 << 4) - 2 + 4); 356fa824dc0SYingwei Zheng constexpr unsigned Expected = 4 * ((NNaNValues + 1) * NNaNValues / 2 + 1); 357fa824dc0SYingwei Zheng unsigned Count = 0; 358fa824dc0SYingwei Zheng EnumerateConstantFPRanges([&](const ConstantFPRange &) { ++Count; }, 359fa824dc0SYingwei Zheng /*Exhaustive=*/false); 360fa824dc0SYingwei Zheng EXPECT_EQ(Expected, Count); 361fa824dc0SYingwei Zheng } 362fa824dc0SYingwei Zheng 363fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, IntersectWith) { 364fa824dc0SYingwei Zheng EXPECT_EQ(Empty.intersectWith(Full), Empty); 365fa824dc0SYingwei Zheng EXPECT_EQ(Empty.intersectWith(Empty), Empty); 366fa824dc0SYingwei Zheng EXPECT_EQ(Empty.intersectWith(One), Empty); 367fa824dc0SYingwei Zheng EXPECT_EQ(Empty.intersectWith(Some), Empty); 368fa824dc0SYingwei Zheng EXPECT_EQ(Full.intersectWith(Full), Full); 369fa824dc0SYingwei Zheng EXPECT_EQ(Some.intersectWith(Some), Some); 370fa824dc0SYingwei Zheng EXPECT_EQ(Some.intersectWith(One), One); 371fa824dc0SYingwei Zheng EXPECT_EQ(Full.intersectWith(One), One); 372fa824dc0SYingwei Zheng EXPECT_EQ(Full.intersectWith(Some), Some); 373fa824dc0SYingwei Zheng EXPECT_EQ(Some.intersectWith(SomePos), SomePos); 374fa824dc0SYingwei Zheng EXPECT_EQ(Some.intersectWith(SomeNeg), SomeNeg); 375fa824dc0SYingwei Zheng EXPECT_EQ(NaN.intersectWith(Finite), Empty); 376fa824dc0SYingwei Zheng EXPECT_EQ(NaN.intersectWith(SNaN), SNaN); 377fa824dc0SYingwei Zheng EXPECT_EQ(NaN.intersectWith(QNaN), QNaN); 378fa824dc0SYingwei Zheng EXPECT_EQ(Finite.intersectWith(One), One); 379fa824dc0SYingwei Zheng EXPECT_EQ(Some.intersectWith(Zero), Zero); 380fa824dc0SYingwei Zheng EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(4.0)) 381fa824dc0SYingwei Zheng .intersectWith( 382fa824dc0SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(3.0), APFloat(6.0))), 383fa824dc0SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(3.0), APFloat(4.0))); 384fa824dc0SYingwei Zheng EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0)) 385fa824dc0SYingwei Zheng .intersectWith( 386fa824dc0SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(5.0), APFloat(6.0))), 387fa824dc0SYingwei Zheng Empty); 388fa824dc0SYingwei Zheng } 389fa824dc0SYingwei Zheng 390fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, UnionWith) { 391fa824dc0SYingwei Zheng EXPECT_EQ(Empty.unionWith(Full), Full); 392fa824dc0SYingwei Zheng EXPECT_EQ(Empty.unionWith(Empty), Empty); 393fa824dc0SYingwei Zheng EXPECT_EQ(Empty.unionWith(One), One); 394fa824dc0SYingwei Zheng EXPECT_EQ(Empty.unionWith(Some), Some); 395fa824dc0SYingwei Zheng EXPECT_EQ(Full.unionWith(Full), Full); 396fa824dc0SYingwei Zheng EXPECT_EQ(Some.unionWith(Some), Some); 397fa824dc0SYingwei Zheng EXPECT_EQ(Some.unionWith(One), Some); 398fa824dc0SYingwei Zheng EXPECT_EQ(Full.unionWith(Some), Full); 399fa824dc0SYingwei Zheng EXPECT_EQ(Some.unionWith(SomePos), Some); 400fa824dc0SYingwei Zheng EXPECT_EQ(Some.unionWith(SomeNeg), Some); 401fa824dc0SYingwei Zheng EXPECT_EQ(Finite.unionWith(One), Finite); 402fa824dc0SYingwei Zheng EXPECT_EQ(Some.unionWith(Zero), Some); 403fa824dc0SYingwei Zheng EXPECT_EQ(Finite.unionWith(PosInf).unionWith(NegInf).unionWith(NaN), Full); 404fa824dc0SYingwei Zheng EXPECT_EQ(PosZero.unionWith(NegZero), Zero); 405fa824dc0SYingwei Zheng EXPECT_EQ(NaN.unionWith(SNaN), NaN); 406fa824dc0SYingwei Zheng EXPECT_EQ(NaN.unionWith(QNaN), NaN); 407fa824dc0SYingwei Zheng EXPECT_EQ(SNaN.unionWith(QNaN), NaN); 408fa824dc0SYingwei Zheng EXPECT_EQ( 409fa824dc0SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(4.0)) 410fa824dc0SYingwei Zheng .unionWith(ConstantFPRange::getNonNaN(APFloat(3.0), APFloat(6.0))), 411fa824dc0SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(6.0))); 412fa824dc0SYingwei Zheng EXPECT_EQ( 413fa824dc0SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0)) 414fa824dc0SYingwei Zheng .unionWith(ConstantFPRange::getNonNaN(APFloat(5.0), APFloat(6.0))), 415fa824dc0SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(6.0))); 416fa824dc0SYingwei Zheng } 417fa824dc0SYingwei Zheng 418fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, FPClassify) { 419fa824dc0SYingwei Zheng EXPECT_EQ(Empty.classify(), fcNone); 420fa824dc0SYingwei Zheng EXPECT_EQ(Full.classify(), fcAllFlags); 421fa824dc0SYingwei Zheng EXPECT_EQ(Finite.classify(), fcFinite); 422fa824dc0SYingwei Zheng EXPECT_EQ(Zero.classify(), fcZero); 423fa824dc0SYingwei Zheng EXPECT_EQ(NaN.classify(), fcNan); 424fa824dc0SYingwei Zheng EXPECT_EQ(SNaN.classify(), fcSNan); 425fa824dc0SYingwei Zheng EXPECT_EQ(QNaN.classify(), fcQNan); 426fa824dc0SYingwei Zheng EXPECT_EQ(One.classify(), fcPosNormal); 427fa824dc0SYingwei Zheng EXPECT_EQ(Some.classify(), fcFinite); 428fa824dc0SYingwei Zheng EXPECT_EQ(SomePos.classify(), fcPosFinite); 429fa824dc0SYingwei Zheng EXPECT_EQ(SomeNeg.classify(), fcNegFinite); 430fa824dc0SYingwei Zheng EXPECT_EQ(PosInf.classify(), fcPosInf); 431fa824dc0SYingwei Zheng EXPECT_EQ(NegInf.classify(), fcNegInf); 432fa824dc0SYingwei Zheng EXPECT_EQ(Finite.getSignBit(), std::nullopt); 433fa824dc0SYingwei Zheng EXPECT_EQ(PosZero.getSignBit(), false); 434fa824dc0SYingwei Zheng EXPECT_EQ(NegZero.getSignBit(), true); 435fa824dc0SYingwei Zheng EXPECT_EQ(SomePos.getSignBit(), false); 436fa824dc0SYingwei Zheng EXPECT_EQ(SomeNeg.getSignBit(), true); 437fa824dc0SYingwei Zheng 438db4874c2SYingwei Zheng #if defined(EXPENSIVE_CHECKS) 439fa824dc0SYingwei Zheng EnumerateConstantFPRanges( 440fa824dc0SYingwei Zheng [](const ConstantFPRange &CR) { 441fa824dc0SYingwei Zheng unsigned Mask = fcNone; 442fa824dc0SYingwei Zheng bool HasPos = false, HasNeg = false; 443856774ddSYingwei Zheng EnumerateValuesInConstantFPRange( 444856774ddSYingwei Zheng CR, 445856774ddSYingwei Zheng [&](const APFloat &V) { 446fa824dc0SYingwei Zheng Mask |= V.classify(); 447fa824dc0SYingwei Zheng if (V.isNegative()) 448fa824dc0SYingwei Zheng HasNeg = true; 449fa824dc0SYingwei Zheng else 450fa824dc0SYingwei Zheng HasPos = true; 451856774ddSYingwei Zheng }, 452856774ddSYingwei Zheng /*IgnoreNaNPayload=*/true); 453fa824dc0SYingwei Zheng 454fa824dc0SYingwei Zheng std::optional<bool> SignBit = std::nullopt; 455fa824dc0SYingwei Zheng if (HasPos != HasNeg) 456fa824dc0SYingwei Zheng SignBit = HasNeg; 457fa824dc0SYingwei Zheng 458fa824dc0SYingwei Zheng EXPECT_EQ(SignBit, CR.getSignBit()) << CR; 459fa824dc0SYingwei Zheng EXPECT_EQ(Mask, CR.classify()) << CR; 460fa824dc0SYingwei Zheng }, 461fa824dc0SYingwei Zheng /*Exhaustive=*/true); 462db4874c2SYingwei Zheng #endif 463fa824dc0SYingwei Zheng } 464fa824dc0SYingwei Zheng 465fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, Print) { 466fa824dc0SYingwei Zheng auto ToString = [](const ConstantFPRange &CR) { 467fa824dc0SYingwei Zheng std::string Str; 468fa824dc0SYingwei Zheng raw_string_ostream OS(Str); 469fa824dc0SYingwei Zheng CR.print(OS); 470fa824dc0SYingwei Zheng return Str; 471fa824dc0SYingwei Zheng }; 472fa824dc0SYingwei Zheng 473fa824dc0SYingwei Zheng EXPECT_EQ(ToString(Full), "full-set"); 474fa824dc0SYingwei Zheng EXPECT_EQ(ToString(Empty), "empty-set"); 475fa824dc0SYingwei Zheng EXPECT_EQ(ToString(NaN), "NaN"); 476fa824dc0SYingwei Zheng EXPECT_EQ(ToString(SNaN), "SNaN"); 477fa824dc0SYingwei Zheng EXPECT_EQ(ToString(QNaN), "QNaN"); 478fa824dc0SYingwei Zheng EXPECT_EQ(ToString(One), "[1, 1]"); 479fa824dc0SYingwei Zheng EXPECT_EQ(ToString(Some.unionWith(SNaN)), "[-3, 3] with SNaN"); 480fa824dc0SYingwei Zheng } 481fa824dc0SYingwei Zheng 482fa824dc0SYingwei Zheng #ifdef GTEST_HAS_DEATH_TEST 483fa824dc0SYingwei Zheng #ifndef NDEBUG 484fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, NonCanonicalEmptySet) { 485c58e51acSYingwei Zheng EXPECT_DEATH((void)(ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(0.0))), 486fa824dc0SYingwei Zheng "Non-canonical form"); 487fa824dc0SYingwei Zheng } 488fa824dc0SYingwei Zheng TEST_F(ConstantFPRangeTest, MismatchedSemantics) { 489c58e51acSYingwei Zheng EXPECT_DEATH((void)(ConstantFPRange::getNonNaN(APFloat(0.0), APFloat(1.0f))), 490fa824dc0SYingwei Zheng "Should only use the same semantics"); 491c58e51acSYingwei Zheng EXPECT_DEATH((void)(One.contains(APFloat(1.0f))), 492fa824dc0SYingwei Zheng "Should only use the same semantics"); 493fa824dc0SYingwei Zheng ConstantFPRange OneF32 = ConstantFPRange(APFloat(1.0f)); 494c58e51acSYingwei Zheng EXPECT_DEATH((void)(One.contains(OneF32)), 495c58e51acSYingwei Zheng "Should only use the same semantics"); 496c58e51acSYingwei Zheng EXPECT_DEATH((void)(One.intersectWith(OneF32)), 497c58e51acSYingwei Zheng "Should only use the same semantics"); 498c58e51acSYingwei Zheng EXPECT_DEATH((void)(One.unionWith(OneF32)), 499c58e51acSYingwei Zheng "Should only use the same semantics"); 500fa824dc0SYingwei Zheng } 501fa824dc0SYingwei Zheng #endif 502fa824dc0SYingwei Zheng #endif 503fa824dc0SYingwei Zheng 50458673622SYingwei Zheng TEST_F(ConstantFPRangeTest, makeAllowedFCmpRegion) { 505db4874c2SYingwei Zheng EXPECT_EQ(ConstantFPRange::makeAllowedFCmpRegion( 506db4874c2SYingwei Zheng FCmpInst::FCMP_OLE, 507db4874c2SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0))), 508db4874c2SYingwei Zheng ConstantFPRange::getNonNaN(APFloat::getInf(Sem, /*Negative=*/true), 509db4874c2SYingwei Zheng APFloat(2.0))); 510db4874c2SYingwei Zheng EXPECT_EQ( 511db4874c2SYingwei Zheng ConstantFPRange::makeAllowedFCmpRegion( 512db4874c2SYingwei Zheng FCmpInst::FCMP_OLT, 513db4874c2SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), 514db4874c2SYingwei Zheng APFloat::getInf(Sem, /*Negative=*/false))), 515db4874c2SYingwei Zheng ConstantFPRange::getNonNaN(APFloat::getInf(Sem, /*Negative=*/true), 516db4874c2SYingwei Zheng APFloat::getLargest(Sem, /*Negative=*/false))); 517db4874c2SYingwei Zheng EXPECT_EQ( 518db4874c2SYingwei Zheng ConstantFPRange::makeAllowedFCmpRegion( 519db4874c2SYingwei Zheng FCmpInst::FCMP_OGT, 520db4874c2SYingwei Zheng ConstantFPRange::getNonNaN(APFloat::getZero(Sem, /*Negative=*/true), 521db4874c2SYingwei Zheng APFloat(2.0))), 522db4874c2SYingwei Zheng ConstantFPRange::getNonNaN(APFloat::getSmallest(Sem, /*Negative=*/false), 523db4874c2SYingwei Zheng APFloat::getInf(Sem, /*Negative=*/false))); 524db4874c2SYingwei Zheng EXPECT_EQ(ConstantFPRange::makeAllowedFCmpRegion( 525db4874c2SYingwei Zheng FCmpInst::FCMP_OGE, 526db4874c2SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0))), 527db4874c2SYingwei Zheng ConstantFPRange::getNonNaN( 528db4874c2SYingwei Zheng APFloat(1.0), APFloat::getInf(Sem, /*Negative=*/false))); 529db4874c2SYingwei Zheng EXPECT_EQ(ConstantFPRange::makeAllowedFCmpRegion( 530db4874c2SYingwei Zheng FCmpInst::FCMP_OEQ, 531db4874c2SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0))), 532db4874c2SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0))); 533db4874c2SYingwei Zheng 534db4874c2SYingwei Zheng #if defined(EXPENSIVE_CHECKS) 53558673622SYingwei Zheng for (auto Pred : FCmpInst::predicates()) { 53658673622SYingwei Zheng EnumerateConstantFPRanges( 53758673622SYingwei Zheng [Pred](const ConstantFPRange &CR) { 53858673622SYingwei Zheng ConstantFPRange Res = 53958673622SYingwei Zheng ConstantFPRange::makeAllowedFCmpRegion(Pred, CR); 54058673622SYingwei Zheng ConstantFPRange Optimal = 54158673622SYingwei Zheng ConstantFPRange::getEmpty(CR.getSemantics()); 54258673622SYingwei Zheng EnumerateValuesInConstantFPRange( 54358673622SYingwei Zheng ConstantFPRange::getFull(CR.getSemantics()), 54458673622SYingwei Zheng [&](const APFloat &V) { 545856774ddSYingwei Zheng if (AnyOfValueInConstantFPRange( 546856774ddSYingwei Zheng CR, 547856774ddSYingwei Zheng [&](const APFloat &U) { 54858673622SYingwei Zheng return FCmpInst::compare(V, U, Pred); 549856774ddSYingwei Zheng }, 550856774ddSYingwei Zheng /*IgnoreNaNPayload=*/true)) 55158673622SYingwei Zheng Optimal = Optimal.unionWith(ConstantFPRange(V)); 552856774ddSYingwei Zheng }, 553856774ddSYingwei Zheng /*IgnoreNaNPayload=*/true); 55458673622SYingwei Zheng 55558673622SYingwei Zheng EXPECT_TRUE(Res.contains(Optimal)) 55658673622SYingwei Zheng << "Wrong result for makeAllowedFCmpRegion(" << Pred << ", " << CR 55758673622SYingwei Zheng << "). Expected " << Optimal << ", but got " << Res; 55858673622SYingwei Zheng EXPECT_EQ(Res, Optimal) 55958673622SYingwei Zheng << "Suboptimal result for makeAllowedFCmpRegion(" << Pred << ", " 56058673622SYingwei Zheng << CR << ")"; 56158673622SYingwei Zheng }, 56258673622SYingwei Zheng /*Exhaustive=*/false); 56358673622SYingwei Zheng } 564db4874c2SYingwei Zheng #endif 56558673622SYingwei Zheng } 56658673622SYingwei Zheng 5674647a466SYingwei Zheng TEST_F(ConstantFPRangeTest, makeSatisfyingFCmpRegion) { 5684647a466SYingwei Zheng EXPECT_EQ(ConstantFPRange::makeSatisfyingFCmpRegion( 5694647a466SYingwei Zheng FCmpInst::FCMP_OLE, 5704647a466SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0))), 5714647a466SYingwei Zheng ConstantFPRange::getNonNaN(APFloat::getInf(Sem, /*Negative=*/true), 5724647a466SYingwei Zheng APFloat(1.0))); 5734647a466SYingwei Zheng EXPECT_EQ( 5744647a466SYingwei Zheng ConstantFPRange::makeSatisfyingFCmpRegion( 5754647a466SYingwei Zheng FCmpInst::FCMP_OLT, ConstantFPRange::getNonNaN( 5764647a466SYingwei Zheng APFloat::getSmallest(Sem, /*Negative=*/false), 5774647a466SYingwei Zheng APFloat::getInf(Sem, /*Negative=*/false))), 5784647a466SYingwei Zheng ConstantFPRange::getNonNaN(APFloat::getInf(Sem, /*Negative=*/true), 5794647a466SYingwei Zheng APFloat::getZero(Sem, /*Negative=*/false))); 5804647a466SYingwei Zheng EXPECT_EQ( 5814647a466SYingwei Zheng ConstantFPRange::makeSatisfyingFCmpRegion( 5824647a466SYingwei Zheng FCmpInst::FCMP_OGT, ConstantFPRange::getNonNaN( 5834647a466SYingwei Zheng APFloat::getZero(Sem, /*Negative=*/true), 5844647a466SYingwei Zheng APFloat::getZero(Sem, /*Negative=*/false))), 5854647a466SYingwei Zheng ConstantFPRange::getNonNaN(APFloat::getSmallest(Sem, /*Negative=*/false), 5864647a466SYingwei Zheng APFloat::getInf(Sem, /*Negative=*/false))); 5874647a466SYingwei Zheng EXPECT_EQ(ConstantFPRange::makeSatisfyingFCmpRegion( 5884647a466SYingwei Zheng FCmpInst::FCMP_OGE, 5894647a466SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0))), 5904647a466SYingwei Zheng ConstantFPRange::getNonNaN( 5914647a466SYingwei Zheng APFloat(2.0), APFloat::getInf(Sem, /*Negative=*/false))); 5924647a466SYingwei Zheng EXPECT_EQ(ConstantFPRange::makeSatisfyingFCmpRegion( 5934647a466SYingwei Zheng FCmpInst::FCMP_OEQ, 5944647a466SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0))), 5954647a466SYingwei Zheng ConstantFPRange::getEmpty(Sem)); 5964647a466SYingwei Zheng EXPECT_EQ(ConstantFPRange::makeSatisfyingFCmpRegion( 5974647a466SYingwei Zheng FCmpInst::FCMP_OEQ, 5984647a466SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(1.0))), 5994647a466SYingwei Zheng ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(1.0))); 6004647a466SYingwei Zheng 6014647a466SYingwei Zheng #if defined(EXPENSIVE_CHECKS) 6024647a466SYingwei Zheng for (auto Pred : FCmpInst::predicates()) { 6034647a466SYingwei Zheng EnumerateConstantFPRanges( 6044647a466SYingwei Zheng [Pred](const ConstantFPRange &CR) { 6054647a466SYingwei Zheng ConstantFPRange Res = 6064647a466SYingwei Zheng ConstantFPRange::makeSatisfyingFCmpRegion(Pred, CR); 6074647a466SYingwei Zheng // Super set of the optimal set excluding NaNs 6084647a466SYingwei Zheng ConstantFPRange SuperSet(CR.getSemantics()); 6094647a466SYingwei Zheng bool ContainsSNaN = false; 6104647a466SYingwei Zheng bool ContainsQNaN = false; 6114647a466SYingwei Zheng unsigned NonNaNValsInOptimalSet = 0; 6124647a466SYingwei Zheng EnumerateValuesInConstantFPRange( 6134647a466SYingwei Zheng ConstantFPRange::getFull(CR.getSemantics()), 6144647a466SYingwei Zheng [&](const APFloat &V) { 6154647a466SYingwei Zheng if (AnyOfValueInConstantFPRange( 6164647a466SYingwei Zheng CR, 6174647a466SYingwei Zheng [&](const APFloat &U) { 6184647a466SYingwei Zheng return !FCmpInst::compare(V, U, Pred); 6194647a466SYingwei Zheng }, 6204647a466SYingwei Zheng /*IgnoreNaNPayload=*/true)) { 6214647a466SYingwei Zheng EXPECT_FALSE(Res.contains(V)) 6224647a466SYingwei Zheng << "Wrong result for makeSatisfyingFCmpRegion(" << Pred 6234647a466SYingwei Zheng << ", " << CR << "). The result " << Res 6244647a466SYingwei Zheng << " should not contain " << V; 6254647a466SYingwei Zheng } else { 6264647a466SYingwei Zheng if (V.isNaN()) { 6274647a466SYingwei Zheng if (V.isSignaling()) 6284647a466SYingwei Zheng ContainsSNaN = true; 6294647a466SYingwei Zheng else 6304647a466SYingwei Zheng ContainsQNaN = true; 6314647a466SYingwei Zheng } else { 6324647a466SYingwei Zheng SuperSet = SuperSet.unionWith(ConstantFPRange(V)); 6334647a466SYingwei Zheng ++NonNaNValsInOptimalSet; 6344647a466SYingwei Zheng } 6354647a466SYingwei Zheng } 6364647a466SYingwei Zheng }, 6374647a466SYingwei Zheng /*IgnoreNaNPayload=*/true); 6384647a466SYingwei Zheng 6394647a466SYingwei Zheng // Check optimality 6404647a466SYingwei Zheng 6414647a466SYingwei Zheng // The usefullness of making the result optimal for one/une is 6424647a466SYingwei Zheng // questionable. 6434647a466SYingwei Zheng if (Pred == FCmpInst::FCMP_ONE || Pred == FCmpInst::FCMP_UNE) 6444647a466SYingwei Zheng return; 6454647a466SYingwei Zheng 6464647a466SYingwei Zheng EXPECT_FALSE(ContainsSNaN && !Res.containsSNaN()) 6474647a466SYingwei Zheng << "Suboptimal result for makeSatisfyingFCmpRegion(" << Pred 6484647a466SYingwei Zheng << ", " << CR << "), should contain SNaN, but got " << Res; 6494647a466SYingwei Zheng EXPECT_FALSE(ContainsQNaN && !Res.containsQNaN()) 6504647a466SYingwei Zheng << "Suboptimal result for makeSatisfyingFCmpRegion(" << Pred 6514647a466SYingwei Zheng << ", " << CR << "), should contain QNaN, but got " << Res; 6524647a466SYingwei Zheng 6534647a466SYingwei Zheng // We only care about the cases where the result is representable by 6544647a466SYingwei Zheng // ConstantFPRange. 6554647a466SYingwei Zheng unsigned NonNaNValsInSuperSet = 0; 6564647a466SYingwei Zheng EnumerateValuesInConstantFPRange( 6574647a466SYingwei Zheng SuperSet, 6584647a466SYingwei Zheng [&](const APFloat &V) { 6594647a466SYingwei Zheng if (!V.isNaN()) 6604647a466SYingwei Zheng ++NonNaNValsInSuperSet; 6614647a466SYingwei Zheng }, 6624647a466SYingwei Zheng /*IgnoreNaNPayload=*/true); 6634647a466SYingwei Zheng 6644647a466SYingwei Zheng if (NonNaNValsInSuperSet == NonNaNValsInOptimalSet) { 6654647a466SYingwei Zheng ConstantFPRange Optimal = 6664647a466SYingwei Zheng ConstantFPRange(SuperSet.getLower(), SuperSet.getUpper(), 6674647a466SYingwei Zheng ContainsQNaN, ContainsSNaN); 6684647a466SYingwei Zheng EXPECT_EQ(Res, Optimal) 6694647a466SYingwei Zheng << "Suboptimal result for makeSatisfyingFCmpRegion(" << Pred 6704647a466SYingwei Zheng << ", " << CR << ")"; 6714647a466SYingwei Zheng } 6724647a466SYingwei Zheng }, 6734647a466SYingwei Zheng /*Exhaustive=*/false); 6744647a466SYingwei Zheng } 6754647a466SYingwei Zheng #endif 6764647a466SYingwei Zheng } 6774647a466SYingwei Zheng 6784647a466SYingwei Zheng TEST_F(ConstantFPRangeTest, fcmp) { 6794647a466SYingwei Zheng std::vector<ConstantFPRange> InterestingRanges; 6804647a466SYingwei Zheng const fltSemantics &Sem = APFloat::Float8E4M3(); 6814647a466SYingwei Zheng auto FpImm = [&](double V) { 6824647a466SYingwei Zheng bool ignored; 6834647a466SYingwei Zheng APFloat APF(V); 6844647a466SYingwei Zheng APF.convert(Sem, APFloat::rmNearestTiesToEven, &ignored); 6854647a466SYingwei Zheng return APF; 6864647a466SYingwei Zheng }; 6874647a466SYingwei Zheng 6884647a466SYingwei Zheng InterestingRanges.push_back(ConstantFPRange::getEmpty(Sem)); 6894647a466SYingwei Zheng InterestingRanges.push_back(ConstantFPRange::getFull(Sem)); 6904647a466SYingwei Zheng InterestingRanges.push_back(ConstantFPRange::getFinite(Sem)); 6914647a466SYingwei Zheng InterestingRanges.push_back(ConstantFPRange(FpImm(1.0))); 6924647a466SYingwei Zheng InterestingRanges.push_back( 6934647a466SYingwei Zheng ConstantFPRange(APFloat::getZero(Sem, /*Negative=*/false))); 6944647a466SYingwei Zheng InterestingRanges.push_back( 6954647a466SYingwei Zheng ConstantFPRange(APFloat::getZero(Sem, /*Negative=*/true))); 6964647a466SYingwei Zheng InterestingRanges.push_back( 6974647a466SYingwei Zheng ConstantFPRange(APFloat::getInf(Sem, /*Negative=*/false))); 6984647a466SYingwei Zheng InterestingRanges.push_back( 6994647a466SYingwei Zheng ConstantFPRange(APFloat::getInf(Sem, /*Negative=*/true))); 7004647a466SYingwei Zheng InterestingRanges.push_back( 7014647a466SYingwei Zheng ConstantFPRange(APFloat::getSmallest(Sem, /*Negative=*/false))); 7024647a466SYingwei Zheng InterestingRanges.push_back( 7034647a466SYingwei Zheng ConstantFPRange(APFloat::getSmallest(Sem, /*Negative=*/true))); 7044647a466SYingwei Zheng InterestingRanges.push_back( 7054647a466SYingwei Zheng ConstantFPRange(APFloat::getLargest(Sem, /*Negative=*/false))); 7064647a466SYingwei Zheng InterestingRanges.push_back( 7074647a466SYingwei Zheng ConstantFPRange(APFloat::getLargest(Sem, /*Negative=*/true))); 7084647a466SYingwei Zheng InterestingRanges.push_back( 7094647a466SYingwei Zheng ConstantFPRange::getNaNOnly(Sem, /*MayBeQNaN=*/true, /*MayBeSNaN=*/true)); 7104647a466SYingwei Zheng InterestingRanges.push_back( 7114647a466SYingwei Zheng ConstantFPRange::getNonNaN(FpImm(0.0), FpImm(1.0))); 7124647a466SYingwei Zheng InterestingRanges.push_back( 7134647a466SYingwei Zheng ConstantFPRange::getNonNaN(FpImm(2.0), FpImm(3.0))); 7144647a466SYingwei Zheng InterestingRanges.push_back( 7154647a466SYingwei Zheng ConstantFPRange::getNonNaN(FpImm(-1.0), FpImm(1.0))); 7164647a466SYingwei Zheng InterestingRanges.push_back( 7174647a466SYingwei Zheng ConstantFPRange::getNonNaN(FpImm(-1.0), FpImm(-0.0))); 7184647a466SYingwei Zheng InterestingRanges.push_back(ConstantFPRange::getNonNaN( 7194647a466SYingwei Zheng APFloat::getInf(Sem, /*Negative=*/true), FpImm(-1.0))); 7204647a466SYingwei Zheng InterestingRanges.push_back(ConstantFPRange::getNonNaN( 7214647a466SYingwei Zheng FpImm(1.0), APFloat::getInf(Sem, /*Negative=*/false))); 7224647a466SYingwei Zheng 7234647a466SYingwei Zheng for (auto &LHS : InterestingRanges) { 7244647a466SYingwei Zheng for (auto &RHS : InterestingRanges) { 7254647a466SYingwei Zheng for (auto Pred : FCmpInst::predicates()) { 7264647a466SYingwei Zheng if (LHS.fcmp(Pred, RHS)) { 7274647a466SYingwei Zheng EnumerateValuesInConstantFPRange( 7284647a466SYingwei Zheng LHS, 7294647a466SYingwei Zheng [&](const APFloat &LHSC) { 7304647a466SYingwei Zheng EnumerateValuesInConstantFPRange( 7314647a466SYingwei Zheng RHS, 7324647a466SYingwei Zheng [&](const APFloat &RHSC) { 7334647a466SYingwei Zheng EXPECT_TRUE(FCmpInst::compare(LHSC, RHSC, Pred)) 7344647a466SYingwei Zheng << LHS << " " << Pred << " " << RHS 7354647a466SYingwei Zheng << " doesn't hold"; 7364647a466SYingwei Zheng }, 7374647a466SYingwei Zheng /*IgnoreNaNPayload=*/true); 7384647a466SYingwei Zheng }, 7394647a466SYingwei Zheng /*IgnoreNaNPayload=*/true); 7404647a466SYingwei Zheng } 7414647a466SYingwei Zheng } 7424647a466SYingwei Zheng } 7434647a466SYingwei Zheng } 7444647a466SYingwei Zheng } 7454647a466SYingwei Zheng 746*a3a253d3SYingwei Zheng TEST_F(ConstantFPRangeTest, makeExactFCmpRegion) { 747*a3a253d3SYingwei Zheng for (auto Pred : FCmpInst::predicates()) { 748*a3a253d3SYingwei Zheng EnumerateValuesInConstantFPRange( 749*a3a253d3SYingwei Zheng ConstantFPRange::getFull(APFloat::Float8E4M3()), 750*a3a253d3SYingwei Zheng [Pred](const APFloat &V) { 751*a3a253d3SYingwei Zheng std::optional<ConstantFPRange> Res = 752*a3a253d3SYingwei Zheng ConstantFPRange::makeExactFCmpRegion(Pred, V); 753*a3a253d3SYingwei Zheng ConstantFPRange Allowed = 754*a3a253d3SYingwei Zheng ConstantFPRange::makeAllowedFCmpRegion(Pred, ConstantFPRange(V)); 755*a3a253d3SYingwei Zheng ConstantFPRange Satisfying = 756*a3a253d3SYingwei Zheng ConstantFPRange::makeSatisfyingFCmpRegion(Pred, 757*a3a253d3SYingwei Zheng ConstantFPRange(V)); 758*a3a253d3SYingwei Zheng if (Allowed == Satisfying) 759*a3a253d3SYingwei Zheng EXPECT_EQ(Res, Allowed) << "Wrong result for makeExactFCmpRegion(" 760*a3a253d3SYingwei Zheng << Pred << ", " << V << ")."; 761*a3a253d3SYingwei Zheng else 762*a3a253d3SYingwei Zheng EXPECT_FALSE(Res.has_value()) 763*a3a253d3SYingwei Zheng << "Wrong result for makeExactFCmpRegion(" << Pred << ", " << V 764*a3a253d3SYingwei Zheng << ")."; 765*a3a253d3SYingwei Zheng }, 766*a3a253d3SYingwei Zheng /*IgnoreNaNPayload=*/true); 767*a3a253d3SYingwei Zheng } 768*a3a253d3SYingwei Zheng } 769*a3a253d3SYingwei Zheng 770fa824dc0SYingwei Zheng } // anonymous namespace 771