From ba31312f6395774e7c0d801a7abb876048e4a1ba Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Fri, 26 Feb 2016 22:08:18 +0000 Subject: [PATCH] [ConstantRange] Add umin/smin operators This was split off from http://reviews.llvm.org/D17184. Reviewed by: Sanjoy llvm-svn: 262080 --- llvm/include/llvm/IR/ConstantRange.h | 8 +++++++ llvm/lib/IR/ConstantRange.cpp | 26 ++++++++++++++++++++++ llvm/unittests/IR/ConstantRangeTest.cpp | 39 +++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h index f2a7776..5038ae1 100644 --- a/llvm/include/llvm/IR/ConstantRange.h +++ b/llvm/include/llvm/IR/ConstantRange.h @@ -254,6 +254,14 @@ public: ConstantRange umax(const ConstantRange &Other) const; /// Return a new range representing the possible values resulting + /// from a signed minimum of a value in this range and a value in \p Other. + ConstantRange smin(const ConstantRange &Other) const; + + /// Return a new range representing the possible values resulting + /// from an unsigned minimum of a value in this range and a value in \p Other. + ConstantRange umin(const ConstantRange &Other) const; + + /// Return a new range representing the possible values resulting /// from an unsigned division of a value in this range and a value in /// \p Other. ConstantRange udiv(const ConstantRange &Other) const; diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index 9bea98c..521511a 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -714,6 +714,32 @@ ConstantRange::umax(const ConstantRange &Other) const { } ConstantRange +ConstantRange::smin(const ConstantRange &Other) const { + // X smin Y is: range(smin(X_smin, Y_smin), + // smin(X_smax, Y_smax)) + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + APInt NewL = APIntOps::smin(getSignedMin(), Other.getSignedMin()); + APInt NewU = APIntOps::smin(getSignedMax(), Other.getSignedMax()) + 1; + if (NewU == NewL) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + return ConstantRange(NewL, NewU); +} + +ConstantRange +ConstantRange::umin(const ConstantRange &Other) const { + // X umin Y is: range(umin(X_umin, Y_umin), + // umin(X_umax, Y_umax)) + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + APInt NewL = APIntOps::umin(getUnsignedMin(), Other.getUnsignedMin()); + APInt NewU = APIntOps::umin(getUnsignedMax(), Other.getUnsignedMax()) + 1; + if (NewU == NewL) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + return ConstantRange(NewL, NewU); +} + +ConstantRange ConstantRange::udiv(const ConstantRange &RHS) const { if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax() == 0) return ConstantRange(getBitWidth(), /*isFullSet=*/false); diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp index af2f133..35b1db3 100644 --- a/llvm/unittests/IR/ConstantRangeTest.cpp +++ b/llvm/unittests/IR/ConstantRangeTest.cpp @@ -450,6 +450,45 @@ TEST_F(ConstantRangeTest, SMax) { EXPECT_EQ(One.smax(One), One); } +TEST_F(ConstantRangeTest, UMin) { + EXPECT_EQ(Full.umin(Full), Full); + EXPECT_EQ(Full.umin(Empty), Empty); + EXPECT_EQ(Full.umin(Some), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); + EXPECT_EQ(Full.umin(Wrap), Full); + EXPECT_EQ(Empty.umin(Empty), Empty); + EXPECT_EQ(Empty.umin(Some), Empty); + EXPECT_EQ(Empty.umin(Wrap), Empty); + EXPECT_EQ(Empty.umin(One), Empty); + EXPECT_EQ(Some.umin(Some), Some); + EXPECT_EQ(Some.umin(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); + EXPECT_EQ(Some.umin(One), One); + // TODO: ConstantRange is currently over-conservative here. + EXPECT_EQ(Wrap.umin(Wrap), Full); + EXPECT_EQ(Wrap.umin(One), ConstantRange(APInt(16, 0), APInt(16, 0xb))); + EXPECT_EQ(One.umin(One), One); +} + +TEST_F(ConstantRangeTest, SMin) { + EXPECT_EQ(Full.smin(Full), Full); + EXPECT_EQ(Full.smin(Empty), Empty); + EXPECT_EQ(Full.smin(Some), ConstantRange(APInt(16, (uint64_t)INT16_MIN), + APInt(16, 0xaaa))); + EXPECT_EQ(Full.smin(Wrap), Full); + EXPECT_EQ(Empty.smin(Empty), Empty); + EXPECT_EQ(Empty.smin(Some), Empty); + EXPECT_EQ(Empty.smin(Wrap), Empty); + EXPECT_EQ(Empty.smin(One), Empty); + EXPECT_EQ(Some.smin(Some), Some); + EXPECT_EQ(Some.smin(Wrap), ConstantRange(APInt(16, (uint64_t)INT16_MIN), + APInt(16, 0xaaa))); + EXPECT_EQ(Some.smin(One), One); + // TODO: ConstantRange is currently over-conservative here. + EXPECT_EQ(Wrap.smin(Wrap), Full); + EXPECT_EQ(Wrap.smin(One), ConstantRange(APInt(16, (uint64_t)INT16_MIN), + APInt(16, 0xb))); + EXPECT_EQ(One.smin(One), One); +} + TEST_F(ConstantRangeTest, UDiv) { EXPECT_EQ(Full.udiv(Full), Full); EXPECT_EQ(Full.udiv(Empty), Empty); -- 2.7.4