summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2015-03-18 00:41:24 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2015-03-18 00:41:24 +0000
commit7182d36f660a8cd439b94198316410080070a6af (patch)
tree90d7ed22c649bc7d2ba3c461fb7c61a5487b72a5 /llvm
parentcba49d4b04fe88c1562df00d9c8bf5568f28cd45 (diff)
downloadbcm5719-llvm-7182d36f660a8cd439b94198316410080070a6af.tar.gz
bcm5719-llvm-7182d36f660a8cd439b94198316410080070a6af.zip
[ConstantRange] Split makeICmpRegion in two.
Summary: This change splits `makeICmpRegion` into `makeAllowedICmpRegion` and `makeSatisfyingICmpRegion` with slightly different contracts. The first one is useful for determining what values some expression //may// take, given that a certain `icmp` evaluates to true. The second one is useful for determining what values are guaranteed to //satisfy// a given `icmp`. Reviewers: nlewycky Reviewed By: nlewycky Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D8345 llvm-svn: 232575
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/IR/ConstantRange.h29
-rw-r--r--llvm/lib/Analysis/LazyValueInfo.cpp4
-rw-r--r--llvm/lib/IR/ConstantRange.cpp17
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp4
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp4
-rw-r--r--llvm/unittests/IR/ConstantRangeTest.cpp58
6 files changed, 96 insertions, 20 deletions
diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h
index ebb1bf0b04b..9ded3ca36a7 100644
--- a/llvm/include/llvm/IR/ConstantRange.h
+++ b/llvm/include/llvm/IR/ConstantRange.h
@@ -33,6 +33,7 @@
#define LLVM_IR_CONSTANTRANGE_H
#include "llvm/ADT/APInt.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@@ -59,15 +60,27 @@ public:
/// assert out if the two APInt's are not the same bit width.
ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper);
- /// Produce the smallest range that contains all values that
- /// might satisfy the comparison specified by Pred when compared to any value
- /// contained within Other.
+ /// Produce the smallest range such that all values that may satisfy the given
+ /// predicate with any value contained within Other is contained in the
+ /// returned range. Formally, this returns a superset of
+ /// 'union over all y in Other . { x : icmp op x y is true }'. If the exact
+ /// answer is not representable as a ConstantRange, the return value will be a
+ /// proper superset of the above.
///
- /// Solves for range X in 'for all x in X, there exists a y in Y such that
- /// icmp op x, y is true'. Every value that might make the comparison true
- /// is included in the resulting range.
- static ConstantRange makeICmpRegion(unsigned Pred,
- const ConstantRange &Other);
+ /// Example: Pred = ult and Other = i8 [2, 5) returns Result = [0, 4)
+ static ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred,
+ const ConstantRange &Other);
+
+ /// Produce the largest range such that all values in the returned range
+ /// satisfy the given predicate with all values contained within Other.
+ /// Formally, this returns a subset of
+ /// 'intersection over all y in Other . { x : icmp op x y is true }'. If the
+ /// exact answer is not representable as a ConstantRange, the return value
+ /// will be a proper subset of the above.
+ ///
+ /// Example: Pred = ult and Other = i8 [2, 5) returns [0, 2)
+ static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
+ const ConstantRange &Other);
/// Return the lower value for this range.
///
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 1f06f117618..e6f586ac702 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -854,10 +854,10 @@ bool getValueFromFromCondition(Value *Val, ICmpInst *ICI,
ConstantInt *CI = dyn_cast<ConstantInt>(ICI->getOperand(1));
if (CI && (ICI->getOperand(0) == Val || NegOffset)) {
- // Calculate the range of values that would satisfy the comparison.
+ // Calculate the range of values that are allowed by the comparison
ConstantRange CmpRange(CI->getValue());
ConstantRange TrueValues =
- ConstantRange::makeICmpRegion(ICI->getPredicate(), CmpRange);
+ ConstantRange::makeAllowedICmpRegion(ICI->getPredicate(), CmpRange);
if (NegOffset) // Apply the offset from above.
TrueValues = TrueValues.subtract(NegOffset->getValue());
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index eec18b95fb8..91095cfe9ee 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -49,14 +49,15 @@ ConstantRange::ConstantRange(APIntMoveTy L, APIntMoveTy U)
"Lower == Upper, but they aren't min or max value!");
}
-ConstantRange ConstantRange::makeICmpRegion(unsigned Pred,
- const ConstantRange &CR) {
+ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred,
+ const ConstantRange &CR) {
if (CR.isEmptySet())
return CR;
uint32_t W = CR.getBitWidth();
switch (Pred) {
- default: llvm_unreachable("Invalid ICmp predicate to makeICmpRegion()");
+ default:
+ llvm_unreachable("Invalid ICmp predicate to makeAllowedICmpRegion()");
case CmpInst::ICMP_EQ:
return CR;
case CmpInst::ICMP_NE:
@@ -114,6 +115,16 @@ ConstantRange ConstantRange::makeICmpRegion(unsigned Pred,
}
}
+ConstantRange ConstantRange::makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
+ const ConstantRange &CR) {
+ // Follows from De-Morgan's laws:
+ //
+ // ~(~A union ~B) == A intersect B.
+ //
+ return makeAllowedICmpRegion(CmpInst::getInversePredicate(Pred), CR)
+ .inverse();
+}
+
/// isFullSet - Return true if this set contains all of the elements possible
/// for this data-type
bool ConstantRange::isFullSet() const {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 3273c661553..ee21c81fa26 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -979,9 +979,9 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
// Make a constant range that's the intersection of the two icmp ranges.
// If the intersection is empty, we know that the result is false.
ConstantRange LHSRange =
- ConstantRange::makeICmpRegion(LHSCC, LHSCst->getValue());
+ ConstantRange::makeAllowedICmpRegion(LHSCC, LHSCst->getValue());
ConstantRange RHSRange =
- ConstantRange::makeICmpRegion(RHSCC, RHSCst->getValue());
+ ConstantRange::makeAllowedICmpRegion(RHSCC, RHSCst->getValue());
if (LHSRange.intersectWith(RHSRange).isEmptySet())
return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0);
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 896da1d3a6b..b45a256bc24 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -421,8 +421,8 @@ private:
}
// If we have "x ult 3", for example, then we can add 0,1,2 to the set.
- ConstantRange Span = ConstantRange::makeICmpRegion(ICI->getPredicate(),
- C->getValue());
+ ConstantRange Span = ConstantRange::makeAllowedICmpRegion(
+ ICI->getPredicate(), C->getValue());
// Shift the range if the compare is fed by an add. This is the range
// compare idiom as emitted by instcombine.
diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp
index fe95b0db9c5..de4eec4abf5 100644
--- a/llvm/unittests/IR/ConstantRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -509,11 +509,63 @@ TEST_F(ConstantRangeTest, Lshr) {
EXPECT_EQ(Wrap.lshr(Wrap), Full);
}
-TEST(ConstantRange, MakeICmpRegion) {
+TEST(ConstantRange, MakeAllowedICmpRegion) {
// PR8250
ConstantRange SMax = ConstantRange(APInt::getSignedMaxValue(32));
- EXPECT_TRUE(ConstantRange::makeICmpRegion(ICmpInst::ICMP_SGT,
- SMax).isEmptySet());
+ EXPECT_TRUE(ConstantRange::makeAllowedICmpRegion(ICmpInst::ICMP_SGT, SMax)
+ .isEmptySet());
+}
+
+TEST(ConstantRange, MakeSatisfyingICmpRegion) {
+ ConstantRange LowHalf(APInt(8, 0), APInt(8, 128));
+ ConstantRange HighHalf(APInt(8, 128), APInt(8, 0));
+ ConstantRange EmptySet(8, /* isFullSet = */ false);
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_NE, LowHalf),
+ HighHalf);
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_NE, HighHalf),
+ LowHalf);
+
+ EXPECT_TRUE(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_EQ,
+ HighHalf).isEmptySet());
+
+ ConstantRange UnsignedSample(APInt(8, 5), APInt(8, 200));
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_ULT,
+ UnsignedSample),
+ ConstantRange(APInt(8, 0), APInt(8, 5)));
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_ULE,
+ UnsignedSample),
+ ConstantRange(APInt(8, 0), APInt(8, 6)));
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_UGT,
+ UnsignedSample),
+ ConstantRange(APInt(8, 200), APInt(8, 0)));
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_UGE,
+ UnsignedSample),
+ ConstantRange(APInt(8, 199), APInt(8, 0)));
+
+ ConstantRange SignedSample(APInt(8, -5), APInt(8, 5));
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_SLT, SignedSample),
+ ConstantRange(APInt(8, -128), APInt(8, -5)));
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_SLE, SignedSample),
+ ConstantRange(APInt(8, -128), APInt(8, -4)));
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_SGT, SignedSample),
+ ConstantRange(APInt(8, 5), APInt(8, -128)));
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_SGE, SignedSample),
+ ConstantRange(APInt(8, 4), APInt(8, -128)));
}
} // anonymous namespace
OpenPOWER on IntegriCloud