[llvm] [DAG] SDPatternMatch - rename m_Opc -> m_SpecificOpc (PR #190215)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 3 08:00:27 PDT 2026


https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/190215

>From 873cfbae11548721171d7cf8f5586232fbefab83 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Thu, 2 Apr 2026 18:14:20 +0100
Subject: [PATCH] [DAG] SDPatternMatch - rename m_Opc -> m_SpecificOpc

Match naming convention for other m_Specific* matchers, and frees up the m_Opc() matcher for future use in #84940 to allow us to capture the opcode of a unknown binop

Moving to m_SpecificOpc does mess up the formatting in a few places, I've tried to refactor to use the m_Value(SDValue, ....) matcher where I can to retrieve some whitespace
---
 llvm/include/llvm/CodeGen/SDPatternMatch.h    | 25 +++++-----
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 16 ++++---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  2 +-
 llvm/lib/Target/X86/X86ISelLowering.cpp       | 11 +++--
 .../CodeGen/SelectionDAGPatternMatchTest.cpp  | 47 +++++++++++--------
 5 files changed, 57 insertions(+), 44 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h
index 62762d0c50d6a..6c356d6ca37a3 100644
--- a/llvm/include/llvm/CodeGen/SDPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h
@@ -28,8 +28,8 @@ namespace llvm {
 namespace SDPatternMatch {
 
 /// MatchContext can repurpose existing patterns to behave differently under
-/// a certain context. For instance, `m_Opc(ISD::ADD)` matches plain ADD nodes
-/// in normal circumstances, but matches VP_ADD nodes under a custom
+/// a certain context. For instance, `m_SpecificOpc(ISD::ADD)` matches plain ADD
+/// nodes in normal circumstances, but matches VP_ADD nodes under a custom
 /// VPMatchContext. This design is meant to facilitate code / pattern reusing.
 class BasicMatchContext {
   const SelectionDAG *DAG;
@@ -223,7 +223,9 @@ template <typename... Preds> auto m_NoneOf(const Preds &...preds) {
   return m_Unless(m_AnyOf(preds...));
 }
 
-inline Opcode_match m_Opc(unsigned Opcode) { return Opcode_match(Opcode); }
+inline Opcode_match m_SpecificOpc(unsigned Opcode) {
+  return Opcode_match(Opcode);
+}
 
 inline auto m_Undef() {
   return m_AnyOf(Opcode_match(ISD::UNDEF), Opcode_match(ISD::POISON));
@@ -496,7 +498,8 @@ struct Operands_match<OpIdx, OpndPred, OpndPreds...>
 
 template <typename... OpndPreds>
 auto m_Node(unsigned Opcode, const OpndPreds &...preds) {
-  return m_AllOf(m_Opc(Opcode), Operands_match<0, OpndPreds...>(preds...));
+  return m_AllOf(m_SpecificOpc(Opcode),
+                 Operands_match<0, OpndPreds...>(preds...));
 }
 
 /// Provide number of operands that are not chain or glue, as well as the first
@@ -546,7 +549,7 @@ struct TernaryOpc_match {
 
   template <typename MatchContext>
   bool match(const MatchContext &Ctx, SDValue N) {
-    if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
+    if (sd_context_match(N, Ctx, m_SpecificOpc(Opcode))) {
       EffectiveOperands<ExcludeChain> EO(N, Ctx);
       assert(EO.Size == 3);
       return ((Op0.match(Ctx, N->getOperand(EO.FirstIndex)) &&
@@ -648,7 +651,7 @@ struct BinaryOpc_match {
 
   template <typename MatchContext>
   bool match(const MatchContext &Ctx, SDValue N) {
-    if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
+    if (sd_context_match(N, Ctx, m_SpecificOpc(Opcode))) {
       EffectiveOperands<ExcludeChain> EO(N, Ctx);
       assert(EO.Size == 2);
       if (!((LHS.match(Ctx, N->getOperand(EO.FirstIndex)) &&
@@ -723,15 +726,15 @@ struct MaxMin_match {
              (Commutable && LHS.match(Ctx, R) && RHS.match(Ctx, L));
     };
 
-    if (sd_context_match(N, Ctx, m_Opc(ISD::SELECT)) ||
-        sd_context_match(N, Ctx, m_Opc(ISD::VSELECT))) {
+    if (sd_context_match(N, Ctx, m_SpecificOpc(ISD::SELECT)) ||
+        sd_context_match(N, Ctx, m_SpecificOpc(ISD::VSELECT))) {
       EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
       assert(EO_SELECT.Size == 3);
       SDValue Cond = N->getOperand(EO_SELECT.FirstIndex);
       SDValue TrueValue = N->getOperand(EO_SELECT.FirstIndex + 1);
       SDValue FalseValue = N->getOperand(EO_SELECT.FirstIndex + 2);
 
-      if (sd_context_match(Cond, Ctx, m_Opc(ISD::SETCC))) {
+      if (sd_context_match(Cond, Ctx, m_SpecificOpc(ISD::SETCC))) {
         EffectiveOperands<ExcludeChain> EO_SETCC(Cond, Ctx);
         assert(EO_SETCC.Size == 3);
         SDValue L = Cond->getOperand(EO_SETCC.FirstIndex);
@@ -742,7 +745,7 @@ struct MaxMin_match {
       }
     }
 
-    if (sd_context_match(N, Ctx, m_Opc(ISD::SELECT_CC))) {
+    if (sd_context_match(N, Ctx, m_SpecificOpc(ISD::SELECT_CC))) {
       EffectiveOperands<ExcludeChain> EO_SELECT(N, Ctx);
       assert(EO_SELECT.Size == 5);
       SDValue L = N->getOperand(EO_SELECT.FirstIndex);
@@ -1025,7 +1028,7 @@ template <typename Opnd_P, bool ExcludeChain = false> struct UnaryOpc_match {
 
   template <typename MatchContext>
   bool match(const MatchContext &Ctx, SDValue N) {
-    if (sd_context_match(N, Ctx, m_Opc(Opcode))) {
+    if (sd_context_match(N, Ctx, m_SpecificOpc(Opcode))) {
       EffectiveOperands<ExcludeChain> EO(N, Ctx);
       assert(EO.Size == 1);
       if (!Opnd.match(Ctx, N->getOperand(EO.FirstIndex)))
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 70d48895a47bf..383e45c5ea3a8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -4935,7 +4935,7 @@ template <class MatchContextClass> SDValue DAGCombiner::visitMUL(SDNode *N) {
   }
 
   // fold (mul (add x, c1), c2) -> (add (mul x, c2), c1*c2)
-  if (sd_context_match(N0, Matcher, m_Opc(ISD::ADD)) &&
+  if (sd_context_match(N0, Matcher, m_SpecificOpc(ISD::ADD)) &&
       isConstantOrConstantVector(N1) &&
       isConstantOrConstantVector(N0.getOperand(1)) &&
       isMulAddWithConstProfitable(N, N0, N1))
@@ -11561,15 +11561,17 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
   // fold (srl (logic_op x, (shl (zext y), c1)), c1)
   //   -> (logic_op (srl x, c1), (zext y))
   // c1 <= leadingzeros(zext(y))
+  // TODO: Replace c1 with valuetracking?
   SDValue X, ZExtY;
-  if (N1C && sd_match(N0, m_OneUse(m_BitwiseLogic(
-                              m_Value(X),
-                              m_OneUse(m_Shl(m_AllOf(m_Value(ZExtY),
-                                                     m_Opc(ISD::ZERO_EXTEND)),
-                                             m_Specific(N1))))))) {
+  if (sd_match(
+          N0,
+          m_OneUse(m_BitwiseLogic(
+              m_Value(X),
+              m_OneUse(m_Shl(m_Value(ZExtY, m_SpecificOpc(ISD::ZERO_EXTEND)),
+                             m_Specific(N1))))))) {
     unsigned NumLeadingZeros = ZExtY.getScalarValueSizeInBits() -
                                ZExtY.getOperand(0).getScalarValueSizeInBits();
-    if (N1C->getZExtValue() <= NumLeadingZeros)
+    if (N1C && N1C->getZExtValue() <= NumLeadingZeros)
       return DAG.getNode(N0.getOpcode(), SDLoc(N0), VT,
                          DAG.getNode(ISD::SRL, SDLoc(N0), VT, X, N1), ZExtY);
   }
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 0650bbdedc08b..d00b734f64509 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -17077,7 +17077,7 @@ static SDValue combineNarrowableShiftedLoad(SDNode *N, SelectionDAG &DAG) {
   APInt MaskVal, ShiftVal;
   // (and (shl (load ...), ShiftAmt), Mask)
   if (!sd_match(
-          N, m_And(m_OneUse(m_Shl(m_AllOf(m_Opc(ISD::LOAD), m_Value(LoadNode)),
+          N, m_And(m_OneUse(m_Shl(m_Value(LoadNode, m_SpecificOpc(ISD::LOAD)),
                                   m_ConstInt(ShiftVal))),
                    m_ConstInt(MaskVal)))) {
     return SDValue();
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index ffd9468a491ee..67d25e4eabbac 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58877,11 +58877,12 @@ static SDValue matchPMADDWD(SelectionDAG &DAG, SDNode *N,
     return SDValue();
 
   SDValue Op0, Op1, Accum;
-  if (!sd_match(N, m_Add(m_AllOf(m_Opc(ISD::BUILD_VECTOR), m_Value(Op0)),
-                         m_AllOf(m_Opc(ISD::BUILD_VECTOR), m_Value(Op1)))) &&
-      !sd_match(N, m_Add(m_AllOf(m_Opc(ISD::BUILD_VECTOR), m_Value(Op0)),
-                         m_Add(m_Value(Accum), m_AllOf(m_Opc(ISD::BUILD_VECTOR),
-                                                       m_Value(Op1))))))
+  if (!sd_match(N, m_Add(m_Value(Op0, m_SpecificOpc(ISD::BUILD_VECTOR)),
+                         m_Value(Op1, m_SpecificOpc(ISD::BUILD_VECTOR)))) &&
+      !sd_match(N,
+                m_Add(m_Value(Op0, m_SpecificOpc(ISD::BUILD_VECTOR)),
+                      m_Add(m_Value(Accum),
+                            m_Value(Op1, m_SpecificOpc(ISD::BUILD_VECTOR))))))
     return SDValue();
 
   // Check if one of Op0,Op1 is of the form:
diff --git a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
index e3f4ce20f4234..810363c8f6384 100644
--- a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
+++ b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
@@ -320,8 +320,8 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
   EXPECT_TRUE(sd_match(Add, m_c_BinOp(ISD::ADD, m_Value(), m_Value())));
   EXPECT_TRUE(sd_match(Add, m_Add(m_Value(), m_Value())));
   EXPECT_TRUE(sd_match(Add, m_AddLike(m_Value(), m_Value())));
-  EXPECT_TRUE(sd_match(
-      Mul, m_Mul(m_OneUse(m_Opc(ISD::SUB)), m_NUses<2>(m_Specific(Add)))));
+  EXPECT_TRUE(sd_match(Mul, m_Mul(m_OneUse(m_SpecificOpc(ISD::SUB)),
+                                  m_NUses<2>(m_Specific(Add)))));
   EXPECT_TRUE(
       sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_SpecificVT(Float32VT),
                                      m_SpecificVT(Float32VT))));
@@ -467,21 +467,25 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
 
   SDValue BindVal;
   // By default, it matches any of the results.
-  EXPECT_TRUE(
-      sd_match(PartsDiff, m_Sub(m_Opc(ISD::SMUL_LOHI), m_Opc(ISD::SMUL_LOHI))));
+  EXPECT_TRUE(sd_match(PartsDiff, m_Sub(m_SpecificOpc(ISD::SMUL_LOHI),
+                                        m_SpecificOpc(ISD::SMUL_LOHI))));
   // Matching a specific result.
-  EXPECT_TRUE(sd_match(PartsDiff, m_Sub(m_Opc(ISD::SMUL_LOHI),
-                                        m_Result<1>(m_Opc(ISD::SMUL_LOHI)))));
-  EXPECT_FALSE(sd_match(PartsDiff, m_Sub(m_Opc(ISD::SMUL_LOHI),
-                                         m_Result<0>(m_Opc(ISD::SMUL_LOHI)))));
+  EXPECT_TRUE(
+      sd_match(PartsDiff, m_Sub(m_SpecificOpc(ISD::SMUL_LOHI),
+                                m_Result<1>(m_SpecificOpc(ISD::SMUL_LOHI)))));
+  EXPECT_FALSE(
+      sd_match(PartsDiff, m_Sub(m_SpecificOpc(ISD::SMUL_LOHI),
+                                m_Result<0>(m_SpecificOpc(ISD::SMUL_LOHI)))));
 
   // Conditionally bind the value from a certain sub-pattern.
-  EXPECT_TRUE(sd_match(PartsDiff, m_Sub(m_Value(BindVal, m_Opc(ISD::SMUL_LOHI)),
-                                        m_Opc(ISD::SMUL_LOHI))));
+  EXPECT_TRUE(
+      sd_match(PartsDiff, m_Sub(m_Value(BindVal, m_SpecificOpc(ISD::SMUL_LOHI)),
+                                m_SpecificOpc(ISD::SMUL_LOHI))));
   EXPECT_EQ(BindVal, SMulLoHi);
   BindVal = SDValue();
-  EXPECT_FALSE(sd_match(PartsDiff, m_Sub(m_Value(BindVal, m_Opc(ISD::ADD)),
-                                         m_Opc(ISD::SMUL_LOHI))));
+  EXPECT_FALSE(
+      sd_match(PartsDiff, m_Sub(m_Value(BindVal, m_SpecificOpc(ISD::ADD)),
+                                m_SpecificOpc(ISD::SMUL_LOHI))));
   EXPECT_NE(BindVal, SMulLoHi);
 
   BindVal = SDValue();
@@ -894,10 +898,12 @@ TEST_F(SelectionDAGPatternMatchTest, patternCombinators) {
   SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0);
 
   using namespace SDPatternMatch;
+  EXPECT_TRUE(
+      sd_match(Sub, m_AnyOf(m_SpecificOpc(ISD::ADD), m_SpecificOpc(ISD::SUB),
+                            m_SpecificOpc(ISD::MUL))));
+  EXPECT_TRUE(sd_match(Add, m_AllOf(m_SpecificOpc(ISD::ADD), m_OneUse())));
   EXPECT_TRUE(sd_match(
-      Sub, m_AnyOf(m_Opc(ISD::ADD), m_Opc(ISD::SUB), m_Opc(ISD::MUL))));
-  EXPECT_TRUE(sd_match(Add, m_AllOf(m_Opc(ISD::ADD), m_OneUse())));
-  EXPECT_TRUE(sd_match(Add, m_NoneOf(m_Opc(ISD::SUB), m_Opc(ISD::MUL))));
+      Add, m_NoneOf(m_SpecificOpc(ISD::SUB), m_SpecificOpc(ISD::MUL))));
 }
 
 TEST_F(SelectionDAGPatternMatchTest, optionalResizing) {
@@ -1073,7 +1079,7 @@ TEST_F(SelectionDAGPatternMatchTest, matchContext) {
 
   using namespace SDPatternMatch;
   VPMatchContext VPCtx(DAG.get());
-  EXPECT_TRUE(sd_context_match(VPAdd, VPCtx, m_Opc(ISD::ADD)));
+  EXPECT_TRUE(sd_context_match(VPAdd, VPCtx, m_SpecificOpc(ISD::ADD)));
   EXPECT_TRUE(
       sd_context_match(VPAdd, VPCtx, m_Node(ISD::ADD, m_Value(), m_Value())));
   // VPMatchContext can't match pattern using explicit VP Opcode
@@ -1086,11 +1092,12 @@ TEST_F(SelectionDAGPatternMatchTest, matchContext) {
   EXPECT_TRUE(sd_context_match(VPAdd, VPCtx, m_Add(m_Value(), m_Value())));
   // VP_REDUCE_ADD doesn't have a based opcode, so we use a normal
   // sd_match before switching to VPMatchContext when checking VPAdd.
-  EXPECT_TRUE(sd_match(VPReduceAdd, m_Node(ISD::VP_REDUCE_ADD, m_Value(),
-                                           m_Context(VPCtx, m_Opc(ISD::ADD)),
-                                           m_Value(), m_Value())));
+  EXPECT_TRUE(
+      sd_match(VPReduceAdd, m_Node(ISD::VP_REDUCE_ADD, m_Value(),
+                                   m_Context(VPCtx, m_SpecificOpc(ISD::ADD)),
+                                   m_Value(), m_Value())));
   // non-vector predicated should match too
-  EXPECT_TRUE(sd_context_match(Add, VPCtx, m_Opc(ISD::ADD)));
+  EXPECT_TRUE(sd_context_match(Add, VPCtx, m_SpecificOpc(ISD::ADD)));
   EXPECT_TRUE(
       sd_context_match(Add, VPCtx, m_Node(ISD::ADD, m_Value(), m_Value())));
   EXPECT_FALSE(sd_context_match(



More information about the llvm-commits mailing list