[llvm] r320976 - [ConstantRange] Support for ashr in ConstantRange computation
Max Kazantsev via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 18 05:01:32 PST 2017
Author: mkazantsev
Date: Mon Dec 18 05:01:32 2017
New Revision: 320976
URL: http://llvm.org/viewvc/llvm-project?rev=320976&view=rev
Log:
[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
Modified:
llvm/trunk/include/llvm/IR/ConstantRange.h
llvm/trunk/lib/IR/ConstantRange.cpp
llvm/trunk/unittests/IR/ConstantRangeTest.cpp
Modified: llvm/trunk/include/llvm/IR/ConstantRange.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ConstantRange.h?rev=320976&r1=320975&r2=320976&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ConstantRange.h (original)
+++ llvm/trunk/include/llvm/IR/ConstantRange.h Mon Dec 18 05:01:32 2017
@@ -317,6 +317,10 @@ public:
/// logical right shift of a value in this range and a value in \p Other.
ConstantRange lshr(const ConstantRange &Other) const;
+ /// Return a new range representing the possible values resulting from a
+ /// arithmetic right shift of a value in this range and a value in \p Other.
+ ConstantRange ashr(const ConstantRange &Other) const;
+
/// Return a new range that is the logical not of the current set.
ConstantRange inverse() const;
Modified: llvm/trunk/lib/IR/ConstantRange.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ConstantRange.cpp?rev=320976&r1=320975&r2=320976&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ConstantRange.cpp (original)
+++ llvm/trunk/lib/IR/ConstantRange.cpp Mon Dec 18 05:01:32 2017
@@ -680,6 +680,8 @@ ConstantRange ConstantRange::binaryOp(In
return shl(Other);
case Instruction::LShr:
return lshr(Other);
+ case Instruction::AShr:
+ return ashr(Other);
case Instruction::And:
return binaryAnd(Other);
case Instruction::Or:
@@ -943,6 +945,60 @@ ConstantRange::lshr(const ConstantRange
if (min == max)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+ 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));
}
Modified: llvm/trunk/unittests/IR/ConstantRangeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/ConstantRangeTest.cpp?rev=320976&r1=320975&r2=320976&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/ConstantRangeTest.cpp (original)
+++ llvm/trunk/unittests/IR/ConstantRangeTest.cpp Mon Dec 18 05:01:32 2017
@@ -606,6 +606,33 @@ TEST_F(ConstantRangeTest, Lshr) {
EXPECT_EQ(Wrap.lshr(Wrap), Full);
}
+TEST_F(ConstantRangeTest, Ashr) {
+ EXPECT_EQ(Full.ashr(Full), Full);
+ EXPECT_EQ(Full.ashr(Empty), Empty);
+ EXPECT_EQ(Full.ashr(One), ConstantRange(APInt(16, 0xffe0),
+ APInt(16, (0x7fff >> 0xa) + 1 )));
+ ConstantRange Small(APInt(16, 0xa), APInt(16, 0xb));
+ EXPECT_EQ(Full.ashr(Small), ConstantRange(APInt(16, 0xffe0),
+ APInt(16, (0x7fff >> 0xa) + 1 )));
+ EXPECT_EQ(Full.ashr(Some), ConstantRange(APInt(16, 0xffe0),
+ APInt(16, (0x7fff >> 0xa) + 1 )));
+ EXPECT_EQ(Full.ashr(Wrap), Full);
+ EXPECT_EQ(Empty.ashr(Empty), Empty);
+ EXPECT_EQ(Empty.ashr(One), Empty);
+ EXPECT_EQ(Empty.ashr(Some), Empty);
+ EXPECT_EQ(Empty.ashr(Wrap), Empty);
+ EXPECT_EQ(One.ashr(One), ConstantRange(APInt(16, 0)));
+ EXPECT_EQ(One.ashr(Some), ConstantRange(APInt(16, 0)));
+ EXPECT_EQ(One.ashr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb)));
+ EXPECT_EQ(Some.ashr(Some), ConstantRange(APInt(16, 0),
+ APInt(16, (0xaaa >> 0xa) + 1)));
+ EXPECT_EQ(Some.ashr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa)));
+ EXPECT_EQ(Wrap.ashr(Wrap), Full);
+ ConstantRange Neg(APInt(16, 0xf3f0, true), APInt(16, 0xf7f8, true));
+ EXPECT_EQ(Neg.ashr(Small), ConstantRange(APInt(16, 0xfffc, true),
+ APInt(16, 0xfffe, true)));
+}
+
TEST(ConstantRange, MakeAllowedICmpRegion) {
// PR8250
ConstantRange SMax = ConstantRange(APInt::getSignedMaxValue(32));
More information about the llvm-commits
mailing list