[llvm] [PatternMatchHelpers] Introduce m_Unless (NFC) (PR #212454)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 30 07:26:39 PDT 2026


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/212454

>From 7aab2e6cfc30cd26213f0020497d7edddb74f96e 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 1/3] [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 70b9a72768ec7..88f3989352cf6 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 06c9233d2f497..7acc44e2c1e37 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 3311a9711cb3f..535ee20bf7e41 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);
       }
     }

>From 434ce8ee1c3d11e15400186b531f7b4b6dbc462d Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Wed, 29 Jul 2026 19:35:02 +0100
Subject: [PATCH 2/3] [PatternMatchHelpers] Strip non-null innovation

---
 llvm/include/llvm/Support/PatternMatchHelpers.h   | 4 ++--
 llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp | 5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/Support/PatternMatchHelpers.h b/llvm/include/llvm/Support/PatternMatchHelpers.h
index 1aae62ce5eaac..6c481b4bda672 100644
--- a/llvm/include/llvm/Support/PatternMatchHelpers.h
+++ b/llvm/include/llvm/Support/PatternMatchHelpers.h
@@ -101,11 +101,11 @@ template <typename Ty> struct match_bind { // NOLINT
   }
 };
 
-/// Inverting matcher that matches a non-null value not matching P.
+/// Inverting matcher that matches a 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 ITy> bool match(ITy *V) const { return !P.match(V); }
 };
 
 template <typename Pattern>
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 535ee20bf7e41..601396c2e4e62 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -2793,12 +2793,13 @@ void VPlanTransforms::dropPoisonGeneratingRecipes(VPlan &Plan) {
     for (VPRecipeBase &Recipe : *VPBB) {
       if (auto *WidenRec = dyn_cast<VPWidenMemoryRecipe>(&Recipe)) {
         VPRecipeBase *AddrDef = WidenRec->getAddr()->getDefiningRecipe();
-        if (AddrDef && WidenRec->isConsecutive() &&
+        if (AddrDef && WidenRec->isConsecutive() && WidenRec->getMask() &&
             match(WidenRec->getMask(), m_UnlessHdrMask))
           CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
       } else if (auto *InterleaveRec = dyn_cast<VPInterleaveRecipe>(&Recipe)) {
         VPRecipeBase *AddrDef = InterleaveRec->getAddr()->getDefiningRecipe();
-        if (AddrDef && match(InterleaveRec->getMask(), m_UnlessHdrMask))
+        if (AddrDef && InterleaveRec->getMask() &&
+            match(InterleaveRec->getMask(), m_UnlessHdrMask))
           CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
       }
     }

>From f7d76e25d6aebf9bcfdfd57c015de451f6a557bf Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Thu, 30 Jul 2026 15:14:28 +0100
Subject: [PATCH 3/3] [DAGCombiner] Revert m_Invert rename, thanks Luke!

---
 llvm/include/llvm/CodeGen/SDPatternMatch.h    | 4 ++--
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h
index 20471efa097c2..e2e20b14bb7f7 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_Invert(const Pred &P) {
+template <typename Pred> inline Not<Pred> m_Unless(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_Invert(m_AnyOf(preds...));
+  return m_Unless(m_AnyOf(preds...));
 }
 
 inline Opcode_match m_SpecificOpc(unsigned Opcode) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 7acc44e2c1e37..06c9233d2f497 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_Invert(m_UnaryOp(RedOpc, m_Value())))))) &&
+                   m_Value(B, m_Unless(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_Invert(m_UnaryOp(RedOpc, m_Value())))))) &&
+                   m_Value(D, m_Unless(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_Invert(m_UnaryOp(RedOpc, m_Value())))))) ||
+                m_Value(Z, m_Unless(m_UnaryOp(RedOpc, m_Value())))))) ||
         X.getValueType() != Y.getValueType() ||
         !hasOperation(Opc, X.getValueType()) ||
         !TLI.shouldReassociateReduction(RedOpc, VT))



More information about the llvm-commits mailing list