diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-12-06 10:51:40 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-12-06 10:51:40 +0000 |
commit | 1af36e5baf4f1d046db4f308a28ca1b18475cab4 (patch) | |
tree | c2452f5c3d6cfea7ecbc6e28706bdccdfdd20373 /llvm/lib/Analysis | |
parent | fc3062f65aee7ed02b0bdb75f3883f6030d7bf9f (diff) | |
download | bcm5719-llvm-1af36e5baf4f1d046db4f308a28ca1b18475cab4.tar.gz bcm5719-llvm-1af36e5baf4f1d046db4f308a28ca1b18475cab4.zip |
InstSimplify: Optimize away useless unsigned comparisons
Code like X < Y && Y == 0 should always be folded away to false.
llvm-svn: 223583
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 45290fdcc00..e58998897c2 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1443,12 +1443,57 @@ Value *llvm::SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, RecursionLimit); } +static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp, + ICmpInst *UnsignedICmp, bool IsAnd) { + Value *X, *Y; + + ICmpInst::Predicate EqPred; + if (!match(ZeroICmp, m_ICmp(EqPred, m_Value(Y), m_Zero())) && + ICmpInst::isEquality(EqPred)) + return nullptr; + + ICmpInst::Predicate UnsignedPred; + if (match(UnsignedICmp, m_ICmp(UnsignedPred, m_Value(X), m_Specific(Y))) && + ICmpInst::isUnsigned(UnsignedPred)) + ; + else if (match(UnsignedICmp, + m_ICmp(UnsignedPred, m_Value(Y), m_Specific(X))) && + ICmpInst::isUnsigned(UnsignedPred)) + UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred); + else + return nullptr; + + // X < Y && Y != 0 --> X < Y + // X < Y || Y != 0 --> Y != 0 + if (UnsignedPred == ICmpInst::ICMP_ULT && EqPred == ICmpInst::ICMP_NE) + return IsAnd ? UnsignedICmp : ZeroICmp; + + // X >= Y || Y != 0 --> true + // X >= Y || Y == 0 --> X >= Y + if (UnsignedPred == ICmpInst::ICMP_UGE && !IsAnd) { + if (EqPred == ICmpInst::ICMP_NE) + return getTrue(UnsignedICmp->getType()); + return UnsignedICmp; + } + + // X < Y && Y == 0 --> false + if (UnsignedPred == ICmpInst::ICMP_ULT && EqPred == ICmpInst::ICMP_EQ && + IsAnd) + return getFalse(UnsignedICmp->getType()); + + return nullptr; +} + // Simplify (and (icmp ...) (icmp ...)) to true when we can tell that the range // of possible values cannot be satisfied. static Value *SimplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) { ICmpInst::Predicate Pred0, Pred1; ConstantInt *CI1, *CI2; Value *V; + + if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/true)) + return X; + if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_ConstantInt(CI1)), m_ConstantInt(CI2)))) return nullptr; @@ -1602,6 +1647,10 @@ static Value *SimplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) { ICmpInst::Predicate Pred0, Pred1; ConstantInt *CI1, *CI2; Value *V; + + if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/false)) + return X; + if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_ConstantInt(CI1)), m_ConstantInt(CI2)))) return nullptr; |