aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/LazyValueInfo.cpp
diff options
context:
space:
mode:
authorAmara Emerson <amara@apple.com>2023-10-20 11:16:05 -0700
committerGitHub <noreply@github.com>2023-10-20 11:16:05 -0700
commit9189822f2c2eca55f6e7adcd26e3f15d65797b76 (patch)
tree19a1a90ddf327bad099f0d89b10f449cf52e261d /llvm/lib/Analysis/LazyValueInfo.cpp
parent3a4b0e9356748fc7d84f25d1b4c81352e9e23cce (diff)
downloadllvm-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.cpp40
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();
}