[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:53:16 PST 2019
lebedev.ri updated this revision to Diff 232120.
lebedev.ri added a comment.
Clarify that if we returned two values, they have different polarity, and the negative-one is returned second.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D71010/new/
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,40 @@
});
}
+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_TRUE(ClosestToZero.front().isStrictlyPositive());
+ EXPECT_TRUE(ClosestToZero.back().isNegative());
+ 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 positive one first, and negative second.
+
+ // 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,11 @@
/// Return the smallest signed value contained in the ConstantRange.
APInt getSignedMin() const;
+ /// Return the value contained in the ConstantRange with smallest absolute
+ /// value. Returns from 0 to 2 values. If two values are returned,
+ /// the first one is strictly positive, and second one is strictly negative.
+ 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.232120.patch
Type: text/x-patch
Size: 3406 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191204/8b91f8b3/attachment.bin>
More information about the llvm-commits
mailing list