[llvm] [PatternMatchHelpers] Introduce variant of m_Unless (NFC) (PR #212454)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 28 03:29:27 PDT 2026
https://github.com/artagnon created https://github.com/llvm/llvm-project/pull/212454
Introduce a variant of the m_Unless pattern in PatternMatch, that inverts a match on a non-null value, in PatternMatchHelpers: as such, having a null value pass the m_Unless match is unhelpful. The patch has necessitated renaming the m_Unless variant in SDPatternMatch to m_Invert to avoid ambiguity.
>From c04708d86dc277732b06d660298cc28e0aaf3288 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Tue, 28 Jul 2026 11:07:38 +0100
Subject: [PATCH] [PatternMatchHelpers] Introduce variant of m_Unless (NFC)
Introduce a variant of the m_Unless pattern in PatternMatch, that
inverts a match on a non-null value, in PatternMatchHelpers: as such,
having a null value pass the m_Unless match is unhelpful. The patch has
necessitated renaming the m_Unless variant in SDPatternMatch to m_Invert
to avoid ambiguity.
---
llvm/include/llvm/CodeGen/SDPatternMatch.h | 4 ++--
llvm/include/llvm/IR/PatternMatch.h | 14 --------------
llvm/include/llvm/Support/PatternMatchHelpers.h | 12 ++++++++++++
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 6 +++---
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp | 10 ++++------
5 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h
index e2e20b14bb7f7..20471efa097c2 100644
--- a/llvm/include/llvm/CodeGen/SDPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h
@@ -208,7 +208,7 @@ template <typename Pred> struct Not {
template <typename Pred> Not(const Pred &P) -> Not<Pred>;
/// Match if the inner pattern does NOT match.
-template <typename Pred> inline Not<Pred> m_Unless(const Pred &P) {
+template <typename Pred> inline Not<Pred> m_Invert(const Pred &P) {
return Not{P};
}
@@ -221,7 +221,7 @@ template <typename... Preds> Or<Preds...> m_AnyOf(const Preds &...preds) {
}
template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
- return m_Unless(m_AnyOf(preds...));
+ return m_Invert(m_AnyOf(preds...));
}
inline Opcode_match m_SpecificOpc(unsigned Opcode) {
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index ca1dd7b46a6c4..b4845ba4dfa38 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -232,20 +232,6 @@ inline Splat_match<T> m_ConstantSplat(const T &SubPattern) {
/// Match an arbitrary basic block value and ignore it.
inline auto m_BasicBlock() { return m_Isa<BasicBlock>(); }
-/// Inverting matcher
-template <typename Ty> struct match_unless {
- Ty M;
-
- match_unless(const Ty &Matcher) : M(Matcher) {}
-
- template <typename ITy> bool match(ITy *V) const { return !M.match(V); }
-};
-
-/// Match if the inner matcher does *NOT* match.
-template <typename Ty> inline match_unless<Ty> m_Unless(const Ty &M) {
- return match_unless<Ty>(M);
-}
-
template <typename APTy> struct ap_match {
static_assert(std::is_same_v<APTy, APInt> || std::is_same_v<APTy, APFloat>);
using ConstantTy =
diff --git a/llvm/include/llvm/Support/PatternMatchHelpers.h b/llvm/include/llvm/Support/PatternMatchHelpers.h
index 4549a14b740cd..1aae62ce5eaac 100644
--- a/llvm/include/llvm/Support/PatternMatchHelpers.h
+++ b/llvm/include/llvm/Support/PatternMatchHelpers.h
@@ -100,6 +100,18 @@ template <typename Ty> struct match_bind { // NOLINT
return false;
}
};
+
+/// Inverting matcher that matches a non-null value not matching P.
+template <typename Ty> struct match_unless { // NOLINT
+ Ty P;
+ match_unless(const Ty &P) : P(P) {}
+ template <typename ITy> bool match(ITy *V) const { return V && !P.match(V); }
+};
+
+template <typename Pattern>
+inline match_unless<Pattern> m_Unless(const Pattern &P) { // NOLINT
+ return P;
+}
} // namespace llvm::PatternMatchHelpers
#endif // LLVM_SUPPORT_PATTERNMATCHHELPERS_H
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index ff54965b64a75..e977b225ca518 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -1376,11 +1376,11 @@ SDValue DAGCombiner::reassociateReduction(unsigned RedOpc, unsigned Opc,
if (sd_match(N0,
m_OneUse(m_c_BinOp(
Opc, m_Value(RedA, m_OneUse(m_UnaryOp(RedOpc, m_Value(A)))),
- m_Value(B, m_Unless(m_UnaryOp(RedOpc, m_Value())))))) &&
+ m_Value(B, m_Invert(m_UnaryOp(RedOpc, m_Value())))))) &&
sd_match(N1,
m_OneUse(m_c_BinOp(
Opc, m_Value(RedB, m_OneUse(m_UnaryOp(RedOpc, m_Value(C)))),
- m_Value(D, m_Unless(m_UnaryOp(RedOpc, m_Value())))))) &&
+ m_Value(D, m_Invert(m_UnaryOp(RedOpc, m_Value())))))) &&
A.getValueType() == C.getValueType() &&
hasOperation(Opc, A.getValueType()) &&
TLI.shouldReassociateReduction(RedOpc, VT)) {
@@ -1413,7 +1413,7 @@ SDValue DAGCombiner::reassociateReduction(unsigned RedOpc, unsigned Opc,
Chain,
m_OneUse(m_c_BinOp(
Opc, m_Value(RedY, m_OneUse(m_UnaryOp(RedOpc, m_Value(Y)))),
- m_Value(Z, m_Unless(m_UnaryOp(RedOpc, m_Value())))))) ||
+ m_Value(Z, m_Invert(m_UnaryOp(RedOpc, m_Value())))))) ||
X.getValueType() != Y.getValueType() ||
!hasOperation(Opc, X.getValueType()) ||
!TLI.shouldReassociateReduction(RedOpc, VT))
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 9990fd142df02..cf9d1135c7c32 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -2781,10 +2781,8 @@ void VPlanTransforms::dropPoisonGeneratingRecipes(VPlan &Plan) {
// wrapped in a Reverse, which is just a permutation of the header mask, so
// peel it off before checking. The header mask is still the abstract region
// value at this point (materialization happens later).
- auto IsNotHeaderMask = [](VPValue *Mask) {
- return Mask &&
- !match(Mask, m_CombineOr(m_HeaderMask(), m_Reverse(m_HeaderMask())));
- };
+ auto m_UnlessHdrMask = m_Unless( // NOLINT
+ m_CombineOr(m_HeaderMask(), m_Reverse(m_HeaderMask())));
// Traverse all the recipes in the VPlan and collect the poison-generating
// recipes in the backward slice starting at the address of a VPWidenRecipe or
@@ -2796,11 +2794,11 @@ void VPlanTransforms::dropPoisonGeneratingRecipes(VPlan &Plan) {
if (auto *WidenRec = dyn_cast<VPWidenMemoryRecipe>(&Recipe)) {
VPRecipeBase *AddrDef = WidenRec->getAddr()->getDefiningRecipe();
if (AddrDef && WidenRec->isConsecutive() &&
- IsNotHeaderMask(WidenRec->getMask()))
+ match(WidenRec->getMask(), m_UnlessHdrMask))
CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
} else if (auto *InterleaveRec = dyn_cast<VPInterleaveRecipe>(&Recipe)) {
VPRecipeBase *AddrDef = InterleaveRec->getAddr()->getDefiningRecipe();
- if (AddrDef && IsNotHeaderMask(InterleaveRec->getMask()))
+ if (AddrDef && match(InterleaveRec->getMask(), m_UnlessHdrMask))
CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
}
}
More information about the llvm-commits
mailing list