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 | |
| 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')
| -rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 49 | ||||
| -rw-r--r-- | llvm/lib/IR/ConstantFold.cpp | 2 |
2 files changed, 50 insertions, 1 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; diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index cdfb41f7dcc..b28effee812 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -1350,7 +1350,7 @@ static ICmpInst::Predicate areGlobalsPotentiallyEqual(const GlobalValue *GV1, const GlobalValue *GV2) { // Don't try to decide equality of aliases. if (!isa<GlobalAlias>(GV1) && !isa<GlobalAlias>(GV2)) - if (!GV1->hasExternalWeakLinkage() || !GV2->hasExternalWeakLinkage()) + if (!GV1->hasExternalWeakLinkage() && !GV2->hasExternalWeakLinkage()) return ICmpInst::ICMP_NE; return ICmpInst::BAD_ICMP_PREDICATE; } |

