@@ -22,6 +22,7 @@ class ConstantFPRangeTest : public ::testing::Test {
2222 static ConstantFPRange Full;
2323 static ConstantFPRange Empty;
2424 static ConstantFPRange Finite;
25+ static ConstantFPRange NonNaN;
2526 static ConstantFPRange One;
2627 static ConstantFPRange PosZero;
2728 static ConstantFPRange NegZero;
@@ -44,6 +45,8 @@ ConstantFPRange ConstantFPRangeTest::Empty =
4445 ConstantFPRange::getEmpty (APFloat::IEEEdouble());
4546ConstantFPRange ConstantFPRangeTest::Finite =
4647 ConstantFPRange::getFinite (APFloat::IEEEdouble());
48+ ConstantFPRange ConstantFPRangeTest::NonNaN =
49+ ConstantFPRange::getNonNaN (APFloat::IEEEdouble());
4750ConstantFPRange ConstantFPRangeTest::One = ConstantFPRange(APFloat(1.0 ));
4851ConstantFPRange ConstantFPRangeTest::PosZero = ConstantFPRange(
4952 APFloat::getZero (APFloat::IEEEdouble(), /* Negative=*/ false));
@@ -79,26 +82,35 @@ static void strictNext(APFloat &V) {
7982 V.next (/* nextDown=*/ false );
8083}
8184
85+ enum class SparseLevel {
86+ Dense,
87+ SpecialValuesWithAllPowerOfTwos,
88+ SpecialValuesOnly,
89+ };
90+
8291template <typename Fn>
83- static void EnumerateConstantFPRangesImpl (Fn TestFn, bool Exhaustive ,
92+ static void EnumerateConstantFPRangesImpl (Fn TestFn, SparseLevel Level ,
8493 bool MayBeQNaN, bool MayBeSNaN) {
8594 const fltSemantics &Sem = APFloat::Float8E4M3 ();
8695 APFloat PosInf = APFloat::getInf (Sem, /* Negative=*/ false );
8796 APFloat NegInf = APFloat::getInf (Sem, /* Negative=*/ true );
8897 TestFn (ConstantFPRange (PosInf, NegInf, MayBeQNaN, MayBeSNaN));
8998
90- if (!Exhaustive ) {
99+ if (Level != SparseLevel::Dense ) {
91100 SmallVector<APFloat, 36 > Values;
92101 Values.push_back (APFloat::getInf (Sem, /* Negative=*/ true ));
93102 Values.push_back (APFloat::getLargest (Sem, /* Negative=*/ true ));
94103 unsigned BitWidth = APFloat::semanticsSizeInBits (Sem);
95104 unsigned Exponents = APFloat::semanticsMaxExponent (Sem) -
96105 APFloat::semanticsMinExponent (Sem) + 3 ;
97106 unsigned MantissaBits = APFloat::semanticsPrecision (Sem) - 1 ;
98- // Add -2^(max exponent), -2^(max exponent-1), ..., -2^(min exponent)
99- for (unsigned M = Exponents - 2 ; M != 0 ; --M)
100- Values.push_back (
101- APFloat (Sem, APInt (BitWidth, (M + Exponents) << MantissaBits)));
107+ if (Level == SparseLevel::SpecialValuesWithAllPowerOfTwos) {
108+ // Add -2^(max exponent), -2^(max exponent-1), ..., -2^(min exponent)
109+ for (unsigned M = Exponents - 2 ; M != 0 ; --M)
110+ Values.push_back (
111+ APFloat (Sem, APInt (BitWidth, (M + Exponents) << MantissaBits)));
112+ }
113+ Values.push_back (APFloat::getSmallestNormalized (Sem, /* Negative=*/ true ));
102114 Values.push_back (APFloat::getSmallest (Sem, /* Negative=*/ true ));
103115 Values.push_back (APFloat::getZero (Sem, /* Negative=*/ true ));
104116 size_t E = Values.size ();
@@ -127,26 +139,30 @@ static void EnumerateConstantFPRangesImpl(Fn TestFn, bool Exhaustive,
127139}
128140
129141template <typename Fn>
130- static void EnumerateConstantFPRanges (Fn TestFn, bool Exhaustive) {
131- EnumerateConstantFPRangesImpl (TestFn, Exhaustive, /* MayBeQNaN=*/ false ,
142+ static void EnumerateConstantFPRanges (Fn TestFn, SparseLevel Level,
143+ bool IgnoreSNaNs = false ) {
144+ EnumerateConstantFPRangesImpl (TestFn, Level, /* MayBeQNaN=*/ false ,
132145 /* MayBeSNaN=*/ false );
133- EnumerateConstantFPRangesImpl (TestFn, Exhaustive, /* MayBeQNaN=*/ false ,
134- /* MayBeSNaN=*/ true );
135- EnumerateConstantFPRangesImpl (TestFn, Exhaustive, /* MayBeQNaN=*/ true ,
146+ EnumerateConstantFPRangesImpl (TestFn, Level, /* MayBeQNaN=*/ true ,
136147 /* MayBeSNaN=*/ false );
137- EnumerateConstantFPRangesImpl (TestFn, Exhaustive, /* MayBeQNaN=*/ true ,
148+ if (IgnoreSNaNs)
149+ return ;
150+ EnumerateConstantFPRangesImpl (TestFn, Level, /* MayBeQNaN=*/ false ,
151+ /* MayBeSNaN=*/ true );
152+ EnumerateConstantFPRangesImpl (TestFn, Level, /* MayBeQNaN=*/ true ,
138153 /* MayBeSNaN=*/ true );
139154}
140155
141156template <typename Fn>
142157static void EnumerateTwoInterestingConstantFPRanges (Fn TestFn,
143- bool Exhaustive ) {
158+ SparseLevel Level ) {
144159 EnumerateConstantFPRanges (
145160 [&](const ConstantFPRange &CR1) {
146161 EnumerateConstantFPRanges (
147- [&](const ConstantFPRange &CR2) { TestFn (CR1, CR2); }, Exhaustive);
162+ [&](const ConstantFPRange &CR2) { TestFn (CR1, CR2); }, Level,
163+ /* IgnoreSNaNs=*/ true );
148164 },
149- Exhaustive );
165+ Level, /* IgnoreSNaNs= */ true );
150166}
151167
152168template <typename Fn>
@@ -348,16 +364,25 @@ TEST_F(ConstantFPRangeTest, ExhaustivelyEnumerate) {
348364 constexpr unsigned Expected = 4 * ((NNaNValues + 1 ) * NNaNValues / 2 + 1 );
349365 unsigned Count = 0 ;
350366 EnumerateConstantFPRanges ([&](const ConstantFPRange &) { ++Count; },
351- /* Exhaustive= */ true );
367+ SparseLevel::Dense );
352368 EXPECT_EQ (Expected, Count);
353369}
354370
355371TEST_F (ConstantFPRangeTest, Enumerate) {
356- constexpr unsigned NNaNValues = 2 * ((1 << 4 ) - 2 + 4 );
372+ constexpr unsigned NNaNValues = 2 * ((1 << 4 ) - 2 + 5 );
357373 constexpr unsigned Expected = 4 * ((NNaNValues + 1 ) * NNaNValues / 2 + 1 );
358374 unsigned Count = 0 ;
359375 EnumerateConstantFPRanges ([&](const ConstantFPRange &) { ++Count; },
360- /* Exhaustive=*/ false );
376+ SparseLevel::SpecialValuesWithAllPowerOfTwos);
377+ EXPECT_EQ (Expected, Count);
378+ }
379+
380+ TEST_F (ConstantFPRangeTest, EnumerateWithSpecialValuesOnly) {
381+ constexpr unsigned NNaNValues = 2 * 5 ;
382+ constexpr unsigned Expected = 4 * ((NNaNValues + 1 ) * NNaNValues / 2 + 1 );
383+ unsigned Count = 0 ;
384+ EnumerateConstantFPRanges ([&](const ConstantFPRange &) { ++Count; },
385+ SparseLevel::SpecialValuesOnly);
361386 EXPECT_EQ (Expected, Count);
362387}
363388
@@ -459,7 +484,7 @@ TEST_F(ConstantFPRangeTest, FPClassify) {
459484 EXPECT_EQ (SignBit, CR.getSignBit ()) << CR;
460485 EXPECT_EQ (Mask, CR.classify ()) << CR;
461486 },
462- /* Exhaustive= */ true );
487+ SparseLevel::Dense );
463488#endif
464489}
465490
@@ -560,7 +585,7 @@ TEST_F(ConstantFPRangeTest, makeAllowedFCmpRegion) {
560585 << " Suboptimal result for makeAllowedFCmpRegion(" << Pred << " , "
561586 << CR << " )" ;
562587 },
563- /* Exhaustive= */ false );
588+ SparseLevel::SpecialValuesWithAllPowerOfTwos );
564589 }
565590#endif
566591}
@@ -671,7 +696,7 @@ TEST_F(ConstantFPRangeTest, makeSatisfyingFCmpRegion) {
671696 << " , " << CR << " )" ;
672697 }
673698 },
674- /* Exhaustive= */ false );
699+ SparseLevel::SpecialValuesWithAllPowerOfTwos );
675700 }
676701#endif
677702}
@@ -804,13 +829,13 @@ TEST_F(ConstantFPRangeTest, negate) {
804829}
805830
806831TEST_F (ConstantFPRangeTest, getWithout) {
807- EXPECT_EQ (Full.getWithoutNaN (), ConstantFPRange::getNonNaN (Sem) );
832+ EXPECT_EQ (Full.getWithoutNaN (), NonNaN );
808833 EXPECT_EQ (NaN.getWithoutNaN (), Empty);
809834
810835 EXPECT_EQ (NaN.getWithoutInf (), NaN);
811836 EXPECT_EQ (PosInf.getWithoutInf (), Empty);
812837 EXPECT_EQ (NegInf.getWithoutInf (), Empty);
813- EXPECT_EQ (ConstantFPRange::getNonNaN (Sem) .getWithoutInf (), Finite);
838+ EXPECT_EQ (NonNaN .getWithoutInf (), Finite);
814839 EXPECT_EQ (Zero.getWithoutInf (), Zero);
815840 EXPECT_EQ (ConstantFPRange::getNonNaN (APFloat::getInf (Sem, /* Negative=*/ true ),
816841 APFloat (3.0 ))
@@ -925,4 +950,119 @@ TEST_F(ConstantFPRangeTest, cast) {
925950 /* IgnoreNaNPayload=*/ true );
926951}
927952
953+ TEST_F (ConstantFPRangeTest, add) {
954+ EXPECT_EQ (Full.add (Full), NonNaN.unionWith (QNaN));
955+ EXPECT_EQ (Full.add (Empty), Empty);
956+ EXPECT_EQ (Empty.add (Full), Empty);
957+ EXPECT_EQ (Empty.add (Empty), Empty);
958+ EXPECT_EQ (One.add (One), ConstantFPRange (APFloat (2.0 )));
959+ EXPECT_EQ (Some.add (Some),
960+ ConstantFPRange::getNonNaN (APFloat (-6.0 ), APFloat (6.0 )));
961+ EXPECT_EQ (SomePos.add (SomeNeg),
962+ ConstantFPRange::getNonNaN (APFloat (-3.0 ), APFloat (3.0 )));
963+ EXPECT_EQ (PosInf.add (PosInf), PosInf);
964+ EXPECT_EQ (NegInf.add (NegInf), NegInf);
965+ EXPECT_EQ (PosInf.add (Finite.unionWith (PosInf)), PosInf);
966+ EXPECT_EQ (NegInf.add (Finite.unionWith (NegInf)), NegInf);
967+ EXPECT_EQ (PosInf.add (Finite.unionWith (NegInf)), PosInf.unionWith (QNaN));
968+ EXPECT_EQ (NegInf.add (Finite.unionWith (PosInf)), NegInf.unionWith (QNaN));
969+ EXPECT_EQ (PosInf.add (NegInf), QNaN);
970+ EXPECT_EQ (NegInf.add (PosInf), QNaN);
971+ EXPECT_EQ (PosZero.add (NegZero), PosZero);
972+ EXPECT_EQ (PosZero.add (Zero), PosZero);
973+ EXPECT_EQ (NegZero.add (NegZero), NegZero);
974+ EXPECT_EQ (NegZero.add (Zero), Zero);
975+ EXPECT_EQ (NaN.add (NaN), QNaN);
976+ EXPECT_EQ (NaN.add (Finite), QNaN);
977+ EXPECT_EQ (NonNaN.unionWith (NaN).add (NonNaN), NonNaN.unionWith (QNaN));
978+ EXPECT_EQ (PosInf.unionWith (QNaN).add (PosInf), PosInf.unionWith (QNaN));
979+ EXPECT_EQ (PosInf.unionWith (NaN).add (ConstantFPRange (APFloat (24.0 ))),
980+ PosInf.unionWith (QNaN));
981+
982+ #if defined(EXPENSIVE_CHECKS)
983+ EnumerateTwoInterestingConstantFPRanges (
984+ [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) {
985+ ConstantFPRange Res = LHS.add (RHS);
986+ ConstantFPRange Expected =
987+ ConstantFPRange::getEmpty (LHS.getSemantics ());
988+ EnumerateValuesInConstantFPRange (
989+ LHS,
990+ [&](const APFloat &LHSC) {
991+ EnumerateValuesInConstantFPRange (
992+ RHS,
993+ [&](const APFloat &RHSC) {
994+ APFloat Sum = LHSC + RHSC;
995+ EXPECT_TRUE (Res.contains (Sum))
996+ << " Wrong result for " << LHS << " + " << RHS
997+ << " . The result " << Res << " should contain " << Sum;
998+ if (!Expected.contains (Sum))
999+ Expected = Expected.unionWith (ConstantFPRange (Sum));
1000+ },
1001+ /* IgnoreNaNPayload=*/ true );
1002+ },
1003+ /* IgnoreNaNPayload=*/ true );
1004+ EXPECT_EQ (Res, Expected)
1005+ << " Suboptimal result for " << LHS << " + " << RHS << " . Expected "
1006+ << Expected << " , but got " << Res;
1007+ },
1008+ SparseLevel::SpecialValuesOnly);
1009+ #endif
1010+ }
1011+
1012+ TEST_F (ConstantFPRangeTest, sub) {
1013+ EXPECT_EQ (Full.sub (Full), NonNaN.unionWith (QNaN));
1014+ EXPECT_EQ (Full.sub (Empty), Empty);
1015+ EXPECT_EQ (Empty.sub (Full), Empty);
1016+ EXPECT_EQ (Empty.sub (Empty), Empty);
1017+ EXPECT_EQ (One.sub (One), ConstantFPRange (APFloat (0.0 )));
1018+ EXPECT_EQ (Some.sub (Some),
1019+ ConstantFPRange::getNonNaN (APFloat (-6.0 ), APFloat (6.0 )));
1020+ EXPECT_EQ (SomePos.sub (SomeNeg),
1021+ ConstantFPRange::getNonNaN (APFloat (0.0 ), APFloat (6.0 )));
1022+ EXPECT_EQ (PosInf.sub (NegInf), PosInf);
1023+ EXPECT_EQ (NegInf.sub (PosInf), NegInf);
1024+ EXPECT_EQ (PosInf.sub (Finite.unionWith (NegInf)), PosInf);
1025+ EXPECT_EQ (NegInf.sub (Finite.unionWith (PosInf)), NegInf);
1026+ EXPECT_EQ (PosInf.sub (Finite.unionWith (PosInf)), PosInf.unionWith (QNaN));
1027+ EXPECT_EQ (NegInf.sub (Finite.unionWith (NegInf)), NegInf.unionWith (QNaN));
1028+ EXPECT_EQ (PosInf.sub (PosInf), QNaN);
1029+ EXPECT_EQ (NegInf.sub (NegInf), QNaN);
1030+ EXPECT_EQ (PosZero.sub (NegZero), PosZero);
1031+ EXPECT_EQ (PosZero.sub (Zero), PosZero);
1032+ EXPECT_EQ (NegZero.sub (NegZero), PosZero);
1033+ EXPECT_EQ (NegZero.sub (PosZero), NegZero);
1034+ EXPECT_EQ (NegZero.sub (Zero), Zero);
1035+ EXPECT_EQ (NaN.sub (NaN), QNaN);
1036+ EXPECT_EQ (NaN.add (Finite), QNaN);
1037+
1038+ #if defined(EXPENSIVE_CHECKS)
1039+ EnumerateTwoInterestingConstantFPRanges (
1040+ [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) {
1041+ ConstantFPRange Res = LHS.sub (RHS);
1042+ ConstantFPRange Expected =
1043+ ConstantFPRange::getEmpty (LHS.getSemantics ());
1044+ EnumerateValuesInConstantFPRange (
1045+ LHS,
1046+ [&](const APFloat &LHSC) {
1047+ EnumerateValuesInConstantFPRange (
1048+ RHS,
1049+ [&](const APFloat &RHSC) {
1050+ APFloat Diff = LHSC - RHSC;
1051+ EXPECT_TRUE (Res.contains (Diff))
1052+ << " Wrong result for " << LHS << " - " << RHS
1053+ << " . The result " << Res << " should contain " << Diff;
1054+ if (!Expected.contains (Diff))
1055+ Expected = Expected.unionWith (ConstantFPRange (Diff));
1056+ },
1057+ /* IgnoreNaNPayload=*/ true );
1058+ },
1059+ /* IgnoreNaNPayload=*/ true );
1060+ EXPECT_EQ (Res, Expected)
1061+ << " Suboptimal result for " << LHS << " - " << RHS << " . Expected "
1062+ << Expected << " , but got " << Res;
1063+ },
1064+ SparseLevel::SpecialValuesOnly);
1065+ #endif
1066+ }
1067+
9281068} // anonymous namespace
0 commit comments