Skip to content

Commit bd66251

Browse files
committed
[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).
1 parent 70ab8e8 commit bd66251

File tree

1 file changed

+50
-51
lines changed

1 file changed

+50
-51
lines changed

llvm/unittests/IR/ConstantRangeTest.cpp

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,25 @@ static void EnumerateConstantRanges(unsigned Bits, Fn TestFn) {
5151
}
5252
}
5353

54-
template<typename Fn>
55-
static void EnumerateTwoConstantRanges(unsigned Bits, Fn TestFn) {
56-
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR1) {
57-
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR2) {
58-
TestFn(CR1, CR2);
54+
template <typename Fn>
55+
static void EnumerateInterestingConstantRanges(Fn TestFn) {
56+
// Check 1 bit ranges, because they may have special cases.
57+
EnumerateConstantRanges(/* Bits */ 1, TestFn);
58+
// Check 4 bit ranges to have decent coverage without being too slow.
59+
EnumerateConstantRanges(/* Bits */ 4, TestFn);
60+
}
61+
62+
template <typename Fn>
63+
static void EnumerateTwoInterestingConstantRanges(Fn TestFn) {
64+
for (unsigned Bits : {1, 4}) {
65+
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR1) {
66+
EnumerateConstantRanges(
67+
Bits, [&](const ConstantRange &CR2) { TestFn(CR1, CR2); });
5968
});
60-
});
69+
}
6170
}
6271

63-
template<typename Fn>
72+
template <typename Fn>
6473
static void ForeachNumInConstantRange(const ConstantRange &CR, Fn TestFn) {
6574
if (!CR.isEmptySet()) {
6675
APInt N = CR.getLower();
@@ -179,16 +188,14 @@ using UnaryIntFn = llvm::function_ref<std::optional<APInt>(const APInt &)>;
179188

180189
static void TestUnaryOpExhaustive(UnaryRangeFn RangeFn, UnaryIntFn IntFn,
181190
PreferFn PreferenceFn = PreferSmallest) {
182-
for (unsigned Bits : {1, 4}) {
183-
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
184-
SmallBitVector Elems(1 << Bits);
185-
ForeachNumInConstantRange(CR, [&](const APInt &N) {
186-
if (std::optional<APInt> ResultN = IntFn(N))
187-
Elems.set(ResultN->getZExtValue());
188-
});
189-
TestRange(RangeFn(CR), Elems, PreferenceFn, {CR});
191+
EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
192+
SmallBitVector Elems(1 << CR.getBitWidth());
193+
ForeachNumInConstantRange(CR, [&](const APInt &N) {
194+
if (std::optional<APInt> ResultN = IntFn(N))
195+
Elems.set(ResultN->getZExtValue());
190196
});
191-
}
197+
TestRange(RangeFn(CR), Elems, PreferenceFn, {CR});
198+
});
192199
}
193200

