llvm.org GIT mirror llvm / a83da3f
[ConstantRange] Add isAllNegative() and isAllNonNegative() methods Add isAllNegative() and isAllNonNegative() methods to ConstantRange, which determine whether all values in the constant range are negative/non-negative. This is useful for replacing KnownBits isNegative() and isNonNegative() calls when changing code to use constant ranges. Differential Revision: https://reviews.llvm.org/D60264 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357871 91177308-0d34-0410-b5e6-96231b3b80d8 Nikita Popov 6 months ago
3 changed file(s) with 78 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
218218 /// Compare set size of this range with the range CR.
219219 bool isSizeStrictlySmallerThan(const ConstantRange &CR) const;
220220
221 // Compare set size of this range with Value.
221 /// Compare set size of this range with Value.
222222 bool isSizeLargerThan(uint64_t MaxSize) const;
223
224 /// Return true if all values in this range are negative.
225 bool isAllNegative() const;
226
227 /// Return true if all values in this range are non-negative.
228 bool isAllNonNegative() const;
223229
224230 /// Return the largest unsigned value contained in the ConstantRange.
225231 APInt getUnsignedMax() const;
388388 return (Upper - Lower).ugt(MaxSize);
389389 }
390390
391 bool ConstantRange::isAllNegative() const {
392 // Empty set is all negative, full set is not.
393 if (isEmptySet())
394 return true;
395 if (isFullSet())
396 return false;
397
398 return !isUpperSignWrapped() && !Upper.isStrictlyPositive();
399 }
400
401 bool ConstantRange::isAllNonNegative() const {
402 // Empty and full set are automatically treated correctly.
403 return !isSignWrappedSet() && Lower.isNonNegative();
404 }
405
391406 APInt ConstantRange::getUnsignedMax() const {
392407 if (isFullSet() || isUpperWrapped())
393408 return APInt::getMaxValue(getBitWidth());
2525 };
2626
2727 template
28 static void EnumerateConstantRanges(unsigned Bits, Fn TestFn) {
29 unsigned Max = 1 << Bits;
30 for (unsigned Lo = 0; Lo < Max; Lo++) {
31 for (unsigned Hi = 0; Hi < Max; Hi++) {
32 // Enforce ConstantRange invariant.
33 if (Lo == Hi && Lo != 0 && Lo != Max - 1)
34 continue;
35
36 ConstantRange CR(APInt(Bits, Lo), APInt(Bits, Hi));
37 TestFn(CR);
38 }
39 }
40 }
41
42 template
2843 static void EnumerateTwoConstantRanges(unsigned Bits, Fn TestFn) {
29 unsigned Max = 1 << Bits;
30 for (unsigned Lo1 = 0; Lo1 < Max; Lo1++) {
31 for (unsigned Hi1 = 0; Hi1 < Max; Hi1++) {
32 // Enforce ConstantRange invariant.
33 if (Lo1 == Hi1 && Lo1 != 0 && Lo1 != Max - 1)
34 continue;
35
36 ConstantRange CR1(APInt(Bits, Lo1), APInt(Bits, Hi1));
37 for (unsigned Lo2 = 0; Lo2 < Max; Lo2++) {
38 for (unsigned Hi2 = 0; Hi2 < Max; Hi2++) {
39 // Enforce ConstantRange invariant.
40 if (Lo2 == Hi2 && Lo2 != 0 && Lo2 != Max - 1)
41 continue;
42
43 ConstantRange CR2(APInt(Bits, Lo2), APInt(Bits, Hi2));
44 TestFn(CR1, CR2);
45 }
46 }
47 }
44 EnumerateConstantRanges(Bits, [&](const ConstantRange &CR1) {
45 EnumerateConstantRanges(Bits, [&](const ConstantRange &CR2) {
46 TestFn(CR1, CR2);
47 });
48 });
49 }
50
51 template
52 static void ForeachNumInConstantRange(const ConstantRange &CR, Fn TestFn) {
53 // The loop is based on the set size to correctly handle empty/full ranges.
54 unsigned Size = CR.getSetSize().getLimitedValue();
55 APInt N = CR.getLower();
56 for (unsigned I = 0; I < Size; ++I, ++N) {
57 TestFn(N);
4858 }
4959 }
5060
15961606 }
15971607 }
15981608
1609 TEST_F(ConstantRangeTest, Negative) {
1610 // All elements in an empty set (of which there are none) are both negative
1611 // and non-negative. Empty & full sets checked explicitly for clarity, but
1612 // they are also covered by the exhaustive test below.
1613 EXPECT_TRUE(Empty.isAllNegative());
1614 EXPECT_TRUE(Empty.isAllNonNegative());
1615 EXPECT_FALSE(Full.isAllNegative());
1616 EXPECT_FALSE(Full.isAllNonNegative());
1617
1618 unsigned Bits = 4;
1619 EnumerateConstantRanges(Bits, [](const ConstantRange &CR) {
1620 bool AllNegative = true;
1621 bool AllNonNegative = true;
1622 ForeachNumInConstantRange(CR, [&](const APInt &N) {
1623 if (!N.isNegative())
1624 AllNegative = false;
1625 if (!N.isNonNegative())
1626 AllNonNegative = false;
1627 });
1628 assert((CR.isEmptySet() || !AllNegative || !AllNonNegative) &&
1629 "Only empty set can be both all negative and all non-negative");
1630
1631 EXPECT_EQ(AllNegative, CR.isAllNegative());
1632 EXPECT_EQ(AllNonNegative, CR.isAllNonNegative());
1633 });
1634 }
1635
15991636 } // anonymous namespace