xref: /llvm-project/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp (revision cf9d1c1486ef53213b434700a4117d71a2cb67e3)
1 //===---- llvm/unittest/CodeGen/SelectionDAGPatternMatchTest.cpp  ---------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
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"
20 
21 using namespace llvm;
22 
23 class SelectionDAGPatternMatchTest : public testing::Test {
24 protected:
25   static void SetUpTestCase() {
26     InitializeAllTargets();
27     InitializeAllTargetMCs();
28   }
29 
30   void SetUp() override {
31     StringRef Assembly = "@g = global i32 0\n"
32                          "@g_alias = alias i32, i32* @g\n"
33                          "define i32 @f() {\n"
34                          "  %1 = load i32, i32* @g\n"
35                          "  ret i32 %1\n"
36                          "}";
37 
38     Triple TargetTriple("riscv64--");
39     std::string Error;
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.
44     if (!T)
45       GTEST_SKIP();
46 
47     TargetOptions Options;
48     TM = std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
49         T->createTargetMachine("riscv64", "", "+m,+f,+d,+v", Options,
50                                std::nullopt, std::nullopt,
51                                CodeGenOptLevel::Aggressive)));
52     if (!TM)
53       GTEST_SKIP();
54 
55     SMDiagnostic SMError;
56     M = parseAssemblyString(Assembly, SMError, Context);
57     if (!M)
58       report_fatal_error(SMError.getMessage());
59     M->setDataLayout(TM->createDataLayout());
60 
61     F = M->getFunction("f");
62     if (!F)
63       report_fatal_error("F?");
64     G = M->getGlobalVariable("g");
65     if (!G)
66       report_fatal_error("G?");
67     AliasedG = M->getNamedAlias("g_alias");
68     if (!AliasedG)
69       report_fatal_error("AliasedG?");
70 
71     MachineModuleInfo MMI(TM.get());
72 
73     MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F),
74                                            MMI.getContext(), 0);
75 
76     DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOptLevel::None);
77     if (!DAG)
78       report_fatal_error("DAG?");
79     OptimizationRemarkEmitter ORE(F);
80     DAG->init(*MF, ORE, nullptr, nullptr, nullptr, nullptr, nullptr, MMI,
81               nullptr);
82   }
83 
84   TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) {
85     return DAG->getTargetLoweringInfo().getTypeAction(Context, VT);
86   }
87 
88   EVT getTypeToTransformTo(EVT VT) {
89     return DAG->getTargetLoweringInfo().getTypeToTransformTo(Context, VT);
90   }
91 
92   LLVMContext Context;
93   std::unique_ptr<LLVMTargetMachine> TM;
94   std::unique_ptr<Module> M;
95   Function *F;
96   GlobalVariable *G;
97   GlobalAlias *AliasedG;
98   std::unique_ptr<MachineFunction> MF;
99   std::unique_ptr<SelectionDAG> DAG;
100 };
101 
102 TEST_F(SelectionDAGPatternMatchTest, matchValueType) {
103   SDLoc DL;
104   auto Int32VT = EVT::getIntegerVT(Context, 32);
105   auto Float32VT = EVT::getFloatingPointVT(32);
106   auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4);
107 
108   SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
109   SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Float32VT);
110   SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, VInt32VT);
111 
112   using namespace SDPatternMatch;
113   EXPECT_TRUE(sd_match(Op0, m_SpecificVT(Int32VT)));
114   EVT BindVT;
115   EXPECT_TRUE(sd_match(Op1, m_VT(BindVT)));
116   EXPECT_EQ(BindVT, Float32VT);
117   EXPECT_TRUE(sd_match(Op0, m_IntegerVT()));
118   EXPECT_TRUE(sd_match(Op1, m_FloatingPointVT()));
119   EXPECT_TRUE(sd_match(Op2, m_VectorVT()));
120   EXPECT_FALSE(sd_match(Op2, m_ScalableVectorVT()));
121 }
122 
123 TEST_F(SelectionDAGPatternMatchTest, matchTernaryOp) {
124   SDLoc DL;
125   auto Int32VT = EVT::getIntegerVT(Context, 32);
126 
127   SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
128   SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT);
129 
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);
133 
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);
139 
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);
144 
145   using namespace SDPatternMatch;
146   ISD::CondCode CC;
147   EXPECT_TRUE(sd_match(ICMP_UGT, m_SetCC(m_Value(), m_Value(),
148                                          m_SpecificCondCode(ISD::SETUGT))));
149   EXPECT_TRUE(
150       sd_match(ICMP_UGT, m_SetCC(m_Value(), m_Value(), m_CondCode(CC))));
151   EXPECT_TRUE(CC == ISD::SETUGT);
152   EXPECT_FALSE(sd_match(
153       ICMP_UGT, m_SetCC(m_Value(), m_Value(), m_SpecificCondCode(ISD::SETLE))));
154 
155   EXPECT_TRUE(sd_match(ICMP_EQ01, m_SetCC(m_Specific(Op0), m_Specific(Op1),
156                                           m_SpecificCondCode(ISD::SETEQ))));
157   EXPECT_TRUE(sd_match(ICMP_EQ10, m_SetCC(m_Specific(Op1), m_Specific(Op0),
158                                           m_SpecificCondCode(ISD::SETEQ))));
159   EXPECT_FALSE(sd_match(ICMP_EQ01, m_SetCC(m_Specific(Op1), m_Specific(Op0),
160                                            m_SpecificCondCode(ISD::SETEQ))));
161   EXPECT_FALSE(sd_match(ICMP_EQ10, m_SetCC(m_Specific(Op0), m_Specific(Op1),
162                                            m_SpecificCondCode(ISD::SETEQ))));
163   EXPECT_TRUE(sd_match(ICMP_EQ01, m_c_SetCC(m_Specific(Op1), m_Specific(Op0),
164                                             m_SpecificCondCode(ISD::SETEQ))));
165   EXPECT_TRUE(sd_match(ICMP_EQ10, m_c_SetCC(m_Specific(Op0), m_Specific(Op1),
166                                             m_SpecificCondCode(ISD::SETEQ))));
167 
168   EXPECT_TRUE(sd_match(
169       Select, m_Select(m_Specific(Cond), m_Specific(T), m_Specific(F))));
170   EXPECT_FALSE(sd_match(
171       Select, m_Select(m_Specific(Cond), m_Specific(F), m_Specific(T))));
172   EXPECT_FALSE(sd_match(ICMP_EQ01, m_Select(m_Specific(Op0), m_Specific(Op1),
173                                             m_SpecificCondCode(ISD::SETEQ))));
174   EXPECT_TRUE(sd_match(
175       VSelect, m_VSelect(m_Specific(Cond), m_Specific(V1), m_Specific(V2))));
176   EXPECT_FALSE(sd_match(
177       Select, m_VSelect(m_Specific(Cond), m_Specific(V1), m_Specific(V2))));
178 }
179 
180 TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
181   SDLoc DL;
182   auto Int32VT = EVT::getIntegerVT(Context, 32);
183   auto Float32VT = EVT::getFloatingPointVT(32);
184 
185   SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
186   SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT);
187   SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Float32VT);
188   SDValue Op3 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 8, Int32VT);
189 
190   SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1);
191   SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0);
192   SDValue Mul = DAG->getNode(ISD::MUL, DL, Int32VT, Add, Sub);
193   SDValue And = DAG->getNode(ISD::AND, DL, Int32VT, Op0, Op1);
194   SDValue Xor = DAG->getNode(ISD::XOR, DL, Int32VT, Op1, Op0);
195   SDValue Or  = DAG->getNode(ISD::OR, DL, Int32VT, Op0, Op1);
196   SDValue DisOr =
197       DAG->getNode(ISD::OR, DL, Int32VT, Op0, Op3, SDNodeFlags::Disjoint);
198   SDValue SMax = DAG->getNode(ISD::SMAX, DL, Int32VT, Op0, Op1);
199   SDValue SMin = DAG->getNode(ISD::SMIN, DL, Int32VT, Op1, Op0);
200   SDValue UMax = DAG->getNode(ISD::UMAX, DL, Int32VT, Op0, Op1);
201   SDValue UMin = DAG->getNode(ISD::UMIN, DL, Int32VT, Op1, Op0);
202   SDValue Rotl = DAG->getNode(ISD::ROTL, DL, Int32VT, Op0, Op1);
203   SDValue Rotr = DAG->getNode(ISD::ROTR, DL, Int32VT, Op1, Op0);
204 
205   SDValue ICMP_GT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETGT);
206   SDValue ICMP_GE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETGE);
207   SDValue ICMP_UGT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETUGT);
208   SDValue ICMP_UGE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETUGE);
209   SDValue ICMP_LT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETLT);
210   SDValue ICMP_LE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETLE);
211   SDValue ICMP_ULT = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETULT);
212   SDValue ICMP_ULE = DAG->getSetCC(DL, MVT::i1, Op0, Op1, ISD::SETULE);
213   SDValue SMaxLikeGT = DAG->getSelect(DL, MVT::i32, ICMP_GT, Op0, Op1);
214   SDValue SMaxLikeGE = DAG->getSelect(DL, MVT::i32, ICMP_GE, Op0, Op1);
215   SDValue UMaxLikeUGT = DAG->getSelect(DL, MVT::i32, ICMP_UGT, Op0, Op1);
216   SDValue UMaxLikeUGE = DAG->getSelect(DL, MVT::i32, ICMP_UGE, Op0, Op1);
217   SDValue SMinLikeLT = DAG->getSelect(DL, MVT::i32, ICMP_LT, Op0, Op1);
218   SDValue SMinLikeLE = DAG->getSelect(DL, MVT::i32, ICMP_LE, Op0, Op1);
219   SDValue UMinLikeULT = DAG->getSelect(DL, MVT::i32, ICMP_ULT, Op0, Op1);
220   SDValue UMinLikeULE = DAG->getSelect(DL, MVT::i32, ICMP_ULE, Op0, Op1);
221 
222   SDValue SFAdd = DAG->getNode(ISD::STRICT_FADD, DL, {Float32VT, MVT::Other},
223                                {DAG->getEntryNode(), Op2, Op2});
224 
225   using namespace SDPatternMatch;
226   EXPECT_TRUE(sd_match(Sub, m_BinOp(ISD::SUB, m_Value(), m_Value())));
227   EXPECT_TRUE(sd_match(Sub, m_Sub(m_Value(), m_Value())));
228   EXPECT_TRUE(sd_match(Add, m_c_BinOp(ISD::ADD, m_Value(), m_Value())));
229   EXPECT_TRUE(sd_match(Add, m_Add(m_Value(), m_Value())));
230   EXPECT_TRUE(sd_match(Add, m_AddLike(m_Value(), m_Value())));
231   EXPECT_TRUE(sd_match(
232       Mul, m_Mul(m_OneUse(m_Opc(ISD::SUB)), m_NUses<2>(m_Specific(Add)))));
233   EXPECT_TRUE(
234       sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_SpecificVT(Float32VT),
235                                      m_SpecificVT(Float32VT))));
236 
237   EXPECT_TRUE(sd_match(And, m_c_BinOp(ISD::AND, m_Value(), m_Value())));
238   EXPECT_TRUE(sd_match(And, m_And(m_Value(), m_Value())));
239   EXPECT_TRUE(sd_match(Xor, m_c_BinOp(ISD::XOR, m_Value(), m_Value())));
240   EXPECT_TRUE(sd_match(Xor, m_Xor(m_Value(), m_Value())));
241   EXPECT_TRUE(sd_match(Or, m_c_BinOp(ISD::OR, m_Value(), m_Value())));
242   EXPECT_TRUE(sd_match(Or, m_Or(m_Value(), m_Value())));
243   EXPECT_FALSE(sd_match(Or, m_DisjointOr(m_Value(), m_Value())));
244 
245   EXPECT_TRUE(sd_match(DisOr, m_Or(m_Value(), m_Value())));
246   EXPECT_TRUE(sd_match(DisOr, m_DisjointOr(m_Value(), m_Value())));
247   EXPECT_FALSE(sd_match(DisOr, m_Add(m_Value(), m_Value())));
248   EXPECT_TRUE(sd_match(DisOr, m_AddLike(m_Value(), m_Value())));
249 
250   EXPECT_TRUE(sd_match(Rotl, m_Rotl(m_Value(), m_Value())));
251   EXPECT_TRUE(sd_match(Rotr, m_Rotr(m_Value(), m_Value())));
252   EXPECT_FALSE(sd_match(Rotl, m_Rotr(m_Value(), m_Value())));
253   EXPECT_FALSE(sd_match(Rotr, m_Rotl(m_Value(), m_Value())));
254 
255   EXPECT_TRUE(sd_match(SMax, m_c_BinOp(ISD::SMAX, m_Value(), m_Value())));
256   EXPECT_TRUE(sd_match(SMax, m_SMax(m_Value(), m_Value())));
257   EXPECT_TRUE(sd_match(SMax, m_SMaxLike(m_Value(), m_Value())));
258   EXPECT_TRUE(sd_match(SMaxLikeGT, m_SMaxLike(m_Value(), m_Value())));
259   EXPECT_TRUE(sd_match(SMaxLikeGE, m_SMaxLike(m_Value(), m_Value())));
260   EXPECT_TRUE(sd_match(SMin, m_c_BinOp(ISD::SMIN, m_Value(), m_Value())));
261   EXPECT_TRUE(sd_match(SMin, m_SMin(m_Value(), m_Value())));
262   EXPECT_TRUE(sd_match(SMin, m_SMinLike(m_Value(), m_Value())));
263   EXPECT_TRUE(sd_match(SMinLikeLT, m_SMinLike(m_Value(), m_Value())));
264   EXPECT_TRUE(sd_match(SMinLikeLE, m_SMinLike(m_Value(), m_Value())));
265   EXPECT_TRUE(sd_match(UMax, m_c_BinOp(ISD::UMAX, m_Value(), m_Value())));
266   EXPECT_TRUE(sd_match(UMax, m_UMax(m_Value(), m_Value())));
267   EXPECT_TRUE(sd_match(UMax, m_UMaxLike(m_Value(), m_Value())));
268   EXPECT_TRUE(sd_match(UMaxLikeUGT, m_UMaxLike(m_Value(), m_Value())));
269   EXPECT_TRUE(sd_match(UMaxLikeUGE, m_UMaxLike(m_Value(), m_Value())));
270   EXPECT_TRUE(sd_match(UMin, m_c_BinOp(ISD::UMIN, m_Value(), m_Value())));
271   EXPECT_TRUE(sd_match(UMin, m_UMin(m_Value(), m_Value())));
272   EXPECT_TRUE(sd_match(UMin, m_UMinLike(m_Value(), m_Value())));
273   EXPECT_TRUE(sd_match(UMinLikeULT, m_UMinLike(m_Value(), m_Value())));
274   EXPECT_TRUE(sd_match(UMinLikeULE, m_UMinLike(m_Value(), m_Value())));
275 
276   SDValue BindVal;
277   EXPECT_TRUE(sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_Value(BindVal),
278                                              m_Deferred(BindVal))));
279   EXPECT_FALSE(sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_OtherVT(),
280                                               m_SpecificVT(Float32VT))));
281 }
282 
283 TEST_F(SelectionDAGPatternMatchTest, matchUnaryOp) {
284   SDLoc DL;
285   auto Int32VT = EVT::getIntegerVT(Context, 32);
286   auto Int64VT = EVT::getIntegerVT(Context, 64);
287   auto FloatVT = EVT::getFloatingPointVT(32);
288 
289   SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
290   SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT);
291   SDValue Op2 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, FloatVT);
292   SDValue Op3 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Int32VT);
293 
294   SDValue ZExt = DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op0);
295   SDValue ZExtNNeg =
296       DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op3, SDNodeFlags::NonNeg);
297   SDValue SExt = DAG->getNode(ISD::SIGN_EXTEND, DL, Int64VT, Op0);
298   SDValue Trunc = DAG->getNode(ISD::TRUNCATE, DL, Int32VT, Op1);
299 
300   SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Trunc, Op0);
301   SDValue Neg = DAG->getNegative(Op0, DL, Int32VT);
302   SDValue Not = DAG->getNOT(DL, Op0, Int32VT);
303 
304   SDValue VScale = DAG->getVScale(DL, Int32VT, APInt::getMaxValue(32));
305 
306   SDValue FPToSI = DAG->getNode(ISD::FP_TO_SINT, DL, FloatVT, Op2);
307   SDValue FPToUI = DAG->getNode(ISD::FP_TO_UINT, DL, FloatVT, Op2);
308 
309   SDValue Brev = DAG->getNode(ISD::BITREVERSE, DL, Int32VT, Op0);
310   SDValue Bswap = DAG->getNode(ISD::BSWAP, DL, Int32VT, Op0);
311 
312   SDValue Ctpop = DAG->getNode(ISD::CTPOP, DL, Int32VT, Op0);
313   SDValue Ctlz = DAG->getNode(ISD::CTLZ, DL, Int32VT, Op0);
314   SDValue Cttz = DAG->getNode(ISD::CTTZ, DL, Int32VT, Op0);
315 
316   using namespace SDPatternMatch;
317   EXPECT_TRUE(sd_match(ZExt, m_UnaryOp(ISD::ZERO_EXTEND, m_Value())));
318   EXPECT_TRUE(sd_match(SExt, m_SExt(m_Value())));
319   EXPECT_TRUE(sd_match(SExt, m_SExtLike(m_Value())));
320   ASSERT_TRUE(ZExtNNeg->getFlags().hasNonNeg());
321   EXPECT_FALSE(sd_match(ZExtNNeg, m_SExt(m_Value())));
322   EXPECT_TRUE(sd_match(ZExtNNeg, m_NNegZExt(m_Value())));
323   EXPECT_FALSE(sd_match(ZExt, m_NNegZExt(m_Value())));
324   EXPECT_TRUE(sd_match(ZExtNNeg, m_SExtLike(m_Value())));
325   EXPECT_FALSE(sd_match(ZExt, m_SExtLike(m_Value())));
326   EXPECT_TRUE(sd_match(Trunc, m_Trunc(m_Specific(Op1))));
327 
328   EXPECT_TRUE(sd_match(Neg, m_Neg(m_Value())));
329   EXPECT_TRUE(sd_match(Not, m_Not(m_Value())));
330   EXPECT_FALSE(sd_match(ZExt, m_Neg(m_Value())));
331   EXPECT_FALSE(sd_match(Sub, m_Neg(m_Value())));
332   EXPECT_FALSE(sd_match(Neg, m_Not(m_Value())));
333   EXPECT_TRUE(sd_match(VScale, m_VScale(m_Value())));
334 
335   EXPECT_TRUE(sd_match(FPToUI, m_FPToUI(m_Value())));
336   EXPECT_TRUE(sd_match(FPToSI, m_FPToSI(m_Value())));
337   EXPECT_FALSE(sd_match(FPToUI, m_FPToSI(m_Value())));
338   EXPECT_FALSE(sd_match(FPToSI, m_FPToUI(m_Value())));
339 
340   EXPECT_TRUE(sd_match(Brev, m_BitReverse(m_Value())));
341   EXPECT_TRUE(sd_match(Bswap, m_BSwap(m_Value())));
342   EXPECT_FALSE(sd_match(Brev, m_BSwap(m_Value())));
343   EXPECT_FALSE(sd_match(Bswap, m_BitReverse(m_Value())));
344 
345   EXPECT_TRUE(sd_match(Ctpop, m_Ctpop(m_Value())));
346   EXPECT_TRUE(sd_match(Ctlz, m_Ctlz(m_Value())));
347   EXPECT_TRUE(sd_match(Cttz, m_Cttz(m_Value())));
348   EXPECT_FALSE(sd_match(Ctpop, m_Ctlz(m_Value())));
349   EXPECT_FALSE(sd_match(Ctlz, m_Cttz(m_Value())));
350   EXPECT_FALSE(sd_match(Cttz, m_Ctlz(m_Value())));
351 }
352 
353 TEST_F(SelectionDAGPatternMatchTest, matchConstants) {
354   SDLoc DL;
355   auto Int32VT = EVT::getIntegerVT(Context, 32);
356   auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4);
357 
358   SDValue Arg0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
359 
360   SDValue Const3 = DAG->getConstant(3, DL, Int32VT);
361   SDValue Const87 = DAG->getConstant(87, DL, Int32VT);
362   SDValue Splat = DAG->getSplat(VInt32VT, DL, Arg0);
363   SDValue ConstSplat = DAG->getSplat(VInt32VT, DL, Const3);
364   SDValue Zero = DAG->getConstant(0, DL, Int32VT);
365   SDValue One = DAG->getConstant(1, DL, Int32VT);
366   SDValue AllOnes = DAG->getConstant(APInt::getAllOnes(32), DL, Int32VT);
367   SDValue SetCC = DAG->getSetCC(DL, Int32VT, Arg0, Const3, ISD::SETULT);
368 
369   using namespace SDPatternMatch;
370   EXPECT_TRUE(sd_match(Const87, m_ConstInt()));
371   EXPECT_FALSE(sd_match(Arg0, m_ConstInt()));
372   APInt ConstVal;
373   EXPECT_TRUE(sd_match(ConstSplat, m_ConstInt(ConstVal)));
374   EXPECT_EQ(ConstVal, 3);
375   EXPECT_FALSE(sd_match(Splat, m_ConstInt()));
376 
377   EXPECT_TRUE(sd_match(Const87, m_SpecificInt(87)));
378   EXPECT_TRUE(sd_match(Const3, m_SpecificInt(ConstVal)));
379   EXPECT_TRUE(sd_match(AllOnes, m_AllOnes()));
380 
381   EXPECT_TRUE(sd_match(Zero, DAG.get(), m_False()));
382   EXPECT_TRUE(sd_match(One, DAG.get(), m_True()));
383   EXPECT_FALSE(sd_match(AllOnes, DAG.get(), m_True()));
384 
385   ISD::CondCode CC;
386   EXPECT_TRUE(sd_match(
387       SetCC, m_Node(ISD::SETCC, m_Value(), m_Value(), m_CondCode(CC))));
388   EXPECT_EQ(CC, ISD::SETULT);
389   EXPECT_TRUE(sd_match(SetCC, m_Node(ISD::SETCC, m_Value(), m_Value(),
390                                      m_SpecificCondCode(ISD::SETULT))));
391 }
392 
393 TEST_F(SelectionDAGPatternMatchTest, patternCombinators) {
394   SDLoc DL;
395   auto Int32VT = EVT::getIntegerVT(Context, 32);
396 
397   SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
398   SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT);
399 
400   SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1);
401   SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0);
402 
403   using namespace SDPatternMatch;
404   EXPECT_TRUE(sd_match(
405       Sub, m_AnyOf(m_Opc(ISD::ADD), m_Opc(ISD::SUB), m_Opc(ISD::MUL))));
406   EXPECT_TRUE(sd_match(Add, m_AllOf(m_Opc(ISD::ADD), m_OneUse())));
407   EXPECT_TRUE(sd_match(Add, m_NoneOf(m_Opc(ISD::SUB), m_Opc(ISD::MUL))));
408 }
409 
410 TEST_F(SelectionDAGPatternMatchTest, optionalResizing) {
411   SDLoc DL;
412   auto Int32VT = EVT::getIntegerVT(Context, 32);
413   auto Int64VT = EVT::getIntegerVT(Context, 64);
414 
415   SDValue Op32 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
416   SDValue Op64 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT);
417   SDValue ZExt = DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op32);
418   SDValue SExt = DAG->getNode(ISD::SIGN_EXTEND, DL, Int64VT, Op32);
419   SDValue AExt = DAG->getNode(ISD::ANY_EXTEND, DL, Int64VT, Op32);
420   SDValue Trunc = DAG->getNode(ISD::TRUNCATE, DL, Int32VT, Op64);
421 
422   using namespace SDPatternMatch;
423   SDValue A;
424   EXPECT_TRUE(sd_match(Op32, m_ZExtOrSelf(m_Value(A))));
425   EXPECT_TRUE(A == Op32);
426   EXPECT_TRUE(sd_match(ZExt, m_ZExtOrSelf(m_Value(A))));
427   EXPECT_TRUE(A == Op32);
428   EXPECT_TRUE(sd_match(Op64, m_SExtOrSelf(m_Value(A))));
429   EXPECT_TRUE(A == Op64);
430   EXPECT_TRUE(sd_match(SExt, m_SExtOrSelf(m_Value(A))));
431   EXPECT_TRUE(A == Op32);
432   EXPECT_TRUE(sd_match(Op32, m_AExtOrSelf(m_Value(A))));
433   EXPECT_TRUE(A == Op32);
434   EXPECT_TRUE(sd_match(AExt, m_AExtOrSelf(m_Value(A))));
435   EXPECT_TRUE(A == Op32);
436   EXPECT_TRUE(sd_match(Op64, m_TruncOrSelf(m_Value(A))));
437   EXPECT_TRUE(A == Op64);
438   EXPECT_TRUE(sd_match(Trunc, m_TruncOrSelf(m_Value(A))));
439   EXPECT_TRUE(A == Op64);
440 }
441 
442 TEST_F(SelectionDAGPatternMatchTest, matchNode) {
443   SDLoc DL;
444   auto Int32VT = EVT::getIntegerVT(Context, 32);
445 
446   SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
447   SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT);
448 
449   SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1);
450 
451   using namespace SDPatternMatch;
452   EXPECT_TRUE(sd_match(Add, m_Node(ISD::ADD, m_Value(), m_Value())));
453   EXPECT_FALSE(sd_match(Add, m_Node(ISD::SUB, m_Value(), m_Value())));
454   EXPECT_FALSE(sd_match(Add, m_Node(ISD::ADD, m_Value())));
455   EXPECT_FALSE(
456       sd_match(Add, m_Node(ISD::ADD, m_Value(), m_Value(), m_Value())));
457   EXPECT_FALSE(sd_match(Add, m_Node(ISD::ADD, m_ConstInt(), m_Value())));
458 }
459 
460 namespace {
461 struct VPMatchContext : public SDPatternMatch::BasicMatchContext {
462   using SDPatternMatch::BasicMatchContext::BasicMatchContext;
463 
464   bool match(SDValue OpVal, unsigned Opc) const {
465     if (!OpVal->isVPOpcode())
466       return OpVal->getOpcode() == Opc;
467 
468     auto BaseOpc = ISD::getBaseOpcodeForVP(OpVal->getOpcode(), false);
469     return BaseOpc.has_value() && *BaseOpc == Opc;
470   }
471 
472   unsigned getNumOperands(SDValue N) const {
473     return N->isVPOpcode() ? N->getNumOperands() - 2 : N->getNumOperands();
474   }
475 };
476 } // anonymous namespace
477 TEST_F(SelectionDAGPatternMatchTest, matchContext) {
478   SDLoc DL;
479   auto BoolVT = EVT::getIntegerVT(Context, 1);
480   auto Int32VT = EVT::getIntegerVT(Context, 32);
481   auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4);
482   auto MaskVT = EVT::getVectorVT(Context, BoolVT, 4);
483 
484   SDValue Scalar0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT);
485   SDValue Vector0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, VInt32VT);
486   SDValue Mask0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, MaskVT);
487 
488   SDValue VPAdd = DAG->getNode(ISD::VP_ADD, DL, VInt32VT,
489                                {Vector0, Vector0, Mask0, Scalar0});
490   SDValue VPReduceAdd = DAG->getNode(ISD::VP_REDUCE_ADD, DL, Int32VT,
491                                      {Scalar0, VPAdd, Mask0, Scalar0});
492   SDValue Add = DAG->getNode(ISD::ADD, DL, VInt32VT, {Vector0, Vector0});
493 
494   using namespace SDPatternMatch;
495   VPMatchContext VPCtx(DAG.get());
496   EXPECT_TRUE(sd_context_match(VPAdd, VPCtx, m_Opc(ISD::ADD)));
497   EXPECT_TRUE(
498       sd_context_match(VPAdd, VPCtx, m_Node(ISD::ADD, m_Value(), m_Value())));
499   // VPMatchContext can't match pattern using explicit VP Opcode
500   EXPECT_FALSE(sd_context_match(VPAdd, VPCtx,
501                                 m_Node(ISD::VP_ADD, m_Value(), m_Value())));
502   EXPECT_FALSE(sd_context_match(
503       VPAdd, VPCtx,
504       m_Node(ISD::VP_ADD, m_Value(), m_Value(), m_Value(), m_Value())));
505   // Check Binary Op Pattern
506   EXPECT_TRUE(sd_context_match(VPAdd, VPCtx, m_Add(m_Value(), m_Value())));
507   // VP_REDUCE_ADD doesn't have a based opcode, so we use a normal
508   // sd_match before switching to VPMatchContext when checking VPAdd.
509   EXPECT_TRUE(sd_match(VPReduceAdd, m_Node(ISD::VP_REDUCE_ADD, m_Value(),
510                                            m_Context(VPCtx, m_Opc(ISD::ADD)),
511                                            m_Value(), m_Value())));
512   // non-vector predicated should match too
513   EXPECT_TRUE(sd_context_match(Add, VPCtx, m_Opc(ISD::ADD)));
514   EXPECT_TRUE(
515       sd_context_match(Add, VPCtx, m_Node(ISD::ADD, m_Value(), m_Value())));
516   EXPECT_FALSE(sd_context_match(
517       Add, VPCtx,
518       m_Node(ISD::ADD, m_Value(), m_Value(), m_Value(), m_Value())));
519   EXPECT_TRUE(sd_context_match(Add, VPCtx, m_Add(m_Value(), m_Value())));
520 }
521 
522 TEST_F(SelectionDAGPatternMatchTest, matchVPWithBasicContext) {
523   SDLoc DL;
524   auto BoolVT = EVT::getIntegerVT(Context, 1);
525   auto Int32VT = EVT::getIntegerVT(Context, 32);
526   auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4);
527   auto MaskVT = EVT::getVectorVT(Context, BoolVT, 4);
528 
529   SDValue Vector0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, VInt32VT);
530   SDValue Mask = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, MaskVT);
531   SDValue EL = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 3, Int32VT);
532 
533   SDValue VPAdd =
534       DAG->getNode(ISD::VP_ADD, DL, VInt32VT, Vector0, Vector0, Mask, EL);
535 
536   using namespace SDPatternMatch;
537   EXPECT_FALSE(sd_match(VPAdd, m_Node(ISD::VP_ADD, m_Value(), m_Value())));
538   EXPECT_TRUE(sd_match(
539       VPAdd, m_Node(ISD::VP_ADD, m_Value(), m_Value(), m_Value(), m_Value())));
540 }
541 
542 TEST_F(SelectionDAGPatternMatchTest, matchAdvancedProperties) {
543   SDLoc DL;
544   auto Int16VT = EVT::getIntegerVT(Context, 16);
545   auto Int64VT = EVT::getIntegerVT(Context, 64);
546 
547   SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT);
548   SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int16VT);
549 
550   SDValue Add = DAG->getNode(ISD::ADD, DL, Int64VT, Op0, Op0);
551 
552   using namespace SDPatternMatch;
553   EXPECT_TRUE(sd_match(Op0, DAG.get(), m_LegalType(m_Value())));
554   EXPECT_FALSE(sd_match(Op1, DAG.get(), m_LegalType(m_Value())));
555   EXPECT_TRUE(sd_match(Add, DAG.get(),
556                        m_LegalOp(m_IntegerVT(m_Add(m_Value(), m_Value())))));
557 }
558