diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2021-10-15 21:25:39 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2021-10-15 23:44:41 +0200 |
commit | 587493b441ea87f132fec680933d3628050756b8 (patch) | |
tree | 5f36204a9eb93dbaf3f196e218b59da2a47b1dd5 /llvm/lib/IR/ConstantRange.cpp | |
parent | f92db6d3fff13bdacdf9b24660eb3f3158c58a17 (diff) | |
download | llvm-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.cpp | 33 |
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 |