From d792171efbf155fc741290e87b7d1e54fb1ece29 Mon Sep 17 00:00:00 2001 From: Max Kazantsev Date: Mon, 18 Dec 2017 13:01:32 +0000 Subject: [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 --- llvm/lib/IR/ConstantRange.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'llvm/lib/IR/ConstantRange.cpp') 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); -- cgit v1.2.3