mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-20 03:23:01 +02:00
[PatternMatch] Make m_c_ICmp swap the predicate (PR42801)
This addresses https://bugs.llvm.org/show_bug.cgi?id=42801. The m_c_ICmp() matcher is changed to provide the swapped predicate if the operands are swapped. Existing uses of m_c_ICmp() fall in one of two categories: Working on equality predicates only, where swapping is irrelevant. Or performing a manual swap, in which case this patch removes it. The only exception is the foldICmpWithLowBitMaskedVal() fold, which does not swap the predicate, and instead reasons about whether a swap occurred or not for each predicate. Getting the swapped predicate allows us to merge the logic for pairs of predicates, instead of duplicating it. Differential Revision: https://reviews.llvm.org/D72976
This commit is contained in:
parent
6f14a89dbb
commit
6d326a1c6b
@ -1190,13 +1190,16 @@ struct CmpClass_match {
|
||||
: Predicate(Pred), L(LHS), R(RHS) {}
|
||||
|
||||
template <typename OpTy> bool match(OpTy *V) {
|
||||
if (auto *I = dyn_cast<Class>(V))
|
||||
if ((L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
|
||||
(Commutable && L.match(I->getOperand(1)) &&
|
||||
R.match(I->getOperand(0)))) {
|
||||
if (auto *I = dyn_cast<Class>(V)) {
|
||||
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
|
||||
Predicate = I->getPredicate();
|
||||
return true;
|
||||
} else if (Commutable && L.match(I->getOperand(1)) &&
|
||||
R.match(I->getOperand(0))) {
|
||||
Predicate = I->getSwappedPredicate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@ -1882,7 +1885,7 @@ inline AnyBinaryOp_match<LHS, RHS, true> m_c_BinOp(const LHS &L, const RHS &R) {
|
||||
}
|
||||
|
||||
/// Matches an ICmp with a predicate over LHS and RHS in either order.
|
||||
/// Does not swap the predicate.
|
||||
/// Swaps the predicate if operands are commuted.
|
||||
template <typename LHS, typename RHS>
|
||||
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
|
||||
m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
|
||||
|
@ -1429,9 +1429,6 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
|
||||
if (match(UnsignedICmp,
|
||||
m_c_ICmp(UnsignedPred, m_Specific(A), m_Specific(B))) &&
|
||||
ICmpInst::isUnsigned(UnsignedPred)) {
|
||||
if (UnsignedICmp->getOperand(0) != A)
|
||||
UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred);
|
||||
|
||||
// A >=/<= B || (A - B) != 0 <--> true
|
||||
if ((UnsignedPred == ICmpInst::ICMP_UGE ||
|
||||
UnsignedPred == ICmpInst::ICMP_ULE) &&
|
||||
@ -1461,9 +1458,6 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
|
||||
// Y < A || Y == 0 --> Y < A iff B != 0
|
||||
if (match(UnsignedICmp,
|
||||
m_c_ICmp(UnsignedPred, m_Specific(Y), m_Specific(A)))) {
|
||||
if (UnsignedICmp->getOperand(0) != Y)
|
||||
UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred);
|
||||
|
||||
if (UnsignedPred == ICmpInst::ICMP_UGE && IsAnd &&
|
||||
EqPred == ICmpInst::ICMP_NE &&
|
||||
isKnownNonZero(B, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT))
|
||||
|
@ -592,10 +592,6 @@ static bool isKnownNonZeroFromAssume(const Value *V, const Query &Q) {
|
||||
CmpInst::Predicate Pred;
|
||||
if (!match(Cmp, m_c_ICmp(Pred, m_V, m_Value(RHS))))
|
||||
return false;
|
||||
// Canonicalize 'v' to be on the LHS of the comparison.
|
||||
if (Cmp->getOperand(1) != RHS)
|
||||
Pred = CmpInst::getSwappedPredicate(Pred);
|
||||
|
||||
// assume(v u> y) -> assume(v != 0)
|
||||
if (Pred == ICmpInst::ICMP_UGT)
|
||||
return true;
|
||||
|
@ -1072,9 +1072,6 @@ static Value *foldUnsignedUnderflowCheck(ICmpInst *ZeroICmp,
|
||||
m_c_ICmp(UnsignedPred, m_Specific(ZeroCmpOp), m_Value(A))) &&
|
||||
match(ZeroCmpOp, m_c_Add(m_Specific(A), m_Value(B))) &&
|
||||
(ZeroICmp->hasOneUse() || UnsignedICmp->hasOneUse())) {
|
||||
if (UnsignedICmp->getOperand(0) != ZeroCmpOp)
|
||||
UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred);
|
||||
|
||||
auto GetKnownNonZeroAndOther = [&](Value *&NonZero, Value *&Other) {
|
||||
if (!IsKnownNonZero(NonZero))
|
||||
std::swap(NonZero, Other);
|
||||
@ -1111,8 +1108,6 @@ static Value *foldUnsignedUnderflowCheck(ICmpInst *ZeroICmp,
|
||||
m_c_ICmp(UnsignedPred, m_Specific(Base), m_Specific(Offset))) ||
|
||||
!ICmpInst::isUnsigned(UnsignedPred))
|
||||
return nullptr;
|
||||
if (UnsignedICmp->getOperand(0) != Base)
|
||||
UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred);
|
||||
|
||||
// Base >=/> Offset && (Base - Offset) != 0 <--> Base > Offset
|
||||
// (no overflow and not null)
|
||||
|
@ -3300,30 +3300,19 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst &I,
|
||||
// x & (-1 >> y) != x -> x u> (-1 >> y)
|
||||
DstPred = ICmpInst::Predicate::ICMP_UGT;
|
||||
break;
|
||||
case ICmpInst::Predicate::ICMP_UGT:
|
||||
case ICmpInst::Predicate::ICMP_ULT:
|
||||
// x & (-1 >> y) u< x -> x u> (-1 >> y)
|
||||
// x u> x & (-1 >> y) -> x u> (-1 >> y)
|
||||
assert(X == I.getOperand(0) && "instsimplify took care of commut. variant");
|
||||
DstPred = ICmpInst::Predicate::ICMP_UGT;
|
||||
break;
|
||||
case ICmpInst::Predicate::ICMP_UGE:
|
||||
// x & (-1 >> y) u>= x -> x u<= (-1 >> y)
|
||||
assert(X == I.getOperand(1) && "instsimplify took care of commut. variant");
|
||||
DstPred = ICmpInst::Predicate::ICMP_ULE;
|
||||
break;
|
||||
case ICmpInst::Predicate::ICMP_ULT:
|
||||
// x & (-1 >> y) u< x -> x u> (-1 >> y)
|
||||
assert(X == I.getOperand(1) && "instsimplify took care of commut. variant");
|
||||
DstPred = ICmpInst::Predicate::ICMP_UGT;
|
||||
break;
|
||||
case ICmpInst::Predicate::ICMP_ULE:
|
||||
// x u<= x & (-1 >> y) -> x u<= (-1 >> y)
|
||||
assert(X == I.getOperand(0) && "instsimplify took care of commut. variant");
|
||||
DstPred = ICmpInst::Predicate::ICMP_ULE;
|
||||
break;
|
||||
case ICmpInst::Predicate::ICMP_SGT:
|
||||
case ICmpInst::Predicate::ICMP_SLT:
|
||||
// x & (-1 >> y) s< x -> x s> (-1 >> y)
|
||||
// x s> x & (-1 >> y) -> x s> (-1 >> y)
|
||||
if (X != I.getOperand(0)) // X must be on LHS of comparison!
|
||||
return nullptr; // Ignore the other case.
|
||||
if (!match(M, m_Constant())) // Can not do this fold with non-constant.
|
||||
return nullptr;
|
||||
if (!match(M, m_NonNegative())) // Must not have any -1 vector elements.
|
||||
@ -3332,34 +3321,20 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst &I,
|
||||
break;
|
||||
case ICmpInst::Predicate::ICMP_SGE:
|
||||
// x & (-1 >> y) s>= x -> x s<= (-1 >> y)
|
||||
if (X != I.getOperand(1)) // X must be on RHS of comparison!
|
||||
return nullptr; // Ignore the other case.
|
||||
if (!match(M, m_Constant())) // Can not do this fold with non-constant.
|
||||
return nullptr;
|
||||
if (!match(M, m_NonNegative())) // Must not have any -1 vector elements.
|
||||
return nullptr;
|
||||
DstPred = ICmpInst::Predicate::ICMP_SLE;
|
||||
break;
|
||||
case ICmpInst::Predicate::ICMP_SLT:
|
||||
// x & (-1 >> y) s< x -> x s> (-1 >> y)
|
||||
if (X != I.getOperand(1)) // X must be on RHS of comparison!
|
||||
return nullptr; // Ignore the other case.
|
||||
if (!match(M, m_Constant())) // Can not do this fold with non-constant.
|
||||
return nullptr;
|
||||
if (!match(M, m_NonNegative())) // Must not have any -1 vector elements.
|
||||
return nullptr;
|
||||
DstPred = ICmpInst::Predicate::ICMP_SGT;
|
||||
break;
|
||||
case ICmpInst::Predicate::ICMP_SLE:
|
||||
// x s<= x & (-1 >> y) -> x s<= (-1 >> y)
|
||||
if (X != I.getOperand(0)) // X must be on LHS of comparison!
|
||||
return nullptr; // Ignore the other case.
|
||||
if (!match(M, m_Constant())) // Can not do this fold with non-constant.
|
||||
return nullptr;
|
||||
if (!match(M, m_NonNegative())) // Must not have any -1 vector elements.
|
||||
return nullptr;
|
||||
DstPred = ICmpInst::Predicate::ICMP_SLE;
|
||||
break;
|
||||
case ICmpInst::Predicate::ICMP_SGT:
|
||||
case ICmpInst::Predicate::ICMP_SLE:
|
||||
return nullptr;
|
||||
case ICmpInst::Predicate::ICMP_UGT:
|
||||
case ICmpInst::Predicate::ICMP_ULE:
|
||||
llvm_unreachable("Instsimplify took care of commut. variant");
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("All possible folds are handled.");
|
||||
}
|
||||
@ -3627,9 +3602,6 @@ Value *InstCombiner::foldUnsignedMultiplicationOverflowCheck(ICmpInst &I) {
|
||||
match(&I, m_c_ICmp(Pred, m_OneUse(m_UDiv(m_AllOnes(), m_Value(X))),
|
||||
m_Value(Y)))) {
|
||||
Mul = nullptr;
|
||||
// Canonicalize as-if y was on RHS.
|
||||
if (I.getOperand(1) != Y)
|
||||
Pred = I.getSwappedPredicate();
|
||||
|
||||
// Are we checking that overflow does not happen, or does happen?
|
||||
switch (Pred) {
|
||||
@ -5338,10 +5310,6 @@ static Instruction *foldICmpWithHighBitMask(ICmpInst &Cmp,
|
||||
Value *X, *Y;
|
||||
if (match(&Cmp,
|
||||
m_c_ICmp(Pred, m_OneUse(m_Shl(m_One(), m_Value(Y))), m_Value(X)))) {
|
||||
// We want X to be the icmp's second operand, so swap predicate if it isn't.
|
||||
if (Cmp.getOperand(0) == X)
|
||||
Pred = Cmp.getSwappedPredicate();
|
||||
|
||||
switch (Pred) {
|
||||
case ICmpInst::ICMP_ULE:
|
||||
NewPred = ICmpInst::ICMP_NE;
|
||||
@ -5361,10 +5329,6 @@ static Instruction *foldICmpWithHighBitMask(ICmpInst &Cmp,
|
||||
// The variant with 'add' is not canonical, (the variant with 'not' is)
|
||||
// we only get it because it has extra uses, and can't be canonicalized,
|
||||
|
||||
// We want X to be the icmp's second operand, so swap predicate if it isn't.
|
||||
if (Cmp.getOperand(0) == X)
|
||||
Pred = Cmp.getSwappedPredicate();
|
||||
|
||||
switch (Pred) {
|
||||
case ICmpInst::ICMP_ULT:
|
||||
NewPred = ICmpInst::ICMP_NE;
|
||||
|
Loading…
Reference in New Issue
Block a user