Skip to content

Commit

Permalink
[PatternMatch] Use m_SpecificCmp matchers. NFC. (#100878)
Browse files Browse the repository at this point in the history
Compile-time improvement:
http://llvm-compile-time-tracker.com/compare.php?from=13996378d81c8fa9a364aeaafd7382abbc1db83a&to=861ffa4ec5f7bde5a194a7715593a1b5359eb581&stat=instructions:u
baseline: 803eaf2
```
Top 5 improvements:
  stockfish/movegen.ll 2541620819 2538599412 -0.12%
  minetest/profiler.cpp.ll 431724935 431246500 -0.11%
  abc/luckySwap.c.ll 581173720 580581935 -0.10%
  abc/kitTruth.c.ll 2521936288 2519445570 -0.10%
  abc/extraUtilTruth.c.ll 1216674614 1215495502 -0.10%
Top 5 regressions:
  openssl/libcrypto-shlib-sm4.ll 1155054721 1155943201 +0.08%
  openssl/libcrypto-lib-sm4.ll 1155054838 1155943063 +0.08%
  spike/vsm4r_vv.ll 1296430080 1297039258 +0.05%
  spike/vsm4r_vs.ll 1312496906 1313093460 +0.05%
  nuttx/lib_rand48.c.ll 126201233 126246692 +0.04%
Overall: -0.02112308%
```
  • Loading branch information
dtcxzyw authored Jul 29, 2024
1 parent 378fe2f commit 62e9f40
Show file tree
Hide file tree
Showing 17 changed files with 131 additions and 115 deletions.
24 changes: 20 additions & 4 deletions llvm/include/llvm/IR/PatternMatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -1616,7 +1616,8 @@ m_FCmp(const LHS &L, const RHS &R) {

// Same as CmpClass, but instead of saving Pred as out output variable, match a
// specific input pred for equality.
template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy>
template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
bool Commutable = false>
struct SpecificCmpClass_match {
const PredicateTy Predicate;
LHS_t L;
Expand All @@ -1626,9 +1627,17 @@ struct SpecificCmpClass_match {
: Predicate(Pred), L(LHS), R(RHS) {}

template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<Class>(V))
return I->getPredicate() == Predicate && L.match(I->getOperand(0)) &&
R.match(I->getOperand(1));
if (auto *I = dyn_cast<Class>(V)) {
if (I->getPredicate() == Predicate && L.match(I->getOperand(0)) &&
R.match(I->getOperand(1)))
return true;
if constexpr (Commutable) {
if (I->getPredicate() == Class::getSwappedPredicate(Predicate) &&
L.match(I->getOperand(1)) && R.match(I->getOperand(0)))
return true;
}
}

return false;
}
};
Expand All @@ -1647,6 +1656,13 @@ m_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
MatchPred, L, R);
}

template <typename LHS, typename RHS>
inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
m_c_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(
MatchPred, L, R);
}

