1 //===---- llvm/unittest/CodeGen/SelectionDAGPatternMatchTest.cpp ---------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/CodeGen/MachineModuleInfo.h"
12 #include "llvm/CodeGen/SDPatternMatch.h"
13 #include "llvm/CodeGen/TargetLowering.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/MC/TargetRegistry.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/TargetSelect.h"
18 #include "llvm/Target/TargetMachine.h"
19 #include "gtest/gtest.h"
23 class SelectionDAGPatternMatchTest
: public testing::Test
{
25 static void SetUpTestCase() {
26 InitializeAllTargets();
27 InitializeAllTargetMCs();
30 void SetUp() override
{
31 StringRef Assembly
= "@g = global i32 0\n"
32 "@g_alias = alias i32, i32* @g\n"
34 " %1 = load i32, i32* @g\n"
38 Triple
TargetTriple("riscv64--");
40 const Target
*T
= TargetRegistry::lookupTarget("", TargetTriple
, Error
);
41 // FIXME: These tests do not depend on RISCV specifically, but we have to
42 // initialize a target. A skeleton Target for unittests would allow us to
43 // always run these tests.
47 TargetOptions Options
;
48 TM
= std::unique_ptr
<TargetMachine
>(T
->createTargetMachine(
49 "riscv64", "", "+m,+f,+d,+v", Options
, std::nullopt
, std::nullopt
,
50 CodeGenOptLevel::Aggressive
));
55 M
= parseAssemblyString(Assembly
, SMError
, Context
);
57 report_fatal_error(SMError
.getMessage());
58 M
->setDataLayout(TM
->createDataLayout());
60 F
= M
->getFunction("f");
62 report_fatal_error("F?");
63 G
= M
->getGlobalVariable("g");
65 report_fatal_error("G?");
66 AliasedG
= M
->getNamedAlias("g_alias");
68 report_fatal_error("AliasedG?");
70 MachineModuleInfo
MMI(TM
.get());
72 MF
= std::make_unique
<MachineFunction
>(*F
, *TM
, *TM
->getSubtargetImpl(*F
),
75 DAG
= std::make_unique
<SelectionDAG
>(*TM
, CodeGenOptLevel::None
);
77 report_fatal_error("DAG?");
78 OptimizationRemarkEmitter
ORE(F
);
79 DAG
->init(*MF
, ORE
, nullptr, nullptr, nullptr, nullptr, nullptr, MMI
,
83 TargetLoweringBase::LegalizeTypeAction
getTypeAction(EVT VT
) {
84 return DAG
->getTargetLoweringInfo().getTypeAction(Context
, VT
);
87 EVT
getTypeToTransformTo(EVT VT
) {
88 return DAG
->getTargetLoweringInfo().getTypeToTransformTo(Context
, VT
);
92 std::unique_ptr
<TargetMachine
> TM
;
93 std::unique_ptr
<Module
> M
;
96 GlobalAlias
*AliasedG
;
97 std::unique_ptr
<MachineFunction
> MF
;
98 std::unique_ptr
<SelectionDAG
> DAG
;
101 TEST_F(SelectionDAGPatternMatchTest
, matchValueType
) {
103 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
104 auto Float32VT
= EVT::getFloatingPointVT(32);
105 auto VInt32VT
= EVT::getVectorVT(Context
, Int32VT
, 4);
107 SDValue Op0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int32VT
);
108 SDValue Op1
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 2, Float32VT
);
109 SDValue Op2
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 2, VInt32VT
);
111 using namespace SDPatternMatch
;
112 EXPECT_TRUE(sd_match(Op0
, m_SpecificVT(Int32VT
)));
114 EXPECT_TRUE(sd_match(Op1
, m_VT(BindVT
)));
115 EXPECT_EQ(BindVT
, Float32VT
);
116 EXPECT_TRUE(sd_match(Op0
, m_IntegerVT()));
117 EXPECT_TRUE(sd_match(Op1
, m_FloatingPointVT()));
118 EXPECT_TRUE(sd_match(Op2
, m_VectorVT()));
119 EXPECT_FALSE(sd_match(Op2
, m_ScalableVectorVT()));
122 TEST_F(SelectionDAGPatternMatchTest
, matchTernaryOp
) {
124 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
126 SDValue Op0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int32VT
);
127 SDValue Op1
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 2, Int32VT
);
128 SDValue Op3
= DAG
->getConstant(1, DL
, Int32VT
);
130 SDValue ICMP_UGT
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETUGT
);
131 SDValue ICMP_EQ01
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETEQ
);
132 SDValue ICMP_EQ10
= DAG
->getSetCC(DL
, MVT::i1
, Op1
, Op0
, ISD::SETEQ
);
134 auto Int1VT
= EVT::getIntegerVT(Context
, 1);
135 SDValue Cond
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 3, Int1VT
);
136 SDValue T
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 4, Int1VT
);
137 SDValue F
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 5, Int1VT
);
138 SDValue Select
= DAG
->getSelect(DL
, MVT::i1
, Cond
, T
, F
);
140 auto VInt32VT
= EVT::getVectorVT(Context
, Int32VT
, 4);
141 SDValue V1
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 6, VInt32VT
);
142 SDValue V2
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 7, VInt32VT
);
143 SDValue VSelect
= DAG
->getNode(ISD::VSELECT
, DL
, VInt32VT
, Cond
, V1
, V2
);
146 DAG
->getNode(ISD::EXTRACT_VECTOR_ELT
, DL
, Int32VT
, V1
, Op3
);
148 using namespace SDPatternMatch
;
150 EXPECT_TRUE(sd_match(ICMP_UGT
, m_SetCC(m_Value(), m_Value(),
151 m_SpecificCondCode(ISD::SETUGT
))));
153 sd_match(ICMP_UGT
, m_SetCC(m_Value(), m_Value(), m_CondCode(CC
))));
154 EXPECT_TRUE(CC
== ISD::SETUGT
);
155 EXPECT_FALSE(sd_match(
156 ICMP_UGT
, m_SetCC(m_Value(), m_Value(), m_SpecificCondCode(ISD::SETLE
))));
158 EXPECT_TRUE(sd_match(ICMP_EQ01
, m_SetCC(m_Specific(Op0
), m_Specific(Op1
),
159 m_SpecificCondCode(ISD::SETEQ
))));
160 EXPECT_TRUE(sd_match(ICMP_EQ10
, m_SetCC(m_Specific(Op1
), m_Specific(Op0
),
161 m_SpecificCondCode(ISD::SETEQ
))));
162 EXPECT_FALSE(sd_match(ICMP_EQ01
, m_SetCC(m_Specific(Op1
), m_Specific(Op0
),
163 m_SpecificCondCode(ISD::SETEQ
))));
164 EXPECT_FALSE(sd_match(ICMP_EQ10
, m_SetCC(m_Specific(Op0
), m_Specific(Op1
),
165 m_SpecificCondCode(ISD::SETEQ
))));
166 EXPECT_TRUE(sd_match(ICMP_EQ01
, m_c_SetCC(m_Specific(Op1
), m_Specific(Op0
),
167 m_SpecificCondCode(ISD::SETEQ
))));
168 EXPECT_TRUE(sd_match(ICMP_EQ10
, m_c_SetCC(m_Specific(Op0
), m_Specific(Op1
),
169 m_SpecificCondCode(ISD::SETEQ
))));
171 EXPECT_TRUE(sd_match(
172 Select
, m_Select(m_Specific(Cond
), m_Specific(T
), m_Specific(F
))));
173 EXPECT_FALSE(sd_match(
174 Select
, m_Select(m_Specific(Cond
), m_Specific(F
), m_Specific(T
))));
175 EXPECT_FALSE(sd_match(ICMP_EQ01
, m_Select(m_Specific(Op0
), m_Specific(Op1
),
176 m_SpecificCondCode(ISD::SETEQ
))));
177 EXPECT_TRUE(sd_match(
178 VSelect
, m_VSelect(m_Specific(Cond
), m_Specific(V1
), m_Specific(V2
))));
179 EXPECT_FALSE(sd_match(
180 Select
, m_VSelect(m_Specific(Cond
), m_Specific(V1
), m_Specific(V2
))));
182 EXPECT_TRUE(sd_match(ExtractELT
, m_ExtractElt(m_Value(), m_Value())));
183 EXPECT_TRUE(sd_match(ExtractELT
, m_ExtractElt(m_Value(), m_ConstInt())));
184 EXPECT_TRUE(sd_match(ExtractELT
, m_ExtractElt(m_Value(), m_SpecificInt(1))));
187 TEST_F(SelectionDAGPatternMatchTest
, matchBinaryOp
) {
189 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
190 auto Float32VT
= EVT::getFloatingPointVT(32);
191 auto VInt32VT
= EVT::getVectorVT(Context
, Int32VT
, 4);
193 SDValue V1
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 6, VInt32VT
);
195 SDValue Op0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int32VT
);
196 SDValue Op1
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 2, Int32VT
);
197 SDValue Op2
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 3, Float32VT
);
198 SDValue Op3
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 8, Int32VT
);
199 SDValue Op4
= DAG
->getConstant(1, DL
, Int32VT
);
201 SDValue Add
= DAG
->getNode(ISD::ADD
, DL
, Int32VT
, Op0
, Op1
);
202 SDValue Sub
= DAG
->getNode(ISD::SUB
, DL
, Int32VT
, Add
, Op0
);
203 SDValue Mul
= DAG
->getNode(ISD::MUL
, DL
, Int32VT
, Add
, Sub
);
204 SDValue And
= DAG
->getNode(ISD::AND
, DL
, Int32VT
, Op0
, Op1
);
205 SDValue Xor
= DAG
->getNode(ISD::XOR
, DL
, Int32VT
, Op1
, Op0
);
206 SDValue Or
= DAG
->getNode(ISD::OR
, DL
, Int32VT
, Op0
, Op1
);
208 DAG
->getNode(ISD::OR
, DL
, Int32VT
, Op0
, Op3
, SDNodeFlags::Disjoint
);
209 SDValue SMax
= DAG
->getNode(ISD::SMAX
, DL
, Int32VT
, Op0
, Op1
);
210 SDValue SMin
= DAG
->getNode(ISD::SMIN
, DL
, Int32VT
, Op1
, Op0
);
211 SDValue UMax
= DAG
->getNode(ISD::UMAX
, DL
, Int32VT
, Op0
, Op1
);
212 SDValue UMin
= DAG
->getNode(ISD::UMIN
, DL
, Int32VT
, Op1
, Op0
);
213 SDValue Rotl
= DAG
->getNode(ISD::ROTL
, DL
, Int32VT
, Op0
, Op1
);
214 SDValue Rotr
= DAG
->getNode(ISD::ROTR
, DL
, Int32VT
, Op1
, Op0
);
216 SDValue ICMP_GT
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETGT
);
217 SDValue ICMP_GE
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETGE
);
218 SDValue ICMP_UGT
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETUGT
);
219 SDValue ICMP_UGE
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETUGE
);
220 SDValue ICMP_LT
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETLT
);
221 SDValue ICMP_LE
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETLE
);
222 SDValue ICMP_ULT
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETULT
);
223 SDValue ICMP_ULE
= DAG
->getSetCC(DL
, MVT::i1
, Op0
, Op1
, ISD::SETULE
);
224 SDValue SMaxLikeGT
= DAG
->getSelect(DL
, MVT::i32
, ICMP_GT
, Op0
, Op1
);
225 SDValue SMaxLikeGE
= DAG
->getSelect(DL
, MVT::i32
, ICMP_GE
, Op0
, Op1
);
226 SDValue UMaxLikeUGT
= DAG
->getSelect(DL
, MVT::i32
, ICMP_UGT
, Op0
, Op1
);
227 SDValue UMaxLikeUGE
= DAG
->getSelect(DL
, MVT::i32
, ICMP_UGE
, Op0
, Op1
);
228 SDValue SMinLikeLT
= DAG
->getSelect(DL
, MVT::i32
, ICMP_LT
, Op0
, Op1
);
229 SDValue SMinLikeLE
= DAG
->getSelect(DL
, MVT::i32
, ICMP_LE
, Op0
, Op1
);
230 SDValue UMinLikeULT
= DAG
->getSelect(DL
, MVT::i32
, ICMP_ULT
, Op0
, Op1
);
231 SDValue UMinLikeULE
= DAG
->getSelect(DL
, MVT::i32
, ICMP_ULE
, Op0
, Op1
);
233 SDValue SFAdd
= DAG
->getNode(ISD::STRICT_FADD
, DL
, {Float32VT
, MVT::Other
},
234 {DAG
->getEntryNode(), Op2
, Op2
});
237 DAG
->getNode(ISD::INSERT_VECTOR_ELT
, DL
, VInt32VT
, V1
, Op0
, Op4
);
239 using namespace SDPatternMatch
;
240 EXPECT_TRUE(sd_match(Sub
, m_BinOp(ISD::SUB
, m_Value(), m_Value())));
241 EXPECT_TRUE(sd_match(Sub
, m_Sub(m_Value(), m_Value())));
242 EXPECT_TRUE(sd_match(Add
, m_c_BinOp(ISD::ADD
, m_Value(), m_Value())));
243 EXPECT_TRUE(sd_match(Add
, m_Add(m_Value(), m_Value())));
244 EXPECT_TRUE(sd_match(Add
, m_AddLike(m_Value(), m_Value())));
245 EXPECT_TRUE(sd_match(
246 Mul
, m_Mul(m_OneUse(m_Opc(ISD::SUB
)), m_NUses
<2>(m_Specific(Add
)))));
248 sd_match(SFAdd
, m_ChainedBinOp(ISD::STRICT_FADD
, m_SpecificVT(Float32VT
),
249 m_SpecificVT(Float32VT
))));
251 EXPECT_TRUE(sd_match(And
, m_c_BinOp(ISD::AND
, m_Value(), m_Value())));
252 EXPECT_TRUE(sd_match(And
, m_And(m_Value(), m_Value())));
253 EXPECT_TRUE(sd_match(Xor
, m_c_BinOp(ISD::XOR
, m_Value(), m_Value())));
254 EXPECT_TRUE(sd_match(Xor
, m_Xor(m_Value(), m_Value())));
255 EXPECT_TRUE(sd_match(Or
, m_c_BinOp(ISD::OR
, m_Value(), m_Value())));
256 EXPECT_TRUE(sd_match(Or
, m_Or(m_Value(), m_Value())));
257 EXPECT_FALSE(sd_match(Or
, m_DisjointOr(m_Value(), m_Value())));
259 EXPECT_TRUE(sd_match(DisOr
, m_Or(m_Value(), m_Value())));
260 EXPECT_TRUE(sd_match(DisOr
, m_DisjointOr(m_Value(), m_Value())));
261 EXPECT_FALSE(sd_match(DisOr
, m_Add(m_Value(), m_Value())));
262 EXPECT_TRUE(sd_match(DisOr
, m_AddLike(m_Value(), m_Value())));
264 EXPECT_TRUE(sd_match(Rotl
, m_Rotl(m_Value(), m_Value())));
265 EXPECT_TRUE(sd_match(Rotr
, m_Rotr(m_Value(), m_Value())));
266 EXPECT_FALSE(sd_match(Rotl
, m_Rotr(m_Value(), m_Value())));
267 EXPECT_FALSE(sd_match(Rotr
, m_Rotl(m_Value(), m_Value())));
269 EXPECT_TRUE(sd_match(SMax
, m_c_BinOp(ISD::SMAX
, m_Value(), m_Value())));
270 EXPECT_TRUE(sd_match(SMax
, m_SMax(m_Value(), m_Value())));
271 EXPECT_TRUE(sd_match(SMax
, m_SMaxLike(m_Value(), m_Value())));
272 EXPECT_TRUE(sd_match(SMaxLikeGT
, m_SMaxLike(m_Value(), m_Value())));
273 EXPECT_TRUE(sd_match(SMaxLikeGE
, m_SMaxLike(m_Value(), m_Value())));
274 EXPECT_TRUE(sd_match(SMin
, m_c_BinOp(ISD::SMIN
, m_Value(), m_Value())));
275 EXPECT_TRUE(sd_match(SMin
, m_SMin(m_Value(), m_Value())));
276 EXPECT_TRUE(sd_match(SMin
, m_SMinLike(m_Value(), m_Value())));
277 EXPECT_TRUE(sd_match(SMinLikeLT
, m_SMinLike(m_Value(), m_Value())));
278 EXPECT_TRUE(sd_match(SMinLikeLE
, m_SMinLike(m_Value(), m_Value())));
279 EXPECT_TRUE(sd_match(UMax
, m_c_BinOp(ISD::UMAX
, m_Value(), m_Value())));
280 EXPECT_TRUE(sd_match(UMax
, m_UMax(m_Value(), m_Value())));
281 EXPECT_TRUE(sd_match(UMax
, m_UMaxLike(m_Value(), m_Value())));
282 EXPECT_TRUE(sd_match(UMaxLikeUGT
, m_UMaxLike(m_Value(), m_Value())));
283 EXPECT_TRUE(sd_match(UMaxLikeUGE
, m_UMaxLike(m_Value(), m_Value())));
284 EXPECT_TRUE(sd_match(UMin
, m_c_BinOp(ISD::UMIN
, m_Value(), m_Value())));
285 EXPECT_TRUE(sd_match(UMin
, m_UMin(m_Value(), m_Value())));
286 EXPECT_TRUE(sd_match(UMin
, m_UMinLike(m_Value(), m_Value())));
287 EXPECT_TRUE(sd_match(UMinLikeULT
, m_UMinLike(m_Value(), m_Value())));
288 EXPECT_TRUE(sd_match(UMinLikeULE
, m_UMinLike(m_Value(), m_Value())));
291 EXPECT_TRUE(sd_match(SFAdd
, m_ChainedBinOp(ISD::STRICT_FADD
, m_Value(BindVal
),
292 m_Deferred(BindVal
))));
293 EXPECT_FALSE(sd_match(SFAdd
, m_ChainedBinOp(ISD::STRICT_FADD
, m_OtherVT(),
294 m_SpecificVT(Float32VT
))));
297 sd_match(InsertELT
, m_InsertElt(m_Value(), m_Value(), m_Value())));
299 sd_match(InsertELT
, m_InsertElt(m_Value(), m_Value(), m_ConstInt())));
301 sd_match(InsertELT
, m_InsertElt(m_Value(), m_Value(), m_SpecificInt(1))));
304 TEST_F(SelectionDAGPatternMatchTest
, matchUnaryOp
) {
306 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
307 auto Int64VT
= EVT::getIntegerVT(Context
, 64);
308 auto FloatVT
= EVT::getFloatingPointVT(32);
310 SDValue Op0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int32VT
);
311 SDValue Op1
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int64VT
);
312 SDValue Op2
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, FloatVT
);
313 SDValue Op3
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 3, Int32VT
);
315 SDValue ZExt
= DAG
->getNode(ISD::ZERO_EXTEND
, DL
, Int64VT
, Op0
);
317 DAG
->getNode(ISD::ZERO_EXTEND
, DL
, Int64VT
, Op3
, SDNodeFlags::NonNeg
);
318 SDValue SExt
= DAG
->getNode(ISD::SIGN_EXTEND
, DL
, Int64VT
, Op0
);
319 SDValue Trunc
= DAG
->getNode(ISD::TRUNCATE
, DL
, Int32VT
, Op1
);
321 SDValue Sub
= DAG
->getNode(ISD::SUB
, DL
, Int32VT
, Trunc
, Op0
);
322 SDValue Neg
= DAG
->getNegative(Op0
, DL
, Int32VT
);
323 SDValue Not
= DAG
->getNOT(DL
, Op0
, Int32VT
);
325 SDValue VScale
= DAG
->getVScale(DL
, Int32VT
, APInt::getMaxValue(32));
327 SDValue FPToSI
= DAG
->getNode(ISD::FP_TO_SINT
, DL
, FloatVT
, Op2
);
328 SDValue FPToUI
= DAG
->getNode(ISD::FP_TO_UINT
, DL
, FloatVT
, Op2
);
330 SDValue Brev
= DAG
->getNode(ISD::BITREVERSE
, DL
, Int32VT
, Op0
);
331 SDValue Bswap
= DAG
->getNode(ISD::BSWAP
, DL
, Int32VT
, Op0
);
333 SDValue Ctpop
= DAG
->getNode(ISD::CTPOP
, DL
, Int32VT
, Op0
);
334 SDValue Ctlz
= DAG
->getNode(ISD::CTLZ
, DL
, Int32VT
, Op0
);
335 SDValue Cttz
= DAG
->getNode(ISD::CTTZ
, DL
, Int32VT
, Op0
);
337 using namespace SDPatternMatch
;
338 EXPECT_TRUE(sd_match(ZExt
, m_UnaryOp(ISD::ZERO_EXTEND
, m_Value())));
339 EXPECT_TRUE(sd_match(SExt
, m_SExt(m_Value())));
340 EXPECT_TRUE(sd_match(SExt
, m_SExtLike(m_Value())));
341 ASSERT_TRUE(ZExtNNeg
->getFlags().hasNonNeg());
342 EXPECT_FALSE(sd_match(ZExtNNeg
, m_SExt(m_Value())));
343 EXPECT_TRUE(sd_match(ZExtNNeg
, m_NNegZExt(m_Value())));
344 EXPECT_FALSE(sd_match(ZExt
, m_NNegZExt(m_Value())));
345 EXPECT_TRUE(sd_match(ZExtNNeg
, m_SExtLike(m_Value())));
346 EXPECT_FALSE(sd_match(ZExt
, m_SExtLike(m_Value())));
347 EXPECT_TRUE(sd_match(Trunc
, m_Trunc(m_Specific(Op1
))));
349 EXPECT_TRUE(sd_match(Neg
, m_Neg(m_Value())));
350 EXPECT_TRUE(sd_match(Not
, m_Not(m_Value())));
351 EXPECT_FALSE(sd_match(ZExt
, m_Neg(m_Value())));
352 EXPECT_FALSE(sd_match(Sub
, m_Neg(m_Value())));
353 EXPECT_FALSE(sd_match(Neg
, m_Not(m_Value())));
354 EXPECT_TRUE(sd_match(VScale
, m_VScale(m_Value())));
356 EXPECT_TRUE(sd_match(FPToUI
, m_FPToUI(m_Value())));
357 EXPECT_TRUE(sd_match(FPToSI
, m_FPToSI(m_Value())));
358 EXPECT_FALSE(sd_match(FPToUI
, m_FPToSI(m_Value())));
359 EXPECT_FALSE(sd_match(FPToSI
, m_FPToUI(m_Value())));
361 EXPECT_TRUE(sd_match(Brev
, m_BitReverse(m_Value())));
362 EXPECT_TRUE(sd_match(Bswap
, m_BSwap(m_Value())));
363 EXPECT_FALSE(sd_match(Brev
, m_BSwap(m_Value())));
364 EXPECT_FALSE(sd_match(Bswap
, m_BitReverse(m_Value())));
366 EXPECT_TRUE(sd_match(Ctpop
, m_Ctpop(m_Value())));
367 EXPECT_TRUE(sd_match(Ctlz
, m_Ctlz(m_Value())));
368 EXPECT_TRUE(sd_match(Cttz
, m_Cttz(m_Value())));
369 EXPECT_FALSE(sd_match(Ctpop
, m_Ctlz(m_Value())));
370 EXPECT_FALSE(sd_match(Ctlz
, m_Cttz(m_Value())));
371 EXPECT_FALSE(sd_match(Cttz
, m_Ctlz(m_Value())));
374 TEST_F(SelectionDAGPatternMatchTest
, matchConstants
) {
376 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
377 auto VInt32VT
= EVT::getVectorVT(Context
, Int32VT
, 4);
379 SDValue Arg0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int32VT
);
381 SDValue Const3
= DAG
->getConstant(3, DL
, Int32VT
);
382 SDValue Const87
= DAG
->getConstant(87, DL
, Int32VT
);
383 SDValue Splat
= DAG
->getSplat(VInt32VT
, DL
, Arg0
);
384 SDValue ConstSplat
= DAG
->getSplat(VInt32VT
, DL
, Const3
);
385 SDValue Zero
= DAG
->getConstant(0, DL
, Int32VT
);
386 SDValue One
= DAG
->getConstant(1, DL
, Int32VT
);
387 SDValue AllOnes
= DAG
->getConstant(APInt::getAllOnes(32), DL
, Int32VT
);
388 SDValue SetCC
= DAG
->getSetCC(DL
, Int32VT
, Arg0
, Const3
, ISD::SETULT
);
390 using namespace SDPatternMatch
;
391 EXPECT_TRUE(sd_match(Const87
, m_ConstInt()));
392 EXPECT_FALSE(sd_match(Arg0
, m_ConstInt()));
394 EXPECT_TRUE(sd_match(ConstSplat
, m_ConstInt(ConstVal
)));
395 EXPECT_EQ(ConstVal
, 3);
396 EXPECT_FALSE(sd_match(Splat
, m_ConstInt()));
398 EXPECT_TRUE(sd_match(Const87
, m_SpecificInt(87)));
399 EXPECT_TRUE(sd_match(Const3
, m_SpecificInt(ConstVal
)));
400 EXPECT_TRUE(sd_match(AllOnes
, m_AllOnes()));
402 EXPECT_TRUE(sd_match(Zero
, DAG
.get(), m_False()));
403 EXPECT_TRUE(sd_match(One
, DAG
.get(), m_True()));
404 EXPECT_FALSE(sd_match(AllOnes
, DAG
.get(), m_True()));
407 EXPECT_TRUE(sd_match(
408 SetCC
, m_Node(ISD::SETCC
, m_Value(), m_Value(), m_CondCode(CC
))));
409 EXPECT_EQ(CC
, ISD::SETULT
);
410 EXPECT_TRUE(sd_match(SetCC
, m_Node(ISD::SETCC
, m_Value(), m_Value(),
411 m_SpecificCondCode(ISD::SETULT
))));
414 TEST_F(SelectionDAGPatternMatchTest
, patternCombinators
) {
416 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
418 SDValue Op0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int32VT
);
419 SDValue Op1
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 2, Int32VT
);
421 SDValue Add
= DAG
->getNode(ISD::ADD
, DL
, Int32VT
, Op0
, Op1
);
422 SDValue Sub
= DAG
->getNode(ISD::SUB
, DL
, Int32VT
, Add
, Op0
);
424 using namespace SDPatternMatch
;
425 EXPECT_TRUE(sd_match(
426 Sub
, m_AnyOf(m_Opc(ISD::ADD
), m_Opc(ISD::SUB
), m_Opc(ISD::MUL
))));
427 EXPECT_TRUE(sd_match(Add
, m_AllOf(m_Opc(ISD::ADD
), m_OneUse())));
428 EXPECT_TRUE(sd_match(Add
, m_NoneOf(m_Opc(ISD::SUB
), m_Opc(ISD::MUL
))));
431 TEST_F(SelectionDAGPatternMatchTest
, optionalResizing
) {
433 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
434 auto Int64VT
= EVT::getIntegerVT(Context
, 64);
436 SDValue Op32
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int32VT
);
437 SDValue Op64
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int64VT
);
438 SDValue ZExt
= DAG
->getNode(ISD::ZERO_EXTEND
, DL
, Int64VT
, Op32
);
439 SDValue SExt
= DAG
->getNode(ISD::SIGN_EXTEND
, DL
, Int64VT
, Op32
);
440 SDValue AExt
= DAG
->getNode(ISD::ANY_EXTEND
, DL
, Int64VT
, Op32
);
441 SDValue Trunc
= DAG
->getNode(ISD::TRUNCATE
, DL
, Int32VT
, Op64
);
443 using namespace SDPatternMatch
;
445 EXPECT_TRUE(sd_match(Op32
, m_ZExtOrSelf(m_Value(A
))));
446 EXPECT_TRUE(A
== Op32
);
447 EXPECT_TRUE(sd_match(ZExt
, m_ZExtOrSelf(m_Value(A
))));
448 EXPECT_TRUE(A
== Op32
);
449 EXPECT_TRUE(sd_match(Op64
, m_SExtOrSelf(m_Value(A
))));
450 EXPECT_TRUE(A
== Op64
);
451 EXPECT_TRUE(sd_match(SExt
, m_SExtOrSelf(m_Value(A
))));
452 EXPECT_TRUE(A
== Op32
);
453 EXPECT_TRUE(sd_match(Op32
, m_AExtOrSelf(m_Value(A
))));
454 EXPECT_TRUE(A
== Op32
);
455 EXPECT_TRUE(sd_match(AExt
, m_AExtOrSelf(m_Value(A
))));
456 EXPECT_TRUE(A
== Op32
);
457 EXPECT_TRUE(sd_match(Op64
, m_TruncOrSelf(m_Value(A
))));
458 EXPECT_TRUE(A
== Op64
);
459 EXPECT_TRUE(sd_match(Trunc
, m_TruncOrSelf(m_Value(A
))));
460 EXPECT_TRUE(A
== Op64
);
463 TEST_F(SelectionDAGPatternMatchTest
, matchNode
) {
465 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
467 SDValue Op0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int32VT
);
468 SDValue Op1
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 2, Int32VT
);
470 SDValue Add
= DAG
->getNode(ISD::ADD
, DL
, Int32VT
, Op0
, Op1
);
472 using namespace SDPatternMatch
;
473 EXPECT_TRUE(sd_match(Add
, m_Node(ISD::ADD
, m_Value(), m_Value())));
474 EXPECT_FALSE(sd_match(Add
, m_Node(ISD::SUB
, m_Value(), m_Value())));
475 EXPECT_FALSE(sd_match(Add
, m_Node(ISD::ADD
, m_Value())));
477 sd_match(Add
, m_Node(ISD::ADD
, m_Value(), m_Value(), m_Value())));
478 EXPECT_FALSE(sd_match(Add
, m_Node(ISD::ADD
, m_ConstInt(), m_Value())));
482 struct VPMatchContext
: public SDPatternMatch::BasicMatchContext
{
483 using SDPatternMatch::BasicMatchContext::BasicMatchContext
;
485 bool match(SDValue OpVal
, unsigned Opc
) const {
486 if (!OpVal
->isVPOpcode())
487 return OpVal
->getOpcode() == Opc
;
489 auto BaseOpc
= ISD::getBaseOpcodeForVP(OpVal
->getOpcode(), false);
490 return BaseOpc
.has_value() && *BaseOpc
== Opc
;
493 unsigned getNumOperands(SDValue N
) const {
494 return N
->isVPOpcode() ? N
->getNumOperands() - 2 : N
->getNumOperands();
497 } // anonymous namespace
498 TEST_F(SelectionDAGPatternMatchTest
, matchContext
) {
500 auto BoolVT
= EVT::getIntegerVT(Context
, 1);
501 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
502 auto VInt32VT
= EVT::getVectorVT(Context
, Int32VT
, 4);
503 auto MaskVT
= EVT::getVectorVT(Context
, BoolVT
, 4);
505 SDValue Scalar0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int32VT
);
506 SDValue Vector0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 2, VInt32VT
);
507 SDValue Mask0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 3, MaskVT
);
509 SDValue VPAdd
= DAG
->getNode(ISD::VP_ADD
, DL
, VInt32VT
,
510 {Vector0
, Vector0
, Mask0
, Scalar0
});
511 SDValue VPReduceAdd
= DAG
->getNode(ISD::VP_REDUCE_ADD
, DL
, Int32VT
,
512 {Scalar0
, VPAdd
, Mask0
, Scalar0
});
513 SDValue Add
= DAG
->getNode(ISD::ADD
, DL
, VInt32VT
, {Vector0
, Vector0
});
515 using namespace SDPatternMatch
;
516 VPMatchContext
VPCtx(DAG
.get());
517 EXPECT_TRUE(sd_context_match(VPAdd
, VPCtx
, m_Opc(ISD::ADD
)));
519 sd_context_match(VPAdd
, VPCtx
, m_Node(ISD::ADD
, m_Value(), m_Value())));
520 // VPMatchContext can't match pattern using explicit VP Opcode
521 EXPECT_FALSE(sd_context_match(VPAdd
, VPCtx
,
522 m_Node(ISD::VP_ADD
, m_Value(), m_Value())));
523 EXPECT_FALSE(sd_context_match(
525 m_Node(ISD::VP_ADD
, m_Value(), m_Value(), m_Value(), m_Value())));
526 // Check Binary Op Pattern
527 EXPECT_TRUE(sd_context_match(VPAdd
, VPCtx
, m_Add(m_Value(), m_Value())));
528 // VP_REDUCE_ADD doesn't have a based opcode, so we use a normal
529 // sd_match before switching to VPMatchContext when checking VPAdd.
530 EXPECT_TRUE(sd_match(VPReduceAdd
, m_Node(ISD::VP_REDUCE_ADD
, m_Value(),
531 m_Context(VPCtx
, m_Opc(ISD::ADD
)),
532 m_Value(), m_Value())));
533 // non-vector predicated should match too
534 EXPECT_TRUE(sd_context_match(Add
, VPCtx
, m_Opc(ISD::ADD
)));
536 sd_context_match(Add
, VPCtx
, m_Node(ISD::ADD
, m_Value(), m_Value())));
537 EXPECT_FALSE(sd_context_match(
539 m_Node(ISD::ADD
, m_Value(), m_Value(), m_Value(), m_Value())));
540 EXPECT_TRUE(sd_context_match(Add
, VPCtx
, m_Add(m_Value(), m_Value())));
543 TEST_F(SelectionDAGPatternMatchTest
, matchVPWithBasicContext
) {
545 auto BoolVT
= EVT::getIntegerVT(Context
, 1);
546 auto Int32VT
= EVT::getIntegerVT(Context
, 32);
547 auto VInt32VT
= EVT::getVectorVT(Context
, Int32VT
, 4);
548 auto MaskVT
= EVT::getVectorVT(Context
, BoolVT
, 4);
550 SDValue Vector0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, VInt32VT
);
551 SDValue Mask
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 2, MaskVT
);
552 SDValue EL
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 3, Int32VT
);
555 DAG
->getNode(ISD::VP_ADD
, DL
, VInt32VT
, Vector0
, Vector0
, Mask
, EL
);
557 using namespace SDPatternMatch
;
558 EXPECT_FALSE(sd_match(VPAdd
, m_Node(ISD::VP_ADD
, m_Value(), m_Value())));
559 EXPECT_TRUE(sd_match(
560 VPAdd
, m_Node(ISD::VP_ADD
, m_Value(), m_Value(), m_Value(), m_Value())));
563 TEST_F(SelectionDAGPatternMatchTest
, matchAdvancedProperties
) {
565 auto Int16VT
= EVT::getIntegerVT(Context
, 16);
566 auto Int64VT
= EVT::getIntegerVT(Context
, 64);
568 SDValue Op0
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 1, Int64VT
);
569 SDValue Op1
= DAG
->getCopyFromReg(DAG
->getEntryNode(), DL
, 2, Int16VT
);
571 SDValue Add
= DAG
->getNode(ISD::ADD
, DL
, Int64VT
, Op0
, Op0
);
573 using namespace SDPatternMatch
;
574 EXPECT_TRUE(sd_match(Op0
, DAG
.get(), m_LegalType(m_Value())));
575 EXPECT_FALSE(sd_match(Op1
, DAG
.get(), m_LegalType(m_Value())));
576 EXPECT_TRUE(sd_match(Add
, DAG
.get(),
577 m_LegalOp(m_IntegerVT(m_Add(m_Value(), m_Value())))));