diff options
| author | Max Kazantsev <max.kazantsev@azul.com> | 2017-12-18 13:01:32 +0000 | 
|---|---|---|
| committer | Max Kazantsev <max.kazantsev@azul.com> | 2017-12-18 13:01:32 +0000 | 
| commit | d792171efbf155fc741290e87b7d1e54fb1ece29 (patch) | |
| tree | 1b4993291e157235c9c5c2b1a40999276df30594 /llvm/lib | |
| parent | f70af977af43380e760f7c722ec089ae10e86208 (diff) | |
| download | bcm5719-llvm-d792171efbf155fc741290e87b7d1e54fb1ece29.tar.gz bcm5719-llvm-d792171efbf155fc741290e87b7d1e54fb1ece29.zip | |
[ConstantRange] Support for ashr in ConstantRange computation
Extend the ConstantRange implementation to compute the range of possible values resulting from an arithmetic right shift operation.
There will be a follow up patch to leverage this constant range infrastructure in LazyValueInfo.
Patch by Surya Kumari Jangala!
Differential Revision: https://reviews.llvm.org/D40881
llvm-svn: 320976
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 56 | 
1 files changed, 56 insertions, 0 deletions
| diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index 77ecd7a9077..48d16f334ba 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -680,6 +680,8 @@ ConstantRange ConstantRange::binaryOp(Instruction::BinaryOps BinOp,      return shl(Other);    case Instruction::LShr:      return lshr(Other); +  case Instruction::AShr: +    return ashr(Other);    case Instruction::And:      return binaryAnd(Other);    case Instruction::Or: @@ -946,6 +948,60 @@ ConstantRange::lshr(const ConstantRange &Other) const {    return ConstantRange(std::move(min), std::move(max));  } +ConstantRange +ConstantRange::ashr(const ConstantRange &Other) const { +  if (isEmptySet() || Other.isEmptySet()) +    return ConstantRange(getBitWidth(), /*isFullSet=*/false); + +  // May straddle zero, so handle both positive and negative cases. +  // 'PosMax' is the upper bound of the result of the ashr +  // operation, when Upper of the LHS of ashr is a non-negative. +  // number. Since ashr of a non-negative number will result in a +  // smaller number, the Upper value of LHS is shifted right with +  // the minimum value of 'Other' instead of the maximum value. +  APInt PosMax = getSignedMax().ashr(Other.getUnsignedMin()) + 1; + +  // 'PosMin' is the lower bound of the result of the ashr +  // operation, when Lower of the LHS is a non-negative number. +  // Since ashr of a non-negative number will result in a smaller +  // number, the Lower value of LHS is shifted right with the +  // maximum value of 'Other'. +  APInt PosMin = getSignedMin().ashr(Other.getUnsignedMax()); + +  // 'NegMax' is the upper bound of the result of the ashr +  // operation, when Upper of the LHS of ashr is a negative number. +  // Since 'ashr' of a negative number will result in a bigger +  // number, the Upper value of LHS is shifted right with the +  // maximum value of 'Other'. +  APInt NegMax = getSignedMax().ashr(Other.getUnsignedMax()) + 1; + +  // 'NegMin' is the lower bound of the result of the ashr +  // operation, when Lower of the LHS of ashr is a negative number. +  // Since 'ashr' of a negative number will result in a bigger +  // number, the Lower value of LHS is shifted right with the +  // minimum value of 'Other'. +  APInt NegMin = getSignedMin().ashr(Other.getUnsignedMin()); + +  APInt max, min; +  if (getSignedMin().isNonNegative()) { +    // Upper and Lower of LHS are non-negative. +    min = PosMin; +    max = PosMax; +  } else if (getSignedMax().isNegative()) { +    // Upper and Lower of LHS are negative. +    min = NegMin; +    max = NegMax; +  } else { +    // Upper is non-negative and Lower is negative. +    min = NegMin; +    max = PosMax; +  } +  if (min == max) +    return ConstantRange(getBitWidth(), /*isFullSet=*/true); + +  return ConstantRange(std::move(min), std::move(max)); +} +  ConstantRange ConstantRange::inverse() const {    if (isFullSet())      return ConstantRange(getBitWidth(), /*isFullSet=*/false); | 

