diff options
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index e4cb4574..07ad65c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -5780,6 +5780,45 @@ Instruction *InstCombinerImpl::foldICmpWithMinMax(Instruction &I, return nullptr; } +/// Match and fold patterns like: +/// icmp eq/ne X, min(max(X, Lo), Hi) +/// which represents a range check and can be repsented as a ConstantRange. +/// +/// For icmp eq, build ConstantRange [Lo, Hi + 1) and convert to: +/// (X - Lo) u< (Hi + 1 - Lo) +/// For icmp ne, build ConstantRange [Hi + 1, Lo) and convert to: +/// (X - (Hi + 1)) u< (Lo - (Hi + 1)) +Instruction *InstCombinerImpl::foldICmpWithClamp(ICmpInst &I, Value *X, + MinMaxIntrinsic *Min) { + if (!I.isEquality() || !Min->hasOneUse() || !Min->isMin()) + return nullptr; + + const APInt *Lo = nullptr, *Hi = nullptr; + if (Min->isSigned()) { + if (!match(Min->getLHS(), m_OneUse(m_SMax(m_Specific(X), m_APInt(Lo)))) || + !match(Min->getRHS(), m_APInt(Hi)) || !Lo->slt(*Hi)) + return nullptr; + } else { + if (!match(Min->getLHS(), m_OneUse(m_UMax(m_Specific(X), m_APInt(Lo)))) || + !match(Min->getRHS(), m_APInt(Hi)) || !Lo->ult(*Hi)) + return nullptr; + } + + ConstantRange CR = ConstantRange::getNonEmpty(*Lo, *Hi + 1); + ICmpInst::Predicate Pred; + APInt C, Offset; + if (I.getPredicate() == ICmpInst::ICMP_EQ) + CR.getEquivalentICmp(Pred, C, Offset); + else + CR.inverse().getEquivalentICmp(Pred, C, Offset); + + if (!Offset.isZero()) + X = Builder.CreateAdd(X, ConstantInt::get(X->getType(), Offset)); + + return replaceInstUsesWith( + I, Builder.CreateICmp(Pred, X, ConstantInt::get(X->getType(), C))); +} + // Canonicalize checking for a power-of-2-or-zero value: static Instruction *foldICmpPow2Test(ICmpInst &I, InstCombiner::BuilderTy &Builder) { @@ -7467,10 +7506,14 @@ Instruction *InstCombinerImpl::foldICmpCommutative(CmpPredicate Pred, if (Instruction *NI = foldSelectICmp(Pred, SI, Op1, CxtI)) return NI; - if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(Op0)) + if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(Op0)) { if (Instruction *Res = foldICmpWithMinMax(CxtI, MinMax, Op1, Pred)) return Res; + if (Instruction *Res = foldICmpWithClamp(CxtI, Op1, MinMax)) + return Res; + } + { Value *X; const APInt *C; @@ -8527,6 +8570,9 @@ static Instruction *foldFCmpFSubIntoFCmp(FCmpInst &I, Instruction *LHSI, DenormalMode::getIEEE()) { CI.replaceOperand(I, 0, X); CI.replaceOperand(I, 1, Y); + I.setHasNoInfs(LHSI->hasNoInfs()); + if (LHSI->hasNoNaNs()) + I.setHasNoNaNs(true); return &I; } break; |