summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Reames <listmail@philipreames.com>2016-02-26 22:08:18 +0000
committerPhilip Reames <listmail@philipreames.com>2016-02-26 22:08:18 +0000
commitba31312f6395774e7c0d801a7abb876048e4a1ba (patch)
tree1795edc90fdc4238b7badd223d5d471ad5b9a973
parent915c5ecee16658544c5a35eabd7cbc404cdedd0d (diff)
downloadbcm5719-llvm-ba31312f6395774e7c0d801a7abb876048e4a1ba.tar.gz
bcm5719-llvm-ba31312f6395774e7c0d801a7abb876048e4a1ba.zip
[ConstantRange] Add umin/smin operators
This was split off from http://reviews.llvm.org/D17184. Reviewed by: Sanjoy llvm-svn: 262080
-rw-r--r--llvm/include/llvm/IR/ConstantRange.h8
-rw-r--r--llvm/lib/IR/ConstantRange.cpp26
-rw-r--r--llvm/unittests/IR/ConstantRangeTest.cpp39
3 files changed, 73 insertions, 0 deletions
diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h
index f2a77765dcf..5038ae13b6a 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 9bea98c7f3c..521511ade5c 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 af2f133d38f..35b1db3ed42 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);
OpenPOWER on IntegriCloud