diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-11-06 19:00:57 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-11-06 19:00:57 +0000 |
commit | 9349dcc74a10f3056639b455d56288e62e23f13c (patch) | |
tree | 4e417fdb1c2345b245b8b1355af0c4a84ebcd2bc /llvm/lib | |
parent | ddcd2de0d1ede1e42453a027d9c9a11c8fa5b6b6 (diff) | |
download | bcm5719-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.cpp | 88 |
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; } |