template <typename LHS, typename RHS>
inline SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
m_SpecificFCmp(FCmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/Analysis/InstructionSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static Value *foldSelectWithBinaryOp(Value *Cond, Value *TrueVal,
else
return nullptr;

CmpInst::Predicate ExpectedPred, Pred1, Pred2;
CmpInst::Predicate ExpectedPred;
if (BinOpCode == BinaryOperator::Or) {
ExpectedPred = ICmpInst::ICMP_NE;
} else if (BinOpCode == BinaryOperator::And) {
Expand All @@ -110,10 +110,10 @@ static Value *foldSelectWithBinaryOp(Value *Cond, Value *TrueVal,
// -->
// %TV
Value *X, *Y;
if (!match(Cond, m_c_BinOp(m_c_ICmp(Pred1, m_Specific(TrueVal),
m_Specific(FalseVal)),
m_ICmp(Pred2, m_Value(X), m_Value(Y)))) ||
Pred1 != Pred2 || Pred1 != ExpectedPred)
if (!match(Cond,
m_c_BinOp(m_c_SpecificICmp(ExpectedPred, m_Specific(TrueVal),
m_Specific(FalseVal)),
m_SpecificICmp(ExpectedPred, m_Value(X), m_Value(Y)))))
return nullptr;

if (X == TrueVal || X == FalseVal || Y == TrueVal || Y == FalseVal)
Expand Down
11 changes: 5 additions & 6 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,7 @@ bool llvm::haveNoCommonBitsSet(const WithCache<const Value *> &LHSCache,

bool llvm::isOnlyUsedInZeroComparison(const Instruction *I) {
return !I->user_empty() && all_of(I->users(), [](const User *U) {
ICmpInst::Predicate P;
return match(U, m_ICmp(P, m_Value(), m_Zero()));
return match(U, m_ICmp(m_Value(), m_Zero()));
});
}

Expand Down Expand Up @@ -2594,10 +2593,10 @@ static bool isNonZeroRecurrence(const PHINode *PN) {
}

static bool matchOpWithOpEqZero(Value *Op0, Value *Op1) {
ICmpInst::Predicate Pred;
return (match(Op0, m_ZExtOrSExt(m_ICmp(Pred, m_Specific(Op1), m_Zero()))) ||
match(Op1, m_ZExtOrSExt(m_ICmp(Pred, m_Specific(Op0), m_Zero())))) &&
Pred == ICmpInst::ICMP_EQ;
return match(Op0, m_ZExtOrSExt(m_SpecificICmp(ICmpInst::ICMP_EQ,
m_Specific(Op1), m_Zero()))) ||
match(Op1, m_ZExtOrSExt(m_SpecificICmp(ICmpInst::ICMP_EQ,
m_Specific(Op0), m_Zero())));
}

static bool isNonZeroAdd(const APInt &DemandedElts, unsigned Depth,
Expand Down
6 changes: 2 additions & 4 deletions llvm/lib/Target/AMDGPU/AMDGPULowerKernelAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,8 @@ static bool processUse(CallInst *CI, bool IsV5OrAbove) {
: m_Intrinsic<Intrinsic::amdgcn_workgroup_id_z>());

for (User *ICmp : BlockCount->users()) {
ICmpInst::Predicate Pred;
if (match(ICmp, m_ICmp(Pred, GroupIDIntrin, m_Specific(BlockCount)))) {
if (Pred != ICmpInst::ICMP_ULT)
continue;
if (match(ICmp, m_SpecificICmp(ICmpInst::ICMP_ULT, GroupIDIntrin,
m_Specific(BlockCount)))) {
ICmp->replaceAllUsesWith(llvm::ConstantInt::getTrue(ICmp->getType()));
MadeChange = true;
}
Expand Down
42 changes: 23 additions & 19 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3435,12 +3435,9 @@ X86TargetLowering::getJumpConditionMergingParams(Instruction::BinaryOps Opc,
if (BaseCost >= 0 && Subtarget.hasCCMP())
BaseCost += BrMergingCcmpBias;
// a == b && a == c is a fast pattern on x86.
ICmpInst::Predicate Pred;
if (BaseCost >= 0 && Opc == Instruction::And &&
match(Lhs, m_ICmp(Pred, m_Value(), m_Value())) &&
Pred == ICmpInst::ICMP_EQ &&
match(Rhs, m_ICmp(Pred, m_Value(), m_Value())) &&
Pred == ICmpInst::ICMP_EQ)
match(Lhs, m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(), m_Value())) &&
match(Rhs, m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(), m_Value())))
BaseCost += 1;
return {BaseCost, BrMergingLikelyBias.getValue(),
BrMergingUnlikelyBias.getValue()};
Expand Down Expand Up @@ -30760,21 +30757,25 @@ static bool shouldExpandCmpArithRMWInIR(AtomicRMWInst *AI) {
if (match(I, m_c_ICmp(Pred, m_Sub(m_ZeroInt(), m_Specific(Op)), m_Value())))
return Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE;
if (match(I, m_OneUse(m_c_Add(m_Specific(Op), m_Value())))) {
if (match(I->user_back(), m_ICmp(Pred, m_Value(), m_ZeroInt())))
return Pred == CmpInst::ICMP_SLT;
if (match(I->user_back(), m_ICmp(Pred, m_Value(), m_AllOnes())))
return Pred == CmpInst::ICMP_SGT;
if (match(I->user_back(),
m_SpecificICmp(CmpInst::ICMP_SLT, m_Value(), m_ZeroInt())))
return true;
if (match(I->user_back(),
m_SpecificICmp(CmpInst::ICMP_SGT, m_Value(), m_AllOnes())))
return true;
}
return false;
}
if (Opc == AtomicRMWInst::Sub) {
if (match(I, m_c_ICmp(Pred, m_Specific(Op), m_Value())))
return Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE;
if (match(I, m_OneUse(m_Sub(m_Value(), m_Specific(Op))))) {
if (match(I->user_back(), m_ICmp(Pred, m_Value(), m_ZeroInt())))
return Pred == CmpInst::ICMP_SLT;
if (match(I->user_back(), m_ICmp(Pred, m_Value(), m_AllOnes())))
return Pred == CmpInst::ICMP_SGT;
if (match(I->user_back(),
m_SpecificICmp(CmpInst::ICMP_SLT, m_Value(), m_ZeroInt())))
return true;
if (match(I->user_back(),
m_SpecificICmp(CmpInst::ICMP_SGT, m_Value(), m_AllOnes())))
return true;
}
return false;
}
Expand All @@ -30785,18 +30786,21 @@ static bool shouldExpandCmpArithRMWInIR(AtomicRMWInst *AI) {
if (match(I->user_back(), m_ICmp(Pred, m_Value(), m_ZeroInt())))
return Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE ||
Pred == CmpInst::ICMP_SLT;
if (match(I->user_back(), m_ICmp(Pred, m_Value(), m_AllOnes())))
return Pred == CmpInst::ICMP_SGT;
if (match(I->user_back(),
m_SpecificICmp(CmpInst::ICMP_SGT, m_Value(), m_AllOnes())))
return true;
return false;
}
if (Opc == AtomicRMWInst::Xor) {
if (match(I, m_c_ICmp(Pred, m_Specific(Op), m_Value())))
return Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE;
if (match(I, m_OneUse(m_c_Xor(m_Specific(Op), m_Value())))) {
if (match(I->user_back(), m_ICmp(Pred, m_Value(), m_ZeroInt())))
return Pred == CmpInst::ICMP_SLT;
if (match(I->user_back(), m_ICmp(Pred, m_Value(), m_AllOnes())))
return Pred == CmpInst::ICMP_SGT;
if (match(I->user_back(),
m_SpecificICmp(CmpInst::ICMP_SLT, m_Value(), m_ZeroInt())))
return true;
if (match(I->user_back(),
m_SpecificICmp(CmpInst::ICMP_SGT, m_Value(), m_AllOnes())))
return true;
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,12 @@ static bool foldGuardedFunnelShift(Instruction &I, const DominatorTree &DT) {
if (!DT.dominates(ShVal0, TermI) || !DT.dominates(ShVal1, TermI))
return false;

ICmpInst::Predicate Pred;
BasicBlock *PhiBB = Phi.getParent();
if (!match(TermI, m_Br(m_ICmp(Pred, m_Specific(ShAmt), m_ZeroInt()),
if (!match(TermI, m_Br(m_SpecificICmp(CmpInst::ICMP_EQ, m_Specific(ShAmt),
m_ZeroInt()),
m_SpecificBB(PhiBB), m_SpecificBB(FunnelBB))))
return false;

if (Pred != CmpInst::ICMP_EQ)
return false;

IRBuilder<> Builder(PhiBB, PhiBB->getFirstInsertionPt());

if (ShVal0 == ShVal1)
Expand Down
12 changes: 6 additions & 6 deletions llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1694,12 +1694,10 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {

// Canonicalize signum variant that ends in add:
// (A s>> (BW - 1)) + (zext (A s> 0)) --> (A s>> (BW - 1)) | (zext (A != 0))
ICmpInst::Predicate Pred;
uint64_t BitWidth = Ty->getScalarSizeInBits();
if (match(LHS, m_AShr(m_Value(A), m_SpecificIntAllowPoison(BitWidth - 1))) &&
match(RHS, m_OneUse(m_ZExt(
m_OneUse(m_ICmp(Pred, m_Specific(A), m_ZeroInt()))))) &&
Pred == CmpInst::ICMP_SGT) {
match(RHS, m_OneUse(m_ZExt(m_OneUse(m_SpecificICmp(
CmpInst::ICMP_SGT, m_Specific(A), m_ZeroInt())))))) {
Value *NotZero = Builder.CreateIsNotNull(A, "isnotnull");
Value *Zext = Builder.CreateZExt(NotZero, Ty, "isnotnull.zext");
return BinaryOperator::CreateOr(LHS, Zext);
Expand All @@ -1711,12 +1709,13 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
// (add X, (sext/zext (icmp eq X, C)))
// -> (select (icmp eq X, C), (add C, (sext/zext 1)), X)
auto CondMatcher = m_CombineAnd(
m_Value(Cond), m_ICmp(Pred, m_Deferred(A), m_ImmConstant(C)));
m_Value(Cond),
m_SpecificICmp(ICmpInst::ICMP_EQ, m_Deferred(A), m_ImmConstant(C)));

if (match(&I,
m_c_Add(m_Value(A),
m_CombineAnd(m_Value(Ext), m_ZExtOrSExt(CondMatcher)))) &&
Pred == ICmpInst::ICMP_EQ && Ext->hasOneUse()) {
Ext->hasOneUse()) {
Value *Add = isa<ZExtInst>(Ext) ? InstCombiner::AddOne(C)
: InstCombiner::SubOne(C);
return replaceInstUsesWith(I, Builder.CreateSelect(Cond, Add, A));
Expand Down Expand Up @@ -1791,6 +1790,7 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
// -->
// BW - ctlz(A - 1, false)
const APInt *XorC;
ICmpInst::Predicate Pred;
if (match(&I,
m_c_Add(
m_ZExt(m_ICmp(Pred, m_Intrinsic<Intrinsic::ctpop>(m_Value(A)),
Expand Down
61 changes: 30 additions & 31 deletions llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,11 +818,11 @@ static Value *foldSignedTruncationCheck(ICmpInst *ICmp0, ICmpInst *ICmp1,
// Match icmp ult (add %arg, C01), C1 (C1 == C01 << 1; powers of two)
auto tryToMatchSignedTruncationCheck = [](ICmpInst *ICmp, Value *&X,
APInt &SignBitMask) -> bool {
CmpInst::Predicate Pred;
const APInt *I01, *I1; // powers of two; I1 == I01 << 1
if (!(match(ICmp,
m_ICmp(Pred, m_Add(m_Value(X), m_Power2(I01)), m_Power2(I1))) &&
Pred == ICmpInst::ICMP_ULT && I1->ugt(*I01) && I01->shl(1) == *I1))
if (!(match(ICmp, m_SpecificICmp(ICmpInst::ICMP_ULT,
m_Add(m_Value(X), m_Power2(I01)),
m_Power2(I1))) &&
I1->ugt(*I01) && I01->shl(1) == *I1))
return false;
// Which bit is the new sign bit as per the 'signed truncation' pattern?
SignBitMask = *I01;
Expand Down Expand Up @@ -936,20 +936,21 @@ static Value *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
std::swap(Cmp0, Cmp1);

// (X != 0) && (ctpop(X) u< 2) --> ctpop(X) == 1
CmpInst::Predicate Pred0, Pred1;
Value *X;
if (JoinedByAnd && match(Cmp0, m_ICmp(Pred0, m_Value(X), m_ZeroInt())) &&
match(Cmp1, m_ICmp(Pred1, m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
m_SpecificInt(2))) &&
Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_ULT) {
if (JoinedByAnd &&
match(Cmp0, m_SpecificICmp(ICmpInst::ICMP_NE, m_Value(X), m_ZeroInt())) &&
match(Cmp1, m_SpecificICmp(ICmpInst::ICMP_ULT,
m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
m_SpecificInt(2)))) {
Value *CtPop = Cmp1->getOperand(0);
return Builder.CreateICmpEQ(CtPop, ConstantInt::get(CtPop->getType(), 1));
}
// (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1
if (!JoinedByAnd && match(Cmp0, m_ICmp(Pred0, m_Value(X), m_ZeroInt())) &&
match(Cmp1, m_ICmp(Pred1, m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
m_SpecificInt(1))) &&
Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_UGT) {
if (!JoinedByAnd &&
match(Cmp0, m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(X), m_ZeroInt())) &&
match(Cmp1, m_SpecificICmp(ICmpInst::ICMP_UGT,
m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
m_SpecificInt(1)))) {
Value *CtPop = Cmp1->getOperand(0);
return Builder.CreateICmpNE(CtPop, ConstantInt::get(CtPop->getType(), 1));
}
Expand Down Expand Up @@ -1608,31 +1609,30 @@ static Instruction *reassociateFCmps(BinaryOperator &BO,
// There are 4 commuted variants of the pattern. Canonicalize operands of this
// logic op so an fcmp is operand 0 and a matching logic op is operand 1.
Value *Op0 = BO.getOperand(0), *Op1 = BO.getOperand(1), *X;
FCmpInst::Predicate Pred;
if (match(Op1, m_FCmp(Pred, m_Value(), m_AnyZeroFP())))
if (match(Op1, m_FCmp(m_Value(), m_AnyZeroFP())))
std::swap(Op0, Op1);

// Match inner binop and the predicate for combining 2 NAN checks into 1.
Value *BO10, *BO11;
FCmpInst::Predicate NanPred = Opcode == Instruction::And ? FCmpInst::FCMP_ORD
: FCmpInst::FCMP_UNO;
if (!match(Op0, m_FCmp(Pred, m_Value(X), m_AnyZeroFP())) || Pred != NanPred ||
if (!match(Op0, m_SpecificFCmp(NanPred, m_Value(X), m_AnyZeroFP())) ||
!match(Op1, m_BinOp(Opcode, m_Value(BO10), m_Value(BO11))))
return nullptr;

// The inner logic op must have a matching fcmp operand.
Value *Y;
if (!match(BO10, m_FCmp(Pred, m_Value(Y), m_AnyZeroFP())) ||
Pred != NanPred || X->getType() != Y->getType())
if (!match(BO10, m_SpecificFCmp(NanPred, m_Value(Y), m_AnyZeroFP())) ||
X->getType() != Y->getType())
std::swap(BO10, BO11);

if (!match(BO10, m_FCmp(Pred, m_Value(Y), m_AnyZeroFP())) ||
Pred != NanPred || X->getType() != Y->getType())
if (!match(BO10, m_SpecificFCmp(NanPred, m_Value(Y), m_AnyZeroFP())) ||
X->getType() != Y->getType())
return nullptr;

// and (fcmp ord X, 0), (and (fcmp ord Y, 0), Z) --> and (fcmp ord X, Y), Z
// or (fcmp uno X, 0), (or (fcmp uno Y, 0), Z) --> or (fcmp uno X, Y), Z
Value *NewFCmp = Builder.CreateFCmp(Pred, X, Y);
Value *NewFCmp = Builder.CreateFCmp(NanPred, X, Y);
if (auto *NewFCmpInst = dyn_cast<FCmpInst>(NewFCmp)) {
// Intersect FMF from the 2 source fcmps.
NewFCmpInst->copyIRFlags(Op0);
Expand Down Expand Up @@ -1744,14 +1744,13 @@ Instruction *InstCombinerImpl::foldCastedBitwiseLogic(BinaryOperator &I) {
// -> zext(bitwise(A < 0, icmp))
auto FoldBitwiseICmpZeroWithICmp = [&](Value *Op0,
Value *Op1) -> Instruction * {
ICmpInst::Predicate Pred;
Value *A;
bool IsMatched =
match(Op0,
m_OneUse(m_LShr(
m_Value(A),
m_SpecificInt(Op0->getType()->getScalarSizeInBits() - 1)))) &&
match(Op1, m_OneUse(m_ZExt(m_ICmp(Pred, m_Value(), m_Value()))));
match(Op1, m_OneUse(m_ZExt(m_ICmp(m_Value(), m_Value()))));

if (!IsMatched)
return nullptr;
Expand Down Expand Up @@ -3878,14 +3877,14 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
if (match(&I,
m_c_Or(m_CombineAnd(m_ExtractValue<1>(m_Value(UMulWithOv)),
m_Value(Ov)),
m_CombineAnd(m_ICmp(Pred,
m_CombineAnd(m_ExtractValue<0>(
m_Deferred(UMulWithOv)),
m_Value(Mul)),
m_ZeroInt()),
m_Value(MulIsNotZero)))) &&
(Ov->hasOneUse() || (MulIsNotZero->hasOneUse() && Mul->hasOneUse())) &&
Pred == CmpInst::ICMP_NE) {
m_CombineAnd(
m_SpecificICmp(ICmpInst::ICMP_NE,
m_CombineAnd(m_ExtractValue<0>(
m_Deferred(UMulWithOv)),
m_Value(Mul)),
m_ZeroInt()),
m_Value(MulIsNotZero)))) &&
(Ov->hasOneUse() || (MulIsNotZero->hasOneUse() && Mul->hasOneUse()))) {
Value *A, *B;
if (match(UMulWithOv, m_Intrinsic<Intrinsic::umul_with_overflow>(
m_Value(A), m_Value(B)))) {
Expand Down
Loading

0 comments on commit 62e9f40

Please sign in to comment.