summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2015-11-06 19:00:57 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2015-11-06 19:00:57 +0000
commit9349dcc74a10f3056639b455d56288e62e23f13c (patch)
tree4e417fdb1c2345b245b8b1355af0c4a84ebcd2bc /llvm/lib
parentddcd2de0d1ede1e42453a027d9c9a11c8fa5b6b6 (diff)
downloadbcm5719-llvm-9349dcc74a10f3056639b455d56288e62e23f13c.tar.gz
bcm5719-llvm-9349dcc74a10f3056639b455d56288e62e23f13c.zip
[ValueTracking] Add a framework for encoding implication rules
Summary: This change adds a framework for adding more smarts to `isImpliedCondition` around inequalities. Informally, `isImpliedCondition` will now try to prove "A < B ==> C < D" by proving "C <= A && B <= D", since then it follows "C <= A < B <= D". While this change is in principle NFC, I could not think of a way to not handle cases like "i +_nsw 1 < L ==> i < L +_nsw 1" (that ValueTracking did not handle before) while keeping the change understandable. I've added tests for these cases. Reviewers: reames, majnemer, hfinkel Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D14368 llvm-svn: 252331
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp88
1 files changed, 67 insertions, 21 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1187de7b59b..3dc9f3a1037 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4082,6 +4082,65 @@ ConstantRange llvm::getConstantRangeFromMetadata(MDNode &Ranges) {
return CR;
}
+/// Return true if "icmp Pred LHS RHS" is always true.
+static bool isTruePredicate(CmpInst::Predicate Pred, Value *LHS, Value *RHS) {
+ if (ICmpInst::isTrueWhenEqual(Pred) && LHS == RHS)
+ return true;
+
+ switch (Pred) {
+ default:
+ return false;
+
+ case CmpInst::ICMP_SLT:
+ case CmpInst::ICMP_SLE: {
+ ConstantInt *CI;
+
+ // LHS s< LHS +_{nsw} C if C > 0
+ // LHS s<= LHS +_{nsw} C if C >= 0
+ if (match(RHS, m_NSWAdd(m_Specific(LHS), m_ConstantInt(CI)))) {
+ if (Pred == CmpInst::ICMP_SLT)
+ return CI->getValue().isStrictlyPositive();
+ return !CI->isNegative();
+ }
+ return false;
+ }
+
+ case CmpInst::ICMP_ULT:
+ case CmpInst::ICMP_ULE: {
+ ConstantInt *CI;
+
+ // LHS u< LHS +_{nuw} C if C > 0
+ // LHS u<= LHS +_{nuw} C if C >= 0
+ if (match(RHS, m_NUWAdd(m_Specific(LHS), m_ConstantInt(CI)))) {
+ if (Pred == CmpInst::ICMP_ULT)
+ return CI->getValue().isStrictlyPositive();
+ return !CI->isNegative();
+ }
+ return false;
+ }
+ }
+}
+
+/// Return true if "icmp Pred BLHS BRHS" is true whenever "icmp Pred
+/// ALHS ARHS" is true.
+static bool isImpliedCondOperands(CmpInst::Predicate Pred, Value *ALHS,
+ Value *ARHS, Value *BLHS, Value *BRHS) {
+ switch (Pred) {
+ default:
+ return false;
+
+ case CmpInst::ICMP_SLT:
+ case CmpInst::ICMP_SLE:
+ return isTruePredicate(CmpInst::ICMP_SLE, BLHS, ALHS) &&
+ isTruePredicate(CmpInst::ICMP_SLE, ARHS, BRHS);
+
+ case CmpInst::ICMP_ULT:
+ case CmpInst::ICMP_ULE:
+ return isTruePredicate(CmpInst::ICMP_ULE, BLHS, ALHS) &&
+ isTruePredicate(CmpInst::ICMP_ULE, ARHS, BRHS);
+ }
+}
+
bool llvm::isImpliedCondition(Value *LHS, Value *RHS) {
assert(LHS->getType() == RHS->getType() && "mismatched type");
Type *OpTy = LHS->getType();
@@ -4096,28 +4155,15 @@ bool llvm::isImpliedCondition(Value *LHS, Value *RHS) {
assert(OpTy->isIntegerTy(1) && "implied by above");
ICmpInst::Predicate APred, BPred;
- Value *I;
- Value *L;
- ConstantInt *CI;
- // i +_{nsw} C_{>0} <s L ==> i <s L
- if (match(LHS, m_ICmp(APred,
- m_NSWAdd(m_Value(I), m_ConstantInt(CI)),
- m_Value(L))) &&
- APred == ICmpInst::ICMP_SLT &&
- !CI->isNegative() &&
- match(RHS, m_ICmp(BPred, m_Specific(I), m_Specific(L))) &&
- BPred == ICmpInst::ICMP_SLT)
- return true;
+ Value *ALHS, *ARHS;
+ Value *BLHS, *BRHS;
- // i +_{nuw} C_{>0} <u L ==> i <u L
- if (match(LHS, m_ICmp(APred,
- m_NUWAdd(m_Value(I), m_ConstantInt(CI)),
- m_Value(L))) &&
- APred == ICmpInst::ICMP_ULT &&
- !CI->isNegative() &&
- match(RHS, m_ICmp(BPred, m_Specific(I), m_Specific(L))) &&
- BPred == ICmpInst::ICMP_ULT)
- return true;
+ if (!match(LHS, m_ICmp(APred, m_Value(ALHS), m_Value(ARHS))) ||
+ !match(RHS, m_ICmp(BPred, m_Value(BLHS), m_Value(BRHS))))
+ return false;
+
+ if (APred == BPred)
+ return isImpliedCondOperands(APred, ALHS, ARHS, BLHS, BRHS);
return false;
}
OpenPOWER on IntegriCloud