mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-28 22:00:30 +00:00
[ConstantRange] Add makeExactNoWrapRegion()
I got confused on the terminology, and the change in D60598 was not correct. I was thinking of "exact" in terms of the result being non-approximate. However, the relevant distinction here is whether the result is * Largest range such that: Forall Y in Other: Forall X in Result: X BinOp Y does not wrap. (makeGuaranteedNoWrapRegion) * Smallest range such that: Forall Y in Other: Forall X not in Result: X BinOp Y wraps. (A hypothetical makeAllowedNoWrapRegion) * Both. (makeExactNoWrapRegion) I'm adding a separate makeExactNoWrapRegion method accepting a single APInt (same as makeExactICmpRegion) and using it in the places where the guarantee is relevant. Differential Revision: https://reviews.llvm.org/D60960 llvm-svn: 359402
This commit is contained in:
parent
768110bf0e
commit
98c50a3578
@ -124,8 +124,10 @@ public:
|
||||
static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred,
|
||||
const APInt &Other);
|
||||
|
||||
/// Return the exact range containing all X such that "X BinOpC Y" is
|
||||
/// guaranteed not to wrap (overflow) for all Y in Other.
|
||||
/// Produce the largest range containing all X such that "X BinOp Y" is
|
||||
/// guaranteed not to wrap (overflow) for *all* Y in Other. However, there may
|
||||
/// be *some* Y in Other for which additional X not contained in the result
|
||||
/// also do not overflow.
|
||||
///
|
||||
/// NoWrapKind must be one of OBO::NoUnsignedWrap or OBO::NoSignedWrap.
|
||||
///
|
||||
@ -142,6 +144,12 @@ public:
|
||||
const ConstantRange &Other,
|
||||
unsigned NoWrapKind);
|
||||
|
||||
/// Produce the range that contains X if and only if "X BinOp Other" does
|
||||
/// not wrap.
|
||||
static ConstantRange makeExactNoWrapRegion(Instruction::BinaryOps BinOp,
|
||||
const APInt &Other,
|
||||
unsigned NoWrapKind);
|
||||
|
||||
/// Set up \p Pred and \p RHS such that
|
||||
/// ConstantRange::makeExactICmpRegion(Pred, RHS) == *this. Return true if
|
||||
/// successful.
|
||||
|
@ -1146,8 +1146,8 @@ static ValueLatticeElement getValueFromOverflowCondition(
|
||||
return ValueLatticeElement::getOverdefined();
|
||||
|
||||
// Calculate the possible values of %x for which no overflow occurs.
|
||||
ConstantRange NWR = ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
WO->getBinaryOp(), ConstantRange(*C), WO->getNoWrapKind());
|
||||
ConstantRange NWR = ConstantRange::makeExactNoWrapRegion(
|
||||
WO->getBinaryOp(), *C, WO->getNoWrapKind());
|
||||
|
||||
// If overflow is false, %x is constrained to NWR. If overflow is true, %x is
|
||||
// constrained to it's inverse (all values that might cause overflow).
|
||||
|
@ -309,6 +309,14 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
|
||||
}
|
||||
}
|
||||
|
||||
ConstantRange ConstantRange::makeExactNoWrapRegion(Instruction::BinaryOps BinOp,
|
||||
const APInt &Other,
|
||||
unsigned NoWrapKind) {
|
||||
// makeGuaranteedNoWrapRegion() is exact for single-element ranges, as
|
||||
// "for all" and "for any" coincide in this case.
|
||||
return makeGuaranteedNoWrapRegion(BinOp, ConstantRange(Other), NoWrapKind);
|
||||
}
|
||||
|
||||
bool ConstantRange::isFullSet() const {
|
||||
return Lower == Upper && Lower.isMaxValue();
|
||||
}
|
||||
@ -843,10 +851,8 @@ ConstantRange::add(const ConstantRange &Other) const {
|
||||
ConstantRange ConstantRange::addWithNoSignedWrap(const APInt &Other) const {
|
||||
// Calculate the subset of this range such that "X + Other" is
|
||||
// guaranteed not to wrap (overflow) for all X in this subset.
|
||||
// makeGuaranteedNoWrapRegion will produce an exact NSW range.
|
||||
auto NSWRange = ConstantRange::makeGuaranteedNoWrapRegion(BinaryOperator::Add,
|
||||
ConstantRange(Other),
|
||||
OverflowingBinaryOperator::NoSignedWrap);
|
||||
auto NSWRange = ConstantRange::makeExactNoWrapRegion(
|
||||
BinaryOperator::Add, Other, OverflowingBinaryOperator::NoSignedWrap);
|
||||
auto NSWConstrainedRange = intersectWith(NSWRange);
|
||||
|
||||
return NSWConstrainedRange.add(ConstantRange(Other));
|
||||
|
@ -1176,17 +1176,25 @@ void TestNoWrapRegionExhaustive(Instruction::BinaryOps BinOp,
|
||||
ConstantRange::makeGuaranteedNoWrapRegion(BinOp, CR2, NoWrapKind);
|
||||
ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
|
||||
bool NoOverflow = true;
|
||||
bool Overflow = true;
|
||||
ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
|
||||
if (OverflowFn(N1, N2))
|
||||
NoOverflow = false;
|
||||
else
|
||||
Overflow = false;
|
||||
});
|
||||
EXPECT_EQ(NoOverflow, NoWrap.contains(N1));
|
||||
|
||||
// The no-wrap range is exact for single-element ranges.
|
||||
if (CR2.isSingleElement()) {
|
||||
EXPECT_EQ(Overflow, !NoWrap.contains(N1));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Show that makeGuaranteedNoWrapRegion is precise if only one of
|
||||
// NoUnsignedWrap or NoSignedWrap is used.
|
||||
// Show that makeGuaranteedNoWrapRegion() is maximal, and for single-element
|
||||
// ranges also exact.
|
||||
TEST(ConstantRange, NoWrapRegionExhaustive) {
|
||||
TestNoWrapRegionExhaustive(
|
||||
Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap,
|
||||
|
Loading…
Reference in New Issue
Block a user