aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/ConstantRange.cpp
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2020-09-22 11:50:25 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2020-09-22 21:37:29 +0300
commitb38d897e802664034c7e6e4654328256ed370a61 (patch)
treee1292e468f28378accd63d4542c5c4439ca7128a /llvm/lib/IR/ConstantRange.cpp
parent4eeeb356fc41babf46797b062f74f978b818622b (diff)
downloadllvm-b38d897e802664034c7e6e4654328256ed370a61.zip
llvm-b38d897e802664034c7e6e4654328256ed370a61.tar.gz
llvm-b38d897e802664034c7e6e4654328256ed370a61.tar.bz2
[ConstantRange] binaryXor(): special-case binary complement case - the result is precise
Use the fact that `~X` is equivalent to `-1 - X`, which gives us fully-precise answer, and we only need to special-handle the wrapped case. This fires ~16k times for vanilla llvm test-suite + RawSpeed.
Diffstat (limited to 'llvm/lib/IR/ConstantRange.cpp')
-rw-r--r--llvm/lib/IR/ConstantRange.cpp16
1 files changed, 16 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 396c39b..7b8dd66 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -1240,6 +1240,16 @@ ConstantRange ConstantRange::srem(const ConstantRange &RHS) const {
return ConstantRange(std::move(Lower), std::move(Upper));
}
+ConstantRange ConstantRange::binaryNot() const {
+ if (isEmptySet())
+ return getEmpty();
+
+ if (isWrappedSet())
+ return getFull();
+
+ return ConstantRange(APInt::getAllOnesValue(getBitWidth())).sub(*this);
+}
+
ConstantRange
ConstantRange::binaryAnd(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
@@ -1278,6 +1288,12 @@ ConstantRange ConstantRange::binaryXor(const ConstantRange &Other) const {
if (isSingleElement() && Other.isSingleElement())
return {*getSingleElement() ^ *Other.getSingleElement()};
+ // Special-case binary complement, since we can give a precise answer.
+ if (Other.isSingleElement() && Other.getSingleElement()->isAllOnesValue())
+ return binaryNot();
+ if (isSingleElement() && getSingleElement()->isAllOnesValue())
+ return Other.binaryNot();
+
// TODO: replace this with something less conservative
return getFull();
}