[llvm] bd66251 - [ConstantRange] Test 1 bit ranges in exhaustive tests (NFC)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 9 07:57:25 PST 2023


Author: Nikita Popov
Date: 2023-01-09T16:57:08+01:00
New Revision: bd66251864acea7a0ffdce58f34bd78c30e014ad

URL: https://github.com/llvm/llvm-project/commit/bd66251864acea7a0ffdce58f34bd78c30e014ad
DIFF: https://github.com/llvm/llvm-project/commit/bd66251864acea7a0ffdce58f34bd78c30e014ad.diff

LOG: [ConstantRange] Test 1 bit ranges in exhaustive tests (NFC)

There have been multiple cases where range calculations were wrong
in the 1 bit case. Make sure we catch these by not specifying the
bit width explicitly, and letting the test framework pick it (which
will now always test 1 and 4 bits both).

Added: 
    

Modified: 
    llvm/unittests/IR/ConstantRangeTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp
index 45398ec6a617..b54746b00536 100644
--- a/llvm/unittests/IR/ConstantRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -51,16 +51,25 @@ static void EnumerateConstantRanges(unsigned Bits, Fn TestFn) {
   }
 }
 
-template<typename Fn>
-static void EnumerateTwoConstantRanges(unsigned Bits, Fn TestFn) {
-  EnumerateConstantRanges(Bits, [&](const ConstantRange &CR1) {
-    EnumerateConstantRanges(Bits, [&](const ConstantRange &CR2) {
-      TestFn(CR1, CR2);
+template <typename Fn>
+static void EnumerateInterestingConstantRanges(Fn TestFn) {
+  // Check 1 bit ranges, because they may have special cases.
+  EnumerateConstantRanges(/* Bits */ 1, TestFn);
+  // Check 4 bit ranges to have decent coverage without being too slow.
+  EnumerateConstantRanges(/* Bits */ 4, TestFn);
+}
+
+template <typename Fn>
+static void EnumerateTwoInterestingConstantRanges(Fn TestFn) {
+  for (unsigned Bits : {1, 4}) {
+    EnumerateConstantRanges(Bits, [&](const ConstantRange &CR1) {
+      EnumerateConstantRanges(
+          Bits, [&](const ConstantRange &CR2) { TestFn(CR1, CR2); });
     });
-  });
+  }
 }
 
-template<typename Fn>
+template <typename Fn>
 static void ForeachNumInConstantRange(const ConstantRange &CR, Fn TestFn) {
   if (!CR.isEmptySet()) {
     APInt N = CR.getLower();
@@ -179,16 +188,14 @@ using UnaryIntFn = llvm::function_ref<std::optional<APInt>(const APInt &)>;
 
 static void TestUnaryOpExhaustive(UnaryRangeFn RangeFn, UnaryIntFn IntFn,
                                   PreferFn PreferenceFn = PreferSmallest) {
-  for (unsigned Bits : {1, 4}) {
-    EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
-      SmallBitVector Elems(1 << Bits);
-      ForeachNumInConstantRange(CR, [&](const APInt &N) {
-        if (std::optional<APInt> ResultN = IntFn(N))
-          Elems.set(ResultN->getZExtValue());
-      });
-      TestRange(RangeFn(CR), Elems, PreferenceFn, {CR});
+  EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
+    SmallBitVector Elems(1 << CR.getBitWidth());
+    ForeachNumInConstantRange(CR, [&](const APInt &N) {
+      if (std::optional<APInt> ResultN = IntFn(N))
+        Elems.set(ResultN->getZExtValue());
     });
-  }
+    TestRange(RangeFn(CR), Elems, PreferenceFn, {CR});
+  });
 }
 
 using BinaryRangeFn = llvm::function_ref<ConstantRange(const ConstantRange &,
@@ -228,10 +235,9 @@ static bool CheckNonWrappedOrSignWrappedOnly(const ConstantRange &CR1,
 static void TestBinaryOpExhaustive(BinaryRangeFn RangeFn, BinaryIntFn IntFn,
                                    PreferFn PreferenceFn = PreferSmallest,
                                    BinaryCheckFn CheckFn = CheckAll) {
-  unsigned Bits = 4;
-  EnumerateTwoConstantRanges(
-      Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
-        SmallBitVector Elems(1 << Bits);
+  EnumerateTwoInterestingConstantRanges(
+      [&](const ConstantRange &CR1, const ConstantRange &CR2) {
+        SmallBitVector Elems(1 << CR1.getBitWidth());
         ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
           ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
             if (std::optional<APInt> ResultN = IntFn(N1, N2))
@@ -535,11 +541,11 @@ TEST_F(ConstantRangeTest, IntersectWith) {
   EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 15), APInt(32, 0)));
 }
 
-template<typename Fn1, typename Fn2, typename Fn3>
+template <typename Fn1, typename Fn2, typename Fn3>
 void testBinarySetOperationExhaustive(Fn1 OpFn, Fn2 ExactOpFn, Fn3 InResultFn) {
-  unsigned Bits = 4;
-  EnumerateTwoConstantRanges(Bits,
+  EnumerateTwoInterestingConstantRanges(
       [=](const ConstantRange &CR1, const ConstantRange &CR2) {
+        unsigned Bits = CR1.getBitWidth();
         SmallBitVector Elems(1 << Bits);
         APInt Num(Bits, 0);
         for (unsigned I = 0, Limit = 1 << Bits; I < Limit; ++I, ++Num)
@@ -630,8 +636,7 @@ TEST_F(ConstantRangeTest, SetDifference) {
 }
 
 TEST_F(ConstantRangeTest, getActiveBits) {
-  unsigned Bits = 4;
-  EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
+  EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
     unsigned Exact = 0;
     ForeachNumInConstantRange(CR, [&](const APInt &N) {
       Exact = std::max(Exact, N.getActiveBits());
@@ -642,8 +647,8 @@ TEST_F(ConstantRangeTest, getActiveBits) {
   });
 }
 TEST_F(ConstantRangeTest, losslessUnsignedTruncationZeroext) {
-  unsigned Bits = 4;
-  EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
+  EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
+    unsigned Bits = CR.getBitWidth();
     unsigned MinBitWidth = CR.getActiveBits();
     if (MinBitWidth == 0) {
       EXPECT_TRUE(CR.isEmptySet() ||
@@ -657,8 +662,7 @@ TEST_F(ConstantRangeTest, losslessUnsignedTruncationZeroext) {
 }
 
 TEST_F(ConstantRangeTest, getMinSignedBits) {
-  unsigned Bits = 4;
-  EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
+  EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
     unsigned Exact = 0;
     ForeachNumInConstantRange(CR, [&](const APInt &N) {
       Exact = std::max(Exact, N.getMinSignedBits());
@@ -669,8 +673,8 @@ TEST_F(ConstantRangeTest, getMinSignedBits) {
   });
 }
 TEST_F(ConstantRangeTest, losslessSignedTruncationSignext) {
-  unsigned Bits = 4;
-  EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
+  EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
+    unsigned Bits = CR.getBitWidth();
     unsigned MinBitWidth = CR.getMinSignedBits();
     if (MinBitWidth == 0) {
       EXPECT_TRUE(CR.isEmptySet());
@@ -1155,11 +1159,11 @@ TEST_F(ConstantRangeTest, SDiv) {
   ConstantRange OneBit = ConstantRange::getFull(1);
   EXPECT_EQ(OneBit.sdiv(OneBit), ConstantRange(APInt(1, 0)));
 
-  unsigned Bits = 4;
-  EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
-                                       const ConstantRange &CR2) {
+  EnumerateTwoInterestingConstantRanges([&](const ConstantRange &CR1,
+                                            const ConstantRange &CR2) {
     // Collect possible results in a bit vector. We store the signed value plus
     // a bias to make it unsigned.
+    unsigned Bits = CR1.getBitWidth();
     int Bias = 1 << (Bits - 1);
     BitVector Results(1 << Bits);
     ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
@@ -1473,9 +1477,8 @@ TEST(ConstantRange, MakeSatisfyingICmpRegion) {
 }
 
 void ICmpTestImpl(CmpInst::Predicate Pred) {
-  unsigned Bits = 4;
-  EnumerateTwoConstantRanges(
-      Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
+  EnumerateTwoInterestingConstantRanges(
+      [&](const ConstantRange &CR1, const ConstantRange &CR2) {
         bool Exhaustive = true;
         ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
           ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
@@ -1888,8 +1891,8 @@ TEST(ConstantRange, GetEquivalentICmp) {
   EXPECT_EQ(Pred, CmpInst::ICMP_NE);
   EXPECT_EQ(RHS, APInt(32, -1));
 
-  unsigned Bits = 4;
-  EnumerateConstantRanges(Bits, [Bits](const ConstantRange &CR) {
+  EnumerateInterestingConstantRanges([](const ConstantRange &CR) {
+    unsigned Bits = CR.getBitWidth();
     CmpInst::Predicate Pred;
     APInt RHS, Offset;
     CR.getEquivalentICmp(Pred, RHS, Offset);
@@ -2079,12 +2082,11 @@ TEST_F(ConstantRangeTest, SignedSubOverflow) {
   EXPECT_MAY_OVERFLOW(F.signedSubMayOverflow(F));
 }
 
-template<typename Fn1, typename Fn2>
+template <typename Fn1, typename Fn2>
 static void TestOverflowExhaustive(Fn1 OverflowFn, Fn2 MayOverflowFn) {
   // Constant range overflow checks are tested exhaustively on 4-bit numbers.
-  unsigned Bits = 4;
-  EnumerateTwoConstantRanges(Bits, [=](const ConstantRange &CR1,
-                                       const ConstantRange &CR2) {
+  EnumerateTwoInterestingConstantRanges([=](const ConstantRange &CR1,
+                                            const ConstantRange &CR2) {
     // Loop over all N1 in CR1 and N2 in CR2 and check whether any of the
     // operations have overflow / have no overflow.
     bool RangeHasOverflowLow = false;
@@ -2259,10 +2261,9 @@ TEST_F(ConstantRangeTest, FromKnownBitsExhaustive) {
 }
 
 TEST_F(ConstantRangeTest, ToKnownBits) {
-  unsigned Bits = 4;
-  EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
+  EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
     KnownBits Known = CR.toKnownBits();
-    KnownBits ExpectedKnown(Bits);
+    KnownBits ExpectedKnown(CR.getBitWidth());
     ExpectedKnown.Zero.setAllBits();
     ExpectedKnown.One.setAllBits();
     ForeachNumInConstantRange(CR, [&](const APInt &N) {
@@ -2285,8 +2286,7 @@ TEST_F(ConstantRangeTest, Negative) {
   EXPECT_FALSE(Full.isAllNegative());
   EXPECT_FALSE(Full.isAllNonNegative());
 
-  unsigned Bits = 4;
-  EnumerateConstantRanges(Bits, [](const ConstantRange &CR) {
+  EnumerateInterestingConstantRanges([](const ConstantRange &CR) {
     bool AllNegative = true;
     bool AllNonNegative = true;
     ForeachNumInConstantRange(CR, [&](const APInt &N) {
@@ -2534,9 +2534,8 @@ TEST_F(ConstantRangeTest, binaryNot) {
 
 template <typename T>
 void testConstantRangeICmpPredEquivalence(ICmpInst::Predicate SrcPred, T Func) {
-  unsigned Bits = 4;
-  EnumerateTwoConstantRanges(
-      Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
+  EnumerateTwoInterestingConstantRanges(
+      [&](const ConstantRange &CR1, const ConstantRange &CR2) {
         ICmpInst::Predicate TgtPred;
         bool ExpectedEquivalent;
         std::tie(TgtPred, ExpectedEquivalent) = Func(CR1, CR2);


        


More information about the llvm-commits mailing list