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

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
This commit is contained in:
Simon Pilgrim 2026-04-03 19:03:00 +01:00 committed by GitHub
parent 68b6a27771
commit 6832709dc0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 57 additions and 44 deletions

View File

@ -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)))

View File

@ -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);
}

View File

@ -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();

View File

@ -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:

View File

@ -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(