Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions llvm/include/llvm/IR/InstrTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -967,14 +967,6 @@ class CmpInst : public Instruction {
/// Determine if the predicate is false when comparing a value with itself.
static bool isFalseWhenEqual(Predicate predicate);

/// Determine if Pred1 implies Pred2 is true when two compares have matching
/// operands.
static bool isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2);

/// Determine if Pred1 implies Pred2 is false when two compares have matching
/// operands.
static bool isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2);

/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::ICmp ||
Expand Down
10 changes: 10 additions & 0 deletions llvm/include/llvm/IR/Instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,16 @@ class ICmpInst: public CmpInst {
return getFlippedSignednessPredicate(getPredicate());
}

/// Determine if Pred1 implies Pred2 is true when two compares have matching
/// operands.
static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
CmpPredicate Pred2);

/// Determine if Pred1 implies Pred2 is false when two compares have matching
/// operands.
static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
CmpPredicate Pred2);

void setSameSign(bool B = true) {
SubclassOptionalData = (SubclassOptionalData & ~SameSign) | (B * SameSign);
}
Expand Down
16 changes: 9 additions & 7 deletions llvm/include/llvm/SandboxIR/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2511,13 +2511,6 @@ class CmpInst : public SingleLLVMInstructionImpl<llvm::CmpInst> {
WRAP_STATIC_PREDICATE(isOrdered);
WRAP_STATIC_PREDICATE(isUnordered);

static bool isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2) {
return llvm::CmpInst::isImpliedTrueByMatchingCmp(Pred1, Pred2);
}
static bool isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2) {
return llvm::CmpInst::isImpliedFalseByMatchingCmp(Pred1, Pred2);
}

/// Method for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Value *From) {
return From->getSubclassID() == ClassID::ICmp ||
Expand Down Expand Up @@ -2554,6 +2547,15 @@ class ICmpInst : public CmpInst {
WRAP_STATIC_PREDICATE(isGE);
WRAP_STATIC_PREDICATE(isLE);

static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
CmpPredicate Pred2) {
return llvm::ICmpInst::isImpliedTrueByMatchingCmp(Pred1, Pred2);
}
static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
CmpPredicate Pred2) {
return llvm::ICmpInst::isImpliedFalseByMatchingCmp(Pred1, Pred2);
}