194201
using BinaryRangeFn = llvm::function_ref<ConstantRange(const ConstantRange &,
@@ -228,10 +235,9 @@ static bool CheckNonWrappedOrSignWrappedOnly(const ConstantRange &CR1,
228235
static void TestBinaryOpExhaustive(BinaryRangeFn RangeFn, BinaryIntFn IntFn,
229236
PreferFn PreferenceFn = PreferSmallest,
230237
BinaryCheckFn CheckFn = CheckAll) {
231-
unsigned Bits = 4;
232-
EnumerateTwoConstantRanges(
233-
Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
234-
SmallBitVector Elems(1 << Bits);
238+
EnumerateTwoInterestingConstantRanges(
239+
[&](const ConstantRange &CR1, const ConstantRange &CR2) {
240+
SmallBitVector Elems(1 << CR1.getBitWidth());
235241
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
236242
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
237243
if (std::optional<APInt> ResultN = IntFn(N1, N2))
@@ -535,11 +541,11 @@ TEST_F(ConstantRangeTest, IntersectWith) {
535541
EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 15), APInt(32, 0)));
536542
}
537543

538-
template<typename Fn1, typename Fn2, typename Fn3>
544+
template <typename Fn1, typename Fn2, typename Fn3>
539545
void testBinarySetOperationExhaustive(Fn1 OpFn, Fn2 ExactOpFn, Fn3 InResultFn) {
540-
unsigned Bits = 4;
541-
EnumerateTwoConstantRanges(Bits,
546+
EnumerateTwoInterestingConstantRanges(
542547
[=](const ConstantRange &CR1, const ConstantRange &CR2) {
548+
unsigned Bits = CR1.getBitWidth();
543549
SmallBitVector Elems(1 << Bits);
544550
APInt Num(Bits, 0);
545551
for (unsigned I = 0, Limit = 1 << Bits; I < Limit; ++I, ++Num)
@@ -630,8 +636,7 @@ TEST_F(ConstantRangeTest, SetDifference) {
630636
}
631637

632638
TEST_F(ConstantRangeTest, getActiveBits) {
633-
unsigned Bits = 4;
634-
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
639+
EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
635640
unsigned Exact = 0;
636641
ForeachNumInConstantRange(CR, [&](const APInt &N) {
637642
Exact = std::max(Exact, N.getActiveBits());
@@ -642,8 +647,8 @@ TEST_F(ConstantRangeTest, getActiveBits) {
642647
});
643648
}
644649
TEST_F(ConstantRangeTest, losslessUnsignedTruncationZeroext) {
645-
unsigned Bits = 4;
646-
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
650+
EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
651+
unsigned Bits = CR.getBitWidth();
647652
unsigned MinBitWidth = CR.getActiveBits();
648653
if (MinBitWidth == 0) {
649654
EXPECT_TRUE(CR.isEmptySet() ||
@@ -657,8 +662,7 @@ TEST_F(ConstantRangeTest, losslessUnsignedTruncationZeroext) {
657662
}
658663

659664
TEST_F(ConstantRangeTest, getMinSignedBits) {
660-
unsigned Bits = 4;
661-
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
665+
EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
662666
unsigned Exact = 0;
663667
ForeachNumInConstantRange(CR, [&](const APInt &N) {
664668
Exact = std::max(Exact, N.getMinSignedBits());
@@ -669,8 +673,8 @@ TEST_F(ConstantRangeTest, getMinSignedBits) {
669673
});
670674
}
671675
TEST_F(ConstantRangeTest, losslessSignedTruncationSignext) {
672-
unsigned Bits = 4;
673-
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
676+
EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
677+
unsigned Bits = CR.getBitWidth();
674678
unsigned MinBitWidth = CR.getMinSignedBits();
675679
if (MinBitWidth == 0) {
676680
EXPECT_TRUE(CR.isEmptySet());
@@ -1155,11 +1159,11 @@ TEST_F(ConstantRangeTest, SDiv) {
11551159
ConstantRange OneBit = ConstantRange::getFull(1);
11561160
EXPECT_EQ(OneBit.sdiv(OneBit), ConstantRange(APInt(1, 0)));
11571161

1158-
unsigned Bits = 4;
1159-
EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
1160-
const ConstantRange &CR2) {
1162+
EnumerateTwoInterestingConstantRanges([&](const ConstantRange &CR1,
1163+
const ConstantRange &CR2) {
11611164
// Collect possible results in a bit vector. We store the signed value plus
11621165
// a bias to make it unsigned.
1166+
unsigned Bits = CR1.getBitWidth();
11631167
int Bias = 1 << (Bits - 1);
11641168
BitVector Results(1 << Bits);
11651169
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
@@ -1473,9 +1477,8 @@ TEST(ConstantRange, MakeSatisfyingICmpRegion) {
14731477
}
14741478

14751479
void ICmpTestImpl(CmpInst::Predicate Pred) {
1476-
unsigned Bits = 4;
1477-
EnumerateTwoConstantRanges(
1478-
Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
1480+
EnumerateTwoInterestingConstantRanges(
1481+
[&](const ConstantRange &CR1, const ConstantRange &CR2) {
14791482
bool Exhaustive = true;
14801483
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
14811484
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
@@ -1888,8 +1891,8 @@ TEST(ConstantRange, GetEquivalentICmp) {
18881891
EXPECT_EQ(Pred, CmpInst::ICMP_NE);
18891892
EXPECT_EQ(RHS, APInt(32, -1));
18901893

1891-
unsigned Bits = 4;
1892-
EnumerateConstantRanges(Bits, [Bits](const ConstantRange &CR) {
1894+
EnumerateInterestingConstantRanges([](const ConstantRange &CR) {
1895+
unsigned Bits = CR.getBitWidth();
18931896
CmpInst::Predicate Pred;
18941897
APInt RHS, Offset;
18951898
CR.getEquivalentICmp(Pred, RHS, Offset);
@@ -2079,12 +2082,11 @@ TEST_F(ConstantRangeTest, SignedSubOverflow) {
20792082
EXPECT_MAY_OVERFLOW(F.signedSubMayOverflow(F));
20802083
}
20812084

2082-
template<typename Fn1, typename Fn2>
2085+
template <typename Fn1, typename Fn2>
20832086
static void TestOverflowExhaustive(Fn1 OverflowFn, Fn2 MayOverflowFn) {
20842087
// Constant range overflow checks are tested exhaustively on 4-bit numbers.
2085-
unsigned Bits = 4;
2086-
EnumerateTwoConstantRanges(Bits, [=](const ConstantRange &CR1,
2087-
const ConstantRange &CR2) {
2088+
EnumerateTwoInterestingConstantRanges([=](const ConstantRange &CR1,
2089+
const ConstantRange &CR2) {
20882090
// Loop over all N1 in CR1 and N2 in CR2 and check whether any of the
20892091
// operations have overflow / have no overflow.
20902092
bool RangeHasOverflowLow = false;
@@ -2259,10 +2261,9 @@ TEST_F(ConstantRangeTest, FromKnownBitsExhaustive) {
22592261
}
22602262

22612263
TEST_F(ConstantRangeTest, ToKnownBits) {
2262-
unsigned Bits = 4;
2263-
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
2264+
EnumerateInterestingConstantRanges([&](const ConstantRange &CR) {
22642265
KnownBits Known = CR.toKnownBits();
2265-
KnownBits ExpectedKnown(Bits);
2266+
KnownBits ExpectedKnown(CR.getBitWidth());
22662267
ExpectedKnown.Zero.setAllBits();
22672268
ExpectedKnown.One.setAllBits();
22682269
ForeachNumInConstantRange(CR, [&](const APInt &N) {
@@ -2285,8 +2286,7 @@ TEST_F(ConstantRangeTest, Negative) {
22852286
EXPECT_FALSE(Full.isAllNegative());
22862287
EXPECT_FALSE(Full.isAllNonNegative());
22872288

2288-
unsigned Bits = 4;
2289-
EnumerateConstantRanges(Bits, [](const ConstantRange &CR) {
2289+
EnumerateInterestingConstantRanges([](const ConstantRange &CR) {
22902290
bool AllNegative = true;
22912291
bool AllNonNegative = true;
22922292
ForeachNumInConstantRange(CR, [&](const APInt &N) {
@@ -2534,9 +2534,8 @@ TEST_F(ConstantRangeTest, binaryNot) {
25342534

25352535
template <typename T>
25362536
void testConstantRangeICmpPredEquivalence(ICmpInst::Predicate SrcPred, T Func) {
2537-
unsigned Bits = 4;
2538-
EnumerateTwoConstantRanges(
2539-
Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
2537+
EnumerateTwoInterestingConstantRanges(
2538+
[&](const ConstantRange &CR1, const ConstantRange &CR2) {
25402539
ICmpInst::Predicate TgtPred;
25412540
bool ExpectedEquivalent;
25422541
std::tie(TgtPred, ExpectedEquivalent) = Func(CR1, CR2);

0 commit comments

Comments
 (0)