1 //===- LegalizerHelperTest.cpp
2 //-----------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "GISelMITest.h"
11 #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
12
13 using namespace LegalizeActions;
14 using namespace LegalizeMutations;
15 using namespace LegalityPredicates;
16
17 namespace {
18
19 class DummyGISelObserver : public GISelChangeObserver {
20 public:
changingInstr(MachineInstr & MI)21 void changingInstr(MachineInstr &MI) override {}
changedInstr(MachineInstr & MI)22 void changedInstr(MachineInstr &MI) override {}
createdInstr(MachineInstr & MI)23 void createdInstr(MachineInstr &MI) override {}
erasingInstr(MachineInstr & MI)24 void erasingInstr(MachineInstr &MI) override {}
25 };
26
27 // Test G_ROTL/G_ROTR lowering.
TEST_F(AArch64GISelMITest,LowerRotates)28 TEST_F(AArch64GISelMITest, LowerRotates) {
29 setUp();
30 if (!TM)
31 return;
32
33 // Declare your legalization info
34 DefineLegalizerInfo(A, {
35 getActionDefinitionsBuilder({G_ROTR, G_ROTL}).lower(); });
36
37 LLT S32 = LLT::scalar(32);
38 auto Src = B.buildTrunc(S32, Copies[0]);
39 auto Amt = B.buildTrunc(S32, Copies[1]);
40 auto ROTR = B.buildInstr(TargetOpcode::G_ROTR, {S32}, {Src, Amt});
41 auto ROTL = B.buildInstr(TargetOpcode::G_ROTL, {S32}, {Src, Amt});
42
43 AInfo Info(MF->getSubtarget());
44 DummyGISelObserver Observer;
45 LegalizerHelper Helper(*MF, Info, Observer, B);
46 // Perform Legalization
47 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
48 Helper.lower(*ROTR, 0, S32));
49 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
50 Helper.lower(*ROTL, 0, S32));
51
52 auto CheckStr = R"(
53 ; Check G_ROTR
54 CHECK: [[SRC:%[0-9]+]]:_(s32) = G_TRUNC
55 CHECK: [[AMT:%[0-9]+]]:_(s32) = G_TRUNC
56 CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
57 CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
58 CHECK: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]]:_, [[AMT]]:_
59 CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMT]]:_, [[C1]]:_
60 CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[SRC]]:_, [[AND]]:_(s32)
61 CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[SUB]]:_, [[C1]]:_
62 CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SRC]]:_, [[AND1]]:_(s32)
63 CHECK: G_OR [[LSHR]]:_, [[SHL]]:_
64
65 ; Check G_ROTL
66 CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
67 CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
68 CHECK: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]]:_, [[AMT]]:_
69 CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMT]]:_, [[C1]]:_
70 CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SRC]]:_, [[AND]]:_(s32)
71 CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[SUB]]:_, [[C1]]:_
72 CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[SRC]]:_, [[AND1]]:_(s32)
73 CHECK: G_OR [[SHL]]:_, [[LSHR]]:_
74 )";
75
76 // Check
77 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
78 }
79
80 // Test G_ROTL/G_ROTR non-pow2 lowering.
TEST_F(AArch64GISelMITest,LowerRotatesNonPow2)81 TEST_F(AArch64GISelMITest, LowerRotatesNonPow2) {
82 setUp();
83 if (!TM)
84 return;
85
86 // Declare your legalization info
87 DefineLegalizerInfo(A, {
88 getActionDefinitionsBuilder({G_ROTR, G_ROTL}).lower(); });
89
90 LLT S24 = LLT::scalar(24);
91 auto Src = B.buildTrunc(S24, Copies[0]);
92 auto Amt = B.buildTrunc(S24, Copies[1]);
93 auto ROTR = B.buildInstr(TargetOpcode::G_ROTR, {S24}, {Src, Amt});
94 auto ROTL = B.buildInstr(TargetOpcode::G_ROTL, {S24}, {Src, Amt});
95
96 AInfo Info(MF->getSubtarget());
97 DummyGISelObserver Observer;
98 LegalizerHelper Helper(*MF, Info, Observer, B);
99 // Perform Legalization
100 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
101 Helper.lower(*ROTR, 0, S24));
102 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
103 Helper.lower(*ROTL, 0, S24));
104
105 auto CheckStr = R"(
106 ; Check G_ROTR
107 CHECK: [[SRC:%[0-9]+]]:_(s24) = G_TRUNC
108 CHECK: [[AMT:%[0-9]+]]:_(s24) = G_TRUNC
109 CHECK: [[C:%[0-9]+]]:_(s24) = G_CONSTANT i24 0
110 CHECK: [[C1:%[0-9]+]]:_(s24) = G_CONSTANT i24 23
111 CHECK: [[C2:%[0-9]+]]:_(s24) = G_CONSTANT i24 24
112 CHECK: [[UREM:%[0-9]+]]:_(s24) = G_UREM [[AMT]]:_, [[C2]]:_
113 CHECK: [[LSHR:%[0-9]+]]:_(s24) = G_LSHR [[SRC]]:_, [[UREM]]:_(s24)
114 CHECK: [[SUB:%[0-9]+]]:_(s24) = G_SUB [[C1]]:_, [[UREM]]:_
115 CHECK: [[C4:%[0-9]+]]:_(s24) = G_CONSTANT i24 1
116 CHECK: [[SHL:%[0-9]+]]:_(s24) = G_SHL [[SRC]]:_, [[C4]]:_(s24)
117 CHECK: [[SHL2:%[0-9]+]]:_(s24) = G_SHL [[SHL]]:_, [[SUB]]:_(s24)
118 CHECK: G_OR [[LSHR]]:_, [[SHL2]]:_
119
120 ; Check G_ROTL
121 CHECK: [[C:%[0-9]+]]:_(s24) = G_CONSTANT i24 0
122 CHECK: [[C1:%[0-9]+]]:_(s24) = G_CONSTANT i24 23
123 CHECK: [[C2:%[0-9]+]]:_(s24) = G_CONSTANT i24 24
124 CHECK: [[UREM:%[0-9]+]]:_(s24) = G_UREM [[AMT]]:_, [[C2]]:_
125 CHECK: [[SHL:%[0-9]+]]:_(s24) = G_SHL [[SRC]]:_, [[UREM]]:_(s24)
126 CHECK: [[SUB:%[0-9]+]]:_(s24) = G_SUB [[C1]]:_, [[UREM]]:_
127 CHECK: [[C4:%[0-9]+]]:_(s24) = G_CONSTANT i24 1
128 CHECK: [[LSHR:%[0-9]+]]:_(s24) = G_LSHR [[SRC]]:_, [[C4]]:_(s24)
129 CHECK: [[LSHR2:%[0-9]+]]:_(s24) = G_LSHR [[LSHR]]:_, [[SUB]]:_(s24)
130 CHECK: G_OR [[SHL]]:_, [[LSHR2]]:_
131 )";
132
133 // Check
134 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
135 }
136
137 // Test vector G_ROTR lowering.
TEST_F(AArch64GISelMITest,LowerRotatesVector)138 TEST_F(AArch64GISelMITest, LowerRotatesVector) {
139 setUp();
140 if (!TM)
141 return;
142
143 // Declare your legalization info
144 DefineLegalizerInfo(A, {
145 getActionDefinitionsBuilder({G_ROTR, G_ROTL}).lower(); });
146
147 LLT S32 = LLT::scalar(32);
148 LLT V4S32 = LLT::fixed_vector(4, S32);
149 auto SrcTrunc = B.buildTrunc(S32, Copies[0]);
150 auto Src = B.buildSplatVector(V4S32, SrcTrunc);
151 auto AmtTrunc = B.buildTrunc(S32, Copies[1]);
152 auto Amt = B.buildSplatVector(V4S32, AmtTrunc);
153 auto ROTR = B.buildInstr(TargetOpcode::G_ROTR, {V4S32}, {Src, Amt});
154
155 AInfo Info(MF->getSubtarget());
156 DummyGISelObserver Observer;
157 LegalizerHelper Helper(*MF, Info, Observer, B);
158 // Perform Legalization
159 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
160 Helper.lower(*ROTR, 0, V4S32));
161
162 auto CheckStr = R"(
163 CHECK: [[SRCTRUNC:%[0-9]+]]:_(s32) = G_TRUNC
164 CHECK: [[SRC:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[SRCTRUNC]]
165 CHECK: [[AMTTRUNC:%[0-9]+]]:_(s32) = G_TRUNC
166 CHECK: [[AMT:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[AMTTRUNC]]
167 CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
168 CHECK: [[ZERO:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]]
169 CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
170 CHECK: [[VEC31:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]]
171 CHECK: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB [[ZERO]]:_, [[AMT]]:_
172 CHECK: [[AND:%[0-9]+]]:_(<4 x s32>) = G_AND [[AMT]]:_, [[VEC31]]:_
173 CHECK: [[LSHR:%[0-9]+]]:_(<4 x s32>) = G_LSHR [[SRC]]:_, [[AND]]:_(<4 x s32>)
174 CHECK: [[AND1:%[0-9]+]]:_(<4 x s32>) = G_AND [[SUB]]:_, [[VEC31]]:_
175 CHECK: [[SHL:%[0-9]+]]:_(<4 x s32>) = G_SHL [[SRC]]:_, [[AND1]]:_(<4 x s32>)
176 CHECK: G_OR [[LSHR]]:_, [[SHL]]:_
177 )";
178
179 // Check
180 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
181 }
182
183 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom,
184 // in which case it becomes CTTZ_ZERO_UNDEF with select.
TEST_F(AArch64GISelMITest,LowerBitCountingCTTZ0)185 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ0) {
186 setUp();
187 if (!TM)
188 return;
189
190 // Declare your legalization info
191 DefineLegalizerInfo(A, {
192 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s32, s64}});
193 });
194 // Build Instr
195 auto MIBCTTZ =
196 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]});
197 AInfo Info(MF->getSubtarget());
198 DummyGISelObserver Observer;
199 LegalizerHelper Helper(*MF, Info, Observer, B);
200 // Perform Legalization
201 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
202 Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)));
203
204 auto CheckStr = R"(
205 CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF %0
206 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
207 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
208 CHECK: [[SIXTY4:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
209 CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
210 )";
211
212 // Check
213 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
214 }
215
216 // CTTZ expansion in terms of CTLZ
TEST_F(AArch64GISelMITest,LowerBitCountingCTTZ1)217 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ1) {
218 setUp();
219 if (!TM)
220 return;
221
222 // Declare your legalization info
223 DefineLegalizerInfo(A, {
224 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}});
225 });
226 // Build Instr
227 auto MIBCTTZ =
228 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
229 AInfo Info(MF->getSubtarget());
230 DummyGISelObserver Observer;
231 LegalizerHelper Helper(*MF, Info, Observer, B);
232 // Perform Legalization
233 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
234 LegalizerHelper::LegalizeResult::Legalized);
235
236 auto CheckStr = R"(
237 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
238 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
239 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
240 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
241 CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
242 CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_
243 CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_
244 )";
245
246 // Check
247 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
248 }
249
250 // CTLZ scalar narrowing
TEST_F(AArch64GISelMITest,NarrowScalarCTLZ)251 TEST_F(AArch64GISelMITest, NarrowScalarCTLZ) {
252 setUp();
253 if (!TM)
254 return;
255
256 // Declare your legalization info
257 DefineLegalizerInfo(A, {
258 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s32, s32}});
259 });
260 // Build Instr
261 auto CTLZ =
262 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]});
263 AInfo Info(MF->getSubtarget());
264 DummyGISelObserver Observer;
265 LegalizerHelper Helper(*MF, Info, Observer, B);
266 // Perform Legalization
267 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
268 Helper.narrowScalar(*CTLZ, 1, LLT::scalar(32)));
269
270 auto CheckStr = R"(
271 CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64)
272 CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
273 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_HI]]:_(s32), [[ZERO]]:_
274 CHECK: [[CTLZ_LO:%[0-9]+]]:_(s32) = G_CTLZ [[UNMERGE_LO]]:_(s32)
275 CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
276 CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTLZ_LO]]:_, [[THIRTYTWO]]:_
277 CHECK: [[CTLZ_HI:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[UNMERGE_HI]]:_(s32)
278 CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTLZ_HI]]:_
279 )";
280
281 // Check
282 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
283 }
284
285 // CTTZ scalar narrowing
TEST_F(AArch64GISelMITest,NarrowScalarCTTZ)286 TEST_F(AArch64GISelMITest, NarrowScalarCTTZ) {
287 setUp();
288 if (!TM)
289 return;
290
291 // Declare your legalization info
292 DefineLegalizerInfo(A, {
293 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s32, s64}});
294 });
295 // Build Instr
296 auto CTTZ =
297 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]});
298 AInfo Info(MF->getSubtarget());
299 DummyGISelObserver Observer;
300 LegalizerHelper Helper(*MF, Info, Observer, B);
301 // Perform Legalization
302 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
303 Helper.narrowScalar(*CTTZ, 1, LLT::scalar(32)));
304
305 auto CheckStr = R"(
306 CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64)
307 CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
308 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_LO]]:_(s32), [[ZERO]]:_
309 CHECK: [[CTTZ_HI:%[0-9]+]]:_(s32) = G_CTTZ [[UNMERGE_HI]]:_(s32)
310 CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
311 CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTTZ_HI]]:_, [[THIRTYTWO]]:_
312 CHECK: [[CTTZ_LO:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[UNMERGE_LO]]:_(s32)
313 CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTTZ_LO]]:_
314 )";
315
316 // Check
317 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
318 }
319
320 // CTTZ expansion in terms of CTPOP
TEST_F(AArch64GISelMITest,LowerBitCountingCTTZ2)321 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ2) {
322 setUp();
323 if (!TM)
324 return;
325
326 // Declare your legalization info
327 DefineLegalizerInfo(A, {
328 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}});
329 });
330 // Build
331 auto MIBCTTZ =
332 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
333 AInfo Info(MF->getSubtarget());
334 DummyGISelObserver Observer;
335 LegalizerHelper Helper(*MF, Info, Observer, B);
336
337 B.setInsertPt(*EntryMBB, MIBCTTZ->getIterator());
338 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
339 LegalizerHelper::LegalizeResult::Legalized);
340
341 auto CheckStr = R"(
342 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
343 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
344 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
345 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
346 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
347 )";
348
349 // Check
350 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
351 }
352
353 // CTPOP widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTPOP1)354 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP1) {
355 setUp();
356 if (!TM)
357 return;
358
359 // Declare your legalization info
360 DefineLegalizerInfo(A, {
361 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
362 });
363
364 // Build
365 // Trunc it to s8.
366 LLT s8{LLT::scalar(8)};
367 LLT s16{LLT::scalar(16)};
368 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
369 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc});
370 AInfo Info(MF->getSubtarget());
371 DummyGISelObserver Observer;
372 LegalizerHelper Helper(*MF, Info, Observer, B);
373 B.setInstr(*MIBCTPOP);
374 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
375 Helper.widenScalar(*MIBCTPOP, 1, s16));
376
377 auto CheckStr = R"(
378 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
379 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
380 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
381 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16)
382 )";
383
384 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
385 }
386
387 // Test a strange case where the result is wider than the source
TEST_F(AArch64GISelMITest,WidenBitCountingCTPOP2)388 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP2) {
389 setUp();
390 if (!TM)
391 return;
392
393 // Declare your legalization info
394 DefineLegalizerInfo(A, {
395 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}});
396 });
397
398 // Build
399 // Trunc it to s8.
400 LLT s8{LLT::scalar(8)};
401 LLT s16{LLT::scalar(16)};
402 LLT s32{LLT::scalar(32)};
403 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
404 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc});
405 AInfo Info(MF->getSubtarget());
406 DummyGISelObserver Observer;
407 LegalizerHelper Helper(*MF, Info, Observer, B);
408 B.setInstr(*MIBCTPOP);
409 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
410 Helper.widenScalar(*MIBCTPOP, 1, s16));
411
412 auto CheckStr = R"(
413 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
414 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
415 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
416 CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16)
417 )";
418
419 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
420 }
421
422 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
TEST_F(AArch64GISelMITest,LowerBitCountingCTTZ3)423 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ3) {
424 setUp();
425 if (!TM)
426 return;
427
428 // Declare your legalization info
429 DefineLegalizerInfo(A, {
430 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
431 });
432 // Build
433 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
434 {LLT::scalar(64)}, {Copies[0]});
435 AInfo Info(MF->getSubtarget());
436 DummyGISelObserver Observer;
437 LegalizerHelper Helper(*MF, Info, Observer, B);
438 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
439 LegalizerHelper::LegalizeResult::Legalized);
440
441 auto CheckStr = R"(
442 CHECK: CTTZ
443 )";
444
445 // Check
446 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
447 }
448
449 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
TEST_F(AArch64GISelMITest,LowerBitCountingCTLZ0)450 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZ0) {
451 setUp();
452 if (!TM)
453 return;
454
455 // Declare your legalization info
456 DefineLegalizerInfo(A, {
457 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
458 });
459 // Build
460 auto MIBCTLZ =
461 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
462 AInfo Info(MF->getSubtarget());
463 DummyGISelObserver Observer;
464 LegalizerHelper Helper(*MF, Info, Observer, B);
465 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
466 LegalizerHelper::LegalizeResult::Legalized);
467
468 auto CheckStr = R"(
469 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
470 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
471 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
472 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
473 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
474 )";
475
476 // Check
477 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
478 }
479
480 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall
TEST_F(AArch64GISelMITest,LowerBitCountingCTLZLibcall)481 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZLibcall) {
482 setUp();
483 if (!TM)
484 return;
485
486 // Declare your legalization info
487 DefineLegalizerInfo(A, {
488 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s32, s64}});
489 });
490 // Build
491 auto MIBCTLZ =
492 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]});
493 AInfo Info(MF->getSubtarget());
494 DummyGISelObserver Observer;
495 LegalizerHelper Helper(*MF, Info, Observer, B);
496 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
497 Helper.lower(*MIBCTLZ, 0, LLT::scalar(32)));
498
499 auto CheckStr = R"(
500 CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF %0
501 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
502 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
503 CHECK: [[THIRTY2:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
504 CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]]
505 )";
506
507 // Check
508 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
509 }
510
511 // CTLZ expansion
TEST_F(AArch64GISelMITest,LowerBitCountingCTLZ1)512 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZ1) {
513 setUp();
514 if (!TM)
515 return;
516
517 // Declare your legalization info
518 DefineLegalizerInfo(A, {
519 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
520 });
521 // Build
522 // Trunc it to s8.
523 LLT s8{LLT::scalar(8)};
524 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
525 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
526 AInfo Info(MF->getSubtarget());
527 DummyGISelObserver Observer;
528 LegalizerHelper Helper(*MF, Info, Observer, B);
529 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
530 LegalizerHelper::LegalizeResult::Legalized);
531
532 auto CheckStr = R"(
533 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
534 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
535 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
536 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
537 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
538 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
539 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
540 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
541 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
542 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
543 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
544 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
545 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
546 )";
547
548 // Check
549 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
550 }
551
552 // CTLZ widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTLZ)553 TEST_F(AArch64GISelMITest, WidenBitCountingCTLZ) {
554 setUp();
555 if (!TM)
556 return;
557
558 // Declare your legalization info
559 DefineLegalizerInfo(A, {
560 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
561 });
562 // Build
563 // Trunc it to s8.
564 LLT s8{LLT::scalar(8)};
565 LLT s16{LLT::scalar(16)};
566 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
567 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
568 AInfo Info(MF->getSubtarget());
569 DummyGISelObserver Observer;
570 LegalizerHelper Helper(*MF, Info, Observer, B);
571 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) ==
572 LegalizerHelper::LegalizeResult::Legalized);
573
574 auto CheckStr = R"(
575 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
576 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
577 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
578 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
579 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
580 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
581 )";
582
583 // Check
584 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
585 }
586
587 // CTLZ_ZERO_UNDEF widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTLZZeroUndef)588 TEST_F(AArch64GISelMITest, WidenBitCountingCTLZZeroUndef) {
589 setUp();
590 if (!TM)
591 return;
592
593 // Declare your legalization info
594 DefineLegalizerInfo(A, {
595 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
596 });
597 // Build
598 // Trunc it to s8.
599 LLT s8{LLT::scalar(8)};
600 LLT s16{LLT::scalar(16)};
601 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
602 auto MIBCTLZ_ZU =
603 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc});
604 AInfo Info(MF->getSubtarget());
605 DummyGISelObserver Observer;
606 LegalizerHelper Helper(*MF, Info, Observer, B);
607 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) ==
608 LegalizerHelper::LegalizeResult::Legalized);
609
610 auto CheckStr = R"(
611 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
612 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
613 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
614 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
615 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
616 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
617 )";
618
619 // Check
620 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
621 }
622
623 // CTPOP widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTPOP)624 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP) {
625 setUp();
626 if (!TM)
627 return;
628
629 // Declare your legalization info
630 DefineLegalizerInfo(A, {
631 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
632 });
633 // Build
634 // Trunc it to s8.
635 LLT s8{LLT::scalar(8)};
636 LLT s16{LLT::scalar(16)};
637 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
638 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc});
639 AInfo Info(MF->getSubtarget());
640 DummyGISelObserver Observer;
641 LegalizerHelper Helper(*MF, Info, Observer, B);
642 EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) ==
643 LegalizerHelper::LegalizeResult::Legalized);
644
645 auto CheckStr = R"(
646 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
647 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
648 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
649 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
650 )";
651
652 // Check
653 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
654 }
655
656 // CTTZ_ZERO_UNDEF widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTTZ_ZERO_UNDEF)657 TEST_F(AArch64GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
658 setUp();
659 if (!TM)
660 return;
661
662 // Declare your legalization info
663 DefineLegalizerInfo(A, {
664 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
665 });
666 // Build
667 // Trunc it to s8.
668 LLT s8{LLT::scalar(8)};
669 LLT s16{LLT::scalar(16)};
670 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
671 auto MIBCTTZ_ZERO_UNDEF =
672 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc});
673 AInfo Info(MF->getSubtarget());
674 DummyGISelObserver Observer;
675 LegalizerHelper Helper(*MF, Info, Observer, B);
676 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) ==
677 LegalizerHelper::LegalizeResult::Legalized);
678
679 auto CheckStr = R"(
680 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
681 CHECK: [[AnyExt:%[0-9]+]]:_(s16) = G_ANYEXT [[Trunc]]
682 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[AnyExt]]
683 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
684 )";
685
686 // Check
687 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
688 }
689
690 // CTTZ widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTTZ)691 TEST_F(AArch64GISelMITest, WidenBitCountingCTTZ) {
692 setUp();
693 if (!TM)
694 return;
695
696 // Declare your legalization info
697 DefineLegalizerInfo(A, {
698 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
699 });
700 // Build
701 // Trunc it to s8.
702 LLT s8{LLT::scalar(8)};
703 LLT s16{LLT::scalar(16)};
704 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
705 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc});
706 AInfo Info(MF->getSubtarget());
707 DummyGISelObserver Observer;
708 LegalizerHelper Helper(*MF, Info, Observer, B);
709 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) ==
710 LegalizerHelper::LegalizeResult::Legalized);
711
712 auto CheckStr = R"(
713 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
714 CHECK: [[AnyExt:%[0-9]+]]:_(s16) = G_ANYEXT [[Trunc]]
715 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
716 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[AnyExt]]:_, [[Cst]]
717 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Or]]
718 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
719 )";
720
721 // Check
722 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
723 }
724 // UADDO widening.
TEST_F(AArch64GISelMITest,WidenUADDO)725 TEST_F(AArch64GISelMITest, WidenUADDO) {
726 setUp();
727 if (!TM)
728 return;
729
730 // Declare your legalization info
731 DefineLegalizerInfo(A, {
732 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
733 });
734 // Build
735 // Trunc it to s8.
736 LLT s8{LLT::scalar(8)};
737 LLT s16{LLT::scalar(16)};
738 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
739 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
740 auto MIBUAddO =
741 B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
742 AInfo Info(MF->getSubtarget());
743 DummyGISelObserver Observer;
744 LegalizerHelper Helper(*MF, Info, Observer, B);
745 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
746 LegalizerHelper::LegalizeResult::Legalized);
747
748 auto CheckStr = R"(
749 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
750 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
751 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
752 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
753 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ADD]]
754 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
755 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[ZEXT]]:_
756 CHECK: G_TRUNC [[ADD]]
757 )";
758
759 // Check
760 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
761 }
762
763 // USUBO widening.
TEST_F(AArch64GISelMITest,WidenUSUBO)764 TEST_F(AArch64GISelMITest, WidenUSUBO) {
765 setUp();
766 if (!TM)
767 return;
768
769 // Declare your legalization info
770 DefineLegalizerInfo(A, {
771 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
772 });
773 // Build
774 // Trunc it to s8.
775 LLT s8{LLT::scalar(8)};
776 LLT s16{LLT::scalar(16)};
777 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
778 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
779 auto MIBUSUBO =
780 B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
781 AInfo Info(MF->getSubtarget());
782 DummyGISelObserver Observer;
783 LegalizerHelper Helper(*MF, Info, Observer, B);
784 EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
785 LegalizerHelper::LegalizeResult::Legalized);
786
787 auto CheckStr = R"(
788 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
789 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
790 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
791 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
792 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SUB]]
793 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
794 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[ZEXT]]:_
795 CHECK: G_TRUNC [[SUB]]
796 )";
797
798 // Check
799 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
800 }
801
802 // SADDO widening.
TEST_F(AArch64GISelMITest,WidenSADDO)803 TEST_F(AArch64GISelMITest, WidenSADDO) {
804 setUp();
805 if (!TM)
806 return;
807
808 // Declare your legalization info
809 DefineLegalizerInfo(A, {
810 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
811 });
812 // Build
813 // Trunc it to s8.
814 LLT s8{LLT::scalar(8)};
815 LLT s16{LLT::scalar(16)};
816 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
817 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
818 auto MIBSAddO =
819 B.buildInstr(TargetOpcode::G_SADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
820 AInfo Info(MF->getSubtarget());
821 DummyGISelObserver Observer;
822 LegalizerHelper Helper(*MF, Info, Observer, B);
823 EXPECT_TRUE(Helper.widenScalar(*MIBSAddO, 0, s16) ==
824 LegalizerHelper::LegalizeResult::Legalized);
825
826 auto CheckStr = R"(
827 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
828 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
829 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
830 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
831 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ADD]]
832 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
833 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[SEXT]]:_
834 CHECK: G_TRUNC [[ADD]]
835 )";
836
837 // Check
838 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
839 }
840
841 // SSUBO widening.
TEST_F(AArch64GISelMITest,WidenSSUBO)842 TEST_F(AArch64GISelMITest, WidenSSUBO) {
843 setUp();
844 if (!TM)
845 return;
846
847 // Declare your legalization info
848 DefineLegalizerInfo(A, {
849 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
850 });
851 // Build
852 // Trunc it to s8.
853 LLT s8{LLT::scalar(8)};
854 LLT s16{LLT::scalar(16)};
855 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
856 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
857 auto MIBSSUBO =
858 B.buildInstr(TargetOpcode::G_SSUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
859 AInfo Info(MF->getSubtarget());
860 DummyGISelObserver Observer;
861 LegalizerHelper Helper(*MF, Info, Observer, B);
862 EXPECT_TRUE(Helper.widenScalar(*MIBSSUBO, 0, s16) ==
863 LegalizerHelper::LegalizeResult::Legalized);
864
865 auto CheckStr = R"(
866 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
867 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
868 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
869 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
870 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SUB]]
871 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
872 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[SEXT]]:_
873 CHECK: G_TRUNC [[SUB]]
874 )";
875
876 // Check
877 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
878 }
879
TEST_F(AArch64GISelMITest,WidenUADDE)880 TEST_F(AArch64GISelMITest, WidenUADDE) {
881 setUp();
882 if (!TM)
883 return;
884
885 // Declare your legalization info
886 DefineLegalizerInfo(A, {
887 getActionDefinitionsBuilder(G_UADDE).legalFor({{s16, s16}});
888 });
889 // Build
890 // Trunc it to s8.
891 LLT s8{LLT::scalar(8)};
892 LLT s16{LLT::scalar(16)};
893 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
894 auto CarryIn = B.buildUndef(LLT::scalar(1));
895 Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
896 auto MIBUAddO = B.buildInstr(TargetOpcode::G_UADDE, {s8, CarryReg},
897 {MIBTrunc, MIBTrunc, CarryIn});
898 AInfo Info(MF->getSubtarget());
899 DummyGISelObserver Observer;
900 LegalizerHelper Helper(*MF, Info, Observer, B);
901 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
902 LegalizerHelper::LegalizeResult::Legalized);
903
904 const char *CheckStr = R"(
905 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
906 CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
907 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
908 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
909 CHECK: [[UADDE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_UADDE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_
910 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[UADDE]]
911 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
912 CHECK: G_ICMP intpred(ne), [[UADDE]]:_(s16), [[ZEXT]]:_
913 CHECK: G_TRUNC [[UADDE]]
914 )";
915
916 // Check
917 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
918 }
919
TEST_F(AArch64GISelMITest,WidenUSUBE)920 TEST_F(AArch64GISelMITest, WidenUSUBE) {
921 setUp();
922 if (!TM)
923 return;
924
925 // Declare your legalization info
926 DefineLegalizerInfo(A, {
927 getActionDefinitionsBuilder(G_USUBE).legalFor({{s16, s16}});
928 });
929 // Build
930 // Trunc it to s8.
931 LLT s8{LLT::scalar(8)};
932 LLT s16{LLT::scalar(16)};
933 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
934 auto CarryIn = B.buildUndef(LLT::scalar(1));
935 Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
936 auto MIBUSUBE = B.buildInstr(TargetOpcode::G_USUBE, {s8, CarryReg},
937 {MIBTrunc, MIBTrunc, CarryIn});
938 AInfo Info(MF->getSubtarget());
939 DummyGISelObserver Observer;
940 LegalizerHelper Helper(*MF, Info, Observer, B);
941 EXPECT_TRUE(Helper.widenScalar(*MIBUSUBE, 0, s16) ==
942 LegalizerHelper::LegalizeResult::Legalized);
943
944 const char *CheckStr = R"(
945 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
946 CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
947 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
948 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
949 CHECK: [[USUBE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_USUBE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_
950 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[USUBE]]
951 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
952 CHECK: G_ICMP intpred(ne), [[USUBE]]:_(s16), [[ZEXT]]:_
953 CHECK: G_TRUNC [[USUBE]]
954 )";
955
956 // Check
957 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
958 }
959
TEST_F(AArch64GISelMITest,WidenSADDE)960 TEST_F(AArch64GISelMITest, WidenSADDE) {
961 setUp();
962 if (!TM)
963 return;
964
965 // Declare your legalization info
966 DefineLegalizerInfo(A, {
967 getActionDefinitionsBuilder({G_SADDE, G_UADDE}).legalFor({{s16, s16}});
968 });
969 // Build
970 // Trunc it to s8.
971 LLT s8{LLT::scalar(8)};
972 LLT s16{LLT::scalar(16)};
973 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
974 auto CarryIn = B.buildUndef(LLT::scalar(1));
975 Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
976 auto MIBUAddO = B.buildInstr(TargetOpcode::G_SADDE, {s8, CarryReg},
977 {MIBTrunc, MIBTrunc, CarryIn});
978 AInfo Info(MF->getSubtarget());
979 DummyGISelObserver Observer;
980 LegalizerHelper Helper(*MF, Info, Observer, B);
981 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
982 LegalizerHelper::LegalizeResult::Legalized);
983
984 const char *CheckStr = R"(
985 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
986 CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
987 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
988 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
989 CHECK: [[SADDE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_UADDE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_
990 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SADDE]]
991 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
992 CHECK: G_ICMP intpred(ne), [[SADDE]]:_(s16), [[SEXT]]:_
993 CHECK: G_TRUNC [[SADDE]]
994 )";
995
996 // Check
997 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
998 }
999
TEST_F(AArch64GISelMITest,WidenSSUBE)1000 TEST_F(AArch64GISelMITest, WidenSSUBE) {
1001 setUp();
1002 if (!TM)
1003 return;
1004
1005 // Declare your legalization info
1006 DefineLegalizerInfo(A, {
1007 getActionDefinitionsBuilder({G_SSUBE, G_USUBE}).legalFor({{s16, s16}});
1008 });
1009 // Build
1010 // Trunc it to s8.
1011 LLT s8{LLT::scalar(8)};
1012 LLT s16{LLT::scalar(16)};
1013 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
1014 auto CarryIn = B.buildUndef(LLT::scalar(1));
1015 Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
1016 auto MIBSSUBE = B.buildInstr(TargetOpcode::G_SSUBE, {s8, CarryReg},
1017 {MIBTrunc, MIBTrunc, CarryIn});
1018 AInfo Info(MF->getSubtarget());
1019 DummyGISelObserver Observer;
1020 LegalizerHelper Helper(*MF, Info, Observer, B);
1021 EXPECT_TRUE(Helper.widenScalar(*MIBSSUBE, 0, s16) ==
1022 LegalizerHelper::LegalizeResult::Legalized);
1023
1024 const char *CheckStr = R"(
1025 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
1026 CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1027 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
1028 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
1029 CHECK: [[SSUBE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_USUBE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_
1030 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SSUBE]]
1031 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
1032 CHECK: G_ICMP intpred(ne), [[SSUBE]]:_(s16), [[SEXT]]:_
1033 CHECK: G_TRUNC [[SSUBE]]
1034 )";
1035
1036 // Check
1037 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1038 }
1039
TEST_F(AArch64GISelMITest,WidenUMULOCondition)1040 TEST_F(AArch64GISelMITest, WidenUMULOCondition) {
1041 setUp();
1042 if (!TM)
1043 return;
1044
1045 // Declare your legalization info
1046 DefineLegalizerInfo(A, {
1047 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
1048 });
1049
1050 LLT s32 = LLT::scalar(32);
1051 LLT s64 = LLT::scalar(64);
1052
1053 auto UMulo =
1054 B.buildInstr(TargetOpcode::G_UMULO, {s64, LLT::scalar(1)},
1055 {Copies[0], Copies[1]});
1056 AInfo Info(MF->getSubtarget());
1057 DummyGISelObserver Observer;
1058 LegalizerHelper Helper(*MF, Info, Observer, B);
1059
1060 B.setInstrAndDebugLoc(*UMulo);
1061 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1062 Helper.widenScalar(*UMulo, 1, s32));
1063
1064 auto CheckStr = R"(
1065 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
1066 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
1067 CHECK: [[ADD:%[0-9]+]]:_(s64), [[OVERFLOW:%[0-9]+]]:_(s32) = G_UMULO [[COPY0]]:_, [[COPY1]]:_
1068 CHECK: {{[0-9]+}}:_(s1) = G_TRUNC [[OVERFLOW]]
1069 )";
1070
1071 // Check
1072 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1073 }
1074
TEST_F(AArch64GISelMITest,NarrowUADDO)1075 TEST_F(AArch64GISelMITest, NarrowUADDO) {
1076 setUp();
1077 if (!TM)
1078 return;
1079
1080 LLT S1 = LLT::scalar(1);
1081 LLT S32 = LLT::scalar(32);
1082 LLT S96 = LLT::scalar(96);
1083 DefineLegalizerInfo(A, {
1084 getActionDefinitionsBuilder({G_UADDO, G_UADDE})
1085 .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1086 });
1087
1088 auto Op0 = B.buildUndef(S96);
1089 auto Op1 = B.buildUndef(S96);
1090 auto UADDO = B.buildUAddo(S96, S1, Op0, Op1);
1091
1092 AInfo Info(MF->getSubtarget());
1093 DummyGISelObserver Observer;
1094 LegalizerHelper Helper(*MF, Info, Observer, B);
1095 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1096 Helper.narrowScalar(*UADDO, 0, S32));
1097
1098 const char *CheckStr = R"(
1099 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1100 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1101 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1102 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1103 CHECK: [[UADDO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDO [[OP0_0]]:_, [[OP1_0]]:_
1104 CHECK: [[UADDO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1105 CHECK: [[UADDO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_UADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1106 CHECK: [[UADDO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[UADDO0]]:_(s32), [[UADDO1]]:_(s32), [[UADDO2]]:_(s32)
1107 )";
1108
1109 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1110 }
1111
TEST_F(AArch64GISelMITest,NarrowUSUBO)1112 TEST_F(AArch64GISelMITest, NarrowUSUBO) {
1113 setUp();
1114 if (!TM)
1115 return;
1116
1117 LLT S1 = LLT::scalar(1);
1118 LLT S32 = LLT::scalar(32);
1119 LLT S96 = LLT::scalar(96);
1120 DefineLegalizerInfo(A, {
1121 getActionDefinitionsBuilder({G_USUBO, G_USUBE})
1122 .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1123 });
1124
1125 auto Op0 = B.buildUndef(S96);
1126 auto Op1 = B.buildUndef(S96);
1127 auto USUBO = B.buildUSubo(S96, S1, Op0, Op1);
1128
1129 AInfo Info(MF->getSubtarget());
1130 DummyGISelObserver Observer;
1131 LegalizerHelper Helper(*MF, Info, Observer, B);
1132 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1133 Helper.narrowScalar(*USUBO, 0, S32));
1134
1135 const char *CheckStr = R"(
1136 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1137 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1138 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1139 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1140 CHECK: [[USUBO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBO [[OP0_0]]:_, [[OP1_0]]:_
1141 CHECK: [[USUBO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1142 CHECK: [[USUBO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_USUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1143 CHECK: [[USUBO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[USUBO0]]:_(s32), [[USUBO1]]:_(s32), [[USUBO2]]:_(s32)
1144 )";
1145
1146 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1147 }
1148
TEST_F(AArch64GISelMITest,NarrowSADDO)1149 TEST_F(AArch64GISelMITest, NarrowSADDO) {
1150 setUp();
1151 if (!TM)
1152 return;
1153
1154 LLT S1 = LLT::scalar(1);
1155 LLT S32 = LLT::scalar(32);
1156 LLT S96 = LLT::scalar(96);
1157 DefineLegalizerInfo(A, {
1158 getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_SADDE})
1159 .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1160 });
1161
1162 auto Op0 = B.buildUndef(S96);
1163 auto Op1 = B.buildUndef(S96);
1164 auto SADDO = B.buildSAddo(S96, S1, Op0, Op1);
1165
1166 AInfo Info(MF->getSubtarget());
1167 DummyGISelObserver Observer;
1168 LegalizerHelper Helper(*MF, Info, Observer, B);
1169 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1170 Helper.narrowScalar(*SADDO, 0, S32));
1171
1172 const char *CheckStr = R"(
1173 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1174 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1175 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1176 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1177 CHECK: [[SADDO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDO [[OP0_0]]:_, [[OP1_0]]:_
1178 CHECK: [[SADDO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1179 CHECK: [[SADDO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1180 CHECK: [[SADDO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SADDO0]]:_(s32), [[SADDO1]]:_(s32), [[SADDO2]]:_(s32)
1181 )";
1182
1183 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1184 }
1185
TEST_F(AArch64GISelMITest,NarrowSSUBO)1186 TEST_F(AArch64GISelMITest, NarrowSSUBO) {
1187 setUp();
1188 if (!TM)
1189 return;
1190
1191 LLT S1 = LLT::scalar(1);
1192 LLT S32 = LLT::scalar(32);
1193 LLT S96 = LLT::scalar(96);
1194 DefineLegalizerInfo(A, {
1195 getActionDefinitionsBuilder({G_USUBO, G_USUBE, G_SSUBE})
1196 .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1197 });
1198
1199 auto Op0 = B.buildUndef(S96);
1200 auto Op1 = B.buildUndef(S96);
1201 auto SSUBO = B.buildSSubo(S96, S1, Op0, Op1);
1202
1203 AInfo Info(MF->getSubtarget());
1204 DummyGISelObserver Observer;
1205 LegalizerHelper Helper(*MF, Info, Observer, B);
1206 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1207 Helper.narrowScalar(*SSUBO, 0, S32));
1208
1209 const char *CheckStr = R"(
1210 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1211 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1212 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1213 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1214 CHECK: [[SSUBO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBO [[OP0_0]]:_, [[OP1_0]]:_
1215 CHECK: [[SSUBO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1216 CHECK: [[SSUBO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SSUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1217 CHECK: [[SSUBO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SSUBO0]]:_(s32), [[SSUBO1]]:_(s32), [[SSUBO2]]:_(s32)
1218 )";
1219
1220 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1221 }
1222
TEST_F(AArch64GISelMITest,NarrowUADDE)1223 TEST_F(AArch64GISelMITest, NarrowUADDE) {
1224 setUp();
1225 if (!TM)
1226 return;
1227
1228 LLT S1 = LLT::scalar(1);
1229 LLT S32 = LLT::scalar(32);
1230 LLT S96 = LLT::scalar(96);
1231 DefineLegalizerInfo(A, {
1232 getActionDefinitionsBuilder(G_UADDE).legalFor(
1233 {{LLT::scalar(32), LLT::scalar(1)}});
1234 });
1235
1236 auto Op0 = B.buildUndef(S96);
1237 auto Op1 = B.buildUndef(S96);
1238 auto Op2 = B.buildUndef(S1);
1239 auto UADDE = B.buildUAdde(S96, S1, Op0, Op1, Op2);
1240
1241 AInfo Info(MF->getSubtarget());
1242 DummyGISelObserver Observer;
1243 LegalizerHelper Helper(*MF, Info, Observer, B);
1244 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1245 Helper.narrowScalar(*UADDE, 0, S32));
1246
1247 const char *CheckStr = R"(
1248 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1249 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1250 CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1251 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1252 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1253 CHECK: [[UADDE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_
1254 CHECK: [[UADDE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1255 CHECK: [[UADDE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_UADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1256 CHECK: [[UADDE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[UADDE0]]:_(s32), [[UADDE1]]:_(s32), [[UADDE2]]:_(s32)
1257 )";
1258
1259 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1260 }
1261
TEST_F(AArch64GISelMITest,NarrowUSUBE)1262 TEST_F(AArch64GISelMITest, NarrowUSUBE) {
1263 setUp();
1264 if (!TM)
1265 return;
1266
1267 LLT S1 = LLT::scalar(1);
1268 LLT S32 = LLT::scalar(32);
1269 LLT S96 = LLT::scalar(96);
1270 DefineLegalizerInfo(A, {
1271 getActionDefinitionsBuilder(G_USUBE).legalFor(
1272 {{LLT::scalar(32), LLT::scalar(1)}});
1273 });
1274
1275 auto Op0 = B.buildUndef(S96);
1276 auto Op1 = B.buildUndef(S96);
1277 auto Op2 = B.buildUndef(S1);
1278 auto USUBE = B.buildUSube(S96, S1, Op0, Op1, Op2);
1279
1280 AInfo Info(MF->getSubtarget());
1281 DummyGISelObserver Observer;
1282 LegalizerHelper Helper(*MF, Info, Observer, B);
1283 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1284 Helper.narrowScalar(*USUBE, 0, S32));
1285
1286 const char *CheckStr = R"(
1287 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1288 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1289 CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1290 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1291 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1292 CHECK: [[USUBE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_
1293 CHECK: [[USUBE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1294 CHECK: [[USUBE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_USUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1295 CHECK: [[USUBE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[USUBE0]]:_(s32), [[USUBE1]]:_(s32), [[USUBE2]]:_(s32)
1296 )";
1297
1298 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1299 }
1300
TEST_F(AArch64GISelMITest,NarrowSADDE)1301 TEST_F(AArch64GISelMITest, NarrowSADDE) {
1302 setUp();
1303 if (!TM)
1304 return;
1305
1306 LLT S1 = LLT::scalar(1);
1307 LLT S32 = LLT::scalar(32);
1308 LLT S96 = LLT::scalar(96);
1309 DefineLegalizerInfo(A, {
1310 getActionDefinitionsBuilder({G_SADDE, G_UADDE})
1311 .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1312 });
1313
1314 auto Op0 = B.buildUndef(S96);
1315 auto Op1 = B.buildUndef(S96);
1316 auto Op2 = B.buildUndef(S1);
1317 auto SADDE = B.buildSAdde(S96, S1, Op0, Op1, Op2);
1318
1319 AInfo Info(MF->getSubtarget());
1320 DummyGISelObserver Observer;
1321 LegalizerHelper Helper(*MF, Info, Observer, B);
1322 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1323 Helper.narrowScalar(*SADDE, 0, S32));
1324
1325 const char *CheckStr = R"(
1326 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1327 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1328 CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1329 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1330 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1331 CHECK: [[SADDE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_
1332 CHECK: [[SADDE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1333 CHECK: [[SADDE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1334 CHECK: [[SADDE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SADDE0]]:_(s32), [[SADDE1]]:_(s32), [[SADDE2]]:_(s32)
1335 )";
1336
1337 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1338 }
1339
TEST_F(AArch64GISelMITest,NarrowSSUBE)1340 TEST_F(AArch64GISelMITest, NarrowSSUBE) {
1341 setUp();
1342 if (!TM)
1343 return;
1344
1345 LLT S1 = LLT::scalar(1);
1346 LLT S32 = LLT::scalar(32);
1347 LLT S96 = LLT::scalar(96);
1348 DefineLegalizerInfo(A, {
1349 getActionDefinitionsBuilder({G_SSUBE, G_USUBE})
1350 .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1351 });
1352
1353 auto Op0 = B.buildUndef(S96);
1354 auto Op1 = B.buildUndef(S96);
1355 auto Op2 = B.buildUndef(S1);
1356 auto SSUBE = B.buildSSube(S96, S1, Op0, Op1, Op2);
1357
1358 AInfo Info(MF->getSubtarget());
1359 DummyGISelObserver Observer;
1360 LegalizerHelper Helper(*MF, Info, Observer, B);
1361 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1362 Helper.narrowScalar(*SSUBE, 0, S32));
1363
1364 const char *CheckStr = R"(
1365 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1366 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1367 CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1368 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1369 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1370 CHECK: [[SSUBE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_
1371 CHECK: [[SSUBE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1372 CHECK: [[SSUBE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SSUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1373 CHECK: [[SSUBE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SSUBE0]]:_(s32), [[SSUBE1]]:_(s32), [[SSUBE2]]:_(s32)
1374 )";
1375
1376 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1377 }
1378
TEST_F(AArch64GISelMITest,FewerElementsAnd)1379 TEST_F(AArch64GISelMITest, FewerElementsAnd) {
1380 setUp();
1381 if (!TM)
1382 return;
1383
1384 const LLT V2S32 = LLT::fixed_vector(2, 32);
1385 const LLT V5S32 = LLT::fixed_vector(5, 32);
1386
1387 // Declare your legalization info
1388 DefineLegalizerInfo(A, {
1389 getActionDefinitionsBuilder(G_AND)
1390 .legalFor({s32});
1391 });
1392
1393 auto Op0 = B.buildUndef(V5S32);
1394 auto Op1 = B.buildUndef(V5S32);
1395 auto And = B.buildAnd(V5S32, Op0, Op1);
1396
1397 AInfo Info(MF->getSubtarget());
1398 DummyGISelObserver Observer;
1399 LegalizerHelper Helper(*MF, Info, Observer, B);
1400 B.setInstr(*And);
1401 EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) ==
1402 LegalizerHelper::LegalizeResult::Legalized);
1403
1404 auto CheckStr = R"(
1405 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
1406 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
1407 CHECK: [[VALUE0:%[0-9]+]]:_(s32), [[VALUE1:%[0-9]+]]:_(s32), [[VALUE2:%[0-9]+]]:_(s32), [[VALUE3:%[0-9]+]]:_(s32), [[VALUE4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]:_(<5 x s32>)
1408 CHECK: [[VECTOR0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE0]]:_(s32), [[VALUE1]]:_(s32)
1409 CHECK: [[VECTOR1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE2]]:_(s32), [[VALUE3]]:_(s32)
1410 CHECK: [[VALUE5:%[0-9]+]]:_(s32), [[VALUE6:%[0-9]+]]:_(s32), [[VALUE7:%[0-9]+]]:_(s32), [[VALUE8:%[0-9]+]]:_(s32), [[VALUE9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]:_(<5 x s32>)
1411 CHECK: [[VECTOR2:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE5]]:_(s32), [[VALUE6]]:_(s32)
1412 CHECK: [[VECTOR3:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE7]]:_(s32), [[VALUE8]]:_(s32)
1413 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[VECTOR0]]:_, [[VECTOR2]]:_
1414 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[VECTOR1]]:_, [[VECTOR3]]:_
1415 CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[VALUE4]]:_, [[VALUE9]]:_
1416 CHECK: [[AND0_E0:%[0-9]+]]:_(s32), [[AND0_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[AND0]]:_(<2 x s32>)
1417 CHECK: [[AND1_E0:%[0-9]+]]:_(s32), [[AND1_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[AND1]]:_(<2 x s32>)
1418 CHECK: [[RESULT:%[0-9]+]]:_(<5 x s32>) = G_BUILD_VECTOR [[AND0_E0]]:_(s32), [[AND0_E1]]:_(s32), [[AND1_E0]]:_(s32), [[AND1_E1]]:_(s32), [[AND2]]:_(s32)
1419 )";
1420
1421 // Check
1422 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1423 }
1424
TEST_F(AArch64GISelMITest,MoreElementsAnd)1425 TEST_F(AArch64GISelMITest, MoreElementsAnd) {
1426 setUp();
1427 if (!TM)
1428 return;
1429
1430 LLT s32 = LLT::scalar(32);
1431 LLT v2s32 = LLT::fixed_vector(2, 32);
1432 LLT v6s32 = LLT::fixed_vector(6, 32);
1433
1434 LegalizerInfo LI;
1435 LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
1436 .legalFor({v6s32})
1437 .clampMinNumElements(0, s32, 6);
1438 LI.getLegacyLegalizerInfo().computeTables();
1439
1440 DummyGISelObserver Observer;
1441 LegalizerHelper Helper(*MF, LI, Observer, B);
1442
1443 B.setInsertPt(*EntryMBB, EntryMBB->end());
1444
1445 auto Val0 = B.buildBitcast(v2s32, Copies[0]);
1446 auto Val1 = B.buildBitcast(v2s32, Copies[1]);
1447
1448 auto And = B.buildAnd(v2s32, Val0, Val1);
1449
1450 B.setInstr(*And);
1451 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1452 Helper.moreElementsVector(*And, 0, v6s32));
1453
1454 auto CheckStr = R"(
1455 CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
1456 CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
1457
1458 CHECK: [[BITCAST0_E0:%[0-9]+]]:_(s32), [[BITCAST0_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST0]]:_(<2 x s32>)
1459 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
1460 CHECK: [[BITCAST0_LARGE:%[0-9]+]]:_(<6 x s32>) = G_BUILD_VECTOR [[BITCAST0_E0]]:_(s32), [[BITCAST0_E1]]:_(s32), [[IMP_DEF0]]:_(s32), [[IMP_DEF0]]:_(s32), [[IMP_DEF0]]:_(s32), [[IMP_DEF0]]:_(s32)
1461
1462 CHECK: [[BITCAST1_E0:%[0-9]+]]:_(s32), [[BITCAST1_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST1]]:_(<2 x s32>)
1463 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
1464 CHECK: [[BITCAST1_LARGE:%[0-9]+]]:_(<6 x s32>) = G_BUILD_VECTOR [[BITCAST1_E0]]:_(s32), [[BITCAST1_E1]]:_(s32), [[IMP_DEF1]]:_(s32), [[IMP_DEF1]]:_(s32), [[IMP_DEF1]]:_(s32), [[IMP_DEF1]]:_(s32)
1465
1466 CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[BITCAST0_LARGE]]:_, [[BITCAST1_LARGE]]:_
1467
1468 CHECK: [[AND_E0:%[0-9]+]]:_(s32), [[AND_E1:%[0-9]+]]:_(s32), [[AND_E2:%[0-9]+]]:_(s32), [[AND_E3:%[0-9]+]]:_(s32), [[AND_E4:%[0-9]+]]:_(s32), [[AND_E5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[AND]]:_(<6 x s32>)
1469 CHECK: (<2 x s32>) = G_BUILD_VECTOR [[AND_E0]]:_(s32), [[AND_E1]]:_(s32)
1470 )";
1471
1472 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1473 }
1474
TEST_F(AArch64GISelMITest,FewerElementsPhi)1475 TEST_F(AArch64GISelMITest, FewerElementsPhi) {
1476 setUp();
1477 if (!TM)
1478 return;
1479
1480 LLT s1 = LLT::scalar(1);
1481 LLT s32 = LLT::scalar(32);
1482 LLT s64 = LLT::scalar(64);
1483 LLT v2s32 = LLT::fixed_vector(2, 32);
1484 LLT v5s32 = LLT::fixed_vector(5, 32);
1485
1486 LegalizerInfo LI;
1487 LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
1488 .legalFor({v2s32})
1489 .clampMinNumElements(0, s32, 2);
1490 LI.getLegacyLegalizerInfo().computeTables();
1491
1492 LLT PhiTy = v5s32;
1493 DummyGISelObserver Observer;
1494 LegalizerHelper Helper(*MF, LI, Observer, B);
1495 B.setMBB(*EntryMBB);
1496
1497 MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock();
1498 MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock();
1499 MF->insert(MF->end(), MidMBB);
1500 MF->insert(MF->end(), EndMBB);
1501
1502 EntryMBB->addSuccessor(MidMBB);
1503 EntryMBB->addSuccessor(EndMBB);
1504 MidMBB->addSuccessor(EndMBB);
1505
1506 auto InitVal = B.buildUndef(PhiTy);
1507 auto InitOtherVal = B.buildConstant(s64, 999);
1508
1509 auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
1510 B.buildBrCond(ICmp.getReg(0), *MidMBB);
1511 B.buildBr(*EndMBB);
1512
1513
1514 B.setMBB(*MidMBB);
1515 auto MidVal = B.buildUndef(PhiTy);
1516 auto MidOtherVal = B.buildConstant(s64, 345);
1517 B.buildBr(*EndMBB);
1518
1519 B.setMBB(*EndMBB);
1520 auto Phi = B.buildInstr(TargetOpcode::G_PHI)
1521 .addDef(MRI->createGenericVirtualRegister(PhiTy))
1522 .addUse(InitVal.getReg(0))
1523 .addMBB(EntryMBB)
1524 .addUse(MidVal.getReg(0))
1525 .addMBB(MidMBB);
1526
1527 // Insert another irrelevant phi to make sure the rebuild is inserted after
1528 // it.
1529 B.buildInstr(TargetOpcode::G_PHI)
1530 .addDef(MRI->createGenericVirtualRegister(s64))
1531 .addUse(InitOtherVal.getReg(0))
1532 .addMBB(EntryMBB)
1533 .addUse(MidOtherVal.getReg(0))
1534 .addMBB(MidMBB);
1535
1536 // Add some use instruction after the phis.
1537 B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0));
1538
1539 B.setInstr(*Phi);
1540 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1541 Helper.fewerElementsVector(*Phi, 0, v2s32));
1542
1543 auto CheckStr = R"(
1544 CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
1545 CHECK: [[INITVAL_E0:%[0-9]+]]:_(s32), [[INITVAL_E1:%[0-9]+]]:_(s32), [[INITVAL_E2:%[0-9]+]]:_(s32), [[INITVAL_E3:%[0-9]+]]:_(s32), [[INITVAL_E4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[INITVAL]]:_(<5 x s32>)
1546 CHECK: [[INITVAL_E01:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[INITVAL_E0]]:_(s32), [[INITVAL_E1]]:_(s32)
1547 CHECK: [[INITVAL_E23:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[INITVAL_E2]]:_(s32), [[INITVAL_E3]]:_(s32)
1548 CHECK: G_BRCOND
1549
1550 CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
1551 CHECK: [[MIDVAL_E0:%[0-9]+]]:_(s32), [[MIDVAL_E1:%[0-9]+]]:_(s32), [[MIDVAL_E2:%[0-9]+]]:_(s32), [[MIDVAL_E3:%[0-9]+]]:_(s32), [[MIDVAL_E4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[MIDVAL]]:_(<5 x s32>)
1552 CHECK: [[MIDVAL_E01:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[MIDVAL_E0]]:_(s32), [[MIDVAL_E1]]:_(s32)
1553 CHECK: [[MIDVAL_E23:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[MIDVAL_E2]]:_(s32), [[MIDVAL_E3]]:_(s32)
1554 CHECK: G_BR
1555
1556 CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[INITVAL_E01]]:_(<2 x s32>), %bb.0, [[MIDVAL_E01]]:_(<2 x s32>), %bb.1
1557 CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[INITVAL_E23]]:_(<2 x s32>), %bb.0, [[MIDVAL_E23]]:_(<2 x s32>), %bb.1
1558 CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[INITVAL_E4]]:_(s32), %bb.0, [[MIDVAL_E4]]:_(s32), %bb.1
1559 CHECK: [[UNMERGE0:%[0-9]+]]:_(s32), [[UNMERGE1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[PHI0]]:_(<2 x s32>)
1560 CHECK: [[UNMERGE2:%[0-9]+]]:_(s32), [[UNMERGE3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[PHI1]]:_(<2 x s32>)
1561 CHECK: [[BV:%[0-9]+]]:_(<5 x s32>) = G_BUILD_VECTOR [[UNMERGE0]]:_(s32), [[UNMERGE1]]:_(s32), [[UNMERGE2]]:_(s32), [[UNMERGE3]]:_(s32), [[PHI2]]:_(s32)
1562
1563 CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI
1564
1565 CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[BV]]:_, [[BV]]:_
1566 )";
1567
1568 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1569 }
1570
1571 // FNEG expansion in terms of XOR
TEST_F(AArch64GISelMITest,LowerFNEG)1572 TEST_F(AArch64GISelMITest, LowerFNEG) {
1573 setUp();
1574 if (!TM)
1575 return;
1576
1577 // Declare your legalization info
1578 DefineLegalizerInfo(A, {
1579 getActionDefinitionsBuilder(G_FSUB).legalFor({s64});
1580 });
1581
1582 // Build Instr. Make sure FMF are preserved.
1583 auto FAdd =
1584 B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]},
1585 MachineInstr::MIFlag::FmNsz);
1586
1587 // Should not propagate the flags of src instruction.
1588 auto FNeg0 =
1589 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)},
1590 {MachineInstr::MIFlag::FmArcp});
1591
1592 // Preserve the one flag.
1593 auto FNeg1 =
1594 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]},
1595 MachineInstr::MIFlag::FmNoInfs);
1596
1597 AInfo Info(MF->getSubtarget());
1598 DummyGISelObserver Observer;
1599 LegalizerHelper Helper(*MF, Info, Observer, B);
1600 // Perform Legalization
1601 B.setInstr(*FNeg0);
1602 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1603 Helper.lower(*FNeg0, 0, LLT::scalar(64)));
1604 B.setInstr(*FNeg1);
1605 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1606 Helper.lower(*FNeg1, 0, LLT::scalar(64)));
1607
1608 auto CheckStr = R"(
1609 CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_
1610 CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808
1611 CHECK: [[FSUB0:%[0-9]+]]:_(s64) = G_XOR [[FADD]]:_, [[CONST0]]:_
1612 CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808
1613 CHECK: [[FSUB1:%[0-9]+]]:_(s64) = G_XOR %0:_, [[CONST1]]:_
1614 )";
1615
1616 // Check
1617 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1618 }
1619
TEST_F(AArch64GISelMITest,LowerMinMax)1620 TEST_F(AArch64GISelMITest, LowerMinMax) {
1621 setUp();
1622 if (!TM)
1623 return;
1624
1625 LLT s64 = LLT::scalar(64);
1626 LLT v2s32 = LLT::fixed_vector(2, 32);
1627
1628 DefineLegalizerInfo(A, {
1629 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1630 .lowerFor({s64, LLT::fixed_vector(2, s32)});
1631 });
1632
1633 auto SMin = B.buildSMin(s64, Copies[0], Copies[1]);
1634 auto SMax = B.buildSMax(s64, Copies[0], Copies[1]);
1635 auto UMin = B.buildUMin(s64, Copies[0], Copies[1]);
1636 auto UMax = B.buildUMax(s64, Copies[0], Copies[1]);
1637
1638 auto VecVal0 = B.buildBitcast(v2s32, Copies[0]);
1639 auto VecVal1 = B.buildBitcast(v2s32, Copies[1]);
1640
1641 auto SMinV = B.buildSMin(v2s32, VecVal0, VecVal1);
1642 auto SMaxV = B.buildSMax(v2s32, VecVal0, VecVal1);
1643 auto UMinV = B.buildUMin(v2s32, VecVal0, VecVal1);
1644 auto UMaxV = B.buildUMax(v2s32, VecVal0, VecVal1);
1645
1646 AInfo Info(MF->getSubtarget());
1647 DummyGISelObserver Observer;
1648 LegalizerHelper Helper(*MF, Info, Observer, B);
1649 B.setInstr(*SMin);
1650 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1651 Helper.lower(*SMin, 0, s64));
1652 B.setInstr(*SMax);
1653 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1654 Helper.lower(*SMax, 0, s64));
1655 B.setInstr(*UMin);
1656 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1657 Helper.lower(*UMin, 0, s64));
1658 B.setInstr(*UMax);
1659 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1660 Helper.lower(*UMax, 0, s64));
1661
1662 B.setInstr(*SMinV);
1663 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1664 Helper.lower(*SMinV, 0, v2s32));
1665 B.setInstr(*SMaxV);
1666 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1667 Helper.lower(*SMaxV, 0, v2s32));
1668 B.setInstr(*UMinV);
1669 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1670 Helper.lower(*UMinV, 0, v2s32));
1671 B.setInstr(*UMaxV);
1672 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1673 Helper.lower(*UMaxV, 0, v2s32));
1674
1675 auto CheckStr = R"(
1676 CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_
1677 CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_
1678
1679 CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_
1680 CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_
1681
1682 CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_
1683 CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_
1684
1685 CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_
1686 CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_
1687
1688 CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
1689 CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
1690
1691 CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1692 CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1693
1694 CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1695 CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1696
1697 CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1698 CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1699
1700 CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1701 CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1702 )";
1703
1704 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1705 }
1706
TEST_F(AArch64GISelMITest,WidenScalarBuildVector)1707 TEST_F(AArch64GISelMITest, WidenScalarBuildVector) {
1708 setUp();
1709 if (!TM)
1710 return;
1711
1712 LLT S32 = LLT::scalar(32);
1713 LLT S16 = LLT::scalar(16);
1714 LLT V2S16 = LLT::fixed_vector(2, S16);
1715 LLT V2S32 = LLT::fixed_vector(2, S32);
1716
1717 DefineLegalizerInfo(A, {
1718 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1719 .lowerFor({s64, LLT::fixed_vector(2, s32)});
1720 });
1721
1722 AInfo Info(MF->getSubtarget());
1723 DummyGISelObserver Observer;
1724 LegalizerHelper Helper(*MF, Info, Observer, B);
1725 B.setInsertPt(*EntryMBB, EntryMBB->end());
1726
1727 Register Constant0 = B.buildConstant(S16, 1).getReg(0);
1728 Register Constant1 = B.buildConstant(S16, 2).getReg(0);
1729 auto BV0 = B.buildBuildVector(V2S16, {Constant0, Constant1});
1730 auto BV1 = B.buildBuildVector(V2S16, {Constant0, Constant1});
1731
1732 B.setInstr(*BV0);
1733 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1734 Helper.widenScalar(*BV0, 0, V2S32));
1735 B.setInstr(*BV1);
1736 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1737 Helper.widenScalar(*BV1, 1, S32));
1738
1739 auto CheckStr = R"(
1740 CHECK: [[K0:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
1741 CHECK-NEXT: [[K1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
1742 CHECK-NEXT: [[EXT_K0_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
1743 CHECK-NEXT: [[EXT_K1_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
1744 CHECK-NEXT: [[BV0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[EXT_K0_0]]:_(s32), [[EXT_K1_0]]:_(s32)
1745 CHECK-NEXT: [[BV0_TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BV0]]
1746
1747 CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
1748 CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
1749
1750 CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32)
1751 )";
1752
1753 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1754 }
1755
TEST_F(AArch64GISelMITest,LowerMergeValues)1756 TEST_F(AArch64GISelMITest, LowerMergeValues) {
1757 setUp();
1758 if (!TM)
1759 return;
1760
1761 const LLT S32 = LLT::scalar(32);
1762 const LLT S24 = LLT::scalar(24);
1763 const LLT S21 = LLT::scalar(21);
1764 const LLT S16 = LLT::scalar(16);
1765 const LLT S9 = LLT::scalar(9);
1766 const LLT S8 = LLT::scalar(8);
1767 const LLT S3 = LLT::scalar(3);
1768
1769 DefineLegalizerInfo(A, {
1770 getActionDefinitionsBuilder(G_UNMERGE_VALUES)
1771 .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9)));
1772 });
1773
1774 AInfo Info(MF->getSubtarget());
1775 DummyGISelObserver Observer;
1776 LegalizerHelper Helper(*MF, Info, Observer, B);
1777 B.setInsertPt(*EntryMBB, EntryMBB->end());
1778
1779 // 24 = 3 3 3 3 3 3 3 3
1780 // => 9
1781 //
1782 // This can do 3 merges, but need an extra implicit_def.
1783 SmallVector<Register, 8> Merge0Ops;
1784 for (int I = 0; I != 8; ++I)
1785 Merge0Ops.push_back(B.buildConstant(S3, I).getReg(0));
1786
1787 auto Merge0 = B.buildMerge(S24, Merge0Ops);
1788
1789 // 21 = 3 3 3 3 3 3 3
1790 // => 9, 2 extra implicit_def needed
1791 //
1792 SmallVector<Register, 8> Merge1Ops;
1793 for (int I = 0; I != 7; ++I)
1794 Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0));
1795
1796 auto Merge1 = B.buildMerge(S21, Merge1Ops);
1797
1798 SmallVector<Register, 8> Merge2Ops;
1799 for (int I = 0; I != 2; ++I)
1800 Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0));
1801
1802 auto Merge2 = B.buildMerge(S16, Merge2Ops);
1803
1804 B.setInstr(*Merge0);
1805 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1806 Helper.widenScalar(*Merge0, 1, S9));
1807 B.setInstr(*Merge1);
1808 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1809 Helper.widenScalar(*Merge1, 1, S9));
1810
1811 // Request a source size greater than the original destination size.
1812 B.setInstr(*Merge2);
1813 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1814 Helper.widenScalar(*Merge2, 1, S32));
1815
1816 auto CheckStr = R"(
1817 CHECK: [[K0:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
1818 CHECK-NEXT: [[K1:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
1819 CHECK-NEXT: [[K2:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
1820 CHECK-NEXT: [[K3:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
1821 CHECK-NEXT: [[K4:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
1822 CHECK-NEXT: [[K5:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1823 CHECK-NEXT: [[K6:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1824 CHECK-NEXT: [[K7:%[0-9]+]]:_(s3) = G_CONSTANT i3 -1
1825 CHECK-NEXT: [[IMPDEF0:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1826 CHECK-NEXT: [[MERGE0:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K0]]:_(s3), [[K1]]:_(s3), [[K2]]:_(s3)
1827 CHECK-NEXT: [[MERGE1:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K3]]:_(s3), [[K4]]:_(s3), [[K5]]:_(s3)
1828 CHECK-NEXT: [[MERGE2:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K6]]:_(s3), [[K7]]:_(s3), [[IMPDEF0]]:_(s3)
1829 CHECK-NEXT: [[MERGE3:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE0]]:_(s9), [[MERGE1]]:_(s9), [[MERGE2]]:_(s9)
1830 CHECK-NEXT: (s24) = G_TRUNC [[MERGE3]]:_(s27)
1831
1832
1833 CHECK: [[K8:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
1834 CHECK-NEXT: [[K9:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
1835 CHECK-NEXT: [[K10:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
1836 CHECK-NEXT: [[K11:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
1837 CHECK-NEXT: [[K12:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
1838 CHECK-NEXT: [[K13:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1839 CHECK-NEXT: [[K14:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1840 CHECK-NEXT: [[IMPDEF1:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1841 CHECK-NEXT: [[MERGE4:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K8]]:_(s3), [[K9]]:_(s3), [[K10]]:_(s3)
1842 CHECK-NEXT: [[MERGE5:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K11]]:_(s3), [[K12]]:_(s3), [[K13]]:_(s3)
1843 CHECK-NEXT: [[MERGE6:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K14]]:_(s3), [[IMPDEF1]]:_(s3), [[IMPDEF1]]:_(s3)
1844 CHECK-NEXT: [[MERGE7:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE4]]:_(s9), [[MERGE5]]:_(s9), [[MERGE6]]:_(s9)
1845 CHECK-NEXT: (s21) = G_TRUNC [[MERGE7]]:_(s27)
1846
1847
1848 CHECK: [[K15:%[0-9]+]]:_(s8) = G_CONSTANT i8 0
1849 CHECK-NEXT: [[K16:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
1850 CHECK-NEXT: [[ZEXT_K15:[0-9]+]]:_(s32) = G_ZEXT [[K15]]:_(s8)
1851 CHECK-NEXT: [[ZEXT_K16:[0-9]+]]:_(s32) = G_ZEXT [[K16]]:_(s8)
1852 [[K16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1853 [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT_K16]]:_, [[K16]]:_(s32)
1854 [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT_K16]]:_, [[SHL]]:_
1855 (s16) = G_TRUNC [[OR]]:_(s32)
1856 )";
1857
1858 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1859 }
1860
TEST_F(AArch64GISelMITest,WidenScalarMergeValuesPointer)1861 TEST_F(AArch64GISelMITest, WidenScalarMergeValuesPointer) {
1862 setUp();
1863 if (!TM)
1864 return;
1865
1866 DefineLegalizerInfo(A, {});
1867
1868 AInfo Info(MF->getSubtarget());
1869 DummyGISelObserver Observer;
1870 LegalizerHelper Helper(*MF, Info, Observer, B);
1871 B.setInsertPt(*EntryMBB, EntryMBB->end());
1872
1873 const LLT S32 = LLT::scalar(32);
1874 const LLT S64 = LLT::scalar(64);
1875 const LLT P0 = LLT::pointer(0, 64);
1876
1877 auto Lo = B.buildTrunc(S32, Copies[0]);
1878 auto Hi = B.buildTrunc(S32, Copies[1]);
1879
1880 auto Merge = B.buildMerge(P0, {Lo, Hi});
1881
1882 B.setInstr(*Merge);
1883 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1884 Helper.widenScalar(*Merge, 1, S64));
1885
1886 auto CheckStr = R"(
1887 CHECK: [[TRUNC0:%[0-9]+]]:_(s32) = G_TRUNC
1888 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC
1889 CHECK: [[ZEXT_TRUNC0:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC0]]
1890 CHECK: [[ZEXT_TRUNC1:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC1]]
1891 CHECK: [[SHIFT_AMT:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
1892 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT_TRUNC1]]:_, [[SHIFT_AMT]]
1893 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[ZEXT_TRUNC0]]:_, [[SHL]]
1894 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]:_(s64)
1895 )";
1896
1897 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1898 }
1899
TEST_F(AArch64GISelMITest,WidenSEXTINREG)1900 TEST_F(AArch64GISelMITest, WidenSEXTINREG) {
1901 setUp();
1902 if (!TM)
1903 return;
1904
1905 // Declare your legalization info
1906 DefineLegalizerInfo(A, {
1907 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1908 });
1909 // Build Instr
1910 auto MIB = B.buildInstr(
1911 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1912 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1913 uint64_t(8)});
1914 AInfo Info(MF->getSubtarget());
1915 DummyGISelObserver Observer;
1916 LegalizerHelper Helper(*MF, Info, Observer, B);
1917 // Perform Legalization
1918 B.setInstr(*MIB);
1919 ASSERT_TRUE(Helper.widenScalar(*MIB, 0, LLT::scalar(64)) ==
1920 LegalizerHelper::LegalizeResult::Legalized);
1921
1922 auto CheckStr = R"(
1923 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1924 CHECK: [[T1:%[0-9]+]]:_(s64) = G_ANYEXT [[T0]]:_(s32)
1925 CHECK: [[T2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[T1]]:_, 8
1926 CHECK: [[T3:%[0-9]+]]:_(s32) = G_TRUNC [[T2]]:_(s64)
1927 )";
1928
1929 // Check
1930 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1931 }
1932
TEST_F(AArch64GISelMITest,NarrowSEXTINREG)1933 TEST_F(AArch64GISelMITest, NarrowSEXTINREG) {
1934 setUp();
1935 if (!TM)
1936 return;
1937
1938 // Declare your legalization info, these aren't actually relevant to the test.
1939 DefineLegalizerInfo(A, {
1940 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1941 });
1942 // Build Instr
1943 auto MIB = B.buildInstr(
1944 TargetOpcode::G_SEXT_INREG, {LLT::scalar(16)},
1945 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(16)}, {Copies[0]}),
1946 uint64_t(8)});
1947 AInfo Info(MF->getSubtarget());
1948 DummyGISelObserver Observer;
1949 LegalizerHelper Helper(*MF, Info, Observer, B);
1950 // Perform Legalization
1951 B.setInstr(*MIB);
1952 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(10)) ==
1953 LegalizerHelper::LegalizeResult::Legalized);
1954
1955 auto CheckStr = R"(
1956 CHECK: [[T0:%[0-9]+]]:_(s16) = G_TRUNC
1957 CHECK: [[T1:%[0-9]+]]:_(s10) = G_TRUNC [[T0]]:_(s16)
1958 CHECK: [[T2:%[0-9]+]]:_(s10) = G_SEXT_INREG [[T1]]:_, 8
1959 CHECK: [[T3:%[0-9]+]]:_(s16) = G_SEXT [[T2]]:_(s10)
1960 )";
1961
1962 // Check
1963 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1964 }
1965
TEST_F(AArch64GISelMITest,NarrowSEXTINREG2)1966 TEST_F(AArch64GISelMITest, NarrowSEXTINREG2) {
1967 setUp();
1968 if (!TM)
1969 return;
1970
1971 // Declare your legalization info, these aren't actually relevant to the test.
1972 DefineLegalizerInfo(
1973 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
1974 // Build Instr
1975 auto MIB = B.buildInstr(
1976 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1977 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1978 uint64_t(9)});
1979 AInfo Info(MF->getSubtarget());
1980 DummyGISelObserver Observer;
1981 LegalizerHelper Helper(*MF, Info, Observer, B);
1982 // Perform Legalization
1983 B.setInstr(*MIB);
1984 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(8)) ==
1985 LegalizerHelper::LegalizeResult::Legalized);
1986
1987 auto CheckStr = R"(
1988 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1989 CHECK: [[T1:%[0-9]+]]:_(s8), [[T2:%[0-9]+]]:_(s8), [[T3:%[0-9]+]]:_(s8), [[T4:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[T0]]:_(s32)
1990 CHECK: [[CST2:%[0-9]+]]:_(s8) = G_CONSTANT i8 7
1991 CHECK: [[T5:%[0-9]+]]:_(s8) = G_SEXT_INREG [[T2]]:_, 1
1992 CHECK: [[T6:%[0-9]+]]:_(s8) = G_ASHR [[T5]]:_, [[CST2]]:_
1993 CHECK: [[T7:%[0-9]+]]:_(s32) = G_MERGE_VALUES [[T1]]:_(s8), [[T5]]:_(s8), [[T6]]:_(s8), [[T6]]:_(s8)
1994 )";
1995
1996 // Check
1997 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1998 }
1999
TEST_F(AArch64GISelMITest,LowerSEXTINREG)2000 TEST_F(AArch64GISelMITest, LowerSEXTINREG) {
2001 setUp();
2002 if (!TM)
2003 return;
2004
2005 // Declare your legalization info, these aren't actually relevant to the test.
2006 DefineLegalizerInfo(
2007 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
2008 // Build Instr
2009 auto MIB = B.buildInstr(
2010 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
2011 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
2012 uint64_t(8)});
2013 AInfo Info(MF->getSubtarget());
2014 DummyGISelObserver Observer;
2015 LegalizerHelper Helper(*MF, Info, Observer, B);
2016 // Perform Legalization
2017 B.setInstr(*MIB);
2018 ASSERT_TRUE(Helper.lower(*MIB, 0, LLT()) ==
2019 LegalizerHelper::LegalizeResult::Legalized);
2020
2021 auto CheckStr = R"(
2022 CHECK: [[T1:%[0-9]+]]:_(s32) = G_TRUNC
2023 CHECK: [[CST:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
2024 CHECK: [[T2:%[0-9]+]]:_(s32) = G_SHL [[T1]]:_, [[CST]]:_
2025 CHECK: [[T3:%[0-9]+]]:_(s32) = G_ASHR [[T2]]:_, [[CST]]:_
2026 )";
2027
2028 // Check
2029 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
2030 }
2031
TEST_F(AArch64GISelMITest,LibcallFPExt)2032 TEST_F(AArch64GISelMITest, LibcallFPExt) {
2033 setUp();
2034 if (!TM)
2035 return;
2036
2037 // Declare your legalization info
2038 DefineLegalizerInfo(A, {
2039 getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s32, s16}, {s128, s64}});
2040 });
2041
2042 LLT S16{LLT::scalar(16)};
2043 LLT S32{LLT::scalar(32)};
2044 LLT S128{LLT::scalar(128)};
2045 auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
2046 auto MIBFPExt1 =
2047 B.buildInstr(TargetOpcode::G_FPEXT, {S32}, {MIBTrunc});
2048
2049 auto MIBFPExt2 =
2050 B.buildInstr(TargetOpcode::G_FPEXT, {S128}, {Copies[1]});
2051 AInfo Info(MF->getSubtarget());
2052 DummyGISelObserver Observer;
2053 LegalizerHelper Helper(*MF, Info, Observer, B);
2054 LostDebugLocObserver DummyLocObserver("");
2055 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2056 Helper.libcall(*MIBFPExt1, DummyLocObserver));
2057
2058 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2059 Helper.libcall(*MIBFPExt2, DummyLocObserver));
2060 auto CheckStr = R"(
2061 CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC
2062 CHECK: $h0 = COPY [[TRUNC]]
2063 CHECK: BL &__gnu_h2f_ieee
2064 CHECK: $d0 = COPY
2065 CHECK: BL &__extenddftf2
2066 )";
2067
2068 // Check
2069 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2070 }
2071
TEST_F(AArch64GISelMITest,LibcallFPTrunc)2072 TEST_F(AArch64GISelMITest, LibcallFPTrunc) {
2073 setUp();
2074 if (!TM)
2075 return;
2076
2077 // Declare your legalization info
2078 DefineLegalizerInfo(A, {
2079 getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s16, s32}, {s64, s128}});
2080 });
2081
2082 LLT S16{LLT::scalar(16)};
2083 LLT S32{LLT::scalar(32)};
2084 LLT S64{LLT::scalar(64)};
2085 LLT S128{LLT::scalar(128)};
2086 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2087 auto MIBFPTrunc1 =
2088 B.buildInstr(TargetOpcode::G_FPTRUNC, {S16}, {MIBTrunc});
2089
2090 auto MIBMerge = B.buildMerge(S128, {Copies[1], Copies[2]});
2091
2092 auto MIBFPTrunc2 =
2093 B.buildInstr(TargetOpcode::G_FPTRUNC, {S64}, {MIBMerge});
2094 AInfo Info(MF->getSubtarget());
2095 DummyGISelObserver Observer;
2096 LostDebugLocObserver DummyLocObserver("");
2097 LegalizerHelper Helper(*MF, Info, Observer, B);
2098 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2099 Helper.libcall(*MIBFPTrunc1, DummyLocObserver));
2100
2101 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2102 Helper.libcall(*MIBFPTrunc2, DummyLocObserver));
2103 auto CheckStr = R"(
2104 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2105 CHECK: $s0 = COPY [[TRUNC]]
2106 CHECK: BL &__gnu_f2h_ieee
2107 CHECK: $q0 = COPY
2108 CHECK: BL &__trunctfdf2
2109 )";
2110
2111 // Check
2112 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2113 }
2114
TEST_F(AArch64GISelMITest,LibcallSimple)2115 TEST_F(AArch64GISelMITest, LibcallSimple) {
2116 setUp();
2117 if (!TM)
2118 return;
2119
2120 // Declare your legalization info
2121 DefineLegalizerInfo(A, {
2122 getActionDefinitionsBuilder(G_FADD).libcallFor({s16});
2123 });
2124
2125 LLT S16{LLT::scalar(16)};
2126 auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
2127 auto MIBFADD =
2128 B.buildInstr(TargetOpcode::G_FADD, {S16}, {MIBTrunc, MIBTrunc});
2129
2130 AInfo Info(MF->getSubtarget());
2131 DummyGISelObserver Observer;
2132 LostDebugLocObserver DummyLocObserver("");
2133 LegalizerHelper Helper(*MF, Info, Observer, B);
2134 // Make sure we do not crash anymore
2135 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
2136 Helper.libcall(*MIBFADD, DummyLocObserver));
2137 }
2138
TEST_F(AArch64GISelMITest,LibcallSRem)2139 TEST_F(AArch64GISelMITest, LibcallSRem) {
2140 setUp();
2141 if (!TM)
2142 return;
2143
2144 // Declare your legalization info
2145 DefineLegalizerInfo(A, {
2146 getActionDefinitionsBuilder(G_SREM).libcallFor({s32, s64, s128});
2147 });
2148
2149 LLT S32{LLT::scalar(32)};
2150 LLT S64{LLT::scalar(64)};
2151 LLT S128{LLT::scalar(128)};
2152 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2153 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2154
2155 auto MIBSRem32 =
2156 B.buildInstr(TargetOpcode::G_SREM, {S32}, {MIBTrunc, MIBTrunc});
2157 auto MIBSRem64 =
2158 B.buildInstr(TargetOpcode::G_SREM, {S64}, {Copies[0], Copies[0]});
2159 auto MIBSRem128 =
2160 B.buildInstr(TargetOpcode::G_SREM, {S128}, {MIBExt, MIBExt});
2161
2162 AInfo Info(MF->getSubtarget());
2163 DummyGISelObserver Observer;
2164 LostDebugLocObserver DummyLocObserver("");
2165 LegalizerHelper Helper(*MF, Info, Observer, B);
2166
2167 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2168 Helper.libcall(*MIBSRem32, DummyLocObserver));
2169 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2170 Helper.libcall(*MIBSRem64, DummyLocObserver));
2171 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2172 Helper.libcall(*MIBSRem128, DummyLocObserver));
2173
2174 auto CheckStr = R"(
2175 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2176 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2177 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2178 CHECK: $w0 = COPY [[TRUNC]]
2179 CHECK: $w1 = COPY [[TRUNC]]
2180 CHECK: BL &__modsi3
2181 CHECK: $x0 = COPY [[COPY]]
2182 CHECK: $x1 = COPY [[COPY]]
2183 CHECK: BL &__moddi3
2184 CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2185 CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2186 CHECK: $x0 = COPY [[UV]]
2187 CHECK: $x1 = COPY [[UV1]]
2188 CHECK: $x2 = COPY [[UV2]]
2189 CHECK: $x3 = COPY [[UV3]]
2190 CHECK: BL &__modti3
2191 )";
2192
2193 // Check
2194 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2195 }
2196
TEST_F(AArch64GISelMITest,LibcallURem)2197 TEST_F(AArch64GISelMITest, LibcallURem) {
2198 setUp();
2199 if (!TM)
2200 return;
2201
2202 // Declare your legalization info
2203 DefineLegalizerInfo(A, {
2204 getActionDefinitionsBuilder(G_UREM).libcallFor({s32, s64, s128});
2205 });
2206
2207 LLT S32{LLT::scalar(32)};
2208 LLT S64{LLT::scalar(64)};
2209 LLT S128{LLT::scalar(128)};
2210 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2211 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2212
2213 auto MIBURem32 =
2214 B.buildInstr(TargetOpcode::G_UREM, {S32}, {MIBTrunc, MIBTrunc});
2215 auto MIBURem64 =
2216 B.buildInstr(TargetOpcode::G_UREM, {S64}, {Copies[0], Copies[0]});
2217 auto MIBURem128 =
2218 B.buildInstr(TargetOpcode::G_UREM, {S128}, {MIBExt, MIBExt});
2219
2220 AInfo Info(MF->getSubtarget());
2221 DummyGISelObserver Observer;
2222 LostDebugLocObserver DummyLocObserver("");
2223 LegalizerHelper Helper(*MF, Info, Observer, B);
2224
2225 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2226 Helper.libcall(*MIBURem32, DummyLocObserver));
2227 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2228 Helper.libcall(*MIBURem64, DummyLocObserver));
2229 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2230 Helper.libcall(*MIBURem128, DummyLocObserver));
2231
2232 const auto *CheckStr = R"(
2233 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2234 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2235 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2236 CHECK: $w0 = COPY [[TRUNC]]
2237 CHECK: $w1 = COPY [[TRUNC]]
2238 CHECK: BL &__umodsi3
2239 CHECK: $x0 = COPY [[COPY]]
2240 CHECK: $x1 = COPY [[COPY]]
2241 CHECK: BL &__umoddi3
2242 CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2243 CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2244 CHECK: $x0 = COPY [[UV]]
2245 CHECK: $x1 = COPY [[UV1]]
2246 CHECK: $x2 = COPY [[UV2]]
2247 CHECK: $x3 = COPY [[UV3]]
2248 CHECK: BL &__umodti3
2249 )";
2250
2251 // Check
2252 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2253 }
2254
TEST_F(AArch64GISelMITest,LibcallCtlzZeroUndef)2255 TEST_F(AArch64GISelMITest, LibcallCtlzZeroUndef) {
2256 setUp();
2257 if (!TM)
2258 return;
2259
2260 // Declare your legalization info
2261 DefineLegalizerInfo(A, {
2262 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF)
2263 .libcallFor({{s32, s32}, {s64, s64}, {s128, s128}});
2264 });
2265
2266 LLT S32{LLT::scalar(32)};
2267 LLT S64{LLT::scalar(64)};
2268 LLT S128{LLT::scalar(128)};
2269 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2270 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2271
2272 auto MIBCtlz32 =
2273 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S32}, {MIBTrunc});
2274 auto MIBCtlz64 =
2275 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S64}, {Copies[0]});
2276 auto MIBCtlz128 =
2277 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S128}, {MIBExt});
2278
2279 AInfo Info(MF->getSubtarget());
2280 DummyGISelObserver Observer;
2281 LostDebugLocObserver DummyLocObserver("");
2282 LegalizerHelper Helper(*MF, Info, Observer, B);
2283
2284 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2285 Helper.libcall(*MIBCtlz32, DummyLocObserver));
2286 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2287 Helper.libcall(*MIBCtlz64, DummyLocObserver));
2288 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2289 Helper.libcall(*MIBCtlz128, DummyLocObserver));
2290
2291 const auto *CheckStr = R"(
2292 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2293 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2294 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2295 CHECK: $w0 = COPY [[TRUNC]]
2296 CHECK: BL &__clzsi2
2297 CHECK: $x0 = COPY [[COPY]]
2298 CHECK: BL &__clzdi2
2299 CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2300 CHECK: $x0 = COPY [[UV]]
2301 CHECK: $x1 = COPY [[UV1]]
2302 CHECK: BL &__clzti2
2303 )";
2304
2305 // Check
2306 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2307 }
2308
TEST_F(AArch64GISelMITest,LibcallFAdd)2309 TEST_F(AArch64GISelMITest, LibcallFAdd) {
2310 setUp();
2311 if (!TM)
2312 return;
2313
2314 // Declare your legalization info
2315 DefineLegalizerInfo(A, {
2316 getActionDefinitionsBuilder(G_FADD).libcallFor({s32, s64, s128});
2317 });
2318
2319 LLT S32{LLT::scalar(32)};
2320 LLT S64{LLT::scalar(64)};
2321 LLT S128{LLT::scalar(128)};
2322 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2323 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2324
2325 auto MIBAdd32 =
2326 B.buildInstr(TargetOpcode::G_FADD, {S32}, {MIBTrunc, MIBTrunc});
2327 auto MIBAdd64 =
2328 B.buildInstr(TargetOpcode::G_FADD, {S64}, {Copies[0], Copies[0]});
2329 auto MIBAdd128 = B.buildInstr(TargetOpcode::G_FADD, {S128}, {MIBExt, MIBExt});
2330
2331 AInfo Info(MF->getSubtarget());
2332 DummyGISelObserver Observer;
2333 LostDebugLocObserver DummyLocObserver("");
2334 LegalizerHelper Helper(*MF, Info, Observer, B);
2335
2336 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2337 Helper.libcall(*MIBAdd32, DummyLocObserver));
2338 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2339 Helper.libcall(*MIBAdd64, DummyLocObserver));
2340 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2341 Helper.libcall(*MIBAdd128, DummyLocObserver));
2342
2343 const auto *CheckStr = R"(
2344 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2345 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2346 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2347 CHECK: $s0 = COPY [[TRUNC]]
2348 CHECK: $s1 = COPY [[TRUNC]]
2349 CHECK: BL &__addsf3
2350 CHECK: $d0 = COPY [[COPY]]
2351 CHECK: $d1 = COPY [[COPY]]
2352 CHECK: BL &__adddf3
2353 CHECK: $q0 = COPY [[ANYEXT]]
2354 CHECK: $q1 = COPY [[ANYEXT]]
2355 CHECK: BL &__addtf3
2356 )";
2357
2358 // Check
2359 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2360 }
2361
TEST_F(AArch64GISelMITest,LibcallFSub)2362 TEST_F(AArch64GISelMITest, LibcallFSub) {
2363 setUp();
2364 if (!TM)
2365 return;
2366
2367 // Declare your legalization info
2368 DefineLegalizerInfo(A, {
2369 getActionDefinitionsBuilder(G_FSUB).libcallFor({s32, s64, s128});
2370 });
2371
2372 LLT S32{LLT::scalar(32)};
2373 LLT S64{LLT::scalar(64)};
2374 LLT S128{LLT::scalar(128)};
2375 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2376 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2377
2378 auto MIBSub32 =
2379 B.buildInstr(TargetOpcode::G_FSUB, {S32}, {MIBTrunc, MIBTrunc});
2380 auto MIBSub64 =
2381 B.buildInstr(TargetOpcode::G_FSUB, {S64}, {Copies[0], Copies[0]});
2382 auto MIBSub128 = B.buildInstr(TargetOpcode::G_FSUB, {S128}, {MIBExt, MIBExt});
2383
2384 AInfo Info(MF->getSubtarget());
2385 DummyGISelObserver Observer;
2386 LostDebugLocObserver DummyLocObserver("");
2387 LegalizerHelper Helper(*MF, Info, Observer, B);
2388
2389 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2390 Helper.libcall(*MIBSub32, DummyLocObserver));
2391 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2392 Helper.libcall(*MIBSub64, DummyLocObserver));
2393 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2394 Helper.libcall(*MIBSub128, DummyLocObserver));
2395
2396 const auto *CheckStr = R"(
2397 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2398 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2399 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2400 CHECK: $s0 = COPY [[TRUNC]]
2401 CHECK: $s1 = COPY [[TRUNC]]
2402 CHECK: BL &__subsf3
2403 CHECK: $d0 = COPY [[COPY]]
2404 CHECK: $d1 = COPY [[COPY]]
2405 CHECK: BL &__subdf3
2406 CHECK: $q0 = COPY [[ANYEXT]]
2407 CHECK: $q1 = COPY [[ANYEXT]]
2408 CHECK: BL &__subtf3
2409 )";
2410
2411 // Check
2412 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2413 }
2414
TEST_F(AArch64GISelMITest,LibcallFMul)2415 TEST_F(AArch64GISelMITest, LibcallFMul) {
2416 setUp();
2417 if (!TM)
2418 return;
2419
2420 // Declare your legalization info
2421 DefineLegalizerInfo(A, {
2422 getActionDefinitionsBuilder(G_FMUL).libcallFor({s32, s64, s128});
2423 });
2424
2425 LLT S32{LLT::scalar(32)};
2426 LLT S64{LLT::scalar(64)};
2427 LLT S128{LLT::scalar(128)};
2428 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2429 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2430
2431 auto MIBMul32 =
2432 B.buildInstr(TargetOpcode::G_FMUL, {S32}, {MIBTrunc, MIBTrunc});
2433 auto MIBMul64 =
2434 B.buildInstr(TargetOpcode::G_FMUL, {S64}, {Copies[0], Copies[0]});
2435 auto MIBMul128 = B.buildInstr(TargetOpcode::G_FMUL, {S128}, {MIBExt, MIBExt});
2436
2437 AInfo Info(MF->getSubtarget());
2438 DummyGISelObserver Observer;
2439 LegalizerHelper Helper(*MF, Info, Observer, B);
2440 LostDebugLocObserver DummyLocObserver("");
2441
2442 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2443 Helper.libcall(*MIBMul32, DummyLocObserver));
2444 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2445 Helper.libcall(*MIBMul64, DummyLocObserver));
2446 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2447 Helper.libcall(*MIBMul128, DummyLocObserver));
2448
2449 const auto *CheckStr = R"(
2450 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2451 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2452 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2453 CHECK: $s0 = COPY [[TRUNC]]
2454 CHECK: $s1 = COPY [[TRUNC]]
2455 CHECK: BL &__mulsf3
2456 CHECK: $d0 = COPY [[COPY]]
2457 CHECK: $d1 = COPY [[COPY]]
2458 CHECK: BL &__muldf3
2459 CHECK: $q0 = COPY [[ANYEXT]]
2460 CHECK: $q1 = COPY [[ANYEXT]]
2461 CHECK: BL &__multf3
2462 )";
2463
2464 // Check
2465 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2466 }
2467
TEST_F(AArch64GISelMITest,LibcallFDiv)2468 TEST_F(AArch64GISelMITest, LibcallFDiv) {
2469 setUp();
2470 if (!TM)
2471 return;
2472
2473 // Declare your legalization info
2474 DefineLegalizerInfo(A, {
2475 getActionDefinitionsBuilder(G_FDIV).libcallFor({s32, s64, s128});
2476 });
2477
2478 LLT S32{LLT::scalar(32)};
2479 LLT S64{LLT::scalar(64)};
2480 LLT S128{LLT::scalar(128)};
2481 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2482 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2483
2484 auto MIBDiv32 =
2485 B.buildInstr(TargetOpcode::G_FDIV, {S32}, {MIBTrunc, MIBTrunc});
2486 auto MIBDiv64 =
2487 B.buildInstr(TargetOpcode::G_FDIV, {S64}, {Copies[0], Copies[0]});
2488 auto MIBDiv128 = B.buildInstr(TargetOpcode::G_FDIV, {S128}, {MIBExt, MIBExt});
2489
2490 AInfo Info(MF->getSubtarget());
2491 DummyGISelObserver Observer;
2492 LostDebugLocObserver DummyLocObserver("");
2493 LegalizerHelper Helper(*MF, Info, Observer, B);
2494
2495 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2496 Helper.libcall(*MIBDiv32, DummyLocObserver));
2497 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2498 Helper.libcall(*MIBDiv64, DummyLocObserver));
2499 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2500 Helper.libcall(*MIBDiv128, DummyLocObserver));
2501
2502 const auto *CheckStr = R"(
2503 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2504 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2505 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2506 CHECK: $s0 = COPY [[TRUNC]]
2507 CHECK: $s1 = COPY [[TRUNC]]
2508 CHECK: BL &__divsf3
2509 CHECK: $d0 = COPY [[COPY]]
2510 CHECK: $d1 = COPY [[COPY]]
2511 CHECK: BL &__divdf3
2512 CHECK: $q0 = COPY [[ANYEXT]]
2513 CHECK: $q1 = COPY [[ANYEXT]]
2514 CHECK: BL &__divtf3
2515 )";
2516
2517 // Check
2518 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2519 }
2520
TEST_F(AArch64GISelMITest,LibcallFExp)2521 TEST_F(AArch64GISelMITest, LibcallFExp) {
2522 setUp();
2523 if (!TM)
2524 return;
2525
2526 // Declare your legalization info
2527 DefineLegalizerInfo(A, {
2528 getActionDefinitionsBuilder(G_FEXP).libcallFor({s32, s64, s128});
2529 });
2530
2531 LLT S32{LLT::scalar(32)};
2532 LLT S64{LLT::scalar(64)};
2533 LLT S128{LLT::scalar(128)};
2534 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2535 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2536
2537 auto MIBExp32 = B.buildInstr(TargetOpcode::G_FEXP, {S32}, {MIBTrunc});
2538 auto MIBExp64 = B.buildInstr(TargetOpcode::G_FEXP, {S64}, {Copies[0]});
2539 auto MIBExp128 = B.buildInstr(TargetOpcode::G_FEXP, {S128}, {MIBExt});
2540
2541 AInfo Info(MF->getSubtarget());
2542 DummyGISelObserver Observer;
2543 LostDebugLocObserver DummyLocObserver("");
2544 LegalizerHelper Helper(*MF, Info, Observer, B);
2545
2546 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2547 Helper.libcall(*MIBExp32, DummyLocObserver));
2548 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2549 Helper.libcall(*MIBExp64, DummyLocObserver));
2550 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2551 Helper.libcall(*MIBExp128, DummyLocObserver));
2552
2553 const auto *CheckStr = R"(
2554 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2555 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2556 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2557 CHECK: $s0 = COPY [[TRUNC]]
2558 CHECK: BL &expf
2559 CHECK: $d0 = COPY [[COPY]]
2560 CHECK: BL &exp
2561 CHECK: $q0 = COPY [[ANYEXT]]
2562 CHECK: BL &expl
2563 )";
2564
2565 // Check
2566 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2567 }
2568
TEST_F(AArch64GISelMITest,LibcallFExp2)2569 TEST_F(AArch64GISelMITest, LibcallFExp2) {
2570 setUp();
2571 if (!TM)
2572 return;
2573
2574 // Declare your legalization info
2575 DefineLegalizerInfo(A, {
2576 getActionDefinitionsBuilder(G_FEXP2).libcallFor({s32, s64, s128});
2577 });
2578
2579 LLT S32{LLT::scalar(32)};
2580 LLT S64{LLT::scalar(64)};
2581 LLT S128{LLT::scalar(128)};
2582 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2583 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2584
2585 auto MIBExp232 = B.buildInstr(TargetOpcode::G_FEXP2, {S32}, {MIBTrunc});
2586 auto MIBExp264 = B.buildInstr(TargetOpcode::G_FEXP2, {S64}, {Copies[0]});
2587 auto MIBExp2128 = B.buildInstr(TargetOpcode::G_FEXP2, {S128}, {MIBExt});
2588
2589 AInfo Info(MF->getSubtarget());
2590 DummyGISelObserver Observer;
2591 LostDebugLocObserver DummyLocObserver("");
2592 LegalizerHelper Helper(*MF, Info, Observer, B);
2593
2594 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2595 Helper.libcall(*MIBExp232, DummyLocObserver));
2596 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2597 Helper.libcall(*MIBExp264, DummyLocObserver));
2598 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2599 Helper.libcall(*MIBExp2128, DummyLocObserver));
2600
2601 const auto *CheckStr = R"(
2602 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2603 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2604 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2605 CHECK: $s0 = COPY [[TRUNC]]
2606 CHECK: BL &exp2f
2607 CHECK: $d0 = COPY [[COPY]]
2608 CHECK: BL &exp2
2609 CHECK: $q0 = COPY [[ANYEXT]]
2610 CHECK: BL &exp2l
2611 )";
2612
2613 // Check
2614 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2615 }
2616
TEST_F(AArch64GISelMITest,LibcallFRem)2617 TEST_F(AArch64GISelMITest, LibcallFRem) {
2618 setUp();
2619 if (!TM)
2620 return;
2621
2622 // Declare your legalization info
2623 DefineLegalizerInfo(A, {
2624 getActionDefinitionsBuilder(G_FREM).libcallFor({s32, s64, s128});
2625 });
2626
2627 LLT S32{LLT::scalar(32)};
2628 LLT S64{LLT::scalar(64)};
2629 LLT S128{LLT::scalar(128)};
2630 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2631 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2632
2633 auto MIBFRem32 = B.buildInstr(TargetOpcode::G_FREM, {S32}, {MIBTrunc});
2634 auto MIBFRem64 = B.buildInstr(TargetOpcode::G_FREM, {S64}, {Copies[0]});
2635 auto MIBFRem128 = B.buildInstr(TargetOpcode::G_FREM, {S128}, {MIBExt});
2636
2637 AInfo Info(MF->getSubtarget());
2638 DummyGISelObserver Observer;
2639 LostDebugLocObserver DummyLocObserver("");
2640 LegalizerHelper Helper(*MF, Info, Observer, B);
2641
2642 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2643 Helper.libcall(*MIBFRem32, DummyLocObserver));
2644 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2645 Helper.libcall(*MIBFRem64, DummyLocObserver));
2646 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2647 Helper.libcall(*MIBFRem128, DummyLocObserver));
2648
2649 const auto *CheckStr = R"(
2650 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2651 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2652 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2653 CHECK: $s0 = COPY [[TRUNC]]
2654 CHECK: BL &fmodf
2655 CHECK: $d0 = COPY [[COPY]]
2656 CHECK: BL &fmod
2657 CHECK: $q0 = COPY [[ANYEXT]]
2658 CHECK: BL &fmodl
2659 )";
2660
2661 // Check
2662 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2663 }
2664
TEST_F(AArch64GISelMITest,LibcallFPow)2665 TEST_F(AArch64GISelMITest, LibcallFPow) {
2666 setUp();
2667 if (!TM)
2668 return;
2669
2670 // Declare your legalization info
2671 DefineLegalizerInfo(A, {
2672 getActionDefinitionsBuilder(G_FPOW).libcallFor({s32, s64, s128});
2673 });
2674
2675 LLT S32{LLT::scalar(32)};
2676 LLT S64{LLT::scalar(64)};
2677 LLT S128{LLT::scalar(128)};
2678 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2679 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2680
2681 auto MIBPow32 = B.buildInstr(TargetOpcode::G_FPOW, {S32}, {MIBTrunc});
2682 auto MIBPow64 = B.buildInstr(TargetOpcode::G_FPOW, {S64}, {Copies[0]});
2683 auto MIBPow128 = B.buildInstr(TargetOpcode::G_FPOW, {S128}, {MIBExt});
2684
2685 AInfo Info(MF->getSubtarget());
2686 DummyGISelObserver Observer;
2687 LostDebugLocObserver DummyLocObserver("");
2688 LegalizerHelper Helper(*MF, Info, Observer, B);
2689
2690 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2691 Helper.libcall(*MIBPow32, DummyLocObserver));
2692 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2693 Helper.libcall(*MIBPow64, DummyLocObserver));
2694 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2695 Helper.libcall(*MIBPow128, DummyLocObserver));
2696
2697 const auto *CheckStr = R"(
2698 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2699 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2700 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2701 CHECK: $s0 = COPY [[TRUNC]]
2702 CHECK: BL &powf
2703 CHECK: $d0 = COPY [[COPY]]
2704 CHECK: BL &pow
2705 CHECK: $q0 = COPY [[ANYEXT]]
2706 CHECK: BL &powl
2707 )";
2708
2709 // Check
2710 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2711 }
2712
TEST_F(AArch64GISelMITest,LibcallFMa)2713 TEST_F(AArch64GISelMITest, LibcallFMa) {
2714 setUp();
2715 if (!TM)
2716 return;
2717
2718 // Declare your legalization info
2719 DefineLegalizerInfo(A, {
2720 getActionDefinitionsBuilder(G_FMA).libcallFor({s32, s64, s128});
2721 });
2722
2723 LLT S32{LLT::scalar(32)};
2724 LLT S64{LLT::scalar(64)};
2725 LLT S128{LLT::scalar(128)};
2726 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2727 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2728
2729 auto MIBMa32 = B.buildInstr(TargetOpcode::G_FMA, {S32}, {MIBTrunc, MIBTrunc});
2730 auto MIBMa64 =
2731 B.buildInstr(TargetOpcode::G_FMA, {S64}, {Copies[0], Copies[0]});
2732 auto MIBMa128 = B.buildInstr(TargetOpcode::G_FMA, {S128}, {MIBExt, MIBExt});
2733
2734 AInfo Info(MF->getSubtarget());
2735 DummyGISelObserver Observer;
2736 LostDebugLocObserver DummyLocObserver("");
2737 LegalizerHelper Helper(*MF, Info, Observer, B);
2738
2739 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2740 Helper.libcall(*MIBMa32, DummyLocObserver));
2741 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2742 Helper.libcall(*MIBMa64, DummyLocObserver));
2743 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2744 Helper.libcall(*MIBMa128, DummyLocObserver));
2745
2746 const auto *CheckStr = R"(
2747 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2748 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2749 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2750 CHECK: $s0 = COPY [[TRUNC]]
2751 CHECK: BL &fmaf
2752 CHECK: $d0 = COPY [[COPY]]
2753 CHECK: BL &fma
2754 CHECK: $q0 = COPY [[ANYEXT]]
2755 CHECK: BL &fmal
2756 )";
2757
2758 // Check
2759 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2760 }
2761
TEST_F(AArch64GISelMITest,LibcallFCeil)2762 TEST_F(AArch64GISelMITest, LibcallFCeil) {
2763 setUp();
2764 if (!TM)
2765 return;
2766
2767 // Declare your legalization info
2768 DefineLegalizerInfo(A, {
2769 getActionDefinitionsBuilder(G_FCEIL).libcallFor({s32, s64, s128});
2770 });
2771
2772 LLT S32{LLT::scalar(32)};
2773 LLT S64{LLT::scalar(64)};
2774 LLT S128{LLT::scalar(128)};
2775 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2776 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2777
2778 auto MIBCeil32 = B.buildInstr(TargetOpcode::G_FCEIL, {S32}, {MIBTrunc});
2779 auto MIBCeil64 = B.buildInstr(TargetOpcode::G_FCEIL, {S64}, {Copies[0]});
2780 auto MIBCeil128 = B.buildInstr(TargetOpcode::G_FCEIL, {S128}, {MIBExt});
2781
2782 AInfo Info(MF->getSubtarget());
2783 DummyGISelObserver Observer;
2784 LegalizerHelper Helper(*MF, Info, Observer, B);
2785 LostDebugLocObserver DummyLocObserver("");
2786
2787 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2788 Helper.libcall(*MIBCeil32, DummyLocObserver));
2789 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2790 Helper.libcall(*MIBCeil64, DummyLocObserver));
2791 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2792 Helper.libcall(*MIBCeil128, DummyLocObserver));
2793
2794 const auto *CheckStr = R"(
2795 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2796 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2797 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2798 CHECK: $s0 = COPY [[TRUNC]]
2799 CHECK: BL &ceilf
2800 CHECK: $d0 = COPY [[COPY]]
2801 CHECK: BL &ceil
2802 CHECK: $q0 = COPY [[ANYEXT]]
2803 CHECK: BL &ceill
2804 )";
2805
2806 // Check
2807 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2808 }
2809
TEST_F(AArch64GISelMITest,LibcallFFloor)2810 TEST_F(AArch64GISelMITest, LibcallFFloor) {
2811 setUp();
2812 if (!TM)
2813 return;
2814
2815 // Declare your legalization info
2816 DefineLegalizerInfo(A, {
2817 getActionDefinitionsBuilder(G_FFLOOR).libcallFor({s32, s64, s128});
2818 });
2819
2820 LLT S32{LLT::scalar(32)};
2821 LLT S64{LLT::scalar(64)};
2822 LLT S128{LLT::scalar(128)};
2823 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2824 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2825
2826 auto MIBFloor32 = B.buildInstr(TargetOpcode::G_FFLOOR, {S32}, {MIBTrunc});
2827 auto MIBFloor64 = B.buildInstr(TargetOpcode::G_FFLOOR, {S64}, {Copies[0]});
2828 auto MIBFloor128 = B.buildInstr(TargetOpcode::G_FFLOOR, {S128}, {MIBExt});
2829
2830 AInfo Info(MF->getSubtarget());
2831 DummyGISelObserver Observer;
2832 LegalizerHelper Helper(*MF, Info, Observer, B);
2833 LostDebugLocObserver DummyLocObserver("");
2834
2835 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2836 Helper.libcall(*MIBFloor32, DummyLocObserver));
2837 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2838 Helper.libcall(*MIBFloor64, DummyLocObserver));
2839 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2840 Helper.libcall(*MIBFloor128, DummyLocObserver));
2841
2842 const auto *CheckStr = R"(
2843 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2844 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2845 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2846 CHECK: $s0 = COPY [[TRUNC]]
2847 CHECK: BL &floorf
2848 CHECK: $d0 = COPY [[COPY]]
2849 CHECK: BL &floor
2850 CHECK: $q0 = COPY [[ANYEXT]]
2851 CHECK: BL &floorl
2852 )";
2853
2854 // Check
2855 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2856 }
2857
TEST_F(AArch64GISelMITest,LibcallFMinNum)2858 TEST_F(AArch64GISelMITest, LibcallFMinNum) {
2859 setUp();
2860 if (!TM)
2861 return;
2862
2863 // Declare your legalization info
2864 DefineLegalizerInfo(A, {
2865 getActionDefinitionsBuilder(G_FMINNUM).libcallFor({s32, s64, s128});
2866 });
2867
2868 LLT S32{LLT::scalar(32)};
2869 LLT S64{LLT::scalar(64)};
2870 LLT S128{LLT::scalar(128)};
2871 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2872 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2873
2874 auto MIBMin32 = B.buildFMinNum(S32, MIBTrunc, MIBTrunc);
2875 auto MIBMin64 = B.buildFMinNum(S64, Copies[0], Copies[0]);
2876 auto MIBMin128 = B.buildFMinNum(S128, MIBExt, MIBExt);
2877
2878 AInfo Info(MF->getSubtarget());
2879 DummyGISelObserver Observer;
2880 LegalizerHelper Helper(*MF, Info, Observer, B);
2881 LostDebugLocObserver DummyLocObserver("");
2882
2883 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2884 Helper.libcall(*MIBMin32, DummyLocObserver));
2885 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2886 Helper.libcall(*MIBMin64, DummyLocObserver));
2887 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2888 Helper.libcall(*MIBMin128, DummyLocObserver));
2889
2890 const auto *CheckStr = R"(
2891 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2892 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2893 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2894 CHECK: $s0 = COPY [[TRUNC]]
2895 CHECK: $s1 = COPY [[TRUNC]]
2896 CHECK: BL &fminf
2897 CHECK: $d0 = COPY [[COPY]]
2898 CHECK: $d1 = COPY [[COPY]]
2899 CHECK: BL &fmin
2900 CHECK: $q0 = COPY [[ANYEXT]]
2901 CHECK: $q1 = COPY [[ANYEXT]]
2902 CHECK: BL &fminl
2903 )";
2904
2905 // Check
2906 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2907 }
2908
TEST_F(AArch64GISelMITest,LibcallFMaxNum)2909 TEST_F(AArch64GISelMITest, LibcallFMaxNum) {
2910 setUp();
2911 if (!TM)
2912 return;
2913
2914 // Declare your legalization info
2915 DefineLegalizerInfo(A, {
2916 getActionDefinitionsBuilder(G_FMAXNUM).libcallFor({s32, s64, s128});
2917 });
2918
2919 LLT S32{LLT::scalar(32)};
2920 LLT S64{LLT::scalar(64)};
2921 LLT S128{LLT::scalar(128)};
2922 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2923 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2924
2925 auto MIBMax32 = B.buildFMaxNum(S32, MIBTrunc, MIBTrunc);
2926 auto MIBMax64 = B.buildFMaxNum(S64, Copies[0], Copies[0]);
2927 auto MIBMax128 = B.buildFMaxNum(S128, MIBExt, MIBExt);
2928
2929 AInfo Info(MF->getSubtarget());
2930 DummyGISelObserver Observer;
2931 LegalizerHelper Helper(*MF, Info, Observer, B);
2932 LostDebugLocObserver DummyLocObserver("");
2933
2934 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2935 Helper.libcall(*MIBMax32, DummyLocObserver));
2936 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2937 Helper.libcall(*MIBMax64, DummyLocObserver));
2938 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2939 Helper.libcall(*MIBMax128, DummyLocObserver));
2940
2941 const auto *CheckStr = R"(
2942 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2943 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2944 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2945 CHECK: $s0 = COPY [[TRUNC]]
2946 CHECK: $s1 = COPY [[TRUNC]]
2947 CHECK: BL &fmaxf
2948 CHECK: $d0 = COPY [[COPY]]
2949 CHECK: $d1 = COPY [[COPY]]
2950 CHECK: BL &fmax
2951 CHECK: $q0 = COPY [[ANYEXT]]
2952 CHECK: $q1 = COPY [[ANYEXT]]
2953 CHECK: BL &fmaxl
2954 )";
2955
2956 // Check
2957 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2958 }
2959
TEST_F(AArch64GISelMITest,LibcallFSqrt)2960 TEST_F(AArch64GISelMITest, LibcallFSqrt) {
2961 setUp();
2962 if (!TM)
2963 return;
2964
2965 // Declare your legalization info
2966 DefineLegalizerInfo(A, {
2967 getActionDefinitionsBuilder(G_FSQRT).libcallFor({s32, s64, s128});
2968 });
2969
2970 LLT S32{LLT::scalar(32)};
2971 LLT S64{LLT::scalar(64)};
2972 LLT S128{LLT::scalar(128)};
2973 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2974 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2975
2976 auto MIBSqrt32 = B.buildInstr(TargetOpcode::G_FSQRT, {S32}, {MIBTrunc});
2977 auto MIBSqrt64 = B.buildInstr(TargetOpcode::G_FSQRT, {S64}, {Copies[0]});
2978 auto MIBSqrt128 = B.buildInstr(TargetOpcode::G_FSQRT, {S128}, {MIBExt});
2979
2980 AInfo Info(MF->getSubtarget());
2981 DummyGISelObserver Observer;
2982 LegalizerHelper Helper(*MF, Info, Observer, B);
2983 LostDebugLocObserver DummyLocObserver("");
2984
2985 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2986 Helper.libcall(*MIBSqrt32, DummyLocObserver));
2987 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2988 Helper.libcall(*MIBSqrt64, DummyLocObserver));
2989 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2990 Helper.libcall(*MIBSqrt128, DummyLocObserver));
2991
2992 const auto *CheckStr = R"(
2993 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2994 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2995 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2996 CHECK: $s0 = COPY [[TRUNC]]
2997 CHECK: BL &sqrtf
2998 CHECK: $d0 = COPY [[COPY]]
2999 CHECK: BL &sqrt
3000 CHECK: $q0 = COPY [[ANYEXT]]
3001 CHECK: BL &sqrtl
3002 )";
3003
3004 // Check
3005 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3006 }
3007
TEST_F(AArch64GISelMITest,LibcallFRint)3008 TEST_F(AArch64GISelMITest, LibcallFRint) {
3009 setUp();
3010 if (!TM)
3011 return;
3012
3013 // Declare your legalization info
3014 DefineLegalizerInfo(A, {
3015 getActionDefinitionsBuilder(G_FRINT).libcallFor({s32, s64, s128});
3016 });
3017
3018 LLT S32{LLT::scalar(32)};
3019 LLT S64{LLT::scalar(64)};
3020 LLT S128{LLT::scalar(128)};
3021 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
3022 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
3023
3024 auto MIBRint32 = B.buildInstr(TargetOpcode::G_FRINT, {S32}, {MIBTrunc});
3025 auto MIBRint64 = B.buildInstr(TargetOpcode::G_FRINT, {S64}, {Copies[0]});
3026 auto MIBRint128 = B.buildInstr(TargetOpcode::G_FRINT, {S128}, {MIBExt});
3027
3028 AInfo Info(MF->getSubtarget());
3029 DummyGISelObserver Observer;
3030 LegalizerHelper Helper(*MF, Info, Observer, B);
3031 LostDebugLocObserver DummyLocObserver("");
3032
3033 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3034 Helper.libcall(*MIBRint32, DummyLocObserver));
3035 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3036 Helper.libcall(*MIBRint64, DummyLocObserver));
3037 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3038 Helper.libcall(*MIBRint128, DummyLocObserver));
3039
3040 const auto *CheckStr = R"(
3041 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3042 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
3043 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
3044 CHECK: $s0 = COPY [[TRUNC]]
3045 CHECK: BL &rintf
3046 CHECK: $d0 = COPY [[COPY]]
3047 CHECK: BL &rint
3048 CHECK: $q0 = COPY [[ANYEXT]]
3049 CHECK: BL &rintl
3050 )";
3051
3052 // Check
3053 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3054 }
3055
TEST_F(AArch64GISelMITest,LibcallFNearbyInt)3056 TEST_F(AArch64GISelMITest, LibcallFNearbyInt) {
3057 setUp();
3058 if (!TM)
3059 return;
3060
3061 // Declare your legalization info
3062 DefineLegalizerInfo(A, {
3063 getActionDefinitionsBuilder(G_FNEARBYINT).libcallFor({s32, s64, s128});
3064 });
3065
3066 LLT S32{LLT::scalar(32)};
3067 LLT S64{LLT::scalar(64)};
3068 LLT S128{LLT::scalar(128)};
3069 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
3070 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
3071
3072 auto MIBNearbyInt32 =
3073 B.buildInstr(TargetOpcode::G_FNEARBYINT, {S32}, {MIBTrunc});
3074 auto MIBNearbyInt64 =
3075 B.buildInstr(TargetOpcode::G_FNEARBYINT, {S64}, {Copies[0]});
3076 auto MIBNearbyInt128 =
3077 B.buildInstr(TargetOpcode::G_FNEARBYINT, {S128}, {MIBExt});
3078
3079 AInfo Info(MF->getSubtarget());
3080 DummyGISelObserver Observer;
3081 LegalizerHelper Helper(*MF, Info, Observer, B);
3082 LostDebugLocObserver DummyLocObserver("");
3083
3084 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3085 Helper.libcall(*MIBNearbyInt32, DummyLocObserver));
3086 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3087 Helper.libcall(*MIBNearbyInt64, DummyLocObserver));
3088 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3089 Helper.libcall(*MIBNearbyInt128, DummyLocObserver));
3090
3091 const auto *CheckStr = R"(
3092 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3093 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
3094 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
3095 CHECK: $s0 = COPY [[TRUNC]]
3096 CHECK: BL &nearbyintf
3097 CHECK: $d0 = COPY [[COPY]]
3098 CHECK: BL &nearbyint
3099 CHECK: $q0 = COPY [[ANYEXT]]
3100 CHECK: BL &nearbyintl
3101 )";
3102
3103 // Check
3104 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3105 }
3106
TEST_F(AArch64GISelMITest,NarrowScalarExtract)3107 TEST_F(AArch64GISelMITest, NarrowScalarExtract) {
3108 setUp();
3109 if (!TM)
3110 return;
3111
3112 // Declare your legalization info
3113 DefineLegalizerInfo(A, {
3114 getActionDefinitionsBuilder(G_UNMERGE_VALUES).legalFor({{s32, s64}});
3115 getActionDefinitionsBuilder(G_EXTRACT).legalForTypeWithAnyImm({{s16, s32}});
3116 });
3117
3118 LLT S16{LLT::scalar(16)};
3119 LLT S32{LLT::scalar(32)};
3120
3121 auto MIBExtractS32 = B.buildExtract(S32, Copies[1], 32);
3122 auto MIBExtractS16 = B.buildExtract(S16, Copies[1], 0);
3123
3124 AInfo Info(MF->getSubtarget());
3125 DummyGISelObserver Observer;
3126 LegalizerHelper Helper(*MF, Info, Observer, B);
3127
3128 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3129 Helper.narrowScalar(*MIBExtractS32, 1, S32));
3130
3131 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3132 Helper.narrowScalar(*MIBExtractS16, 1, S32));
3133
3134 const auto *CheckStr = R"(
3135 CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES
3136 CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY [[UV1]]
3137 CHECK: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES
3138 CHECK: [[EXTR:%[0-9]+]]:_(s16) = G_EXTRACT [[UV3]]:_(s32), 0
3139 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[EXTR]]
3140 )";
3141
3142 // Check
3143 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3144 }
3145
TEST_F(AArch64GISelMITest,LowerInsert)3146 TEST_F(AArch64GISelMITest, LowerInsert) {
3147 setUp();
3148 if (!TM)
3149 return;
3150
3151 // Declare your legalization info
3152 DefineLegalizerInfo(A, { getActionDefinitionsBuilder(G_INSERT).lower(); });
3153
3154 LLT S32{LLT::scalar(32)};
3155 LLT S64{LLT::scalar(64)};
3156 LLT P0{LLT::pointer(0, 64)};
3157 LLT P1{LLT::pointer(1, 32)};
3158 LLT V2S32{LLT::fixed_vector(2, 32)};
3159
3160 auto TruncS32 = B.buildTrunc(S32, Copies[0]);
3161 auto IntToPtrP0 = B.buildIntToPtr(P0, Copies[0]);
3162 auto IntToPtrP1 = B.buildIntToPtr(P1, TruncS32);
3163 auto BitcastV2S32 = B.buildBitcast(V2S32, Copies[0]);
3164
3165 auto InsertS64S32 = B.buildInsert(S64, Copies[0], TruncS32, 0);
3166 auto InsertS64P1 = B.buildInsert(S64, Copies[0], IntToPtrP1, 8);
3167 auto InsertP0S32 = B.buildInsert(P0, IntToPtrP0, TruncS32, 16);
3168 auto InsertP0P1 = B.buildInsert(P0, IntToPtrP0, IntToPtrP1, 4);
3169 auto InsertV2S32S32 = B.buildInsert(V2S32, BitcastV2S32, TruncS32, 32);
3170 auto InsertV2S32P1 = B.buildInsert(V2S32, BitcastV2S32, IntToPtrP1, 0);
3171
3172 AInfo Info(MF->getSubtarget());
3173 DummyGISelObserver Observer;
3174 LegalizerHelper Helper(*MF, Info, Observer, B);
3175
3176 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3177 Helper.lower(*InsertS64S32, 0, LLT{}));
3178
3179 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3180 Helper.lower(*InsertS64P1, 0, LLT{}));
3181
3182 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3183 Helper.lower(*InsertP0S32, 0, LLT{}));
3184
3185 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3186 Helper.lower(*InsertP0P1, 0, LLT{}));
3187
3188 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3189 Helper.lower(*InsertV2S32S32, 0, LLT{}));
3190
3191 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
3192 Helper.lower(*InsertV2S32P1, 0, LLT{}));
3193
3194 const auto *CheckStr = R"(
3195 CHECK: [[S64:%[0-9]+]]:_(s64) = COPY
3196 CHECK: [[S32:%[0-9]+]]:_(s32) = G_TRUNC [[S64]]
3197 CHECK: [[P0:%[0-9]+]]:_(p0) = G_INTTOPTR [[S64]]
3198 CHECK: [[P1:%[0-9]+]]:_(p1) = G_INTTOPTR [[S32]]
3199 CHECK: [[V2S32:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[S64]]
3200 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]]
3201 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3202 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[S64]]:_, [[C]]:_
3203 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[ZEXT]]:_
3204
3205 CHECK: [[PTRTOINT:%[0-9]+]]:_(s32) = G_PTRTOINT [[P1]]
3206 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[PTRTOINT]]
3207 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3208 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
3209 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3210 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[S64]]:_, [[C]]:_
3211 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
3212
3213 CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[P0]]
3214 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]]
3215 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3216 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
3217 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3218 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[PTRTOINT]]:_, [[C]]:_
3219 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
3220 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]
3221
3222 CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[P0]]
3223 CHECK: [[PTRTOINT1:%[0-9]+]]:_(s32) = G_PTRTOINT [[P1]]
3224 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[PTRTOINT1]]
3225 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3226 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
3227 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3228 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[PTRTOINT]]:_, [[C]]:_
3229 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
3230 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]
3231
3232 CHECK: [[V2S32_E0:%[0-9]+]]:_(s32), [[V2S32_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[V2S32]]
3233 CHECK: [[BV:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[V2S32_E0]]:_(s32), [[S32]]:_(s32)
3234 )";
3235
3236 // Check
3237 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3238 }
3239
3240 // Test lowering of G_FFLOOR
TEST_F(AArch64GISelMITest,LowerFFloor)3241 TEST_F(AArch64GISelMITest, LowerFFloor) {
3242 setUp();
3243 if (!TM)
3244 return;
3245
3246 // Declare your legalization info
3247 DefineLegalizerInfo(A, {});
3248 // Build Instr
3249 auto Floor = B.buildFFloor(LLT::scalar(64), Copies[0], MachineInstr::MIFlag::FmNoInfs);
3250 AInfo Info(MF->getSubtarget());
3251 DummyGISelObserver Observer;
3252 LegalizerHelper Helper(*MF, Info, Observer, B);
3253 // Perform Legalization
3254 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3255 Helper.lower(*Floor, 0, LLT()));
3256
3257 auto CheckStr = R"(
3258 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3259 CHECK: [[TRUNC:%[0-9]+]]:_(s64) = ninf G_INTRINSIC_TRUNC [[COPY]]
3260 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_FCONSTANT double 0.000000e+00
3261 CHECK: [[CMP0:%[0-9]+]]:_(s1) = ninf G_FCMP floatpred(olt), [[COPY]]:_(s64), [[ZERO]]:_
3262 CHECK: [[CMP1:%[0-9]+]]:_(s1) = ninf G_FCMP floatpred(one), [[COPY]]:_(s64), [[TRUNC]]:_
3263 CHECK: [[AND:%[0-9]+]]:_(s1) = G_AND [[CMP0]]:_, [[CMP1]]:_
3264 CHECK: [[ITOFP:%[0-9]+]]:_(s64) = G_SITOFP [[AND]]
3265 = ninf G_FADD [[TRUNC]]:_, [[ITOFP]]:_
3266 )";
3267
3268 // Check
3269 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3270 }
3271
3272 // Test lowering of G_BSWAP
TEST_F(AArch64GISelMITest,LowerBSWAP)3273 TEST_F(AArch64GISelMITest, LowerBSWAP) {
3274 setUp();
3275 if (!TM)
3276 return;
3277
3278 DefineLegalizerInfo(A, {});
3279
3280 // Make sure vector lowering doesn't assert.
3281 auto Cast = B.buildBitcast(LLT::fixed_vector(2, 32), Copies[0]);
3282 auto BSwap = B.buildBSwap(LLT::fixed_vector(2, 32), Cast);
3283 AInfo Info(MF->getSubtarget());
3284 DummyGISelObserver Observer;
3285 LegalizerHelper Helper(*MF, Info, Observer, B);
3286 // Perform Legalization
3287 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3288 Helper.lower(*BSwap, 0, LLT()));
3289
3290 auto CheckStr = R"(
3291 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3292 CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3293 CHECK: [[K24:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
3294 CHECK: [[SPLAT24:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[K24]]:_(s32), [[K24]]:_(s32)
3295 CHECK: [[SHL0:%[0-9]+]]:_(<2 x s32>) = G_SHL [[VEC]]:_, [[SPLAT24]]
3296 CHECK: [[SHR0:%[0-9]+]]:_(<2 x s32>) = G_LSHR [[VEC]]:_, [[SPLAT24]]
3297 CHECK: [[OR0:%[0-9]+]]:_(<2 x s32>) = G_OR [[SHR0]]:_, [[SHL0]]:_
3298 CHECK: [[KMASK:%[0-9]+]]:_(s32) = G_CONSTANT i32 65280
3299 CHECK: [[SPLATMASK:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[KMASK]]:_(s32), [[KMASK]]:_(s32)
3300 CHECK: [[K8:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
3301 CHECK: [[SPLAT8:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[K8]]:_(s32), [[K8]]:_(s32)
3302 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[VEC]]:_, [[SPLATMASK]]:_
3303 CHECK: [[SHL1:%[0-9]+]]:_(<2 x s32>) = G_SHL [[AND0]]:_, [[SPLAT8]]
3304 CHECK: [[OR1:%[0-9]+]]:_(<2 x s32>) = G_OR [[OR0]]:_, [[SHL1]]:_
3305 CHECK: [[SHR1:%[0-9]+]]:_(<2 x s32>) = G_LSHR [[VEC]]:_, [[SPLAT8]]
3306 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[SHR1]]:_, [[SPLATMASK]]:_
3307 CHECK: [[BSWAP:%[0-9]+]]:_(<2 x s32>) = G_OR [[OR1]]:_, [[AND1]]:_
3308 )";
3309
3310 // Check
3311 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3312 }
3313
3314 // Test lowering of G_SDIVREM into G_SDIV and G_SREM
TEST_F(AArch64GISelMITest,LowerSDIVREM)3315 TEST_F(AArch64GISelMITest, LowerSDIVREM) {
3316 setUp();
3317 if (!TM)
3318 return;
3319
3320 // Declare your legalization info
3321 DefineLegalizerInfo(
3322 A, { getActionDefinitionsBuilder(G_SDIVREM).lowerFor({s64}); });
3323
3324 LLT S64{LLT::scalar(64)};
3325
3326 // Build Instr
3327 auto SDivrem =
3328 B.buildInstr(TargetOpcode::G_SDIVREM, {S64, S64}, {Copies[0], Copies[1]});
3329 AInfo Info(MF->getSubtarget());
3330 DummyGISelObserver Observer;
3331 LegalizerHelper Helper(*MF, Info, Observer, B);
3332 // Perform Legalization
3333 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3334 Helper.lower(*SDivrem, 0, S64));
3335
3336 const auto *CheckStr = R"(
3337 CHECK: [[DIV:%[0-9]+]]:_(s64) = G_SDIV %0:_, %1:_
3338 CHECK: [[REM:%[0-9]+]]:_(s64) = G_SREM %0:_, %1:_
3339 )";
3340
3341 // Check
3342 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3343 }
3344
3345 // Test lowering of G_UDIVREM into G_UDIV and G_UREM
TEST_F(AArch64GISelMITest,LowerUDIVREM)3346 TEST_F(AArch64GISelMITest, LowerUDIVREM) {
3347 setUp();
3348 if (!TM)
3349 return;
3350
3351 // Declare your legalization info
3352 DefineLegalizerInfo(
3353 A, { getActionDefinitionsBuilder(G_UDIVREM).lowerFor({s64}); });
3354
3355 LLT S64{LLT::scalar(64)};
3356
3357 // Build Instr
3358 auto UDivrem =
3359 B.buildInstr(TargetOpcode::G_UDIVREM, {S64, S64}, {Copies[0], Copies[1]});
3360 AInfo Info(MF->getSubtarget());
3361 DummyGISelObserver Observer;
3362 LegalizerHelper Helper(*MF, Info, Observer, B);
3363 // Perform Legalization
3364 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3365 Helper.lower(*UDivrem, 0, S64));
3366
3367 const auto *CheckStr = R"(
3368 CHECK: [[DIV:%[0-9]+]]:_(s64) = G_UDIV %0:_, %1:_
3369 CHECK: [[REM:%[0-9]+]]:_(s64) = G_UREM %0:_, %1:_
3370 )";
3371
3372 // Check
3373 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3374 }
3375
3376 // Test widening of G_UNMERGE_VALUES
TEST_F(AArch64GISelMITest,WidenUnmerge)3377 TEST_F(AArch64GISelMITest, WidenUnmerge) {
3378 setUp();
3379 if (!TM)
3380 return;
3381
3382 DefineLegalizerInfo(A, {});
3383
3384 // Check that widening G_UNMERGE_VALUES to a larger type than the source type
3385 // works as expected
3386 LLT P0{LLT::pointer(0, 64)};
3387 LLT S32{LLT::scalar(32)};
3388 LLT S96{LLT::scalar(96)};
3389
3390 auto IntToPtr = B.buildIntToPtr(P0, Copies[0]);
3391 auto UnmergePtr = B.buildUnmerge(S32, IntToPtr);
3392 auto UnmergeScalar = B.buildUnmerge(S32, Copies[0]);
3393
3394 AInfo Info(MF->getSubtarget());
3395 DummyGISelObserver Observer;
3396 LegalizerHelper Helper(*MF, Info, Observer, B);
3397
3398 // Perform Legalization
3399 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3400 Helper.widenScalar(*UnmergePtr, 0, S96));
3401
3402 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3403 Helper.widenScalar(*UnmergeScalar, 0, S96));
3404
3405 const auto *CheckStr = R"(
3406 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3407 CHECK: [[PTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY]]
3408 CHECK: [[INT:%[0-9]+]]:_(s64) = G_PTRTOINT [[PTR]]
3409 CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[INT]]
3410 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]]
3411 CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32
3412 CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]]
3413 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]]
3414 CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY]]
3415 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]]
3416 CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32
3417 CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]]
3418 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]]
3419 )";
3420
3421 // Check
3422 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3423 }
3424
TEST_F(AArch64GISelMITest,BitcastLoad)3425 TEST_F(AArch64GISelMITest, BitcastLoad) {
3426 setUp();
3427 if (!TM)
3428 return;
3429
3430 LLT P0 = LLT::pointer(0, 64);
3431 LLT S32 = LLT::scalar(32);
3432 LLT V4S8 = LLT::fixed_vector(4, 8);
3433 auto Ptr = B.buildUndef(P0);
3434
3435 DefineLegalizerInfo(A, {});
3436
3437 MachineMemOperand *MMO = B.getMF().getMachineMemOperand(
3438 MachinePointerInfo(), MachineMemOperand::MOLoad, 4, Align(4));
3439 auto Load = B.buildLoad(V4S8, Ptr, *MMO);
3440
3441 AInfo Info(MF->getSubtarget());
3442 DummyGISelObserver Observer;
3443 B.setInsertPt(*EntryMBB, Load->getIterator());
3444 LegalizerHelper Helper(*MF, Info, Observer, B);
3445 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3446 Helper.bitcast(*Load, 0, S32));
3447
3448 auto CheckStr = R"(
3449 CHECK: [[PTR:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF
3450 CHECK: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD
3451 CHECK: [[CAST:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[LOAD]]
3452
3453 )";
3454
3455 // Check
3456 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3457 }
3458
TEST_F(AArch64GISelMITest,BitcastStore)3459 TEST_F(AArch64GISelMITest, BitcastStore) {
3460 setUp();
3461 if (!TM)
3462 return;
3463
3464 LLT P0 = LLT::pointer(0, 64);
3465 LLT S32 = LLT::scalar(32);
3466 LLT V4S8 = LLT::fixed_vector(4, 8);
3467 auto Ptr = B.buildUndef(P0);
3468
3469 DefineLegalizerInfo(A, {});
3470
3471 MachineMemOperand *MMO = B.getMF().getMachineMemOperand(
3472 MachinePointerInfo(), MachineMemOperand::MOStore, 4, Align(4));
3473 auto Val = B.buildUndef(V4S8);
3474 auto Store = B.buildStore(Val, Ptr, *MMO);
3475
3476 AInfo Info(MF->getSubtarget());
3477 DummyGISelObserver Observer;
3478 LegalizerHelper Helper(*MF, Info, Observer, B);
3479 B.setInsertPt(*EntryMBB, Store->getIterator());
3480 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3481 Helper.bitcast(*Store, 0, S32));
3482
3483 auto CheckStr = R"(
3484 CHECK: [[VAL:%[0-9]+]]:_(<4 x s8>) = G_IMPLICIT_DEF
3485 CHECK: [[CAST:%[0-9]+]]:_(s32) = G_BITCAST [[VAL]]
3486 CHECK: G_STORE [[CAST]]
3487 )";
3488
3489 // Check
3490 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3491 }
3492
TEST_F(AArch64GISelMITest,BitcastSelect)3493 TEST_F(AArch64GISelMITest, BitcastSelect) {
3494 setUp();
3495 if (!TM)
3496 return;
3497
3498 LLT S1 = LLT::scalar(1);
3499 LLT S32 = LLT::scalar(32);
3500 LLT V4S8 = LLT::fixed_vector(4, 8);
3501
3502 DefineLegalizerInfo(A, {});
3503
3504 auto Cond = B.buildUndef(S1);
3505 auto Val0 = B.buildConstant(V4S8, 123);
3506 auto Val1 = B.buildConstant(V4S8, 99);
3507
3508 auto Select = B.buildSelect(V4S8, Cond, Val0, Val1);
3509
3510 AInfo Info(MF->getSubtarget());
3511 DummyGISelObserver Observer;
3512 LegalizerHelper Helper(*MF, Info, Observer, B);
3513 B.setInsertPt(*EntryMBB, Select->getIterator());
3514 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3515 Helper.bitcast(*Select, 0, S32));
3516
3517 auto CheckStr = R"(
3518 CHECK: [[VAL0:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
3519 CHECK: [[VAL1:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
3520 CHECK: [[CAST0:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
3521 CHECK: [[CAST1:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
3522 CHECK: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT %{{[0-9]+}}:_(s1), [[CAST0]]:_, [[CAST1]]:_
3523 CHECK: [[CAST2:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[SELECT]]
3524 )";
3525
3526 // Check
3527 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3528
3529 // Doesn't make sense
3530 auto VCond = B.buildUndef(LLT::fixed_vector(4, 1));
3531 auto VSelect = B.buildSelect(V4S8, VCond, Val0, Val1);
3532
3533 B.setInsertPt(*EntryMBB, VSelect->getIterator());
3534 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
3535 Helper.bitcast(*VSelect, 0, S32));
3536 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
3537 Helper.bitcast(*VSelect, 1, LLT::scalar(4)));
3538 }
3539
TEST_F(AArch64GISelMITest,BitcastBitOps)3540 TEST_F(AArch64GISelMITest, BitcastBitOps) {
3541 setUp();
3542 if (!TM)
3543 return;
3544
3545 LLT S32 = LLT::scalar(32);
3546 LLT V4S8 = LLT::fixed_vector(4, 8);
3547
3548 DefineLegalizerInfo(A, {});
3549
3550 auto Val0 = B.buildConstant(V4S8, 123);
3551 auto Val1 = B.buildConstant(V4S8, 99);
3552 auto And = B.buildAnd(V4S8, Val0, Val1);
3553 auto Or = B.buildOr(V4S8, Val0, Val1);
3554 auto Xor = B.buildXor(V4S8, Val0, Val1);
3555
3556 AInfo Info(MF->getSubtarget());
3557 DummyGISelObserver Observer;
3558 LegalizerHelper Helper(*MF, Info, Observer, B);
3559 B.setInsertPt(*EntryMBB, And->getIterator());
3560 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3561 Helper.bitcast(*And, 0, S32));
3562
3563 B.setInsertPt(*EntryMBB, Or->getIterator());
3564 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3565 Helper.bitcast(*Or, 0, S32));
3566
3567 B.setInsertPt(*EntryMBB, Xor->getIterator());
3568 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3569 Helper.bitcast(*Xor, 0, S32));
3570
3571 auto CheckStr = R"(
3572 CHECK: [[VAL0:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
3573 CHECK: [[VAL1:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
3574 CHECK: [[CAST0:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
3575 CHECK: [[CAST1:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
3576 CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[CAST0]]:_, [[CAST1]]:_
3577 CHECK: [[CAST_AND:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[AND]]
3578 CHECK: [[CAST2:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
3579 CHECK: [[CAST3:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
3580 CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[CAST2]]:_, [[CAST3]]:_
3581 CHECK: [[CAST_OR:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[OR]]
3582 CHECK: [[CAST4:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
3583 CHECK: [[CAST5:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
3584 CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[CAST4]]:_, [[CAST5]]:_
3585 CHECK: [[CAST_XOR:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[XOR]]
3586 )";
3587
3588 // Check
3589 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3590 }
3591
TEST_F(AArch64GISelMITest,CreateLibcall)3592 TEST_F(AArch64GISelMITest, CreateLibcall) {
3593 setUp();
3594 if (!TM)
3595 return;
3596
3597 DefineLegalizerInfo(A, {});
3598
3599 AInfo Info(MF->getSubtarget());
3600 DummyGISelObserver Observer;
3601
3602 LLVMContext &Ctx = MF->getFunction().getContext();
3603 auto *RetTy = Type::getVoidTy(Ctx);
3604
3605 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3606 createLibcall(B, "abort", {{}, RetTy, 0}, {}, CallingConv::C));
3607
3608 auto CheckStr = R"(
3609 CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
3610 CHECK: BL &abort
3611 CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
3612 )";
3613
3614 // Check
3615 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3616 }
3617
3618 // Test narrowing of G_IMPLICIT_DEF
TEST_F(AArch64GISelMITest,NarrowImplicitDef)3619 TEST_F(AArch64GISelMITest, NarrowImplicitDef) {
3620 setUp();
3621 if (!TM)
3622 return;
3623
3624 DefineLegalizerInfo(A, {});
3625
3626 // Make sure that G_IMPLICIT_DEF can be narrowed if the original size is not a
3627 // multiple of narrow size
3628 LLT S32{LLT::scalar(32)};
3629 LLT S48{LLT::scalar(48)};
3630 LLT S64{LLT::scalar(64)};
3631 LLT V2S64{{LLT::fixed_vector(2, 64)}};
3632
3633 auto Implicit1 = B.buildUndef(S64);
3634 auto Implicit2 = B.buildUndef(S64);
3635 auto Implicit3 = B.buildUndef(V2S64);
3636 auto Implicit4 = B.buildUndef(V2S64);
3637
3638 AInfo Info(MF->getSubtarget());
3639 DummyGISelObserver Observer;
3640 LegalizerHelper Helper(*MF, Info, Observer, B);
3641
3642 // Perform Legalization
3643
3644 B.setInsertPt(*EntryMBB, Implicit1->getIterator());
3645 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3646 Helper.narrowScalar(*Implicit1, 0, S48));
3647
3648 B.setInsertPt(*EntryMBB, Implicit2->getIterator());
3649 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3650 Helper.narrowScalar(*Implicit2, 0, S32));
3651
3652 B.setInsertPt(*EntryMBB, Implicit3->getIterator());
3653 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3654 Helper.narrowScalar(*Implicit3, 0, S48));
3655
3656 B.setInsertPt(*EntryMBB, Implicit4->getIterator());
3657 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3658 Helper.narrowScalar(*Implicit4, 0, S32));
3659
3660 const auto *CheckStr = R"(
3661 CHECK: [[DEF:%[0-9]+]]:_(s48) = G_IMPLICIT_DEF
3662 CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[DEF]]
3663
3664 CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3665 CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3666 CHECK: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[DEF]]:_(s32), [[DEF1]]
3667
3668 CHECK: [[DEF:%[0-9]+]]:_(<2 x s48>) = G_IMPLICIT_DEF
3669 CHECK: [[ANYEXT:%[0-9]+]]:_(<2 x s64>) = G_ANYEXT [[DEF]]
3670
3671 CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3672 CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3673 CHECK: [[DEF2:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3674 CHECK: [[DEF3:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3675 CHECK: [[BV:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[DEF]]:_(s32), [[DEF1]]:_(s32), [[DEF2]]:_(s32), [[DEF3]]:_(s32)
3676 )";
3677
3678 // Check
3679 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3680 }
3681
3682 // Test widening of G_FREEZE
TEST_F(AArch64GISelMITest,WidenFreeze)3683 TEST_F(AArch64GISelMITest, WidenFreeze) {
3684 setUp();
3685 if (!TM)
3686 return;
3687
3688 DefineLegalizerInfo(A, {});
3689
3690 // Make sure that G_FREEZE is widened with anyext
3691 LLT S64{LLT::scalar(64)};
3692 LLT S128{LLT::scalar(128)};
3693 LLT V2S32{LLT::fixed_vector(2, 32)};
3694 LLT V2S64{LLT::fixed_vector(2, 64)};
3695
3696 auto Vector = B.buildBitcast(V2S32, Copies[0]);
3697
3698 auto FreezeScalar = B.buildInstr(TargetOpcode::G_FREEZE, {S64}, {Copies[0]});
3699 auto FreezeVector = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector});
3700
3701 AInfo Info(MF->getSubtarget());
3702 DummyGISelObserver Observer;
3703 LegalizerHelper Helper(*MF, Info, Observer, B);
3704
3705 // Perform Legalization
3706
3707 B.setInsertPt(*EntryMBB, FreezeScalar->getIterator());
3708 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3709 Helper.widenScalar(*FreezeScalar, 0, S128));
3710
3711 B.setInsertPt(*EntryMBB, FreezeVector->getIterator());
3712 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3713 Helper.widenScalar(*FreezeVector, 0, V2S64));
3714
3715 const auto *CheckStr = R"(
3716 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3717 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3718
3719 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT [[COPY]]
3720 CHECK: [[FREEZE:%[0-9]+]]:_(s128) = G_FREEZE [[ANYEXT]]
3721 CHECK: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[FREEZE]]
3722
3723 CHECK: [[ANYEXT1:%[0-9]+]]:_(<2 x s64>) = G_ANYEXT [[BITCAST]]
3724 CHECK: [[FREEZE1:%[0-9]+]]:_(<2 x s64>) = G_FREEZE [[ANYEXT1]]
3725 CHECK: [[TRUNC1:%[0-9]+]]:_(<2 x s32>) = G_TRUNC [[FREEZE1]]
3726 )";
3727
3728 // Check
3729 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3730 }
3731
3732 // Test narrowing of G_FREEZE
TEST_F(AArch64GISelMITest,NarrowFreeze)3733 TEST_F(AArch64GISelMITest, NarrowFreeze) {
3734 setUp();
3735 if (!TM)
3736 return;
3737
3738 DefineLegalizerInfo(A, {});
3739
3740 // Make sure that G_FREEZE is narrowed using unmerge/extract
3741 LLT S32{LLT::scalar(32)};
3742 LLT S33{LLT::scalar(33)};
3743 LLT S48{LLT::scalar(48)};
3744 LLT S64{LLT::scalar(64)};
3745 LLT V2S16{LLT::fixed_vector(2, 16)};
3746 LLT V3S16{LLT::fixed_vector(3, 16)};
3747 LLT V4S16{LLT::fixed_vector(4, 16)};
3748
3749 auto Trunc = B.buildTrunc(S33, {Copies[0]});
3750 auto Trunc1 = B.buildTrunc(S48, {Copies[0]});
3751 auto Vector = B.buildBitcast(V3S16, Trunc1);
3752
3753 auto FreezeScalar = B.buildInstr(TargetOpcode::G_FREEZE, {S64}, {Copies[0]});
3754 auto FreezeOdd = B.buildInstr(TargetOpcode::G_FREEZE, {S33}, {Trunc});
3755 auto FreezeVector = B.buildInstr(TargetOpcode::G_FREEZE, {V3S16}, {Vector});
3756 auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V3S16}, {Vector});
3757
3758 AInfo Info(MF->getSubtarget());
3759 DummyGISelObserver Observer;
3760 LegalizerHelper Helper(*MF, Info, Observer, B);
3761
3762 // Perform Legalization
3763
3764 B.setInsertPt(*EntryMBB, FreezeScalar->getIterator());
3765 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3766 Helper.narrowScalar(*FreezeScalar, 0, S32));
3767
3768 // This should be followed by narrowScalar to S32.
3769 B.setInsertPt(*EntryMBB, FreezeOdd->getIterator());
3770 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3771 Helper.widenScalar(*FreezeOdd, 0, S64));
3772
3773 B.setInsertPt(*EntryMBB, FreezeVector->getIterator());
3774 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3775 Helper.fewerElementsVector(*FreezeVector, 0, V2S16));
3776
3777 // This should be followed by fewerElements to V2S16.
3778 B.setInsertPt(*EntryMBB, FreezeVector1->getIterator());
3779 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3780 Helper.moreElementsVector(*FreezeVector1, 0, V4S16));
3781
3782 const auto *CheckStr = R"(
3783 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3784 CHECK: [[TRUNC:%[0-9]+]]:_(s33) = G_TRUNC [[COPY]]
3785 CHECK: [[TRUNC1:%[0-9]+]]:_(s48) = G_TRUNC [[COPY]]
3786 CHECK: [[BITCAST:%[0-9]+]]:_(<3 x s16>) = G_BITCAST [[TRUNC1]]
3787
3788 CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]]
3789 CHECK: [[FREEZE:%[0-9]+]]:_(s32) = G_FREEZE [[UV]]
3790 CHECK: [[FREEZE1:%[0-9]+]]:_(s32) = G_FREEZE [[UV1]]
3791 CHECK: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[FREEZE]]:_(s32), [[FREEZE1]]
3792
3793 CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[TRUNC]]
3794 CHECK: [[FREEZE2:%[0-9]+]]:_(s64) = G_FREEZE [[ANYEXT]]
3795 CHECK: [[TRUNC1:%[0-9]+]]:_(s33) = G_TRUNC [[FREEZE2]]
3796
3797 CHECK: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[BITCAST]]
3798 CHECK: [[BV:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[UV2]]:_(s16), [[UV3]]:_(s16)
3799 CHECK: [[FREEZE3:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[BV]]
3800 CHECK: [[FREEZE4:%[0-9]+]]:_(s16) = G_FREEZE [[UV4]]
3801 CHECK: [[FREEZE3_E0:%[0-9]+]]:_(s16), [[FREEZE3_E1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[FREEZE3]]
3802 CHECK: [[BV1:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[FREEZE3_E0]]:_(s16), [[FREEZE3_E1]]:_(s16), [[FREEZE4]]:_(s16)
3803
3804 CHECK: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[BITCAST]]
3805 CHECK: [[IMP_DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
3806 CHECK: [[BV1:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[UV5]]:_(s16), [[UV6]]:_(s16), [[UV7]]:_(s16), [[IMP_DEF]]:_(s16)
3807 CHECK: [[FREEZE5:%[0-9]+]]:_(<4 x s16>) = G_FREEZE [[BV1]]
3808 CHECK: [[FREEZE5_E0:%[0-9]+]]:_(s16), [[FREEZE5_E1:%[0-9]+]]:_(s16), [[FREEZE5_E2:%[0-9]+]]:_(s16), [[FREEZE5_E3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[FREEZE5]]
3809 CHECK: [[BV2:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[FREEZE5_E0]]:_(s16), [[FREEZE5_E1]]:_(s16), [[FREEZE5_E2]]:_(s16)
3810 )";
3811
3812 // Check
3813 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3814 }
3815
3816 // Test fewer elements of G_FREEZE
TEST_F(AArch64GISelMITest,FewerElementsFreeze)3817 TEST_F(AArch64GISelMITest, FewerElementsFreeze) {
3818 setUp();
3819 if (!TM)
3820 return;
3821
3822 DefineLegalizerInfo(A, {});
3823
3824 LLT S32{LLT::scalar(32)};
3825 LLT V2S16{LLT::fixed_vector(2, 16)};
3826 LLT V2S32{LLT::fixed_vector(2, 32)};
3827 LLT V4S16{LLT::fixed_vector(4, 16)};
3828
3829 auto Vector1 = B.buildBitcast(V2S32, Copies[0]);
3830 auto Vector2 = B.buildBitcast(V4S16, Copies[0]);
3831
3832 auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector1});
3833 auto FreezeVector2 = B.buildInstr(TargetOpcode::G_FREEZE, {V4S16}, {Vector2});
3834
3835 AInfo Info(MF->getSubtarget());
3836 DummyGISelObserver Observer;
3837 LegalizerHelper Helper(*MF, Info, Observer, B);
3838
3839 // Perform Legalization
3840
3841 B.setInsertPt(*EntryMBB, FreezeVector1->getIterator());
3842 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3843 Helper.fewerElementsVector(*FreezeVector1, 0, S32));
3844
3845 B.setInsertPt(*EntryMBB, FreezeVector2->getIterator());
3846 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3847 Helper.fewerElementsVector(*FreezeVector2, 0, V2S16));
3848
3849 const auto *CheckStr = R"(
3850 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3851 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3852 CHECK: [[BITCAST1:%[0-9]+]]:_(<4 x s16>) = G_BITCAST [[COPY]]
3853
3854 CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST]]
3855 CHECK: [[FREEZE:%[0-9]+]]:_(s32) = G_FREEZE [[UV]]
3856 CHECK: [[FREEZE1:%[0-9]+]]:_(s32) = G_FREEZE [[UV1]]
3857 CHECK: [[MV:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FREEZE]]:_(s32), [[FREEZE1]]
3858
3859 CHECK: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[BITCAST1]]
3860 CHECK: [[FREEZE2:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[UV]]
3861 CHECK: [[FREEZE3:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[UV1]]
3862 CHECK: [[MV:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[FREEZE2]]:_(<2 x s16>), [[FREEZE3]]
3863 )";
3864
3865 // Check
3866 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3867 }
3868
3869 // Test more elements of G_FREEZE
TEST_F(AArch64GISelMITest,MoreElementsFreeze)3870 TEST_F(AArch64GISelMITest, MoreElementsFreeze) {
3871 setUp();
3872 if (!TM)
3873 return;
3874
3875 DefineLegalizerInfo(A, {});
3876
3877 LLT V2S32{LLT::fixed_vector(2, 32)};
3878 LLT V4S32{LLT::fixed_vector(4, 32)};
3879
3880 auto Vector1 = B.buildBitcast(V2S32, Copies[0]);
3881 auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector1});
3882
3883 AInfo Info(MF->getSubtarget());
3884 DummyGISelObserver Observer;
3885 LegalizerHelper Helper(*MF, Info, Observer, B);
3886
3887 // Perform Legalization
3888 B.setInsertPt(*EntryMBB, FreezeVector1->getIterator());
3889 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3890 Helper.moreElementsVector(*FreezeVector1, 0, V4S32));
3891
3892 const auto *CheckStr = R"(
3893 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3894 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3895 CHECK: [[BITCAST_E0:%[0-9]+]]:_(s32), [[BITCAST_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST]]:_(<2 x s32>)
3896 CHECK: [[IMP_DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3897 CHECK: [[BITCAST_LARGE:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[BITCAST_E0]]:_(s32), [[BITCAST_E1]]:_(s32), [[IMP_DEF]]:_(s32), [[IMP_DEF]]:_(s32)
3898 CHECK: [[FREEZE:%[0-9]+]]:_(<4 x s32>) = G_FREEZE [[BITCAST_LARGE]]
3899 CHECK: [[FREEZE_E0:%[0-9]+]]:_(s32), [[FREEZE_E1:%[0-9]+]]:_(s32), [[FREEZE_E2:%[0-9]+]]:_(s32), [[FREEZE_E3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FREEZE]]:_(<4 x s32>)
3900 CHECK: (<2 x s32>) = G_BUILD_VECTOR [[FREEZE_E0]]:_(s32), [[FREEZE_E1]]:_(s32)
3901 )";
3902
3903 // Check
3904 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3905 }
3906
3907 // Test fewer elements of G_INSERT_VECTOR_ELEMENT
TEST_F(AArch64GISelMITest,FewerElementsInsertVectorElt)3908 TEST_F(AArch64GISelMITest, FewerElementsInsertVectorElt) {
3909 setUp();
3910 if (!TM)
3911 return;
3912
3913 DefineLegalizerInfo(A, {});
3914
3915 LLT P0{LLT::pointer(0, 64)};
3916 LLT S64{LLT::scalar(64)};
3917 LLT S16{LLT::scalar(16)};
3918 LLT V2S16{LLT::fixed_vector(2, 16)};
3919 LLT V3S16{LLT::fixed_vector(3, 16)};
3920 LLT V8S16{LLT::fixed_vector(8, 16)};
3921
3922 auto Ptr0 = B.buildIntToPtr(P0, Copies[0]);
3923 auto VectorV8 = B.buildLoad(V8S16, Ptr0, MachinePointerInfo(), Align(8));
3924 auto Value = B.buildTrunc(S16, Copies[1]);
3925
3926 auto Seven = B.buildConstant(S64, 7);
3927 auto InsertV8Constant7_0 =
3928 B.buildInsertVectorElement(V8S16, VectorV8, Value, Seven);
3929 auto InsertV8Constant7_1 =
3930 B.buildInsertVectorElement(V8S16, VectorV8, Value, Seven);
3931
3932 B.buildStore(InsertV8Constant7_0, Ptr0, MachinePointerInfo(), Align(8),
3933 MachineMemOperand::MOVolatile);
3934 B.buildStore(InsertV8Constant7_1, Ptr0, MachinePointerInfo(), Align(8),
3935 MachineMemOperand::MOVolatile);
3936
3937 AInfo Info(MF->getSubtarget());
3938 DummyGISelObserver Observer;
3939 LegalizerHelper Helper(*MF, Info, Observer, B);
3940
3941 // Perform Legalization
3942 B.setInsertPt(*EntryMBB, InsertV8Constant7_0->getIterator());
3943
3944 // This should index the high element of the 4th piece of an unmerge.
3945 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3946 Helper.fewerElementsVector(*InsertV8Constant7_0, 0, V2S16));
3947
3948 // This case requires extracting an intermediate vector type into the target
3949 // v4s16.
3950 B.setInsertPt(*EntryMBB, InsertV8Constant7_1->getIterator());
3951 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3952 Helper.fewerElementsVector(*InsertV8Constant7_1, 0, V3S16));
3953
3954 const auto *CheckStr = R"(
3955 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
3956 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
3957 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY
3958 CHECK: [[PTR0:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY0]]
3959 CHECK: [[VEC8:%[0-9]+]]:_(<8 x s16>) = G_LOAD [[PTR0]]:_(p0) :: (load (<8 x s16>), align 8)
3960 CHECK: [[INSERT_VAL:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]]
3961
3962
3963 CHECK: [[UNMERGE0:%[0-9]+]]:_(<2 x s16>), [[UNMERGE1:%[0-9]+]]:_(<2 x s16>), [[UNMERGE2:%[0-9]+]]:_(<2 x s16>), [[UNMERGE3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[VEC8]]
3964 CHECK: [[ONE:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
3965 CHECK: [[SUB_INSERT_7:%[0-9]+]]:_(<2 x s16>) = G_INSERT_VECTOR_ELT [[UNMERGE3]]:_, [[INSERT_VAL]]:_(s16), [[ONE]]
3966 CHECK: [[INSERT_V8_7_0:%[0-9]+]]:_(<8 x s16>) = G_CONCAT_VECTORS [[UNMERGE0]]:_(<2 x s16>), [[UNMERGE1]]:_(<2 x s16>), [[UNMERGE2]]:_(<2 x s16>), [[SUB_INSERT_7]]:_(<2 x s16>)
3967
3968
3969 CHECK: [[UNMERGE1_0:%[0-9]+]]:_(s16), [[UNMERGE1_1:%[0-9]+]]:_(s16), [[UNMERGE1_2:%[0-9]+]]:_(s16), [[UNMERGE1_3:%[0-9]+]]:_(s16), [[UNMERGE1_4:%[0-9]+]]:_(s16), [[UNMERGE1_5:%[0-9]+]]:_(s16), [[UNMERGE1_6:%[0-9]+]]:_(s16), [[UNMERGE1_7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[VEC8]]:_(<8 x s16>)
3970 CHECK: [[IMPDEF_S16:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
3971 CHECK: [[BUILD0:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_0]]:_(s16), [[UNMERGE1_1]]:_(s16), [[UNMERGE1_2]]:_(s16)
3972 CHECK: [[BUILD1:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_3]]:_(s16), [[UNMERGE1_4]]:_(s16), [[UNMERGE1_5]]:_(s16)
3973 CHECK: [[BUILD2:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_6]]:_(s16), [[UNMERGE1_7]]:_(s16), [[IMPDEF_S16]]:_(s16)
3974 CHECK: [[IMPDEF_V3S16:%[0-9]+]]:_(<3 x s16>) = G_IMPLICIT_DEF
3975 CHECK: [[ONE_1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
3976 CHECK: [[SUB_INSERT_7_V3S16:%[0-9]+]]:_(<3 x s16>) = G_INSERT_VECTOR_ELT [[BUILD2]]:_, [[INSERT_VAL]]:_(s16), [[ONE_1]]
3977
3978 CHECK: [[WIDE_CONCAT_DEAD:%[0-9]+]]:_(<24 x s16>) = G_CONCAT_VECTORS [[BUILD0]]:_(<3 x s16>), [[BUILD1]]:_(<3 x s16>), [[SUB_INSERT_7_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>)
3979 CHECK: [[WIDE_CONCAT:%[0-9]+]]:_(<24 x s16>) = G_CONCAT_VECTORS [[BUILD0]]:_(<3 x s16>), [[BUILD1]]:_(<3 x s16>), [[SUB_INSERT_7_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>)
3980 CHECK: [[INSERT_V8_7_1:%[0-9]+]]:_(<8 x s16>), %{{[0-9]+}}:_(<8 x s16>), %{{[0-9]+}}:_(<8 x s16>) = G_UNMERGE_VALUES [[WIDE_CONCAT]]:_(<24 x s16>)
3981
3982
3983 CHECK: G_STORE [[INSERT_V8_7_0]]
3984 CHECK: G_STORE [[INSERT_V8_7_1]]
3985 )";
3986
3987 // Check
3988 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3989 }
3990
3991 // Test widen scalar of G_UNMERGE_VALUES
TEST_F(AArch64GISelMITest,widenScalarUnmerge)3992 TEST_F(AArch64GISelMITest, widenScalarUnmerge) {
3993 setUp();
3994 if (!TM)
3995 return;
3996
3997 DefineLegalizerInfo(A, {});
3998
3999 LLT S96{LLT::scalar(96)};
4000 LLT S64{LLT::scalar(64)};
4001 LLT S48{LLT::scalar(48)};
4002
4003 auto Src = B.buildAnyExt(S96, Copies[0]);
4004 auto Unmerge = B.buildUnmerge(S48, Src);
4005
4006 AInfo Info(MF->getSubtarget());
4007 DummyGISelObserver Observer;
4008 LegalizerHelper Helper(*MF, Info, Observer, B);
4009
4010 // Perform Legalization
4011 B.setInsertPt(*EntryMBB, Unmerge->getIterator());
4012
4013 // This should create unmerges to a GCD type (S16), then remerge to S48
4014 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
4015 Helper.widenScalar(*Unmerge, 0, S64));
4016
4017 const auto *CheckStr = R"(
4018 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
4019 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
4020 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY
4021 CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY0]]
4022 CHECK: [[ANYEXT1:%[0-9]+]]:_(s192) = G_ANYEXT [[ANYEXT]]
4023 CHECK: [[UNMERGE:%[0-9]+]]:_(s64), [[UNMERGE1:%[0-9]+]]:_(s64), [[UNMERGE2:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT1]]
4024 CHECK: [[UNMERGE3:%[0-9]+]]:_(s16), [[UNMERGE4:%[0-9]+]]:_(s16), [[UNMERGE5:%[0-9]+]]:_(s16), [[UNMERGE6:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE]]
4025 CHECK: [[UNMERGE7:%[0-9]+]]:_(s16), [[UNMERGE8:%[0-9]+]]:_(s16), [[UNMERGE9:%[0-9]+]]:_(s16), [[UNMERGE10:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE1]]
4026 CHECK: [[UNMERGE11:%[0-9]+]]:_(s16), [[UNMERGE12:%[0-9]+]]:_(s16), [[UNMERGE13:%[0-9]+]]:_(s16), [[UNMERGE14:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE2]]
4027 CHECK: [[MERGE:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE3]]:_(s16), [[UNMERGE4]]:_(s16), [[UNMERGE5]]:_(s16)
4028 CHECK: [[MERGE1:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE6]]:_(s16), [[UNMERGE7]]:_(s16), [[UNMERGE8]]:_(s16)
4029 )";
4030
4031 // Check
4032 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
4033 }
4034
4035 // Test moreElements of G_SHUFFLE_VECTOR.
TEST_F(AArch64GISelMITest,moreElementsShuffle)4036 TEST_F(AArch64GISelMITest, moreElementsShuffle) {
4037 setUp();
4038 if (!TM)
4039 return;
4040
4041 DefineLegalizerInfo(A, {});
4042
4043 LLT S64{LLT::scalar(64)};
4044 LLT V6S64 = LLT::fixed_vector(6, S64);
4045
4046 auto V1 = B.buildBuildVector(V6S64, {Copies[0], Copies[1], Copies[0],
4047 Copies[1], Copies[0], Copies[1]});
4048 auto V2 = B.buildBuildVector(V6S64, {Copies[0], Copies[1], Copies[0],
4049 Copies[1], Copies[0], Copies[1]});
4050 auto Shuffle = B.buildShuffleVector(V6S64, V1, V2, {3, 4, 7, 0, 1, 11});
4051
4052 AInfo Info(MF->getSubtarget());
4053 DummyGISelObserver Observer;
4054 LegalizerHelper Helper(*MF, Info, Observer, B);
4055
4056 // Perform Legalization
4057 B.setInsertPt(*EntryMBB, Shuffle->getIterator());
4058
4059 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
4060 Helper.moreElementsVector(*Shuffle, 0, LLT::fixed_vector(8, S64)));
4061
4062 const auto *CheckStr = R"(
4063 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
4064 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
4065 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY
4066 CHECK: [[BV1:%[0-9]+]]:_(<6 x s64>) = G_BUILD_VECTOR
4067 CHECK: [[BV2:%[0-9]+]]:_(<6 x s64>) = G_BUILD_VECTOR
4068
4069 CHECK: [[BV1_E0:%[0-9]+]]:_(s64), [[BV1_E1:%[0-9]+]]:_(s64), [[BV1_E2:%[0-9]+]]:_(s64), [[BV1_E3:%[0-9]+]]:_(s64), [[BV1_E4:%[0-9]+]]:_(s64), [[BV1_E5:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[BV1]]:_(<6 x s64>)
4070 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
4071 CHECK: [[BV1_LARGE:%[0-9]+]]:_(<8 x s64>) = G_BUILD_VECTOR [[BV1_E0]]:_(s64), [[BV1_E1]]:_(s64), [[BV1_E2]]:_(s64), [[BV1_E3]]:_(s64), [[BV1_E4]]:_(s64), [[BV1_E5]]:_(s64), [[IMP_DEF0]]:_(s64), [[IMP_DEF0]]:_(s64)
4072
4073 CHECK: [[BV2_E0:%[0-9]+]]:_(s64), [[BV2_E1:%[0-9]+]]:_(s64), [[BV2_E2:%[0-9]+]]:_(s64), [[BV2_E3:%[0-9]+]]:_(s64), [[BV2_E4:%[0-9]+]]:_(s64), [[BV2_E5:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[BV2]]:_(<6 x s64>)
4074 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
4075 CHECK: [[BV2_LARGE:%[0-9]+]]:_(<8 x s64>) = G_BUILD_VECTOR [[BV2_E0]]:_(s64), [[BV2_E1]]:_(s64), [[BV2_E2]]:_(s64), [[BV2_E3]]:_(s64), [[BV2_E4]]:_(s64), [[BV2_E5]]:_(s64), [[IMP_DEF1]]:_(s64), [[IMP_DEF1]]:_(s64)
4076
4077 CHECK: [[SHUF:%[0-9]+]]:_(<8 x s64>) = G_SHUFFLE_VECTOR [[BV1_LARGE]]:_(<8 x s64>), [[BV2_LARGE]]:_, shufflemask(3, 4, 9, 0, 1, 13, undef, undef)
4078
4079 CHECK: [[SHUF_E0:%[0-9]+]]:_(s64), [[SHUF_E1:%[0-9]+]]:_(s64), [[SHUF_E2:%[0-9]+]]:_(s64), [[SHUF_E3:%[0-9]+]]:_(s64), [[SHUF_E4:%[0-9]+]]:_(s64), [[SHUF_E5:%[0-9]+]]:_(s64), [[SHUF_E6:%[0-9]+]]:_(s64), [[SHUF_E7:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[SHUF]]:_(<8 x s64>)
4080 CHECK: (<6 x s64>) = G_BUILD_VECTOR [[SHUF_E0]]:_(s64), [[SHUF_E1]]:_(s64), [[SHUF_E2]]:_(s64), [[SHUF_E3]]:_(s64), [[SHUF_E4]]:_(s64), [[SHUF_E5]]:_(s64)
4081 )";
4082
4083 // Check
4084 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
4085 }
4086
4087 // Test narror scalar of G_SHL with constant shift amount
TEST_F(AArch64GISelMITest,narrowScalarShiftByConstant)4088 TEST_F(AArch64GISelMITest, narrowScalarShiftByConstant) {
4089 setUp();
4090 if (!TM)
4091 return;
4092
4093 DefineLegalizerInfo(A, {});
4094
4095 LLT S64{LLT::scalar(64)};
4096 LLT S32{LLT::scalar(32)};
4097
4098 auto Constant = B.buildConstant(S64, 33);
4099 auto Trunc = B.buildTrunc(S32, Constant);
4100 auto Shift = B.buildShl(S64, Copies[0], Trunc);
4101
4102 AInfo Info(MF->getSubtarget());
4103 DummyGISelObserver Observer;
4104 LegalizerHelper Helper(*MF, Info, Observer, B);
4105
4106 // Perform Legalization
4107 B.setInsertPt(*EntryMBB, Shift->getIterator());
4108
4109 // This should detect the G_CONSTANT feeding the G_SHL through a G_TRUNC
4110 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
4111 Helper.narrowScalarShift(*Shift, 0, S32));
4112
4113 const auto *CheckStr = R"(
4114 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
4115 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
4116 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY
4117 CHECK: [[THIRTY3:%[0-9]+]]:_(s64) = G_CONSTANT i64 33
4118 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %4:_(s64)
4119 CHECK: [[UNMERGE:%[0-9]+]]:_(s32), [[UNMERGE2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY0]]
4120 CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
4121 CHECK: [[ONE:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
4122 CHECK: [[SHIFT:%[0-9]+]]:_(s32) = G_SHL [[UNMERGE]]:_, [[ONE]]:_(s32)
4123 CHECK: [[MERGE:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ZERO]]:_(s32), [[SHIFT]]:_(s32)
4124 )";
4125
4126 // Check
4127 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
4128 }
4129
TEST_F(AArch64GISelMITest,MoreElementsSelect)4130 TEST_F(AArch64GISelMITest, MoreElementsSelect) {
4131 setUp();
4132 if (!TM)
4133 return;
4134
4135 LLT s1 = LLT::scalar(1);
4136 LLT s64 = LLT::scalar(64);
4137 LLT v2s1 = LLT::fixed_vector(2, 1);
4138 LLT v2s32 = LLT::fixed_vector(2, 32);
4139
4140 LegalizerInfo LI;
4141 DummyGISelObserver Observer;
4142 LegalizerHelper Helper(*MF, LI, Observer, B);
4143
4144 B.setInsertPt(*EntryMBB, EntryMBB->end());
4145
4146 auto Val0 = B.buildBitcast(v2s32, Copies[0]);
4147 auto Val1 = B.buildBitcast(v2s32, Copies[1]);
4148
4149 // Build select of vectors with scalar condition.
4150 auto Zero = B.buildConstant(s64, 0);
4151 auto Cond = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[2], Zero);
4152 auto Select = B.buildSelect(v2s32, Cond, Val0, Val1);
4153
4154 // Splat the condition into a vector select
4155 B.setInstr(*Select);
4156
4157 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
4158 Helper.moreElementsVector(*Select, 1, LLT::fixed_vector(3, 1)));
4159 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
4160 Helper.moreElementsVector(*Select, 1, v2s1));
4161
4162 auto CheckStr = R"(
4163 CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
4164 CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
4165 CHECK: [[ZERO0:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
4166 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %{{[0-9]+}}:_(s64), [[ZERO0]]
4167 CHECK: [[IMPDEF:%[0-9]+]]:_(<2 x s1>) = G_IMPLICIT_DEF
4168 CHECK: [[ZERO1:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
4169 CHECK: [[INSERT:%[0-9]+]]:_(<2 x s1>) = G_INSERT_VECTOR_ELT [[IMPDEF]]:_, [[CMP]]:_(s1), [[ZERO1]]
4170 CHECK: [[SHUFFLE:%[0-9]+]]:_(<2 x s1>) = G_SHUFFLE_VECTOR [[INSERT]]:_(<2 x s1>), [[IMPDEF]]:_, shufflemask(0, 0)
4171 CHECK: [[SELECT:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[SHUFFLE]]:_(<2 x s1>), [[BITCAST0]]:_, [[BITCAST1]]:_
4172 )";
4173
4174 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
4175 }
4176
4177 } // namespace
4178