diff options
author | Sanjay Patel <spatel@rotateright.com> | 2016-06-20 20:59:59 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2016-06-20 20:59:59 +0000 |
commit | 9ad8fb68f77594829fa88a19981fbb55ab1abf2f (patch) | |
tree | bd98378e01d18765baa85bf34e0e03667c2557c6 /llvm/lib/Analysis/InstructionSimplify.cpp | |
parent | 071bb9d7afe4bc491684737e672f35f2e14a1f3e (diff) | |
download | llvm-9ad8fb68f77594829fa88a19981fbb55ab1abf2f.zip llvm-9ad8fb68f77594829fa88a19981fbb55ab1abf2f.tar.gz llvm-9ad8fb68f77594829fa88a19981fbb55ab1abf2f.tar.bz2 |
[InstSimplify] analyze (optionally casted) icmps to eliminate obviously false logic (PR27869)
By moving this transform to InstSimplify from InstCombine, we sidestep the problem/question
raised by PR27869:
https://llvm.org/bugs/show_bug.cgi?id=27869
...where InstCombine turns an icmp+zext into a shift causing us to miss the fold.
Credit to David Majnemer for a draft patch of the changes to InstructionSimplify.cpp.
Differential Revision: http://reviews.llvm.org/D21512
llvm-svn: 273200
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 25ce4db..746b740 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1492,9 +1492,8 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp, 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) { + Type *ITy = Op0->getType(); ICmpInst::Predicate Pred0, Pred1; ConstantInt *CI1, *CI2; Value *V; @@ -1502,6 +1501,18 @@ static Value *SimplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) { if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/true)) return X; + // Look for this pattern: (icmp V, C0) & (icmp V, C1)). + const APInt *C0, *C1; + if (match(Op0, m_ICmp(Pred0, m_Value(V), m_APInt(C0))) && + match(Op1, m_ICmp(Pred1, m_Specific(V), m_APInt(C1)))) { + // Make a constant range that's the intersection of the two icmp ranges. + // If the intersection is empty, we know that the result is false. + auto Range0 = ConstantRange::makeAllowedICmpRegion(Pred0, *C0); + auto Range1 = ConstantRange::makeAllowedICmpRegion(Pred1, *C1); + if (Range0.intersectWith(Range1).isEmptySet()) + return getFalse(ITy); + } + if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_ConstantInt(CI1)), m_ConstantInt(CI2)))) return nullptr; @@ -1509,8 +1520,6 @@ static Value *SimplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) { if (!match(Op1, m_ICmp(Pred1, m_Specific(V), m_Specific(CI1)))) return nullptr; - Type *ITy = Op0->getType(); - auto *AddInst = cast<BinaryOperator>(Op0->getOperand(0)); bool isNSW = AddInst->hasNoSignedWrap(); bool isNUW = AddInst->hasNoUnsignedWrap(); @@ -1608,6 +1617,24 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const Query &Q, } } + // The compares may be hidden behind casts. Look through those and try the + // same folds as above. + auto *Cast0 = dyn_cast<CastInst>(Op0); + auto *Cast1 = dyn_cast<CastInst>(Op1); + if (Cast0 && Cast1 && Cast0->getOpcode() == Cast1->getOpcode() && + Cast0->getSrcTy() == Cast1->getSrcTy()) { + auto *Cmp0 = dyn_cast<ICmpInst>(Cast0->getOperand(0)); + auto *Cmp1 = dyn_cast<ICmpInst>(Cast1->getOperand(0)); + if (Cmp0 && Cmp1) { + Instruction::CastOps CastOpc = Cast0->getOpcode(); + Type *ResultType = Cast0->getType(); + if (auto *V = dyn_cast_or_null<Constant>(SimplifyAndOfICmps(Cmp0, Cmp1))) + return ConstantExpr::getCast(CastOpc, V, ResultType); + if (auto *V = dyn_cast_or_null<Constant>(SimplifyAndOfICmps(Cmp1, Cmp0))) + return ConstantExpr::getCast(CastOpc, V, ResultType); + } + } + // Try some generic simplifications for associative operations. if (Value *V = SimplifyAssociativeBinOp(Instruction::And, Op0, Op1, Q, MaxRecurse)) |