diff options
author | Amara Emerson <amara@apple.com> | 2023-10-20 11:16:05 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-20 11:16:05 -0700 |
commit | 9189822f2c2eca55f6e7adcd26e3f15d65797b76 (patch) | |
tree | 19a1a90ddf327bad099f0d89b10f449cf52e261d /llvm/lib/Analysis/LazyValueInfo.cpp | |
parent | 3a4b0e9356748fc7d84f25d1b4c81352e9e23cce (diff) | |
download | llvm-9189822f2c2eca55f6e7adcd26e3f15d65797b76.zip llvm-9189822f2c2eca55f6e7adcd26e3f15d65797b76.tar.gz llvm-9189822f2c2eca55f6e7adcd26e3f15d65797b76.tar.bz2 |
[LVI] Handle icmp of ashr. (#68010)
This handles the case where this combine:
icmp sgt (ashr X, ShAmtC), C --> icmp sgt X, ((C + 1) << ShAmtC) - 1
wasn't performed by instcombine.
Proof of the original combine: https://alive2.llvm.org/ce/z/SfpsvX
This is a port of the review in https://reviews.llvm.org/D151911 to
GitHub.
Diffstat (limited to 'llvm/lib/Analysis/LazyValueInfo.cpp')
-rw-r--r-- | llvm/lib/Analysis/LazyValueInfo.cpp | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index 789a02e..5cb207c 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Dominators.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" @@ -1083,6 +1084,26 @@ static ValueLatticeElement getValueFromSimpleICmpCondition( return ValueLatticeElement::getRange(TrueValues.subtract(Offset)); } +static std::optional<ConstantRange> +getRangeViaSLT(CmpInst::Predicate Pred, APInt RHS, + function_ref<std::optional<ConstantRange>(const APInt &)> Fn) { + bool Invert = false; + if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) { + Pred = ICmpInst::getInversePredicate(Pred); + Invert = true; + } + if (Pred == ICmpInst::ICMP_SLE) { + Pred = ICmpInst::ICMP_SLT; + if (RHS.isMaxSignedValue()) + return std::nullopt; // Could also return full/empty here, if we wanted. + ++RHS; + } + assert(Pred == ICmpInst::ICMP_SLT && "Must be signed predicate"); + if (auto CR = Fn(RHS)) + return Invert ? CR->inverse() : CR; + return std::nullopt; +} + static ValueLatticeElement getValueFromICmpCondition(Value *Val, ICmpInst *ICI, bool isTrueDest) { Value *LHS = ICI->getOperand(0); @@ -1148,6 +1169,25 @@ static ValueLatticeElement getValueFromICmpCondition(Value *Val, ICmpInst *ICI, CR.getUnsignedMin().zext(BitWidth), APInt(BitWidth, 0))); } + // Recognize: + // icmp slt (ashr X, ShAmtC), C --> icmp slt X, C << ShAmtC + // Preconditions: (C << ShAmtC) >> ShAmtC == C + const APInt *ShAmtC; + if (CmpInst::isSigned(EdgePred) && + match(LHS, m_AShr(m_Specific(Val), m_APInt(ShAmtC))) && + match(RHS, m_APInt(C))) { + auto CR = getRangeViaSLT( + EdgePred, *C, [&](const APInt &RHS) -> std::optional<ConstantRange> { + APInt New = RHS << *ShAmtC; + if ((New.ashr(*ShAmtC)) != RHS) + return std::nullopt; + return ConstantRange::getNonEmpty( + APInt::getSignedMinValue(New.getBitWidth()), New); + }); + if (CR) + return ValueLatticeElement::getRange(*CR); + } + return ValueLatticeElement::getOverdefined(); } |