[PATCH] D71010: [ConstantRange] Add `getClosestToZero()` method - what value[s] are closest to signed zero?
Roman Lebedev via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 4 06:16:04 PST 2019
lebedev.ri created this revision.
lebedev.ri added reviewers: reames, nikic, efriedma, spatel, sanjoy.
lebedev.ri added a project: LLVM.
Herald added a subscriber: hiraditya.
lebedev.ri added a child revision: D70043: [ConstantRange] Add `mulWithNoWrap()` method.
lebedev.ri added a child revision: D71011: [ConstantRange] Add `shlWithNoWrap()` method.
This method is needed in the follow-up patches adding
`ConstantRange::mulWithNoWrap()`/`ConstantRange::shlWithNoWrap()` support
to detect the all-overflow cases where we should/could return empty-set.
There's an exhaustive test so we know this is correct and optimal.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D71010
Files:
llvm/include/llvm/IR/ConstantRange.h
llvm/lib/IR/ConstantRange.cpp
llvm/unittests/IR/ConstantRangeTest.cpp
Index: llvm/unittests/IR/ConstantRangeTest.cpp
===================================================================
--- llvm/unittests/IR/ConstantRangeTest.cpp
+++ llvm/unittests/IR/ConstantRangeTest.cpp
@@ -2295,4 +2295,37 @@
});
}
+TEST_F(ConstantRangeTest, getClosestToZero) {
+ unsigned Bits = 4;
+ EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
+ const SmallVector<APInt, 2> ClosestToZero = CR.getClosestToZero();
+
+ EXPECT_EQ(ClosestToZero.empty(), CR.isEmptySet());
+ if (ClosestToZero.empty())
+ return;
+
+ EXPECT_LE(ClosestToZero.size(), 2U);
+ if (ClosestToZero.size() == 2U)
+ EXPECT_EQ(ClosestToZero.front(), -(ClosestToZero.back()));
+
+ for (const APInt &V : ClosestToZero)
+ EXPECT_TRUE(CR.contains(V));
+
+ if (llvm::any_of(ClosestToZero, [Bits](const APInt &V) {
+ return V == APInt::getSignedMinValue(Bits);
+ })) {
+ EXPECT_EQ(ClosestToZero.size(), 1U);
+ const APInt *S = CR.getSingleElement();
+ EXPECT_NE(S, nullptr);
+ EXPECT_EQ(*S, ClosestToZero.front());
+
+ return;
+ }
+
+ APInt ClosestToZeroAbs = ClosestToZero.front().abs();
+ for (APInt C = APInt(Bits, 0); C.ult(ClosestToZeroAbs); ++C)
+ EXPECT_FALSE(CR.contains(C) || CR.contains(-C));
+ });
+}
+
} // anonymous namespace
Index: llvm/lib/IR/ConstantRange.cpp
===================================================================
--- llvm/lib/IR/ConstantRange.cpp
+++ llvm/lib/IR/ConstantRange.cpp
@@ -385,6 +385,30 @@
return getLower();
}
+SmallVector<APInt, 2> ConstantRange::getClosestToZero() const {
+ if (isEmptySet())
+ return {};
+
+ // If the range contains zero, said zero itself is the answer.
+ APInt Zero = APInt::getNullValue(getBitWidth());
+ if (contains(Zero))
+ return {Zero};
+
+ APInt Lower = getLower();
+ APInt Upper = getUpper() - 1;
+
+ // If both limits are equidistant from zero, then we *MUST* return both!
+ // We can don't bother checking for zero, we know we don't have it by now.
+ if (Lower.isNonNegative() && Upper.isNegative() && Lower == -Upper)
+ return {Lower, Upper};
+
+ // Return the limit that has smallest absolute value. This is INT_MIN-safe.
+ auto CompareAbs = [](const APInt &A, const APInt &B) {
+ return A.abs().ult(B.abs());
+ };
+ return {std::min({Lower, Upper}, CompareAbs)};
+}
+
bool ConstantRange::contains(const APInt &V) const {
if (Lower == Upper)
return isFullSet();
Index: llvm/include/llvm/IR/ConstantRange.h
===================================================================
--- llvm/include/llvm/IR/ConstantRange.h
+++ llvm/include/llvm/IR/ConstantRange.h
@@ -245,6 +245,10 @@
/// Return the smallest signed value contained in the ConstantRange.
APInt getSignedMin() const;
+ /// Return the value contained in the ConstantRange with smallest absolute
+ /// value.
+ SmallVector<APInt, 2> getClosestToZero() const;
+
/// Return true if this range is equal to another range.
bool operator==(const ConstantRange &CR) const {
return Lower == CR.Lower && Upper == CR.Upper;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D71010.232105.patch
Type: text/x-patch
Size: 3091 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191204/26a9b072/attachment.bin>
More information about the llvm-commits
mailing list