[llvm] r359402 - [ConstantRange] Add makeExactNoWrapRegion()
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 28 08:40:56 PDT 2019
Author: nikic
Date: Sun Apr 28 08:40:56 2019
New Revision: 359402
URL: http://llvm.org/viewvc/llvm-project?rev=359402&view=rev
Log:
[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
Modified:
llvm/trunk/include/llvm/IR/ConstantRange.h
llvm/trunk/lib/Analysis/LazyValueInfo.cpp
llvm/trunk/lib/IR/ConstantRange.cpp
llvm/trunk/unittests/IR/ConstantRangeTest.cpp
Modified: llvm/trunk/include/llvm/IR/ConstantRange.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ConstantRange.h?rev=359402&r1=359401&r2=359402&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ConstantRange.h (original)
+++ llvm/trunk/include/llvm/IR/ConstantRange.h Sun Apr 28 08:40:56 2019
@@ -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.
Modified: llvm/trunk/lib/Analysis/LazyValueInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyValueInfo.cpp?rev=359402&r1=359401&r2=359402&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/LazyValueInfo.cpp (original)
+++ llvm/trunk/lib/Analysis/LazyValueInfo.cpp Sun Apr 28 08:40:56 2019
@@ -1146,8 +1146,8 @@ static ValueLatticeElement getValueFromO
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).
Modified: llvm/trunk/lib/IR/ConstantRange.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ConstantRange.cpp?rev=359402&r1=359401&r2=359402&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ConstantRange.cpp (original)
+++ llvm/trunk/lib/IR/ConstantRange.cpp Sun Apr 28 08:40:56 2019
@@ -309,6 +309,14 @@ ConstantRange::makeGuaranteedNoWrapRegio
}
}
+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 &
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));
Modified: llvm/trunk/unittests/IR/ConstantRangeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/ConstantRangeTest.cpp?rev=359402&r1=359401&r2=359402&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/ConstantRangeTest.cpp (original)
+++ llvm/trunk/unittests/IR/ConstantRangeTest.cpp Sun Apr 28 08:40:56 2019
@@ -1176,17 +1176,25 @@ void TestNoWrapRegionExhaustive(Instruct
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,
More information about the llvm-commits
mailing list