1 //===- PatternMatchTest.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 "GISelMITest.h"
10 #include "llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h"
11 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
12 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
13 #include "llvm/CodeGen/GlobalISel/Utils.h"
14 #include "llvm/CodeGen/MIRParser/MIRParser.h"
15 #include "llvm/CodeGen/MachineFunction.h"
16 #include "llvm/CodeGen/MachineModuleInfo.h"
17 #include "llvm/CodeGen/TargetFrameLowering.h"
18 #include "llvm/CodeGen/TargetInstrInfo.h"
19 #include "llvm/CodeGen/TargetLowering.h"
20 #include "llvm/CodeGen/TargetSubtargetInfo.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/Support/TargetRegistry.h"
23 #include "llvm/Support/TargetSelect.h"
24 #include "llvm/Target/TargetMachine.h"
25 #include "llvm/Target/TargetOptions.h"
26 #include "gtest/gtest.h"
27 
28 using namespace llvm;
29 using namespace MIPatternMatch;
30 
31 namespace {
32 
33 TEST_F(GISelMITest, MatchIntConstant) {
34   setUp();
35   if (!TM)
36     return;
37   auto MIBCst = B.buildConstant(LLT::scalar(64), 42);
38   int64_t Cst;
39   bool match = mi_match(MIBCst.getReg(0), *MRI, m_ICst(Cst));
40   EXPECT_TRUE(match);
41   EXPECT_EQ(Cst, 42);
42 }
43 
44 TEST_F(GISelMITest, MatchBinaryOp) {
45   setUp();
46   if (!TM)
47     return;
48   LLT s64 = LLT::scalar(64);
49   auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]);
50   // Test case for no bind.
51   bool match =
52       mi_match(MIBAdd.getReg(0), *MRI, m_GAdd(m_Reg(), m_Reg()));
53   EXPECT_TRUE(match);
54   Register Src0, Src1, Src2;
55   match = mi_match(MIBAdd.getReg(0), *MRI,
56                    m_GAdd(m_Reg(Src0), m_Reg(Src1)));
57   EXPECT_TRUE(match);
58   EXPECT_EQ(Src0, Copies[0]);
59   EXPECT_EQ(Src1, Copies[1]);
60 
61   // Build MUL(ADD %0, %1), %2
62   auto MIBMul = B.buildMul(s64, MIBAdd, Copies[2]);
63 
64   // Try to match MUL.
65   match = mi_match(MIBMul.getReg(0), *MRI,
66                    m_GMul(m_Reg(Src0), m_Reg(Src1)));
67   EXPECT_TRUE(match);
68   EXPECT_EQ(Src0, MIBAdd.getReg(0));
69   EXPECT_EQ(Src1, Copies[2]);
70 
71   // Try to match MUL(ADD)
72   match = mi_match(MIBMul.getReg(0), *MRI,
73                    m_GMul(m_GAdd(m_Reg(Src0), m_Reg(Src1)), m_Reg(Src2)));
74   EXPECT_TRUE(match);
75   EXPECT_EQ(Src0, Copies[0]);
76   EXPECT_EQ(Src1, Copies[1]);
77   EXPECT_EQ(Src2, Copies[2]);
78 
79   // Test Commutativity.
80   auto MIBMul2 = B.buildMul(s64, Copies[0], B.buildConstant(s64, 42));
81   // Try to match MUL(Cst, Reg) on src of MUL(Reg, Cst) to validate
82   // commutativity.
83   int64_t Cst;
84   match = mi_match(MIBMul2.getReg(0), *MRI,
85                    m_GMul(m_ICst(Cst), m_Reg(Src0)));
86   EXPECT_TRUE(match);
87   EXPECT_EQ(Cst, 42);
88   EXPECT_EQ(Src0, Copies[0]);
89 
90   // Make sure commutative doesn't work with something like SUB.
91   auto MIBSub = B.buildSub(s64, Copies[0], B.buildConstant(s64, 42));
92   match = mi_match(MIBSub.getReg(0), *MRI,
93                    m_GSub(m_ICst(Cst), m_Reg(Src0)));
94   EXPECT_FALSE(match);
95 
96   auto MIBFMul = B.buildInstr(TargetOpcode::G_FMUL, {s64},
97                               {Copies[0], B.buildConstant(s64, 42)});
98   // Match and test commutativity for FMUL.
99   match = mi_match(MIBFMul.getReg(0), *MRI,
100                    m_GFMul(m_ICst(Cst), m_Reg(Src0)));
101   EXPECT_TRUE(match);
102   EXPECT_EQ(Cst, 42);
103   EXPECT_EQ(Src0, Copies[0]);
104 
105   // FSUB
106   auto MIBFSub = B.buildInstr(TargetOpcode::G_FSUB, {s64},
107                               {Copies[0], B.buildConstant(s64, 42)});
108   match = mi_match(MIBFSub.getReg(0), *MRI,
109                    m_GFSub(m_Reg(Src0), m_Reg()));
110   EXPECT_TRUE(match);
111   EXPECT_EQ(Src0, Copies[0]);
112 
113   // Build AND %0, %1
114   auto MIBAnd = B.buildAnd(s64, Copies[0], Copies[1]);
115   // Try to match AND.
116   match = mi_match(MIBAnd.getReg(0), *MRI,
117                    m_GAnd(m_Reg(Src0), m_Reg(Src1)));
118   EXPECT_TRUE(match);
119   EXPECT_EQ(Src0, Copies[0]);
120   EXPECT_EQ(Src1, Copies[1]);
121 
122   // Build OR %0, %1
123   auto MIBOr = B.buildOr(s64, Copies[0], Copies[1]);
124   // Try to match OR.
125   match = mi_match(MIBOr.getReg(0), *MRI,
126                    m_GOr(m_Reg(Src0), m_Reg(Src1)));
127   EXPECT_TRUE(match);
128   EXPECT_EQ(Src0, Copies[0]);
129   EXPECT_EQ(Src1, Copies[1]);
130 }
131 
132 TEST_F(GISelMITest, MatchFPUnaryOp) {
133   setUp();
134   if (!TM)
135     return;
136 
137   // Truncate s64 to s32.
138   LLT s32 = LLT::scalar(32);
139   auto Copy0s32 = B.buildFPTrunc(s32, Copies[0]);
140 
141   // Match G_FABS.
142   auto MIBFabs = B.buildInstr(TargetOpcode::G_FABS, {s32}, {Copy0s32});
143   bool match =
144       mi_match(MIBFabs.getReg(0), *MRI, m_GFabs(m_Reg()));
145   EXPECT_TRUE(match);
146 
147   Register Src;
148   auto MIBFNeg = B.buildInstr(TargetOpcode::G_FNEG, {s32}, {Copy0s32});
149   match = mi_match(MIBFNeg.getReg(0), *MRI, m_GFNeg(m_Reg(Src)));
150   EXPECT_TRUE(match);
151   EXPECT_EQ(Src, Copy0s32.getReg(0));
152 
153   match = mi_match(MIBFabs.getReg(0), *MRI, m_GFabs(m_Reg(Src)));
154   EXPECT_TRUE(match);
155   EXPECT_EQ(Src, Copy0s32.getReg(0));
156 
157   // Build and match FConstant.
158   auto MIBFCst = B.buildFConstant(s32, .5);
159   const ConstantFP *TmpFP{};
160   match = mi_match(MIBFCst.getReg(0), *MRI, m_GFCst(TmpFP));
161   EXPECT_TRUE(match);
162   EXPECT_TRUE(TmpFP);
163   APFloat APF((float).5);
164   auto *CFP = ConstantFP::get(Context, APF);
165   EXPECT_EQ(CFP, TmpFP);
166 
167   // Build double float.
168   LLT s64 = LLT::scalar(64);
169   auto MIBFCst64 = B.buildFConstant(s64, .5);
170   const ConstantFP *TmpFP64{};
171   match = mi_match(MIBFCst64.getReg(0), *MRI, m_GFCst(TmpFP64));
172   EXPECT_TRUE(match);
173   EXPECT_TRUE(TmpFP64);
174   APFloat APF64(.5);
175   auto CFP64 = ConstantFP::get(Context, APF64);
176   EXPECT_EQ(CFP64, TmpFP64);
177   EXPECT_NE(TmpFP64, TmpFP);
178 
179   // Build half float.
180   LLT s16 = LLT::scalar(16);
181   auto MIBFCst16 = B.buildFConstant(s16, .5);
182   const ConstantFP *TmpFP16{};
183   match = mi_match(MIBFCst16.getReg(0), *MRI, m_GFCst(TmpFP16));
184   EXPECT_TRUE(match);
185   EXPECT_TRUE(TmpFP16);
186   bool Ignored;
187   APFloat APF16(.5);
188   APF16.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);
189   auto CFP16 = ConstantFP::get(Context, APF16);
190   EXPECT_EQ(TmpFP16, CFP16);
191   EXPECT_NE(TmpFP16, TmpFP);
192 }
193 
194 TEST_F(GISelMITest, MatchExtendsTrunc) {
195   setUp();
196   if (!TM)
197     return;
198 
199   LLT s64 = LLT::scalar(64);
200   LLT s32 = LLT::scalar(32);
201 
202   auto MIBTrunc = B.buildTrunc(s32, Copies[0]);
203   auto MIBAExt = B.buildAnyExt(s64, MIBTrunc);
204   auto MIBZExt = B.buildZExt(s64, MIBTrunc);
205   auto MIBSExt = B.buildSExt(s64, MIBTrunc);
206   Register Src0;
207   bool match =
208       mi_match(MIBTrunc.getReg(0), *MRI, m_GTrunc(m_Reg(Src0)));
209   EXPECT_TRUE(match);
210   EXPECT_EQ(Src0, Copies[0]);
211   match =
212       mi_match(MIBAExt.getReg(0), *MRI, m_GAnyExt(m_Reg(Src0)));
213   EXPECT_TRUE(match);
214   EXPECT_EQ(Src0, MIBTrunc.getReg(0));
215 
216   match = mi_match(MIBSExt.getReg(0), *MRI, m_GSExt(m_Reg(Src0)));
217   EXPECT_TRUE(match);
218   EXPECT_EQ(Src0, MIBTrunc.getReg(0));
219 
220   match = mi_match(MIBZExt.getReg(0), *MRI, m_GZExt(m_Reg(Src0)));
221   EXPECT_TRUE(match);
222   EXPECT_EQ(Src0, MIBTrunc.getReg(0));
223 
224   // Match ext(trunc src)
225   match = mi_match(MIBAExt.getReg(0), *MRI,
226                    m_GAnyExt(m_GTrunc(m_Reg(Src0))));
227   EXPECT_TRUE(match);
228   EXPECT_EQ(Src0, Copies[0]);
229 
230   match = mi_match(MIBSExt.getReg(0), *MRI,
231                    m_GSExt(m_GTrunc(m_Reg(Src0))));
232   EXPECT_TRUE(match);
233   EXPECT_EQ(Src0, Copies[0]);
234 
235   match = mi_match(MIBZExt.getReg(0), *MRI,
236                    m_GZExt(m_GTrunc(m_Reg(Src0))));
237   EXPECT_TRUE(match);
238   EXPECT_EQ(Src0, Copies[0]);
239 }
240 
241 TEST_F(GISelMITest, MatchSpecificType) {
242   setUp();
243   if (!TM)
244     return;
245 
246   // Try to match a 64bit add.
247   LLT s64 = LLT::scalar(64);
248   LLT s32 = LLT::scalar(32);
249   auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]);
250   EXPECT_FALSE(mi_match(MIBAdd.getReg(0), *MRI,
251                         m_GAdd(m_SpecificType(s32), m_Reg())));
252   EXPECT_TRUE(mi_match(MIBAdd.getReg(0), *MRI,
253                        m_GAdd(m_SpecificType(s64), m_Reg())));
254 
255   // Try to match the destination type of a bitcast.
256   LLT v2s32 = LLT::vector(2, 32);
257   auto MIBCast = B.buildCast(v2s32, Copies[0]);
258   EXPECT_TRUE(
259       mi_match(MIBCast.getReg(0), *MRI, m_GBitcast(m_Reg())));
260   EXPECT_TRUE(
261       mi_match(MIBCast.getReg(0), *MRI, m_SpecificType(v2s32)));
262   EXPECT_TRUE(
263       mi_match(MIBCast.getReg(1), *MRI, m_SpecificType(s64)));
264 
265   // Build a PTRToInt and INTTOPTR and match and test them.
266   LLT PtrTy = LLT::pointer(0, 64);
267   auto MIBIntToPtr = B.buildCast(PtrTy, Copies[0]);
268   auto MIBPtrToInt = B.buildCast(s64, MIBIntToPtr);
269   Register Src0;
270 
271   // match the ptrtoint(inttoptr reg)
272   bool match = mi_match(MIBPtrToInt.getReg(0), *MRI,
273                         m_GPtrToInt(m_GIntToPtr(m_Reg(Src0))));
274   EXPECT_TRUE(match);
275   EXPECT_EQ(Src0, Copies[0]);
276 }
277 
278 TEST_F(GISelMITest, MatchCombinators) {
279   setUp();
280   if (!TM)
281     return;
282 
283   LLT s64 = LLT::scalar(64);
284   LLT s32 = LLT::scalar(32);
285   auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]);
286   Register Src0, Src1;
287   bool match =
288       mi_match(MIBAdd.getReg(0), *MRI,
289                m_all_of(m_SpecificType(s64), m_GAdd(m_Reg(Src0), m_Reg(Src1))));
290   EXPECT_TRUE(match);
291   EXPECT_EQ(Src0, Copies[0]);
292   EXPECT_EQ(Src1, Copies[1]);
293   // Check for s32 (which should fail).
294   match =
295       mi_match(MIBAdd.getReg(0), *MRI,
296                m_all_of(m_SpecificType(s32), m_GAdd(m_Reg(Src0), m_Reg(Src1))));
297   EXPECT_FALSE(match);
298   match =
299       mi_match(MIBAdd.getReg(0), *MRI,
300                m_any_of(m_SpecificType(s32), m_GAdd(m_Reg(Src0), m_Reg(Src1))));
301   EXPECT_TRUE(match);
302   EXPECT_EQ(Src0, Copies[0]);
303   EXPECT_EQ(Src1, Copies[1]);
304 
305   // Match a case where none of the predicates hold true.
306   match = mi_match(
307       MIBAdd.getReg(0), *MRI,
308       m_any_of(m_SpecificType(LLT::scalar(16)), m_GSub(m_Reg(), m_Reg())));
309   EXPECT_FALSE(match);
310 }
311 
312 TEST_F(GISelMITest, MatchMiscellaneous) {
313   setUp();
314   if (!TM)
315     return;
316 
317   LLT s64 = LLT::scalar(64);
318   auto MIBAdd = B.buildAdd(s64, Copies[0], Copies[1]);
319   // Make multiple uses of this add.
320   B.buildCast(LLT::pointer(0, 32), MIBAdd);
321   B.buildCast(LLT::pointer(1, 32), MIBAdd);
322   bool match = mi_match(MIBAdd.getReg(0), *MRI, m_GAdd(m_Reg(), m_Reg()));
323   EXPECT_TRUE(match);
324   match = mi_match(MIBAdd.getReg(0), *MRI, m_OneUse(m_GAdd(m_Reg(), m_Reg())));
325   EXPECT_FALSE(match);
326 }
327 } // namespace
328 
329 int main(int argc, char **argv) {
330   ::testing::InitGoogleTest(&argc, argv);
331   initLLVM();
332   return RUN_ALL_TESTS();
333 }
334