mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[ConstantRange] Support abs with poison flag
This just adds the ConstantRange support, including exhaustive testing. It's not wired up to the IR intrinsic flag yet.
This commit is contained in:
parent
c1baeb79cd
commit
9bc2ea2f9d
@ -464,8 +464,9 @@ public:
|
|||||||
ConstantRange inverse() const;
|
ConstantRange inverse() const;
|
||||||
|
|
||||||
/// Calculate absolute value range. If the original range contains signed
|
/// Calculate absolute value range. If the original range contains signed
|
||||||
/// min, then the resulting range will also contain signed min.
|
/// min, then the resulting range will contain signed min if and only if
|
||||||
ConstantRange abs() const;
|
/// \p IntMinIsPoison is false.
|
||||||
|
ConstantRange abs(bool IntMinIsPoison = false) const;
|
||||||
|
|
||||||
/// Represents whether an operation on the given constant range is known to
|
/// Represents whether an operation on the given constant range is known to
|
||||||
/// always or never overflow.
|
/// always or never overflow.
|
||||||
|
@ -1464,7 +1464,7 @@ ConstantRange ConstantRange::inverse() const {
|
|||||||
return ConstantRange(Upper, Lower);
|
return ConstantRange(Upper, Lower);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantRange ConstantRange::abs() const {
|
ConstantRange ConstantRange::abs(bool IntMinIsPoison) const {
|
||||||
if (isEmptySet())
|
if (isEmptySet())
|
||||||
return getEmpty();
|
return getEmpty();
|
||||||
|
|
||||||
@ -1476,12 +1476,23 @@ ConstantRange ConstantRange::abs() const {
|
|||||||
else
|
else
|
||||||
Lo = APIntOps::umin(Lower, -Upper + 1);
|
Lo = APIntOps::umin(Lower, -Upper + 1);
|
||||||
|
|
||||||
// SignedMin is included in the result range.
|
// If SignedMin is not poison, then it is included in the result range.
|
||||||
return ConstantRange(Lo, APInt::getSignedMinValue(getBitWidth()) + 1);
|
if (IntMinIsPoison)
|
||||||
|
return ConstantRange(Lo, APInt::getSignedMinValue(getBitWidth()));
|
||||||
|
else
|
||||||
|
return ConstantRange(Lo, APInt::getSignedMinValue(getBitWidth()) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
APInt SMin = getSignedMin(), SMax = getSignedMax();
|
APInt SMin = getSignedMin(), SMax = getSignedMax();
|
||||||
|
|
||||||
|
// Skip SignedMin if it is poison.
|
||||||
|
if (IntMinIsPoison && SMin.isMinSignedValue()) {
|
||||||
|
// The range may become empty if it *only* contains SignedMin.
|
||||||
|
if (SMax.isMinSignedValue())
|
||||||
|
return getEmpty();
|
||||||
|
++SMin;
|
||||||
|
}
|
||||||
|
|
||||||
// All non-negative.
|
// All non-negative.
|
||||||
if (SMin.isNonNegative())
|
if (SMin.isNonNegative())
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -59,6 +59,35 @@ static void ForeachNumInConstantRange(const ConstantRange &CR, Fn TestFn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Fn1, typename Fn2>
|
||||||
|
static void TestUnsignedUnaryOpExhaustive(
|
||||||
|
Fn1 RangeFn, Fn2 IntFn, bool SkipSignedIntMin = false) {
|
||||||
|
unsigned Bits = 4;
|
||||||
|
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
|
||||||
|
APInt Min = APInt::getMaxValue(Bits);
|
||||||
|
APInt Max = APInt::getMinValue(Bits);
|
||||||
|
ForeachNumInConstantRange(CR, [&](const APInt &N) {
|
||||||
|
if (SkipSignedIntMin && N.isMinSignedValue())
|
||||||
|
return;
|
||||||
|
|
||||||
|
APInt AbsN = IntFn(N);
|
||||||
|
if (AbsN.ult(Min))
|
||||||
|
Min = AbsN;
|
||||||
|
if (AbsN.ugt(Max))
|
||||||
|
Max = AbsN;
|
||||||
|
});
|
||||||
|
|
||||||
|
ConstantRange ResultCR = RangeFn(CR);
|
||||||
|
if (Min.ugt(Max)) {
|
||||||
|
EXPECT_TRUE(ResultCR.isEmptySet());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
|
||||||
|
EXPECT_EQ(Exact, ResultCR);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Fn1, typename Fn2>
|
template<typename Fn1, typename Fn2>
|
||||||
static void TestUnsignedBinOpExhaustive(
|
static void TestUnsignedBinOpExhaustive(
|
||||||
Fn1 RangeFn, Fn2 IntFn,
|
Fn1 RangeFn, Fn2 IntFn,
|
||||||
@ -2270,29 +2299,16 @@ TEST_F(ConstantRangeTest, SShlSat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ConstantRangeTest, Abs) {
|
TEST_F(ConstantRangeTest, Abs) {
|
||||||
unsigned Bits = 4;
|
// We're working with unsigned integers here, because it makes the signed
|
||||||
EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
|
// min case non-wrapping.
|
||||||
// We're working with unsigned integers here, because it makes the signed
|
TestUnsignedUnaryOpExhaustive(
|
||||||
// min case non-wrapping.
|
[](const ConstantRange &CR) { return CR.abs(); },
|
||||||
APInt Min = APInt::getMaxValue(Bits);
|
[](const APInt &N) { return N.abs(); });
|
||||||
APInt Max = APInt::getMinValue(Bits);
|
|
||||||
ForeachNumInConstantRange(CR, [&](const APInt &N) {
|
|
||||||
APInt AbsN = N.abs();
|
|
||||||
if (AbsN.ult(Min))
|
|
||||||
Min = AbsN;
|
|
||||||
if (AbsN.ugt(Max))
|
|
||||||
Max = AbsN;
|
|
||||||
});
|
|
||||||
|
|
||||||
ConstantRange AbsCR = CR.abs();
|
TestUnsignedUnaryOpExhaustive(
|
||||||
if (Min.ugt(Max)) {
|
[](const ConstantRange &CR) { return CR.abs(/*IntMinIsPoison=*/true); },
|
||||||
EXPECT_TRUE(AbsCR.isEmptySet());
|
[](const APInt &N) { return N.abs(); },
|
||||||
return;
|
/*SkipSignedIntMin=*/true);
|
||||||
}
|
|
||||||
|
|
||||||
ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
|
|
||||||
EXPECT_EQ(Exact, AbsCR);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ConstantRangeTest, castOps) {
|
TEST_F(ConstantRangeTest, castOps) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user