@@ -79,26 +79,35 @@ static void strictNext(APFloat &V) {
7979 V.next (/* nextDown=*/ false );
8080}
8181
82+ enum class SparseLevel {
83+ Dense,
84+ SpecialValuesWithAllPowerOfTwos,
85+ SpecialValuesOnly,
86+ };
87+
8288template <typename Fn>
83- static void EnumerateConstantFPRangesImpl (Fn TestFn, bool Exhaustive ,
89+ static void EnumerateConstantFPRangesImpl (Fn TestFn, SparseLevel Level ,
8490 bool MayBeQNaN, bool MayBeSNaN) {
8591 const fltSemantics &Sem = APFloat::Float8E4M3 ();
8692 APFloat PosInf = APFloat::getInf (Sem, /* Negative=*/ false );
8793 APFloat NegInf = APFloat::getInf (Sem, /* Negative=*/ true );
8894 TestFn (ConstantFPRange (PosInf, NegInf, MayBeQNaN, MayBeSNaN));
8995
90- if (!Exhaustive ) {
96+ if (Level != SparseLevel::Dense ) {
9197 SmallVector<APFloat, 36 > Values;
9298 Values.push_back (APFloat::getInf (Sem, /* Negative=*/ true ));
9399 Values.push_back (APFloat::getLargest (Sem, /* Negative=*/ true ));
94100 unsigned BitWidth = APFloat::semanticsSizeInBits (Sem);
95101 unsigned Exponents = APFloat::semanticsMaxExponent (Sem) -
96102 APFloat::semanticsMinExponent (Sem) + 3 ;
97103 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)));
104+ if (Level == SparseLevel::SpecialValuesWithAllPowerOfTwos) {
105+ // Add -2^(max exponent), -2^(max exponent-1), ..., -2^(min exponent)
106+ for (unsigned M = Exponents - 2 ; M != 0 ; --M)
107+ Values.push_back (
108+ APFloat (Sem, APInt (BitWidth, (M + Exponents) << MantissaBits)));
109+ }
110+ Values.push_back (APFloat::getSmallestNormalized (Sem, /* Negative=*/ true ));
102111 Values.push_back (APFloat::getSmallest (Sem, /* Negative=*/ true ));
103112 Values.push_back (APFloat::getZero (Sem, /* Negative=*/ true ));
104113 size_t E = Values.size ();
@@ -127,26 +136,30 @@ static void EnumerateConstantFPRangesImpl(Fn TestFn, bool Exhaustive,
127136}
128137
129138template <typename Fn>
130- static void EnumerateConstantFPRanges (Fn TestFn, bool Exhaustive) {
131- EnumerateConstantFPRangesImpl (TestFn, Exhaustive, /* MayBeQNaN=*/ false ,
139+ static void EnumerateConstantFPRanges (Fn TestFn, SparseLevel Level,
140+ bool IgnoreNaNs = false ) {
141+ EnumerateConstantFPRangesImpl (TestFn, Level, /* MayBeQNaN=*/ false ,
132142 /* MayBeSNaN=*/ false );
133- EnumerateConstantFPRangesImpl (TestFn, Exhaustive, /* MayBeQNaN=*/ false ,
143+ if (IgnoreNaNs)
144+ return ;
145+ EnumerateConstantFPRangesImpl (TestFn, Level, /* MayBeQNaN=*/ false ,
134146 /* MayBeSNaN=*/ true );
135- EnumerateConstantFPRangesImpl (TestFn, Exhaustive , /* MayBeQNaN=*/ true ,
147+ EnumerateConstantFPRangesImpl (TestFn, Level , /* MayBeQNaN=*/ true ,
136148 /* MayBeSNaN=*/ false );
137- EnumerateConstantFPRangesImpl (TestFn, Exhaustive , /* MayBeQNaN=*/ true ,
149+ EnumerateConstantFPRangesImpl (TestFn, Level , /* MayBeQNaN=*/ true ,
138150 /* MayBeSNaN=*/ true );
139151}
140152
141153template <typename Fn>
142154static void EnumerateTwoInterestingConstantFPRanges (Fn TestFn,
143- bool Exhaustive ) {
155+ SparseLevel Level ) {
144156 EnumerateConstantFPRanges (
145157 [&](const ConstantFPRange &CR1) {
146158 EnumerateConstantFPRanges (
147- [&](const ConstantFPRange &CR2) { TestFn (CR1, CR2); }, Exhaustive);
159+ [&](const ConstantFPRange &CR2) { TestFn (CR1, CR2); }, Level,
160+ /* IgnoreNaNs=*/ true );
148161 },
149- Exhaustive );
162+ Level, /* IgnoreNaNs= */ true );
150163}
151164
152165template <typename Fn>
@@ -348,16 +361,25 @@ TEST_F(ConstantFPRangeTest, ExhaustivelyEnumerate) {
348361 constexpr unsigned Expected = 4 * ((NNaNValues + 1 ) * NNaNValues / 2 + 1 );
349362 unsigned Count = 0 ;
350363 EnumerateConstantFPRanges ([&](const ConstantFPRange &) { ++Count; },
351- /* Exhaustive= */ true );
364+ SparseLevel::Dense );
352365 EXPECT_EQ (Expected, Count);
353366}
354367
355368TEST_F (ConstantFPRangeTest, Enumerate) {
356- constexpr unsigned NNaNValues = 2 * ((1 << 4 ) - 2 + 4 );
369+ constexpr unsigned NNaNValues = 2 * ((1 << 4 ) - 2 + 5 );
370+ constexpr unsigned Expected = 4 * ((NNaNValues + 1 ) * NNaNValues / 2 + 1 );
371+ unsigned Count = 0 ;
372+ EnumerateConstantFPRanges ([&](const ConstantFPRange &) { ++Count; },
373+ SparseLevel::SpecialValuesWithAllPowerOfTwos);
374+ EXPECT_EQ (Expected, Count);
375+ }
376+
377+ TEST_F (ConstantFPRangeTest, EnumerateWithSpecialValuesOnly) {
378+ constexpr unsigned NNaNValues = 2 * 5 ;
357379 constexpr unsigned Expected = 4 * ((NNaNValues + 1 ) * NNaNValues / 2 + 1 );
358380 unsigned Count = 0 ;
359381 EnumerateConstantFPRanges ([&](const ConstantFPRange &) { ++Count; },
360- /* Exhaustive= */ false );
382+ SparseLevel::SpecialValuesOnly );
361383 EXPECT_EQ (Expected, Count);
362384}
363385
@@ -459,7 +481,7 @@ TEST_F(ConstantFPRangeTest, FPClassify) {
459481 EXPECT_EQ (SignBit, CR.getSignBit ()) << CR;
460482 EXPECT_EQ (Mask, CR.classify ()) << CR;
461483 },
462- /* Exhaustive= */ true );
484+ SparseLevel::Dense );
463485#endif
464486}
465487
@@ -560,7 +582,7 @@ TEST_F(ConstantFPRangeTest, makeAllowedFCmpRegion) {
560582 << " Suboptimal result for makeAllowedFCmpRegion(" << Pred << " , "
561583 << CR << " )" ;
562584 },
563- /* Exhaustive= */ false );
585+ SparseLevel::SpecialValuesWithAllPowerOfTwos );
564586 }
565587#endif
566588}
@@ -671,7 +693,7 @@ TEST_F(ConstantFPRangeTest, makeSatisfyingFCmpRegion) {
671693 << " , " << CR << " )" ;
672694 }
673695 },
674- /* Exhaustive= */ false );
696+ SparseLevel::SpecialValuesWithAllPowerOfTwos );
675697 }
676698#endif
677699}
@@ -925,4 +947,113 @@ TEST_F(ConstantFPRangeTest, cast) {
925947 /* IgnoreNaNPayload=*/ true );
926948}
927949
950+ TEST_F (ConstantFPRangeTest, add) {
951+ EXPECT_EQ (Full.add (Full), ConstantFPRange::getNonNaN (Sem).unionWith (QNaN));
952+ EXPECT_EQ (Full.add (Empty), Empty);
953+ EXPECT_EQ (Empty.add (Full), Empty);
954+ EXPECT_EQ (Empty.add (Empty), Empty);
955+ EXPECT_EQ (One.add (One), ConstantFPRange (APFloat (2.0 )));
956+ EXPECT_EQ (Some.add (Some),
957+ ConstantFPRange::getNonNaN (APFloat (-6.0 ), APFloat (6.0 )));
958+ EXPECT_EQ (SomePos.add (SomeNeg),
959+ ConstantFPRange::getNonNaN (APFloat (-3.0 ), APFloat (3.0 )));
960+ EXPECT_EQ (PosInf.add (PosInf), PosInf);
961+ EXPECT_EQ (NegInf.add (NegInf), NegInf);
962+ EXPECT_EQ (PosInf.add (Finite.unionWith (PosInf)), PosInf);
963+ EXPECT_EQ (NegInf.add (Finite.unionWith (NegInf)), NegInf);
964+ EXPECT_EQ (PosInf.add (Finite.unionWith (NegInf)), PosInf.unionWith (QNaN));
965+ EXPECT_EQ (NegInf.add (Finite.unionWith (PosInf)), NegInf.unionWith (QNaN));
966+ EXPECT_EQ (PosInf.add (NegInf), QNaN);
967+ EXPECT_EQ (NegInf.add (PosInf), QNaN);
968+ EXPECT_EQ (PosZero.add (NegZero), PosZero);
969+ EXPECT_EQ (PosZero.add (Zero), PosZero);
970+ EXPECT_EQ (NegZero.add (NegZero), NegZero);
971+ EXPECT_EQ (NegZero.add (Zero), Zero);
972+ EXPECT_EQ (NaN.add (NaN), QNaN);
973+
974+ #if defined(EXPENSIVE_CHECKS)
975+ EnumerateTwoInterestingConstantFPRanges (
976+ [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) {
977+ ConstantFPRange Res = LHS.add (RHS);
978+ ConstantFPRange Expected =
979+ ConstantFPRange::getEmpty (LHS.getSemantics ());
980+ EnumerateValuesInConstantFPRange (
981+ LHS,
982+ [&](const APFloat &LHSC) {
983+ EnumerateValuesInConstantFPRange (
984+ RHS,
985+ [&](const APFloat &RHSC) {
986+ APFloat Sum = LHSC + RHSC;
987+ EXPECT_TRUE (Res.contains (Sum))
988+ << " Wrong result for " << LHS << " + " << RHS
989+ << " . The result " << Res << " should contain " << Sum;
990+ if (!Expected.contains (Sum))
991+ Expected = Expected.unionWith (ConstantFPRange (Sum));
992+ },
993+ /* IgnoreNaNPayload=*/ true );
994+ },
995+ /* IgnoreNaNPayload=*/ true );
996+ EXPECT_EQ (Res, Expected)
997+ << " Suboptimal result for " << LHS << " + " << RHS << " . Expected "
998+ << Expected << " , but got " << Res;
999+ },
1000+ SparseLevel::SpecialValuesOnly);
1001+ #endif
1002+ }
1003+
1004+ TEST_F (ConstantFPRangeTest, sub) {
1005+ EXPECT_EQ (Full.sub (Full), ConstantFPRange::getNonNaN (Sem).unionWith (QNaN));
1006+ EXPECT_EQ (Full.sub (Empty), Empty);
1007+ EXPECT_EQ (Empty.sub (Full), Empty);
1008+ EXPECT_EQ (Empty.sub (Empty), Empty);
1009+ EXPECT_EQ (One.sub (One), ConstantFPRange (APFloat (0.0 )));
1010+ EXPECT_EQ (Some.sub (Some),
1011+ ConstantFPRange::getNonNaN (APFloat (-6.0 ), APFloat (6.0 )));
1012+ EXPECT_EQ (SomePos.sub (SomeNeg),
1013+ ConstantFPRange::getNonNaN (APFloat (0.0 ), APFloat (6.0 )));
1014+ EXPECT_EQ (PosInf.sub (NegInf), PosInf);
1015+ EXPECT_EQ (NegInf.sub (PosInf), NegInf);
1016+ EXPECT_EQ (PosInf.sub (Finite.unionWith (NegInf)), PosInf);
1017+ EXPECT_EQ (NegInf.sub (Finite.unionWith (PosInf)), NegInf);
1018+ EXPECT_EQ (PosInf.sub (Finite.unionWith (PosInf)), PosInf.unionWith (QNaN));
1019+ EXPECT_EQ (NegInf.sub (Finite.unionWith (NegInf)), NegInf.unionWith (QNaN));
1020+ EXPECT_EQ (PosInf.sub (PosInf), QNaN);
1021+ EXPECT_EQ (NegInf.sub (NegInf), QNaN);
1022+ EXPECT_EQ (PosZero.sub (NegZero), PosZero);
1023+ EXPECT_EQ (PosZero.sub (Zero), PosZero);
1024+ EXPECT_EQ (NegZero.sub (NegZero), PosZero);
1025+ EXPECT_EQ (NegZero.sub (PosZero), NegZero);
1026+ EXPECT_EQ (NegZero.sub (Zero), Zero);
1027+ EXPECT_EQ (NaN.sub (NaN), QNaN);
1028+
1029+ #if defined(EXPENSIVE_CHECKS)
1030+ EnumerateTwoInterestingConstantFPRanges (
1031+ [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) {
1032+ ConstantFPRange Res = LHS.sub (RHS);
1033+ ConstantFPRange Expected =
1034+ ConstantFPRange::getEmpty (LHS.getSemantics ());
1035+ EnumerateValuesInConstantFPRange (
1036+ LHS,
1037+ [&](const APFloat &LHSC) {
1038+ EnumerateValuesInConstantFPRange (
1039+ RHS,
1040+ [&](const APFloat &RHSC) {
1041+ APFloat Diff = LHSC - RHSC;
1042+ EXPECT_TRUE (Res.contains (Diff))
1043+ << " Wrong result for " << LHS << " - " << RHS
1044+ << " . The result " << Res << " should contain " << Diff;
1045+ if (!Expected.contains (Diff))
1046+ Expected = Expected.unionWith (ConstantFPRange (Diff));
1047+ },
1048+ /* IgnoreNaNPayload=*/ true );
1049+ },
1050+ /* IgnoreNaNPayload=*/ true );
1051+ EXPECT_EQ (Res, Expected)
1052+ << " Suboptimal result for " << LHS << " - " << RHS << " . Expected "
1053+ << Expected << " , but got " << Res;
1054+ },
1055+ SparseLevel::SpecialValuesOnly);
1056+ #endif
1057+ }
1058+
9281059} // anonymous namespace
0 commit comments