static auto predicates() { return llvm::ICmpInst::predicates(); }
static bool compare(const APInt &LHS, const APInt &RHS,
ICmpInst::Predicate Pred) {
Expand Down
80 changes: 47 additions & 33 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9141,7 +9141,7 @@ bool llvm::matchSimpleRecurrence(const BinaryOperator *I, PHINode *&P,
}

/// Return true if "icmp Pred LHS RHS" is always true.
static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
static bool isTruePredicate(CmpPredicate Pred, const Value *LHS,
const Value *RHS) {
if (ICmpInst::isTrueWhenEqual(Pred) && LHS == RHS)
return true;
Expand Down Expand Up @@ -9223,8 +9223,8 @@ static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
/// Return true if "icmp Pred BLHS BRHS" is true whenever "icmp Pred
/// ALHS ARHS" is true. Otherwise, return std::nullopt.
static std::optional<bool>
isImpliedCondOperands(CmpInst::Predicate Pred, const Value *ALHS,
const Value *ARHS, const Value *BLHS, const Value *BRHS) {
isImpliedCondOperands(CmpPredicate Pred, const Value *ALHS, const Value *ARHS,
const Value *BLHS, const Value *BRHS) {
switch (Pred) {
default:
return std::nullopt;
Expand Down Expand Up @@ -9262,12 +9262,11 @@ isImpliedCondOperands(CmpInst::Predicate Pred, const Value *ALHS,
/// Return true if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is true.
/// Return false if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is false.
/// Otherwise, return std::nullopt if we can't infer anything.
static std::optional<bool>
isImpliedCondMatchingOperands(CmpInst::Predicate LPred,
CmpInst::Predicate RPred) {
if (CmpInst::isImpliedTrueByMatchingCmp(LPred, RPred))
static std::optional<bool> isImpliedCondMatchingOperands(CmpPredicate LPred,
CmpPredicate RPred) {
if (ICmpInst::isImpliedTrueByMatchingCmp(LPred, RPred))
return true;
if (CmpInst::isImpliedFalseByMatchingCmp(LPred, RPred))
if (ICmpInst::isImpliedFalseByMatchingCmp(LPred, RPred))
return false;

return std::nullopt;
Expand All @@ -9276,53 +9275,66 @@ isImpliedCondMatchingOperands(CmpInst::Predicate LPred,
/// Return true if "icmp LPred X, LCR" implies "icmp RPred X, RCR" is true.
/// Return false if "icmp LPred X, LCR" implies "icmp RPred X, RCR" is false.
/// Otherwise, return std::nullopt if we can't infer anything.
static std::optional<bool> isImpliedCondCommonOperandWithCR(
CmpInst::Predicate LPred, const ConstantRange &LCR,
CmpInst::Predicate RPred, const ConstantRange &RCR) {
ConstantRange DomCR = ConstantRange::makeAllowedICmpRegion(LPred, LCR);
// If all true values for lhs and true for rhs, lhs implies rhs
if (DomCR.icmp(RPred, RCR))
return true;
static std::optional<bool>
isImpliedCondCommonOperandWithCR(CmpPredicate LPred, const ConstantRange &LCR,
CmpPredicate RPred, const ConstantRange &RCR) {
auto CRImpliesPred = [&](ConstantRange CR,
CmpInst::Predicate Pred) -> std::optional<bool> {
// If all true values for lhs and true for rhs, lhs implies rhs
if (CR.icmp(Pred, RCR))
return true;

// If there is no overlap, lhs implies not rhs
if (DomCR.icmp(CmpInst::getInversePredicate(RPred), RCR))
return false;
// If there is no overlap, lhs implies not rhs
if (CR.icmp(CmpInst::getInversePredicate(Pred), RCR))
return false;

return std::nullopt;
};
if (auto Res = CRImpliesPred(ConstantRange::makeAllowedICmpRegion(LPred, LCR),
RPred))
return Res;
if (LPred.hasSameSign() ^ RPred.hasSameSign()) {
LPred = LPred.hasSameSign() ? ICmpInst::getFlippedSignednessPredicate(LPred)
: static_cast<CmpInst::Predicate>(LPred);
RPred = RPred.hasSameSign() ? ICmpInst::getFlippedSignednessPredicate(RPred)
: static_cast<CmpInst::Predicate>(RPred);
return CRImpliesPred(ConstantRange::makeAllowedICmpRegion(LPred, LCR),
RPred);
}
return std::nullopt;
}

/// Return true if LHS implies RHS (expanded to its components as "R0 RPred R1")
/// is true. Return false if LHS implies RHS is false. Otherwise, return
/// std::nullopt if we can't infer anything.
static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
CmpInst::Predicate RPred,
const Value *R0, const Value *R1,
const DataLayout &DL,
bool LHSIsTrue) {
static std::optional<bool>
isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
const Value *R1, const DataLayout &DL, bool LHSIsTrue) {
Value *L0 = LHS->getOperand(0);
Value *L1 = LHS->getOperand(1);

// The rest of the logic assumes the LHS condition is true. If that's not the
// case, invert the predicate to make it so.
CmpInst::Predicate LPred =
LHSIsTrue ? LHS->getPredicate() : LHS->getInversePredicate();
CmpPredicate LPred =
LHSIsTrue ? LHS->getCmpPredicate() : LHS->getInverseCmpPredicate();

// We can have non-canonical operands, so try to normalize any common operand
// to L0/R0.
if (L0 == R1) {
std::swap(R0, R1);
RPred = ICmpInst::getSwappedPredicate(RPred);
RPred = ICmpInst::getSwappedCmpPredicate(RPred);
}
if (R0 == L1) {
std::swap(L0, L1);
LPred = ICmpInst::getSwappedPredicate(LPred);
LPred = ICmpInst::getSwappedCmpPredicate(LPred);
}
if (L1 == R1) {
// If we have L0 == R0 and L1 == R1, then make L1/R1 the constants.
if (L0 != R0 || match(L0, m_ImmConstant())) {
std::swap(L0, L1);
LPred = ICmpInst::getSwappedPredicate(LPred);
LPred = ICmpInst::getSwappedCmpPredicate(LPred);
std::swap(R0, R1);
RPred = ICmpInst::getSwappedPredicate(RPred);
RPred = ICmpInst::getSwappedCmpPredicate(RPred);
}
}

Expand Down Expand Up @@ -9358,7 +9370,8 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
// must be positive if X >= Y and no overflow".
// Take SGT as an example: L0:x > L1:y and C >= 0
// ==> R0:(x -nsw y) < R1:(-C) is false
if ((LPred == ICmpInst::ICMP_SGT || LPred == ICmpInst::ICMP_SGE) &&
if ((ICmpInst::isSigned(LPred) || LPred.hasSameSign()) &&
(ICmpInst::isGE(LPred) || ICmpInst::isGT(LPred)) &&
match(R0, m_NSWSub(m_Specific(L0), m_Specific(L1)))) {
if (match(R1, m_NonPositive()) &&
isImpliedCondMatchingOperands(LPred, RPred) == false)
Expand All @@ -9367,7 +9380,8 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,

// Take SLT as an example: L0:x < L1:y and C <= 0
// ==> R0:(x -nsw y) < R1:(-C) is true
if ((LPred == ICmpInst::ICMP_SLT || LPred == ICmpInst::ICMP_SLE) &&
if ((ICmpInst::isSigned(LPred) || LPred.hasSameSign()) &&
(ICmpInst::isLE(LPred) || ICmpInst::isLT(LPred)) &&
match(R0, m_NSWSub(m_Specific(L0), m_Specific(L1)))) {
if (match(R1, m_NonNegative()) &&
isImpliedCondMatchingOperands(LPred, RPred) == true)
Expand All @@ -9381,8 +9395,8 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
match(L0, m_c_Add(m_Specific(L1), m_Specific(R1))))
return CmpPredicate::getMatching(LPred, RPred).has_value();

if (LPred == RPred)
return isImpliedCondOperands(LPred, L0, L1, R0, R1);
if (auto P = CmpPredicate::getMatching(LPred, RPred))
return isImpliedCondOperands(*P, L0, L1, R0, R1);

return std::nullopt;
}
Expand Down
13 changes: 10 additions & 3 deletions llvm/lib/IR/Instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3886,12 +3886,18 @@ bool CmpInst::isFalseWhenEqual(Predicate predicate) {
}
}

bool CmpInst::isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2) {
bool ICmpInst::isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
CmpPredicate Pred2) {
// If the predicates match, then we know the first condition implies the
// second is true.
if (Pred1 == Pred2)
if (CmpPredicate::getMatching(Pred1, Pred2))
return true;

if (Pred1.hasSameSign() && CmpInst::isSigned(Pred2))
Pred1 = ICmpInst::getFlippedSignednessPredicate(Pred1);
else if (Pred2.hasSameSign() && CmpInst::isSigned(Pred1))
Pred2 = ICmpInst::getFlippedSignednessPredicate(Pred2);

switch (Pred1) {
default:
break;
Expand All @@ -3911,7 +3917,8 @@ bool CmpInst::isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2) {
return false;
}

bool CmpInst::isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2) {
bool ICmpInst::isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
CmpPredicate Pred2) {
return isImpliedTrueByMatchingCmp(Pred1, getInversePredicate(Pred2));
}

Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Transforms/Scalar/NewGVN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1964,15 +1964,15 @@ NewGVN::ExprResult NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
if (PBranch->TrueEdge) {
// If we know the previous predicate is true and we are in the true
// edge then we may be implied true or false.
if (CmpInst::isImpliedTrueByMatchingCmp(BranchPredicate,
OurPredicate)) {
if (ICmpInst::isImpliedTrueByMatchingCmp(BranchPredicate,
OurPredicate)) {
return ExprResult::some(
createConstantExpression(ConstantInt::getTrue(CI->getType())),
PI);
}

if (CmpInst::isImpliedFalseByMatchingCmp(BranchPredicate,
OurPredicate)) {
if (ICmpInst::isImpliedFalseByMatchingCmp(BranchPredicate,
OurPredicate)) {
return ExprResult::some(
createConstantExpression(ConstantInt::getFalse(CI->getType())),
PI);
Expand Down
Loading
Loading