mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
[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 llvm-svn: 357871
This commit is contained in:
parent
e86666d9c2
commit
6fe1b695c4
@ -219,9 +219,15 @@ public:
|
||||
/// Compare set size of this range with the range CR.
|
||||
bool isSizeStrictlySmallerThan(const ConstantRange &CR) const;
|
||||
|
||||
// Compare set size of this range with Value.
|
||||
/// Compare set size of this range with Value.
|
||||
bool isSizeLargerThan(uint64_t MaxSize) const;
|
||||
|
||||
/// Return true if all values in this range are negative.
|
||||
bool isAllNegative() const;
|
||||
|
||||
/// Return true if all values in this range are non-negative.
|
||||
bool isAllNonNegative() const;
|
||||
|
||||
/// Return the largest unsigned value contained in the ConstantRange.
|
||||
APInt getUnsignedMax() const;
|
||||
|
||||
|
@ -389,6 +389,21 @@ ConstantRange::isSizeLargerThan(uint64_t MaxSize) const {
|
||||
return (Upper - Lower).ugt(MaxSize);
|
||||
}
|
||||
|
||||
bool ConstantRange::isAllNegative() const {
|
||||
// Empty set is all negative, full set is not.
|
||||
if (isEmptySet())
|
||||
return true;
|
||||
if (isFullSet())
|
||||
return false;
|
||||
|
||||
return !isUpperSignWrapped() && !Upper.isStrictlyPositive();
|
||||
}
|
||||
|
||||
bool ConstantRange::isAllNonNegative() const {
|
||||
// Empty and full set are automatically treated correctly.
|
||||
return !isSignWrappedSet() && Lower.isNonNegative();
|
||||
}
|
||||
|
||||
APInt ConstantRange::getUnsignedMax() const {
|
||||
if (isFullSet() || isUpperWrapped())
|
||||
return APInt::getMaxValue(getBitWidth());
|
||||
|
@ -26,29 +26,39 @@ protected:
|
||||
};
|
||||
|
||||
template<typename Fn>
|
||||
static void EnumerateTwoConstantRanges(unsigned Bits, Fn TestFn) {
|
||||
static void EnumerateConstantRanges(unsigned Bits, Fn TestFn) {
|
||||
unsigned Max = 1 << Bits;
|
||||
for (unsigned Lo1 = 0; Lo1 < Max; Lo1++) {
|
||||
for (unsigned Hi1 = 0; Hi1 < Max; Hi1++) {
|
||||
for (unsigned Lo = 0; Lo < Max; Lo++) {
|
||||
for (unsigned Hi = 0; Hi < Max; Hi++) {
|
||||
// Enforce ConstantRange invariant.
|
||||
if (Lo1 == Hi1 && Lo1 != 0 && Lo1 != Max - 1)
|
||||
if (Lo == Hi && Lo != 0 && Lo != Max - 1)
|
||||
continue;
|
||||
|
||||
ConstantRange CR1(APInt(Bits, Lo1), APInt(Bits, Hi1));
|
||||
for (unsigned Lo2 = 0; Lo2 < Max; Lo2++) {
|
||||
for (unsigned Hi2 = 0; Hi2 < Max; Hi2++) {
|
||||
// Enforce ConstantRange invariant.
|
||||
if (Lo2 == Hi2 && Lo2 != 0 && Lo2 != Max - 1)
|
||||
continue;
|
||||
|
||||
ConstantRange CR2(APInt(Bits, Lo2), APInt(Bits, Hi2));
|
||||
TestFn(CR1, CR2);
|
||||
}
|
||||
}
|
||||
ConstantRange CR(APInt(Bits, Lo), APInt(Bits, Hi));
|
||||
TestFn(CR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 ForeachNumInConstantRange(const ConstantRange &CR, Fn TestFn) {
|
||||
// The loop is based on the set size to correctly handle empty/full ranges.
|
||||
unsigned Size = CR.getSetSize().getLimitedValue();
|
||||
APInt N = CR.getLower();
|
||||
for (unsigned I = 0; I < Size; ++I, ++N) {
|
||||
TestFn(N);
|
||||
}
|
||||
}
|
||||
|
||||
ConstantRange ConstantRangeTest::Full(16, true);
|
||||
ConstantRange ConstantRangeTest::Empty(16, false);
|
||||
ConstantRange ConstantRangeTest::One(APInt(16, 0xa));
|
||||
@ -1597,4 +1607,31 @@ TEST_F(ConstantRangeTest, FromKnownBitsExhaustive) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ConstantRangeTest, Negative) {
|
||||
// All elements in an empty set (of which there are none) are both negative
|
||||
// and non-negative. Empty & full sets checked explicitly for clarity, but
|
||||
// they are also covered by the exhaustive test below.
|
||||
EXPECT_TRUE(Empty.isAllNegative());
|
||||
EXPECT_TRUE(Empty.isAllNonNegative());
|
||||
EXPECT_FALSE(Full.isAllNegative());
|
||||
EXPECT_FALSE(Full.isAllNonNegative());
|
||||
|
||||
unsigned Bits = 4;
|
||||
EnumerateConstantRanges(Bits, [](const ConstantRange &CR) {
|
||||
bool AllNegative = true;
|
||||
bool AllNonNegative = true;
|
||||
ForeachNumInConstantRange(CR, [&](const APInt &N) {
|
||||
if (!N.isNegative())
|
||||
AllNegative = false;
|
||||
if (!N.isNonNegative())
|
||||
AllNonNegative = false;
|
||||
});
|
||||
assert((CR.isEmptySet() || !AllNegative || !AllNonNegative) &&
|
||||
"Only empty set can be both all negative and all non-negative");
|
||||
|
||||
EXPECT_EQ(AllNegative, CR.isAllNegative());
|
||||
EXPECT_EQ(AllNonNegative, CR.isAllNonNegative());
|
||||
});
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
Loading…
Reference in New Issue
Block a user