From: David Majnemer Date: Sat, 6 Dec 2014 10:51:40 +0000 (+0000) Subject: InstSimplify: Optimize away useless unsigned comparisons X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1af36e5baf4f1d046db4f308a28ca1b18475cab4;p=platform%2Fupstream%2Fllvm.git InstSimplify: Optimize away useless unsigned comparisons Code like X < Y && Y == 0 should always be folded away to false. llvm-svn: 223583 --- diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 45290fd..e589988 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 cdfb41f..b28effe 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(GV1) && !isa(GV2)) - if (!GV1->hasExternalWeakLinkage() || !GV2->hasExternalWeakLinkage()) + if (!GV1->hasExternalWeakLinkage() && !GV2->hasExternalWeakLinkage()) return ICmpInst::ICMP_NE; return ICmpInst::BAD_ICMP_PREDICATE; } diff --git a/llvm/test/Transforms/InstSimplify/AndOrXor.ll b/llvm/test/Transforms/InstSimplify/AndOrXor.ll index bf7e9a2..ce3c2aa 100644 --- a/llvm/test/Transforms/InstSimplify/AndOrXor.ll +++ b/llvm/test/Transforms/InstSimplify/AndOrXor.ll @@ -155,3 +155,51 @@ define i32 @neg_nuw(i32 %x) { ret i32 %neg ; CHECK: ret i32 0 } + +define i1 @and_icmp1(i32 %x, i32 %y) { + %1 = icmp ult i32 %x, %y + %2 = icmp ne i32 %y, 0 + %3 = and i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @and_icmp1( +; CHECK: %[[cmp:.*]] = icmp ult i32 %x, %y +; CHECK: ret i1 %[[cmp]] + +define i1 @and_icmp2(i32 %x, i32 %y) { + %1 = icmp ult i32 %x, %y + %2 = icmp eq i32 %y, 0 + %3 = and i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @and_icmp2( +; CHECK: ret i1 false + +define i1 @or_icmp1(i32 %x, i32 %y) { + %1 = icmp ult i32 %x, %y + %2 = icmp ne i32 %y, 0 + %3 = or i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @or_icmp1( +; CHECK: %[[cmp:.*]] = icmp ne i32 %y, 0 +; CHECK: ret i1 %[[cmp]] + +define i1 @or_icmp2(i32 %x, i32 %y) { + %1 = icmp uge i32 %x, %y + %2 = icmp ne i32 %y, 0 + %3 = or i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @or_icmp2( +; CHECK: ret i1 true + +define i1 @or_icmp3(i32 %x, i32 %y) { + %1 = icmp uge i32 %x, %y + %2 = icmp eq i32 %y, 0 + %3 = or i1 %1, %2 + ret i1 %3 +} +; CHECK-LABEL: @or_icmp3( +; CHECK: %[[cmp:.*]] = icmp uge i32 %x, %y +; CHECK: ret i1 %[[cmp]]