xref: /llvm-project/llvm/unittests/IR/ConstantFPRangeTest.cpp (revision a3a253d3c7780977077dd46493917b1949c0166d)
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