Skip to content

Commit 9b513ad

Browse files
[DAG] Add generic m_TernaryOp() / m_c_TernaryOp() matchers (llvm#165520)
Similar to the m_BinOp/m_c_BinOp matchers, this patch introduces generic matchers for SelectionDAG nodes with three operands. This includes: - Adding m_TernaryOp() and m_c_TernaryOp() templates in SDPatternMatch.h. - Adding comprehensive test coverage in SelectionDAGPatternMatchTest.cpp. Fixes llvm#165378
1 parent 9ab9d33 commit 9b513ad

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

llvm/include/llvm/CodeGen/SDPatternMatch.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,18 @@ m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx) {
583583
return TernaryOpc_match<LHS, RHS, IDX>(ISD::INSERT_SUBVECTOR, Base, Sub, Idx);
584584
}
585585

586+
template <typename T0_P, typename T1_P, typename T2_P>
587+
inline TernaryOpc_match<T0_P, T1_P, T2_P>
588+
m_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
589+
return TernaryOpc_match<T0_P, T1_P, T2_P>(Opc, Op0, Op1, Op2);
590+
}
591+
592+
template <typename T0_P, typename T1_P, typename T2_P>
593+
inline TernaryOpc_match<T0_P, T1_P, T2_P, true>
594+
m_c_TernaryOp(unsigned Opc, const T0_P &Op0, const T1_P &Op1, const T2_P &Op2) {
595+
return TernaryOpc_match<T0_P, T1_P, T2_P, true>(Opc, Op0, Op1, Op2);
596+
}
597+
586598
template <typename LTy, typename RTy, typename TTy, typename FTy, typename CCTy>
587599
inline auto m_SelectCC(const LTy &L, const RTy &R, const TTy &T, const FTy &F,
588600
const CCTy &CC) {

llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,76 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
354354
sd_match(InsertELT, m_InsertElt(m_Value(), m_Value(), m_SpecificInt(1))));
355355
}
356356

357+
TEST_F(SelectionDAGPatternMatchTest, matchGenericTernaryOp) {
358+
SDLoc DL;
359+
auto Float32VT = EVT::getFloatingPointVT(32);
360+
361+
SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Float32VT);
362+
SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Float32VT);
363+
SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Float32VT);
364+
365+
SDValue FMA = DAG->getNode(ISD::FMA, DL, Float32VT, Op0, Op1, Op2);
366+
SDValue FAdd = DAG->getNode(ISD::FADD, DL, Float32VT, Op0, Op1);
367+
368+
using namespace SDPatternMatch;
369+
SDValue A, B, C;
370+
371+
EXPECT_TRUE(sd_match(FMA, m_TernaryOp(ISD::FMA, m_Specific(Op0),
372+
m_Specific(Op1), m_Specific(Op2))));
373+
EXPECT_FALSE(sd_match(FMA, m_TernaryOp(ISD::FADD, m_Specific(Op0),
374+
m_Specific(Op1), m_Specific(Op2))));
375+
EXPECT_FALSE(
376+
sd_match(FAdd, m_TernaryOp(ISD::FMA, m_Value(), m_Value(), m_Value())));
377+
EXPECT_FALSE(sd_match(FMA, m_TernaryOp(ISD::FMA, m_Specific(Op1),
378+
m_Specific(Op0), m_Specific(Op2))));
379+
380+
EXPECT_TRUE(
381+
sd_match(FMA, m_TernaryOp(ISD::FMA, m_Value(A), m_Value(B), m_Value(C))));
382+
EXPECT_EQ(A, Op0);
383+
EXPECT_EQ(B, Op1);
384+
EXPECT_EQ(C, Op2);
385+
386+
A = B = C = SDValue();
387+
388+
EXPECT_TRUE(sd_match(FMA, m_c_TernaryOp(ISD::FMA, m_Specific(Op0),
389+
m_Specific(Op1), m_Specific(Op2))));
390+
EXPECT_TRUE(sd_match(FMA, m_c_TernaryOp(ISD::FMA, m_Specific(Op1),
391+
m_Specific(Op0), m_Specific(Op2))));
392+
393+
EXPECT_FALSE(sd_match(FMA, m_c_TernaryOp(ISD::FMA, m_Specific(Op2),
394+
m_Specific(Op1), m_Specific(Op0))));
395+
EXPECT_FALSE(sd_match(FMA, m_c_TernaryOp(ISD::FMA, m_Specific(Op2),
396+
m_Specific(Op0), m_Specific(Op1))));
397+
398+
EXPECT_FALSE(sd_match(FMA, m_c_TernaryOp(ISD::FMA, m_Specific(Op0),
399+
m_Specific(Op2), m_Specific(Op1))));
400+
EXPECT_FALSE(sd_match(FMA, m_c_TernaryOp(ISD::FMA, m_Specific(Op1),
401+
m_Specific(Op2), m_Specific(Op0))));
402+
403+
EXPECT_TRUE(sd_match(
404+
FMA, m_c_TernaryOp(ISD::FMA, m_Value(A), m_Value(B), m_Value(C))));
405+
EXPECT_EQ(A, Op0);
406+
EXPECT_EQ(B, Op1);
407+
EXPECT_EQ(C, Op2);
408+
409+
A = B = C = SDValue();
410+
EXPECT_TRUE(sd_match(
411+
FMA, m_c_TernaryOp(ISD::FMA, m_Value(B), m_Value(A), m_Value(C))));
412+
EXPECT_EQ(A, Op1);
413+
EXPECT_EQ(B, Op0);
414+
EXPECT_EQ(C, Op2);
415+
416+
A = B = C = SDValue();
417+
EXPECT_TRUE(sd_match(
418+
FMA, m_c_TernaryOp(ISD::FMA, m_Value(A), m_Value(B), m_Value(C))));
419+
EXPECT_EQ(A, Op0);
420+
EXPECT_EQ(B, Op1);
421+
EXPECT_EQ(C, Op2);
422+
423+
EXPECT_FALSE(
424+
sd_match(FAdd, m_c_TernaryOp(ISD::FMA, m_Value(), m_Value(), m_Value())));
425+
}
426+
357427
TEST_F(SelectionDAGPatternMatchTest, matchUnaryOp) {
358428
SDLoc DL;
359429
auto Int32VT = EVT::getIntegerVT(Context, 32);

0 commit comments

Comments
 (0)