diff options
author | Philip Reames <listmail@philipreames.com> | 2015-09-28 17:14:24 +0000 |
---|---|---|
committer | Philip Reames <listmail@philipreames.com> | 2015-09-28 17:14:24 +0000 |
commit | 13f023c09dcc89ce19bccdbcdf29127a4f4c0065 (patch) | |
tree | 309a85ae4274acfb405e3b9d140eb4f546259f3b /llvm/lib/Analysis | |
parent | 310770a90fe20783ef7798c98b6e556eb3dd3040 (diff) | |
download | bcm5719-llvm-13f023c09dcc89ce19bccdbcdf29127a4f4c0065.tar.gz bcm5719-llvm-13f023c09dcc89ce19bccdbcdf29127a4f4c0065.zip |
[InstSimplify] Fold simple known implications to true
This was split off of http://reviews.llvm.org/D13040 to make it easier to test the correctness of the implication logic. For the moment, this only handles a single easy case which shows up when eliminating and combining range checks. In the (near) future, I plan to extend this for other cases which show up in range checks, but I wanted to make those changes incrementally once the framework was in place.
At the moment, the implication logic will be used by three places. One in InstSimplify (this review) and two in SimplifyCFG (http://reviews.llvm.org/D13040 & http://reviews.llvm.org/D13070). Can anyone think of other locations this style of reasoning would make sense?
Differential Revision: http://reviews.llvm.org/D13074
llvm-svn: 248719
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 2086337df8b..c8a13c79f57 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2128,6 +2128,47 @@ static Constant *computePointerICmp(const DataLayout &DL, return nullptr; } +/// Return true if B is known to be implied by A. A & B must be i1 (boolean) +/// values. Note that the truth table for implication is the same as <=u on i1 +/// values (but not <=s!). The truth table for both is: +/// | T | F (B) +/// T | T | F +/// F | T | T +/// (A) +static bool implies(Value *A, Value *B) { + // TODO: Consider extending this to vector of i1? + assert(A->getType()->isIntegerTy(1) && B->getType()->isIntegerTy(1)); + + // A ==> A by definition + if (A == B) return true; + + ICmpInst::Predicate APred, BPred; + Value *I; + Value *L; + ConstantInt *CI; + // i +_{nsw} C_{>0} <s L ==> i <s L + if (match(A, m_ICmp(APred, + m_NSWAdd(m_Value(I), m_ConstantInt(CI)), + m_Value(L))) && + APred == ICmpInst::ICMP_SLT && + !CI->isNegative() && + match(B, m_ICmp(BPred, m_Specific(I), m_Specific(L))) && + BPred == ICmpInst::ICMP_SLT) + return true; + + // i +_{nuw} C_{>0} <u L ==> i <u L + if (match(A, m_ICmp(APred, + m_NUWAdd(m_Value(I), m_ConstantInt(CI)), + m_Value(L))) && + APred == ICmpInst::ICMP_ULT && + !CI->isNegative() && + match(B, m_ICmp(BPred, m_Specific(I), m_Specific(L))) && + BPred == ICmpInst::ICMP_ULT) + return true; + + return false; +} + static ConstantRange GetConstantRangeFromMetadata(MDNode *Ranges, uint32_t BitWidth) { const unsigned NumRanges = Ranges->getNumOperands() / 2; assert(NumRanges >= 1); @@ -2199,6 +2240,8 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, // X >=u 1 -> X if (match(RHS, m_One())) return LHS; + if (implies(RHS, LHS)) + return getTrue(ITy); break; case ICmpInst::ICMP_SLT: // X <s 0 -> X @@ -2210,6 +2253,10 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, if (match(RHS, m_One())) return LHS; break; + case ICmpInst::ICMP_ULE: + if (implies(LHS, RHS)) + return getTrue(ITy); + break; } } |