aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/ConstantRange.cpp
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2021-10-15 21:25:39 +0200
committerNikita Popov <nikita.ppv@gmail.com>2021-10-15 23:44:41 +0200
commit587493b441ea87f132fec680933d3628050756b8 (patch)
tree5f36204a9eb93dbaf3f196e218b59da2a47b1dd5 /llvm/lib/IR/ConstantRange.cpp
parentf92db6d3fff13bdacdf9b24660eb3f3158c58a17 (diff)
downloadllvm-587493b441ea87f132fec680933d3628050756b8.zip
llvm-587493b441ea87f132fec680933d3628050756b8.tar.gz
llvm-587493b441ea87f132fec680933d3628050756b8.tar.bz2
[ConstantRange] Compute precise shl range for single elements
For the common case where the shift amount is constant (a single element range) we can easily compute a precise range (up to unsigned envelope), so do that.
Diffstat (limited to 'llvm/lib/IR/ConstantRange.cpp')
-rw-r--r--llvm/lib/IR/ConstantRange.cpp33
1 files changed, 21 insertions, 12 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 530a378..d8b4262 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -1346,24 +1346,33 @@ ConstantRange::shl(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return getEmpty();
- APInt max = getUnsignedMax();
- APInt Other_umax = Other.getUnsignedMax();
+ APInt Min = getUnsignedMin();
+ APInt Max = getUnsignedMax();
+ if (const APInt *RHS = Other.getSingleElement()) {
+ unsigned BW = getBitWidth();
+ if (RHS->uge(BW))
+ return getEmpty();
- // If we are shifting by maximum amount of
- // zero return return the original range.
- if (Other_umax.isZero())
- return *this;
- // there's overflow!
- if (Other_umax.ugt(max.countLeadingZeros()))
+ unsigned EqualLeadingBits = (Min ^ Max).countLeadingZeros();
+ if (RHS->ule(EqualLeadingBits))
+ return getNonEmpty(Min << *RHS, (Max << *RHS) + 1);
+
+ return getNonEmpty(APInt::getZero(BW),
+ APInt::getBitsSetFrom(BW, RHS->getZExtValue()) + 1);
+ }
+
+ APInt OtherMax = Other.getUnsignedMax();
+
+ // There's overflow!
+ if (OtherMax.ugt(Max.countLeadingZeros()))
return getFull();
// FIXME: implement the other tricky cases
- APInt min = getUnsignedMin();
- min <<= Other.getUnsignedMin();
- max <<= Other_umax;
+ Min <<= Other.getUnsignedMin();
+ Max <<= OtherMax;
- return ConstantRange(std::move(min), std::move(max) + 1);
+ return ConstantRange::getNonEmpty(std::move(Min), std::move(Max) + 1);
}
ConstantRange