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
12 using namespace LegalizeActions;
13 using namespace LegalizeMutations;
14 using namespace LegalityPredicates;
15
16 namespace {
17
18 class DummyGISelObserver : public GISelChangeObserver {
19 public:
changingInstr(MachineInstr & MI)20 void changingInstr(MachineInstr &MI) override {}
changedInstr(MachineInstr & MI)21 void changedInstr(MachineInstr &MI) override {}
createdInstr(MachineInstr & MI)22 void createdInstr(MachineInstr &MI) override {}
erasingInstr(MachineInstr & MI)23 void erasingInstr(MachineInstr &MI) override {}
24 };
25
26 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom,
27 // in which case it becomes CTTZ_ZERO_UNDEF with select.
TEST_F(AArch64GISelMITest,LowerBitCountingCTTZ0)28 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ0) {
29 setUp();
30 if (!TM)
31 return;
32
33 // Declare your legalization info
34 DefineLegalizerInfo(A, {
35 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s32, s64}});
36 });
37 // Build Instr
38 auto MIBCTTZ =
39 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]});
40 AInfo Info(MF->getSubtarget());
41 DummyGISelObserver Observer;
42 LegalizerHelper Helper(*MF, Info, Observer, B);
43 // Perform Legalization
44 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
45 Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)));
46
47 auto CheckStr = R"(
48 CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF %0
49 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
50 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
51 CHECK: [[SIXTY4:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
52 CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
53 )";
54
55 // Check
56 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
57 }
58
59 // CTTZ expansion in terms of CTLZ
TEST_F(AArch64GISelMITest,LowerBitCountingCTTZ1)60 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ1) {
61 setUp();
62 if (!TM)
63 return;
64
65 // Declare your legalization info
66 DefineLegalizerInfo(A, {
67 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}});
68 });
69 // Build Instr
70 auto MIBCTTZ =
71 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
72 AInfo Info(MF->getSubtarget());
73 DummyGISelObserver Observer;
74 LegalizerHelper Helper(*MF, Info, Observer, B);
75 // Perform Legalization
76 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
77 LegalizerHelper::LegalizeResult::Legalized);
78
79 auto CheckStr = R"(
80 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
81 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
82 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
83 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
84 CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
85 CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_
86 CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_
87 )";
88
89 // Check
90 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
91 }
92
93 // CTLZ scalar narrowing
TEST_F(AArch64GISelMITest,NarrowScalarCTLZ)94 TEST_F(AArch64GISelMITest, NarrowScalarCTLZ) {
95 setUp();
96 if (!TM)
97 return;
98
99 // Declare your legalization info
100 DefineLegalizerInfo(A, {
101 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s32, s32}});
102 });
103 // Build Instr
104 auto CTLZ =
105 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]});
106 AInfo Info(MF->getSubtarget());
107 DummyGISelObserver Observer;
108 LegalizerHelper Helper(*MF, Info, Observer, B);
109 // Perform Legalization
110 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
111 Helper.narrowScalar(*CTLZ, 1, LLT::scalar(32)));
112
113 auto CheckStr = R"(
114 CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64)
115 CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
116 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_HI]]:_(s32), [[ZERO]]:_
117 CHECK: [[CTLZ_LO:%[0-9]+]]:_(s32) = G_CTLZ [[UNMERGE_LO]]:_(s32)
118 CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
119 CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTLZ_LO]]:_, [[THIRTYTWO]]:_
120 CHECK: [[CTLZ_HI:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[UNMERGE_HI]]:_(s32)
121 CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTLZ_HI]]:_
122 )";
123
124 // Check
125 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
126 }
127
128 // CTTZ scalar narrowing
TEST_F(AArch64GISelMITest,NarrowScalarCTTZ)129 TEST_F(AArch64GISelMITest, NarrowScalarCTTZ) {
130 setUp();
131 if (!TM)
132 return;
133
134 // Declare your legalization info
135 DefineLegalizerInfo(A, {
136 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s32, s64}});
137 });
138 // Build Instr
139 auto CTTZ =
140 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]});
141 AInfo Info(MF->getSubtarget());
142 DummyGISelObserver Observer;
143 LegalizerHelper Helper(*MF, Info, Observer, B);
144 // Perform Legalization
145 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
146 Helper.narrowScalar(*CTTZ, 1, LLT::scalar(32)));
147
148 auto CheckStr = R"(
149 CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64)
150 CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
151 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_LO]]:_(s32), [[ZERO]]:_
152 CHECK: [[CTTZ_HI:%[0-9]+]]:_(s32) = G_CTTZ [[UNMERGE_HI]]:_(s32)
153 CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
154 CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTTZ_HI]]:_, [[THIRTYTWO]]:_
155 CHECK: [[CTTZ_LO:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[UNMERGE_LO]]:_(s32)
156 CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTTZ_LO]]:_
157 )";
158
159 // Check
160 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
161 }
162
163 // CTTZ expansion in terms of CTPOP
TEST_F(AArch64GISelMITest,LowerBitCountingCTTZ2)164 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ2) {
165 setUp();
166 if (!TM)
167 return;
168
169 // Declare your legalization info
170 DefineLegalizerInfo(A, {
171 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}});
172 });
173 // Build
174 auto MIBCTTZ =
175 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
176 AInfo Info(MF->getSubtarget());
177 DummyGISelObserver Observer;
178 LegalizerHelper Helper(*MF, Info, Observer, B);
179
180 B.setInsertPt(*EntryMBB, MIBCTTZ->getIterator());
181 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
182 LegalizerHelper::LegalizeResult::Legalized);
183
184 auto CheckStr = R"(
185 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
186 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
187 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
188 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
189 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
190 )";
191
192 // Check
193 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
194 }
195
196 // CTPOP widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTPOP1)197 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP1) {
198 if (!TM)
199 return;
200
201 // Declare your legalization info
202 DefineLegalizerInfo(A, {
203 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
204 });
205
206 // Build
207 // Trunc it to s8.
208 LLT s8{LLT::scalar(8)};
209 LLT s16{LLT::scalar(16)};
210 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
211 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc});
212 AInfo Info(MF->getSubtarget());
213 DummyGISelObserver Observer;
214 LegalizerHelper Helper(*MF, Info, Observer, B);
215 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
216 Helper.widenScalar(*MIBCTPOP, 1, s16));
217
218 auto CheckStr = R"(
219 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
220 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
221 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
222 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16)
223 )";
224
225 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
226 }
227
228 // Test a strange case where the result is wider than the source
TEST_F(AArch64GISelMITest,WidenBitCountingCTPOP2)229 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP2) {
230 if (!TM)
231 return;
232
233 // Declare your legalization info
234 DefineLegalizerInfo(A, {
235 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}});
236 });
237
238 // Build
239 // Trunc it to s8.
240 LLT s8{LLT::scalar(8)};
241 LLT s16{LLT::scalar(16)};
242 LLT s32{LLT::scalar(32)};
243 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
244 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc});
245 AInfo Info(MF->getSubtarget());
246 DummyGISelObserver Observer;
247 LegalizerHelper Helper(*MF, Info, Observer, B);
248 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
249 Helper.widenScalar(*MIBCTPOP, 1, s16));
250
251 auto CheckStr = R"(
252 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
253 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
254 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
255 CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16)
256 )";
257
258 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
259 }
260
261 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
TEST_F(AArch64GISelMITest,LowerBitCountingCTTZ3)262 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ3) {
263 setUp();
264 if (!TM)
265 return;
266
267 // Declare your legalization info
268 DefineLegalizerInfo(A, {
269 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
270 });
271 // Build
272 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
273 {LLT::scalar(64)}, {Copies[0]});
274 AInfo Info(MF->getSubtarget());
275 DummyGISelObserver Observer;
276 LegalizerHelper Helper(*MF, Info, Observer, B);
277 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
278 LegalizerHelper::LegalizeResult::Legalized);
279
280 auto CheckStr = R"(
281 CHECK: CTTZ
282 )";
283
284 // Check
285 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
286 }
287
288 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
TEST_F(AArch64GISelMITest,LowerBitCountingCTLZ0)289 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZ0) {
290 setUp();
291 if (!TM)
292 return;
293
294 // Declare your legalization info
295 DefineLegalizerInfo(A, {
296 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
297 });
298 // Build
299 auto MIBCTLZ =
300 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
301 AInfo Info(MF->getSubtarget());
302 DummyGISelObserver Observer;
303 LegalizerHelper Helper(*MF, Info, Observer, B);
304 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
305 LegalizerHelper::LegalizeResult::Legalized);
306
307 auto CheckStr = R"(
308 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
309 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
310 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
311 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
312 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
313 )";
314
315 // Check
316 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
317 }
318
319 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall
TEST_F(AArch64GISelMITest,LowerBitCountingCTLZLibcall)320 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZLibcall) {
321 setUp();
322 if (!TM)
323 return;
324
325 // Declare your legalization info
326 DefineLegalizerInfo(A, {
327 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s32, s64}});
328 });
329 // Build
330 auto MIBCTLZ =
331 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]});
332 AInfo Info(MF->getSubtarget());
333 DummyGISelObserver Observer;
334 LegalizerHelper Helper(*MF, Info, Observer, B);
335 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
336 Helper.lower(*MIBCTLZ, 0, LLT::scalar(32)));
337
338 auto CheckStr = R"(
339 CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF %0
340 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
341 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
342 CHECK: [[THIRTY2:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
343 CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]]
344 )";
345
346 // Check
347 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
348 }
349
350 // CTLZ expansion
TEST_F(AArch64GISelMITest,LowerBitCountingCTLZ1)351 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZ1) {
352 setUp();
353 if (!TM)
354 return;
355
356 // Declare your legalization info
357 DefineLegalizerInfo(A, {
358 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
359 });
360 // Build
361 // Trunc it to s8.
362 LLT s8{LLT::scalar(8)};
363 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
364 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
365 AInfo Info(MF->getSubtarget());
366 DummyGISelObserver Observer;
367 LegalizerHelper Helper(*MF, Info, Observer, B);
368 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
369 LegalizerHelper::LegalizeResult::Legalized);
370
371 auto CheckStr = R"(
372 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
373 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
374 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
375 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
376 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
377 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
378 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
379 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
380 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
381 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
382 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
383 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
384 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
385 )";
386
387 // Check
388 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
389 }
390
391 // CTLZ widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTLZ)392 TEST_F(AArch64GISelMITest, WidenBitCountingCTLZ) {
393 setUp();
394 if (!TM)
395 return;
396
397 // Declare your legalization info
398 DefineLegalizerInfo(A, {
399 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
400 });
401 // Build
402 // Trunc it to s8.
403 LLT s8{LLT::scalar(8)};
404 LLT s16{LLT::scalar(16)};
405 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
406 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
407 AInfo Info(MF->getSubtarget());
408 DummyGISelObserver Observer;
409 LegalizerHelper Helper(*MF, Info, Observer, B);
410 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) ==
411 LegalizerHelper::LegalizeResult::Legalized);
412
413 auto CheckStr = R"(
414 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
415 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
416 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
417 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
418 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
419 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
420 )";
421
422 // Check
423 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
424 }
425
426 // CTLZ_ZERO_UNDEF widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTLZZeroUndef)427 TEST_F(AArch64GISelMITest, WidenBitCountingCTLZZeroUndef) {
428 setUp();
429 if (!TM)
430 return;
431
432 // Declare your legalization info
433 DefineLegalizerInfo(A, {
434 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
435 });
436 // Build
437 // Trunc it to s8.
438 LLT s8{LLT::scalar(8)};
439 LLT s16{LLT::scalar(16)};
440 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
441 auto MIBCTLZ_ZU =
442 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc});
443 AInfo Info(MF->getSubtarget());
444 DummyGISelObserver Observer;
445 LegalizerHelper Helper(*MF, Info, Observer, B);
446 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) ==
447 LegalizerHelper::LegalizeResult::Legalized);
448
449 auto CheckStr = R"(
450 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
451 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
452 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
453 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
454 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
455 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
456 )";
457
458 // Check
459 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
460 }
461
462 // CTPOP widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTPOP)463 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP) {
464 setUp();
465 if (!TM)
466 return;
467
468 // Declare your legalization info
469 DefineLegalizerInfo(A, {
470 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
471 });
472 // Build
473 // Trunc it to s8.
474 LLT s8{LLT::scalar(8)};
475 LLT s16{LLT::scalar(16)};
476 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
477 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc});
478 AInfo Info(MF->getSubtarget());
479 DummyGISelObserver Observer;
480 LegalizerHelper Helper(*MF, Info, Observer, B);
481 EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) ==
482 LegalizerHelper::LegalizeResult::Legalized);
483
484 auto CheckStr = R"(
485 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
486 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
487 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
488 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
489 )";
490
491 // Check
492 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
493 }
494
495 // CTTZ_ZERO_UNDEF widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTTZ_ZERO_UNDEF)496 TEST_F(AArch64GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
497 setUp();
498 if (!TM)
499 return;
500
501 // Declare your legalization info
502 DefineLegalizerInfo(A, {
503 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
504 });
505 // Build
506 // Trunc it to s8.
507 LLT s8{LLT::scalar(8)};
508 LLT s16{LLT::scalar(16)};
509 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
510 auto MIBCTTZ_ZERO_UNDEF =
511 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc});
512 AInfo Info(MF->getSubtarget());
513 DummyGISelObserver Observer;
514 LegalizerHelper Helper(*MF, Info, Observer, B);
515 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) ==
516 LegalizerHelper::LegalizeResult::Legalized);
517
518 auto CheckStr = R"(
519 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
520 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
521 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
522 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
523 )";
524
525 // Check
526 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
527 }
528
529 // CTTZ widening.
TEST_F(AArch64GISelMITest,WidenBitCountingCTTZ)530 TEST_F(AArch64GISelMITest, WidenBitCountingCTTZ) {
531 setUp();
532 if (!TM)
533 return;
534
535 // Declare your legalization info
536 DefineLegalizerInfo(A, {
537 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
538 });
539 // Build
540 // Trunc it to s8.
541 LLT s8{LLT::scalar(8)};
542 LLT s16{LLT::scalar(16)};
543 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
544 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc});
545 AInfo Info(MF->getSubtarget());
546 DummyGISelObserver Observer;
547 LegalizerHelper Helper(*MF, Info, Observer, B);
548 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) ==
549 LegalizerHelper::LegalizeResult::Legalized);
550
551 auto CheckStr = R"(
552 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
553 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
554 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
555 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
556 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
557 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
558 )";
559
560 // Check
561 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
562 }
563 // UADDO widening.
TEST_F(AArch64GISelMITest,WidenUADDO)564 TEST_F(AArch64GISelMITest, WidenUADDO) {
565 setUp();
566 if (!TM)
567 return;
568
569 // Declare your legalization info
570 DefineLegalizerInfo(A, {
571 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
572 });
573 // Build
574 // Trunc it to s8.
575 LLT s8{LLT::scalar(8)};
576 LLT s16{LLT::scalar(16)};
577 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
578 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
579 auto MIBUAddO =
580 B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
581 AInfo Info(MF->getSubtarget());
582 DummyGISelObserver Observer;
583 LegalizerHelper Helper(*MF, Info, Observer, B);
584 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
585 LegalizerHelper::LegalizeResult::Legalized);
586
587 auto CheckStr = R"(
588 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
589 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
590 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
591 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
592 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ADD]]
593 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
594 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[ZEXT]]:_
595 CHECK: G_TRUNC [[ADD]]
596 )";
597
598 // Check
599 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
600 }
601
602 // USUBO widening.
TEST_F(AArch64GISelMITest,WidenUSUBO)603 TEST_F(AArch64GISelMITest, WidenUSUBO) {
604 setUp();
605 if (!TM)
606 return;
607
608 // Declare your legalization info
609 DefineLegalizerInfo(A, {
610 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
611 });
612 // Build
613 // Trunc it to s8.
614 LLT s8{LLT::scalar(8)};
615 LLT s16{LLT::scalar(16)};
616 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
617 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
618 auto MIBUSUBO =
619 B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
620 AInfo Info(MF->getSubtarget());
621 DummyGISelObserver Observer;
622 LegalizerHelper Helper(*MF, Info, Observer, B);
623 EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
624 LegalizerHelper::LegalizeResult::Legalized);
625
626 auto CheckStr = R"(
627 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
628 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
629 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
630 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
631 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SUB]]
632 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
633 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[ZEXT]]:_
634 CHECK: G_TRUNC [[SUB]]
635 )";
636
637 // Check
638 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
639 }
640
641 // SADDO widening.
TEST_F(AArch64GISelMITest,WidenSADDO)642 TEST_F(AArch64GISelMITest, WidenSADDO) {
643 setUp();
644 if (!TM)
645 return;
646
647 // Declare your legalization info
648 DefineLegalizerInfo(A, {
649 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
650 });
651 // Build
652 // Trunc it to s8.
653 LLT s8{LLT::scalar(8)};
654 LLT s16{LLT::scalar(16)};
655 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
656 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
657 auto MIBSAddO =
658 B.buildInstr(TargetOpcode::G_SADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
659 AInfo Info(MF->getSubtarget());
660 DummyGISelObserver Observer;
661 LegalizerHelper Helper(*MF, Info, Observer, B);
662 EXPECT_TRUE(Helper.widenScalar(*MIBSAddO, 0, s16) ==
663 LegalizerHelper::LegalizeResult::Legalized);
664
665 auto CheckStr = R"(
666 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
667 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
668 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
669 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
670 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ADD]]
671 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
672 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[SEXT]]:_
673 CHECK: G_TRUNC [[ADD]]
674 )";
675
676 // Check
677 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
678 }
679
680 // SSUBO widening.
TEST_F(AArch64GISelMITest,WidenSSUBO)681 TEST_F(AArch64GISelMITest, WidenSSUBO) {
682 setUp();
683 if (!TM)
684 return;
685
686 // Declare your legalization info
687 DefineLegalizerInfo(A, {
688 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
689 });
690 // Build
691 // Trunc it to s8.
692 LLT s8{LLT::scalar(8)};
693 LLT s16{LLT::scalar(16)};
694 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
695 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
696 auto MIBSSUBO =
697 B.buildInstr(TargetOpcode::G_SSUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
698 AInfo Info(MF->getSubtarget());
699 DummyGISelObserver Observer;
700 LegalizerHelper Helper(*MF, Info, Observer, B);
701 EXPECT_TRUE(Helper.widenScalar(*MIBSSUBO, 0, s16) ==
702 LegalizerHelper::LegalizeResult::Legalized);
703
704 auto CheckStr = R"(
705 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
706 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
707 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
708 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
709 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SUB]]
710 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
711 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[SEXT]]:_
712 CHECK: G_TRUNC [[SUB]]
713 )";
714
715 // Check
716 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
717 }
718
TEST_F(AArch64GISelMITest,FewerElementsAnd)719 TEST_F(AArch64GISelMITest, FewerElementsAnd) {
720 if (!TM)
721 return;
722
723 const LLT V2S32 = LLT::vector(2, 32);
724 const LLT V5S32 = LLT::vector(5, 32);
725
726 // Declare your legalization info
727 DefineLegalizerInfo(A, {
728 getActionDefinitionsBuilder(G_AND)
729 .legalFor({s32});
730 });
731
732 auto Op0 = B.buildUndef(V5S32);
733 auto Op1 = B.buildUndef(V5S32);
734 auto And = B.buildAnd(V5S32, Op0, Op1);
735
736 AInfo Info(MF->getSubtarget());
737 DummyGISelObserver Observer;
738 LegalizerHelper Helper(*MF, Info, Observer, B);
739 EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) ==
740 LegalizerHelper::LegalizeResult::Legalized);
741
742 auto CheckStr = R"(
743 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
744 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
745 CHECK: [[IMP_DEF2:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
746 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 0
747 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 0
748 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT0]]:_, [[EXTRACT1]]:_
749 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[IMP_DEF2]]:_, [[AND0]]:_(<2 x s32>), 0
750
751 CHECK: [[EXTRACT2:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 64
752 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 64
753 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT2]]:_, [[EXTRACT3]]:_
754 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[AND1]]:_(<2 x s32>), 64
755
756 CHECK: [[EXTRACT4:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 128
757 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 128
758 CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[EXTRACT4]]:_, [[EXTRACT5]]:_
759 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[AND2]]:_(s32), 128
760 )";
761
762 // Check
763 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
764 }
765
TEST_F(AArch64GISelMITest,MoreElementsAnd)766 TEST_F(AArch64GISelMITest, MoreElementsAnd) {
767 if (!TM)
768 return;
769
770 LLT s32 = LLT::scalar(32);
771 LLT v2s32 = LLT::vector(2, 32);
772 LLT v6s32 = LLT::vector(6, 32);
773
774 LegalizerInfo LI;
775 LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
776 .legalFor({v6s32})
777 .clampMinNumElements(0, s32, 6);
778 LI.computeTables();
779
780 DummyGISelObserver Observer;
781 LegalizerHelper Helper(*MF, LI, Observer, B);
782
783 B.setInsertPt(*EntryMBB, EntryMBB->end());
784
785 auto Val0 = B.buildBitcast(v2s32, Copies[0]);
786 auto Val1 = B.buildBitcast(v2s32, Copies[1]);
787
788 auto And = B.buildAnd(v2s32, Val0, Val1);
789
790 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
791 Helper.moreElementsVector(*And, 0, v6s32));
792
793 auto CheckStr = R"(
794 CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
795 CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
796 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
797 CHECK: [[CONCAT0:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>)
798 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
799 CHECK: [[CONCAT1:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>)
800 CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[CONCAT0]]:_, [[CONCAT1]]:_
801 CHECK: (<2 x s32>) = G_EXTRACT [[AND]]:_(<6 x s32>), 0
802 )";
803
804 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
805 }
806
TEST_F(AArch64GISelMITest,FewerElementsPhi)807 TEST_F(AArch64GISelMITest, FewerElementsPhi) {
808 if (!TM)
809 return;
810
811 LLT s1 = LLT::scalar(1);
812 LLT s32 = LLT::scalar(32);
813 LLT s64 = LLT::scalar(64);
814 LLT v2s32 = LLT::vector(2, 32);
815 LLT v5s32 = LLT::vector(5, 32);
816
817 LegalizerInfo LI;
818 LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
819 .legalFor({v2s32})
820 .clampMinNumElements(0, s32, 2);
821 LI.computeTables();
822
823 LLT PhiTy = v5s32;
824 DummyGISelObserver Observer;
825 LegalizerHelper Helper(*MF, LI, Observer, B);
826 B.setMBB(*EntryMBB);
827
828 MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock();
829 MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock();
830 MF->insert(MF->end(), MidMBB);
831 MF->insert(MF->end(), EndMBB);
832
833 EntryMBB->addSuccessor(MidMBB);
834 EntryMBB->addSuccessor(EndMBB);
835 MidMBB->addSuccessor(EndMBB);
836
837 auto InitVal = B.buildUndef(PhiTy);
838 auto InitOtherVal = B.buildConstant(s64, 999);
839
840 auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
841 B.buildBrCond(ICmp.getReg(0), *MidMBB);
842 B.buildBr(*EndMBB);
843
844
845 B.setMBB(*MidMBB);
846 auto MidVal = B.buildUndef(PhiTy);
847 auto MidOtherVal = B.buildConstant(s64, 345);
848 B.buildBr(*EndMBB);
849
850 B.setMBB(*EndMBB);
851 auto Phi = B.buildInstr(TargetOpcode::G_PHI)
852 .addDef(MRI->createGenericVirtualRegister(PhiTy))
853 .addUse(InitVal.getReg(0))
854 .addMBB(EntryMBB)
855 .addUse(MidVal.getReg(0))
856 .addMBB(MidMBB);
857
858 // Insert another irrelevant phi to make sure the rebuild is inserted after
859 // it.
860 B.buildInstr(TargetOpcode::G_PHI)
861 .addDef(MRI->createGenericVirtualRegister(s64))
862 .addUse(InitOtherVal.getReg(0))
863 .addMBB(EntryMBB)
864 .addUse(MidOtherVal.getReg(0))
865 .addMBB(MidMBB);
866
867 // Add some use instruction after the phis.
868 B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0));
869
870 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
871 Helper.fewerElementsVector(*Phi, 0, v2s32));
872
873 auto CheckStr = R"(
874 CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
875 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 0
876 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 64
877 CHECK: [[EXTRACT2:%[0-9]+]]:_(s32) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 128
878 CHECK: G_BRCOND
879
880 CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
881 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 0
882 CHECK: [[EXTRACT4:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 64
883 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 128
884 CHECK: G_BR
885
886 CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT0]]:_(<2 x s32>), %bb.0, [[EXTRACT3]]:_(<2 x s32>), %bb.1
887 CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT1]]:_(<2 x s32>), %bb.0, [[EXTRACT4]]:_(<2 x s32>), %bb.1
888 CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[EXTRACT2]]:_(s32), %bb.0, [[EXTRACT5]]:_(s32), %bb.1
889
890 CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI
891 CHECK: [[REBUILD_VAL_IMPDEF:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
892 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[REBUILD_VAL_IMPDEF]]:_, [[PHI0]]:_(<2 x s32>), 0
893 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[PHI1]]:_(<2 x s32>), 64
894 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[PHI2]]:_(s32), 128
895 CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[INSERT2]]:_, [[INSERT2]]:_
896 )";
897
898 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
899 }
900
901 // FNEG expansion in terms of FSUB
TEST_F(AArch64GISelMITest,LowerFNEG)902 TEST_F(AArch64GISelMITest, LowerFNEG) {
903 if (!TM)
904 return;
905
906 // Declare your legalization info
907 DefineLegalizerInfo(A, {
908 getActionDefinitionsBuilder(G_FSUB).legalFor({s64});
909 });
910
911 // Build Instr. Make sure FMF are preserved.
912 auto FAdd =
913 B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]},
914 MachineInstr::MIFlag::FmNsz);
915
916 // Should not propagate the flags of src instruction.
917 auto FNeg0 =
918 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)},
919 {MachineInstr::MIFlag::FmArcp});
920
921 // Preserve the one flag.
922 auto FNeg1 =
923 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]},
924 MachineInstr::MIFlag::FmNoInfs);
925
926 AInfo Info(MF->getSubtarget());
927 DummyGISelObserver Observer;
928 LegalizerHelper Helper(*MF, Info, Observer, B);
929 // Perform Legalization
930 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
931 Helper.lower(*FNeg0, 0, LLT::scalar(64)));
932 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
933 Helper.lower(*FNeg1, 0, LLT::scalar(64)));
934
935 auto CheckStr = R"(
936 CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_
937 CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
938 CHECK: [[FSUB0:%[0-9]+]]:_(s64) = arcp G_FSUB [[CONST0]]:_, [[FADD]]:_
939 CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
940 CHECK: [[FSUB1:%[0-9]+]]:_(s64) = ninf G_FSUB [[CONST1]]:_, %0:_
941 )";
942
943 // Check
944 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
945 }
946
TEST_F(AArch64GISelMITest,LowerMinMax)947 TEST_F(AArch64GISelMITest, LowerMinMax) {
948 if (!TM)
949 return;
950
951 LLT s64 = LLT::scalar(64);
952 LLT v2s32 = LLT::vector(2, 32);
953
954 DefineLegalizerInfo(A, {
955 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
956 .lowerFor({s64, LLT::vector(2, s32)});
957 });
958
959 auto SMin = B.buildSMin(s64, Copies[0], Copies[1]);
960 auto SMax = B.buildSMax(s64, Copies[0], Copies[1]);
961 auto UMin = B.buildUMin(s64, Copies[0], Copies[1]);
962 auto UMax = B.buildUMax(s64, Copies[0], Copies[1]);
963
964 auto VecVal0 = B.buildBitcast(v2s32, Copies[0]);
965 auto VecVal1 = B.buildBitcast(v2s32, Copies[1]);
966
967 auto SMinV = B.buildSMin(v2s32, VecVal0, VecVal1);
968 auto SMaxV = B.buildSMax(v2s32, VecVal0, VecVal1);
969 auto UMinV = B.buildUMin(v2s32, VecVal0, VecVal1);
970 auto UMaxV = B.buildUMax(v2s32, VecVal0, VecVal1);
971
972 AInfo Info(MF->getSubtarget());
973 DummyGISelObserver Observer;
974 LegalizerHelper Helper(*MF, Info, Observer, B);
975 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
976 Helper.lower(*SMin, 0, s64));
977 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
978 Helper.lower(*SMax, 0, s64));
979 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
980 Helper.lower(*UMin, 0, s64));
981 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
982 Helper.lower(*UMax, 0, s64));
983
984 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
985 Helper.lower(*SMinV, 0, v2s32));
986 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
987 Helper.lower(*SMaxV, 0, v2s32));
988 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
989 Helper.lower(*UMinV, 0, v2s32));
990 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
991 Helper.lower(*UMaxV, 0, v2s32));
992
993 auto CheckStr = R"(
994 CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_
995 CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_
996
997 CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_
998 CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_
999
1000 CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_
1001 CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_
1002
1003 CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_
1004 CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_
1005
1006 CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
1007 CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
1008
1009 CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1010 CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1011
1012 CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1013 CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1014
1015 CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1016 CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1017
1018 CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1019 CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1020 )";
1021
1022 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1023 }
1024
TEST_F(AArch64GISelMITest,WidenScalarBuildVector)1025 TEST_F(AArch64GISelMITest, WidenScalarBuildVector) {
1026 if (!TM)
1027 return;
1028
1029 LLT S32 = LLT::scalar(32);
1030 LLT S16 = LLT::scalar(16);
1031 LLT V2S16 = LLT::vector(2, S16);
1032 LLT V2S32 = LLT::vector(2, S32);
1033
1034 DefineLegalizerInfo(A, {
1035 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1036 .lowerFor({s64, LLT::vector(2, s32)});
1037 });
1038
1039 AInfo Info(MF->getSubtarget());
1040 DummyGISelObserver Observer;
1041 LegalizerHelper Helper(*MF, Info, Observer, B);
1042 B.setInsertPt(*EntryMBB, EntryMBB->end());
1043
1044 Register Constant0 = B.buildConstant(S16, 1).getReg(0);
1045 Register Constant1 = B.buildConstant(S16, 2).getReg(0);
1046 auto BV0 = B.buildBuildVector(V2S16, {Constant0, Constant1});
1047 auto BV1 = B.buildBuildVector(V2S16, {Constant0, Constant1});
1048
1049 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1050 Helper.widenScalar(*BV0, 0, V2S32));
1051 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1052 Helper.widenScalar(*BV1, 1, S32));
1053
1054 auto CheckStr = R"(
1055 CHECK: [[K0:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
1056 CHECK-NEXT: [[K1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
1057 CHECK-NEXT: [[EXT_K0_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
1058 CHECK-NEXT: [[EXT_K1_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
1059 CHECK-NEXT: [[BV0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[EXT_K0_0]]:_(s32), [[EXT_K1_0]]:_(s32)
1060 CHECK-NEXT: [[BV0_TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BV0]]
1061
1062 CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
1063 CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
1064
1065 CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32)
1066 )";
1067
1068 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1069 }
1070
TEST_F(AArch64GISelMITest,LowerMergeValues)1071 TEST_F(AArch64GISelMITest, LowerMergeValues) {
1072 if (!TM)
1073 return;
1074
1075 const LLT S32 = LLT::scalar(32);
1076 const LLT S24 = LLT::scalar(24);
1077 const LLT S21 = LLT::scalar(21);
1078 const LLT S16 = LLT::scalar(16);
1079 const LLT S9 = LLT::scalar(9);
1080 const LLT S8 = LLT::scalar(8);
1081 const LLT S3 = LLT::scalar(3);
1082
1083 DefineLegalizerInfo(A, {
1084 getActionDefinitionsBuilder(G_UNMERGE_VALUES)
1085 .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9)));
1086 });
1087
1088 AInfo Info(MF->getSubtarget());
1089 DummyGISelObserver Observer;
1090 LegalizerHelper Helper(*MF, Info, Observer, B);
1091 B.setInsertPt(*EntryMBB, EntryMBB->end());
1092
1093 // 24 = 3 3 3 3 3 3 3 3
1094 // => 9
1095 //
1096 // This can do 3 merges, but need an extra implicit_def.
1097 SmallVector<Register, 8> Merge0Ops;
1098 for (int I = 0; I != 8; ++I)
1099 Merge0Ops.push_back(B.buildConstant(S3, I).getReg(0));
1100
1101 auto Merge0 = B.buildMerge(S24, Merge0Ops);
1102
1103 // 21 = 3 3 3 3 3 3 3
1104 // => 9, 2 extra implicit_def needed
1105 //
1106 SmallVector<Register, 8> Merge1Ops;
1107 for (int I = 0; I != 7; ++I)
1108 Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0));
1109
1110 auto Merge1 = B.buildMerge(S21, Merge1Ops);
1111
1112 SmallVector<Register, 8> Merge2Ops;
1113 for (int I = 0; I != 2; ++I)
1114 Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0));
1115
1116 auto Merge2 = B.buildMerge(S16, Merge2Ops);
1117
1118 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1119 Helper.widenScalar(*Merge0, 1, S9));
1120 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1121 Helper.widenScalar(*Merge1, 1, S9));
1122
1123 // Request a source size greater than the original destination size.
1124 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1125 Helper.widenScalar(*Merge2, 1, S32));
1126
1127 auto CheckStr = R"(
1128 CHECK: [[K0:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
1129 CHECK-NEXT: [[K1:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
1130 CHECK-NEXT: [[K2:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
1131 CHECK-NEXT: [[K3:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
1132 CHECK-NEXT: [[K4:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
1133 CHECK-NEXT: [[K5:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1134 CHECK-NEXT: [[K6:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1135 CHECK-NEXT: [[K7:%[0-9]+]]:_(s3) = G_CONSTANT i3 -1
1136 CHECK-NEXT: [[IMPDEF0:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1137 CHECK-NEXT: [[MERGE0:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K0]]:_(s3), [[K1]]:_(s3), [[K2]]:_(s3)
1138 CHECK-NEXT: [[MERGE1:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K3]]:_(s3), [[K4]]:_(s3), [[K5]]:_(s3)
1139 CHECK-NEXT: [[MERGE2:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K6]]:_(s3), [[K7]]:_(s3), [[IMPDEF0]]:_(s3)
1140 CHECK-NEXT: [[MERGE3:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE0]]:_(s9), [[MERGE1]]:_(s9), [[MERGE2]]:_(s9)
1141 CHECK-NEXT: (s24) = G_TRUNC [[MERGE3]]:_(s27)
1142
1143
1144 CHECK: [[K8:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
1145 CHECK-NEXT: [[K9:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
1146 CHECK-NEXT: [[K10:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
1147 CHECK-NEXT: [[K11:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
1148 CHECK-NEXT: [[K12:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
1149 CHECK-NEXT: [[K13:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1150 CHECK-NEXT: [[K14:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1151 CHECK-NEXT: [[IMPDEF1:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1152 CHECK-NEXT: [[MERGE4:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K8]]:_(s3), [[K9]]:_(s3), [[K10]]:_(s3)
1153 CHECK-NEXT: [[MERGE5:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K11]]:_(s3), [[K12]]:_(s3), [[K13]]:_(s3)
1154 CHECK-NEXT: [[MERGE6:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K14]]:_(s3), [[IMPDEF1]]:_(s3), [[IMPDEF1]]:_(s3)
1155 CHECK-NEXT: [[MERGE7:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE4]]:_(s9), [[MERGE5]]:_(s9), [[MERGE6]]:_(s9)
1156 CHECK-NEXT: (s21) = G_TRUNC [[MERGE7]]:_(s27)
1157
1158
1159 CHECK: [[K15:%[0-9]+]]:_(s8) = G_CONSTANT i8 0
1160 CHECK-NEXT: [[K16:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
1161 CHECK-NEXT: [[ZEXT_K15:[0-9]+]]:_(s32) = G_ZEXT [[K15]]:_(s8)
1162 CHECK-NEXT: [[ZEXT_K16:[0-9]+]]:_(s32) = G_ZEXT [[K16]]:_(s8)
1163 [[K16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1164 [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT_K16]]:_, [[K16]]:_(s32)
1165 [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT_K16]]:_, [[SHL]]:_
1166 (s16) = G_TRUNC [[OR]]:_(s32)
1167 )";
1168
1169 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1170 }
1171
TEST_F(AArch64GISelMITest,WidenScalarMergeValuesPointer)1172 TEST_F(AArch64GISelMITest, WidenScalarMergeValuesPointer) {
1173 if (!TM)
1174 return;
1175
1176 DefineLegalizerInfo(A, {});
1177
1178 AInfo Info(MF->getSubtarget());
1179 DummyGISelObserver Observer;
1180 LegalizerHelper Helper(*MF, Info, Observer, B);
1181 B.setInsertPt(*EntryMBB, EntryMBB->end());
1182
1183 const LLT S32 = LLT::scalar(32);
1184 const LLT S64 = LLT::scalar(64);
1185 const LLT P0 = LLT::pointer(0, 64);
1186
1187 auto Lo = B.buildTrunc(S32, Copies[0]);
1188 auto Hi = B.buildTrunc(S32, Copies[1]);
1189
1190 auto Merge = B.buildMerge(P0, {Lo, Hi});
1191
1192 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1193 Helper.widenScalar(*Merge, 1, S64));
1194
1195 auto CheckStr = R"(
1196 CHECK: [[TRUNC0:%[0-9]+]]:_(s32) = G_TRUNC
1197 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC
1198 CHECK: [[ZEXT_TRUNC0:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC0]]
1199 CHECK: [[ZEXT_TRUNC1:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC1]]
1200 CHECK: [[SHIFT_AMT:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
1201 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT_TRUNC1]]:_, [[SHIFT_AMT]]
1202 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[ZEXT_TRUNC0]]:_, [[SHL]]
1203 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]:_(s64)
1204 )";
1205
1206 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1207 }
1208
TEST_F(AArch64GISelMITest,WidenSEXTINREG)1209 TEST_F(AArch64GISelMITest, WidenSEXTINREG) {
1210 if (!TM)
1211 return;
1212
1213 // Declare your legalization info
1214 DefineLegalizerInfo(A, {
1215 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1216 });
1217 // Build Instr
1218 auto MIB = B.buildInstr(
1219 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1220 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1221 uint64_t(8)});
1222 AInfo Info(MF->getSubtarget());
1223 DummyGISelObserver Observer;
1224 LegalizerHelper Helper(*MF, Info, Observer, B);
1225 // Perform Legalization
1226 ASSERT_TRUE(Helper.widenScalar(*MIB, 0, LLT::scalar(64)) ==
1227 LegalizerHelper::LegalizeResult::Legalized);
1228
1229 auto CheckStr = R"(
1230 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1231 CHECK: [[T1:%[0-9]+]]:_(s64) = G_ANYEXT [[T0]]:_(s32)
1232 CHECK: [[T2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[T1]]:_, 8
1233 CHECK: [[T3:%[0-9]+]]:_(s32) = G_TRUNC [[T2]]:_(s64)
1234 )";
1235
1236 // Check
1237 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1238 }
1239
TEST_F(AArch64GISelMITest,NarrowSEXTINREG)1240 TEST_F(AArch64GISelMITest, NarrowSEXTINREG) {
1241 if (!TM)
1242 return;
1243
1244 // Declare your legalization info, these aren't actually relevant to the test.
1245 DefineLegalizerInfo(A, {
1246 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1247 });
1248 // Build Instr
1249 auto MIB = B.buildInstr(
1250 TargetOpcode::G_SEXT_INREG, {LLT::scalar(16)},
1251 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(16)}, {Copies[0]}),
1252 uint64_t(8)});
1253 AInfo Info(MF->getSubtarget());
1254 DummyGISelObserver Observer;
1255 LegalizerHelper Helper(*MF, Info, Observer, B);
1256 // Perform Legalization
1257 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(10)) ==
1258 LegalizerHelper::LegalizeResult::Legalized);
1259
1260 auto CheckStr = R"(
1261 CHECK: [[T0:%[0-9]+]]:_(s16) = G_TRUNC
1262 CHECK: [[T1:%[0-9]+]]:_(s10) = G_TRUNC [[T0]]:_(s16)
1263 CHECK: [[T2:%[0-9]+]]:_(s10) = G_SEXT_INREG [[T1]]:_, 8
1264 CHECK: [[T3:%[0-9]+]]:_(s16) = G_SEXT [[T2]]:_(s10)
1265 )";
1266
1267 // Check
1268 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1269 }
1270
TEST_F(AArch64GISelMITest,NarrowSEXTINREG2)1271 TEST_F(AArch64GISelMITest, NarrowSEXTINREG2) {
1272 if (!TM)
1273 return;
1274
1275 // Declare your legalization info, these aren't actually relevant to the test.
1276 DefineLegalizerInfo(
1277 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
1278 // Build Instr
1279 auto MIB = B.buildInstr(
1280 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1281 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1282 uint64_t(9)});
1283 AInfo Info(MF->getSubtarget());
1284 DummyGISelObserver Observer;
1285 LegalizerHelper Helper(*MF, Info, Observer, B);
1286 // Perform Legalization
1287 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(8)) ==
1288 LegalizerHelper::LegalizeResult::Legalized);
1289
1290 auto CheckStr = R"(
1291 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1292 CHECK: [[T1:%[0-9]+]]:_(s8), [[T2:%[0-9]+]]:_(s8), [[T3:%[0-9]+]]:_(s8), [[T4:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[T0]]:_(s32)
1293 CHECK: [[CST2:%[0-9]+]]:_(s8) = G_CONSTANT i8 7
1294 CHECK: [[T5:%[0-9]+]]:_(s8) = G_SEXT_INREG [[T2]]:_, 1
1295 CHECK: [[T6:%[0-9]+]]:_(s8) = G_ASHR [[T5]]:_, [[CST2]]:_
1296 CHECK: [[T7:%[0-9]+]]:_(s32) = G_MERGE_VALUES [[T1]]:_(s8), [[T5]]:_(s8), [[T6]]:_(s8), [[T6]]:_(s8)
1297 )";
1298
1299 // Check
1300 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1301 }
1302
TEST_F(AArch64GISelMITest,LowerSEXTINREG)1303 TEST_F(AArch64GISelMITest, LowerSEXTINREG) {
1304 if (!TM)
1305 return;
1306
1307 // Declare your legalization info, these aren't actually relevant to the test.
1308 DefineLegalizerInfo(
1309 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
1310 // Build Instr
1311 auto MIB = B.buildInstr(
1312 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1313 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1314 uint64_t(8)});
1315 AInfo Info(MF->getSubtarget());
1316 DummyGISelObserver Observer;
1317 LegalizerHelper Helper(*MF, Info, Observer, B);
1318 // Perform Legalization
1319 ASSERT_TRUE(Helper.lower(*MIB, 0, LLT()) ==
1320 LegalizerHelper::LegalizeResult::Legalized);
1321
1322 auto CheckStr = R"(
1323 CHECK: [[T1:%[0-9]+]]:_(s32) = G_TRUNC
1324 CHECK: [[CST:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
1325 CHECK: [[T2:%[0-9]+]]:_(s32) = G_SHL [[T1]]:_, [[CST]]:_
1326 CHECK: [[T3:%[0-9]+]]:_(s32) = G_ASHR [[T2]]:_, [[CST]]:_
1327 )";
1328
1329 // Check
1330 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1331 }
1332
TEST_F(AArch64GISelMITest,LibcallFPExt)1333 TEST_F(AArch64GISelMITest, LibcallFPExt) {
1334 setUp();
1335 if (!TM)
1336 return;
1337
1338 // Declare your legalization info
1339 DefineLegalizerInfo(A, {
1340 getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s32, s16}, {s128, s64}});
1341 });
1342
1343 LLT S16{LLT::scalar(16)};
1344 LLT S32{LLT::scalar(32)};
1345 LLT S128{LLT::scalar(128)};
1346 auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
1347 auto MIBFPExt1 =
1348 B.buildInstr(TargetOpcode::G_FPEXT, {S32}, {MIBTrunc});
1349
1350 auto MIBFPExt2 =
1351 B.buildInstr(TargetOpcode::G_FPEXT, {S128}, {Copies[1]});
1352 AInfo Info(MF->getSubtarget());
1353 DummyGISelObserver Observer;
1354 LegalizerHelper Helper(*MF, Info, Observer, B);
1355 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1356 Helper.libcall(*MIBFPExt1));
1357
1358 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1359 Helper.libcall(*MIBFPExt2));
1360 auto CheckStr = R"(
1361 CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC
1362 CHECK: $h0 = COPY [[TRUNC]]
1363 CHECK: BL &__gnu_h2f_ieee
1364 CHECK: $d0 = COPY
1365 CHECK: BL &__extenddftf2
1366 )";
1367
1368 // Check
1369 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1370 }
1371
TEST_F(AArch64GISelMITest,LibcallFPTrunc)1372 TEST_F(AArch64GISelMITest, LibcallFPTrunc) {
1373 setUp();
1374 if (!TM)
1375 return;
1376
1377 // Declare your legalization info
1378 DefineLegalizerInfo(A, {
1379 getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s16, s32}, {s64, s128}});
1380 });
1381
1382 LLT S16{LLT::scalar(16)};
1383 LLT S32{LLT::scalar(32)};
1384 LLT S64{LLT::scalar(64)};
1385 LLT S128{LLT::scalar(128)};
1386 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1387 auto MIBFPTrunc1 =
1388 B.buildInstr(TargetOpcode::G_FPTRUNC, {S16}, {MIBTrunc});
1389
1390 auto MIBMerge = B.buildMerge(S128, {Copies[1], Copies[2]});
1391
1392 auto MIBFPTrunc2 =
1393 B.buildInstr(TargetOpcode::G_FPTRUNC, {S64}, {MIBMerge});
1394 AInfo Info(MF->getSubtarget());
1395 DummyGISelObserver Observer;
1396 LegalizerHelper Helper(*MF, Info, Observer, B);
1397 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1398 Helper.libcall(*MIBFPTrunc1));
1399
1400 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1401 Helper.libcall(*MIBFPTrunc2));
1402 auto CheckStr = R"(
1403 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1404 CHECK: $s0 = COPY [[TRUNC]]
1405 CHECK: BL &__gnu_f2h_ieee
1406 CHECK: $q0 = COPY
1407 CHECK: BL &__trunctfdf2
1408 )";
1409
1410 // Check
1411 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1412 }
1413
TEST_F(AArch64GISelMITest,LibcallSimple)1414 TEST_F(AArch64GISelMITest, LibcallSimple) {
1415 setUp();
1416 if (!TM)
1417 return;
1418
1419 // Declare your legalization info
1420 DefineLegalizerInfo(A, {
1421 getActionDefinitionsBuilder(G_FADD).libcallFor({s16});
1422 });
1423
1424 LLT S16{LLT::scalar(16)};
1425 auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
1426 auto MIBFADD =
1427 B.buildInstr(TargetOpcode::G_FADD, {S16}, {MIBTrunc, MIBTrunc});
1428
1429 AInfo Info(MF->getSubtarget());
1430 DummyGISelObserver Observer;
1431 LegalizerHelper Helper(*MF, Info, Observer, B);
1432 // Make sure we do not crash anymore
1433 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
1434 Helper.libcall(*MIBFADD));
1435 }
1436
TEST_F(AArch64GISelMITest,LibcallSRem)1437 TEST_F(AArch64GISelMITest, LibcallSRem) {
1438 setUp();
1439 if (!TM)
1440 return;
1441
1442 // Declare your legalization info
1443 DefineLegalizerInfo(A, {
1444 getActionDefinitionsBuilder(G_SREM).libcallFor({s32, s64, s128});
1445 });
1446
1447 LLT S32{LLT::scalar(32)};
1448 LLT S64{LLT::scalar(64)};
1449 LLT S128{LLT::scalar(128)};
1450 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1451 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1452
1453 auto MIBSRem32 =
1454 B.buildInstr(TargetOpcode::G_SREM, {S32}, {MIBTrunc, MIBTrunc});
1455 auto MIBSRem64 =
1456 B.buildInstr(TargetOpcode::G_SREM, {S64}, {Copies[0], Copies[0]});
1457 auto MIBSRem128 =
1458 B.buildInstr(TargetOpcode::G_SREM, {S128}, {MIBExt, MIBExt});
1459
1460 AInfo Info(MF->getSubtarget());
1461 DummyGISelObserver Observer;
1462 LegalizerHelper Helper(*MF, Info, Observer, B);
1463
1464 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1465 Helper.libcall(*MIBSRem32));
1466 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1467 Helper.libcall(*MIBSRem64));
1468 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1469 Helper.libcall(*MIBSRem128));
1470
1471 auto CheckStr = R"(
1472 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1473 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1474 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1475 CHECK: $w0 = COPY [[TRUNC]]
1476 CHECK: $w1 = COPY [[TRUNC]]
1477 CHECK: BL &__modsi3
1478 CHECK: $x0 = COPY [[COPY]]
1479 CHECK: $x1 = COPY [[COPY]]
1480 CHECK: BL &__moddi3
1481 CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
1482 CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
1483 CHECK: $x0 = COPY [[UV]]
1484 CHECK: $x1 = COPY [[UV1]]
1485 CHECK: $x2 = COPY [[UV2]]
1486 CHECK: $x3 = COPY [[UV3]]
1487 CHECK: BL &__modti3
1488 )";
1489
1490 // Check
1491 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1492 }
1493
TEST_F(AArch64GISelMITest,LibcallURem)1494 TEST_F(AArch64GISelMITest, LibcallURem) {
1495 setUp();
1496 if (!TM)
1497 return;
1498
1499 // Declare your legalization info
1500 DefineLegalizerInfo(A, {
1501 getActionDefinitionsBuilder(G_UREM).libcallFor({s32, s64, s128});
1502 });
1503
1504 LLT S32{LLT::scalar(32)};
1505 LLT S64{LLT::scalar(64)};
1506 LLT S128{LLT::scalar(128)};
1507 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1508 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1509
1510 auto MIBURem32 =
1511 B.buildInstr(TargetOpcode::G_UREM, {S32}, {MIBTrunc, MIBTrunc});
1512 auto MIBURem64 =
1513 B.buildInstr(TargetOpcode::G_UREM, {S64}, {Copies[0], Copies[0]});
1514 auto MIBURem128 =
1515 B.buildInstr(TargetOpcode::G_UREM, {S128}, {MIBExt, MIBExt});
1516
1517 AInfo Info(MF->getSubtarget());
1518 DummyGISelObserver Observer;
1519 LegalizerHelper Helper(*MF, Info, Observer, B);
1520
1521 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1522 Helper.libcall(*MIBURem32));
1523 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1524 Helper.libcall(*MIBURem64));
1525 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1526 Helper.libcall(*MIBURem128));
1527
1528 const auto *CheckStr = R"(
1529 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1530 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1531 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1532 CHECK: $w0 = COPY [[TRUNC]]
1533 CHECK: $w1 = COPY [[TRUNC]]
1534 CHECK: BL &__umodsi3
1535 CHECK: $x0 = COPY [[COPY]]
1536 CHECK: $x1 = COPY [[COPY]]
1537 CHECK: BL &__umoddi3
1538 CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
1539 CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
1540 CHECK: $x0 = COPY [[UV]]
1541 CHECK: $x1 = COPY [[UV1]]
1542 CHECK: $x2 = COPY [[UV2]]
1543 CHECK: $x3 = COPY [[UV3]]
1544 CHECK: BL &__umodti3
1545 )";
1546
1547 // Check
1548 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1549 }
1550
TEST_F(AArch64GISelMITest,LibcallCtlzZeroUndef)1551 TEST_F(AArch64GISelMITest, LibcallCtlzZeroUndef) {
1552 setUp();
1553 if (!TM)
1554 return;
1555
1556 // Declare your legalization info
1557 DefineLegalizerInfo(A, {
1558 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF)
1559 .libcallFor({{s32, s32}, {s64, s64}, {s128, s128}});
1560 });
1561
1562 LLT S32{LLT::scalar(32)};
1563 LLT S64{LLT::scalar(64)};
1564 LLT S128{LLT::scalar(128)};
1565 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1566 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1567
1568 auto MIBCtlz32 =
1569 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S32}, {MIBTrunc});
1570 auto MIBCtlz64 =
1571 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S64}, {Copies[0]});
1572 auto MIBCtlz128 =
1573 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S128}, {MIBExt});
1574
1575 AInfo Info(MF->getSubtarget());
1576 DummyGISelObserver Observer;
1577 LegalizerHelper Helper(*MF, Info, Observer, B);
1578
1579 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1580 Helper.libcall(*MIBCtlz32));
1581 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1582 Helper.libcall(*MIBCtlz64));
1583 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1584 Helper.libcall(*MIBCtlz128));
1585
1586 const auto *CheckStr = R"(
1587 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1588 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1589 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1590 CHECK: $w0 = COPY [[TRUNC]]
1591 CHECK: BL &__clzsi2
1592 CHECK: $x0 = COPY [[COPY]]
1593 CHECK: BL &__clzdi2
1594 CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
1595 CHECK: $x0 = COPY [[UV]]
1596 CHECK: $x1 = COPY [[UV1]]
1597 CHECK: BL &__clzti2
1598 )";
1599
1600 // Check
1601 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1602 }
1603
TEST_F(AArch64GISelMITest,LibcallFAdd)1604 TEST_F(AArch64GISelMITest, LibcallFAdd) {
1605 setUp();
1606 if (!TM)
1607 return;
1608
1609 // Declare your legalization info
1610 DefineLegalizerInfo(A, {
1611 getActionDefinitionsBuilder(G_FADD).libcallFor({s32, s64, s128});
1612 });
1613
1614 LLT S32{LLT::scalar(32)};
1615 LLT S64{LLT::scalar(64)};
1616 LLT S128{LLT::scalar(128)};
1617 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1618 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1619
1620 auto MIBAdd32 =
1621 B.buildInstr(TargetOpcode::G_FADD, {S32}, {MIBTrunc, MIBTrunc});
1622 auto MIBAdd64 =
1623 B.buildInstr(TargetOpcode::G_FADD, {S64}, {Copies[0], Copies[0]});
1624 auto MIBAdd128 = B.buildInstr(TargetOpcode::G_FADD, {S128}, {MIBExt, MIBExt});
1625
1626 AInfo Info(MF->getSubtarget());
1627 DummyGISelObserver Observer;
1628 LegalizerHelper Helper(*MF, Info, Observer, B);
1629
1630 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1631 Helper.libcall(*MIBAdd32));
1632 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1633 Helper.libcall(*MIBAdd64));
1634 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1635 Helper.libcall(*MIBAdd128));
1636
1637 const auto *CheckStr = R"(
1638 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1639 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1640 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1641 CHECK: $s0 = COPY [[TRUNC]]
1642 CHECK: $s1 = COPY [[TRUNC]]
1643 CHECK: BL &__addsf3
1644 CHECK: $d0 = COPY [[COPY]]
1645 CHECK: $d1 = COPY [[COPY]]
1646 CHECK: BL &__adddf3
1647 CHECK: $q0 = COPY [[ANYEXT]]
1648 CHECK: $q1 = COPY [[ANYEXT]]
1649 CHECK: BL &__addtf3
1650 )";
1651
1652 // Check
1653 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1654 }
1655
TEST_F(AArch64GISelMITest,LibcallFSub)1656 TEST_F(AArch64GISelMITest, LibcallFSub) {
1657 setUp();
1658 if (!TM)
1659 return;
1660
1661 // Declare your legalization info
1662 DefineLegalizerInfo(A, {
1663 getActionDefinitionsBuilder(G_FSUB).libcallFor({s32, s64, s128});
1664 });
1665
1666 LLT S32{LLT::scalar(32)};
1667 LLT S64{LLT::scalar(64)};
1668 LLT S128{LLT::scalar(128)};
1669 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1670 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1671
1672 auto MIBSub32 =
1673 B.buildInstr(TargetOpcode::G_FSUB, {S32}, {MIBTrunc, MIBTrunc});
1674 auto MIBSub64 =
1675 B.buildInstr(TargetOpcode::G_FSUB, {S64}, {Copies[0], Copies[0]});
1676 auto MIBSub128 = B.buildInstr(TargetOpcode::G_FSUB, {S128}, {MIBExt, MIBExt});
1677
1678 AInfo Info(MF->getSubtarget());
1679 DummyGISelObserver Observer;
1680 LegalizerHelper Helper(*MF, Info, Observer, B);
1681
1682 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1683 Helper.libcall(*MIBSub32));
1684 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1685 Helper.libcall(*MIBSub64));
1686 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1687 Helper.libcall(*MIBSub128));
1688
1689 const auto *CheckStr = R"(
1690 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1691 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1692 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1693 CHECK: $s0 = COPY [[TRUNC]]
1694 CHECK: $s1 = COPY [[TRUNC]]
1695 CHECK: BL &__subsf3
1696 CHECK: $d0 = COPY [[COPY]]
1697 CHECK: $d1 = COPY [[COPY]]
1698 CHECK: BL &__subdf3
1699 CHECK: $q0 = COPY [[ANYEXT]]
1700 CHECK: $q1 = COPY [[ANYEXT]]
1701 CHECK: BL &__subtf3
1702 )";
1703
1704 // Check
1705 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1706 }
1707
TEST_F(AArch64GISelMITest,LibcallFMul)1708 TEST_F(AArch64GISelMITest, LibcallFMul) {
1709 setUp();
1710 if (!TM)
1711 return;
1712
1713 // Declare your legalization info
1714 DefineLegalizerInfo(A, {
1715 getActionDefinitionsBuilder(G_FMUL).libcallFor({s32, s64, s128});
1716 });
1717
1718 LLT S32{LLT::scalar(32)};
1719 LLT S64{LLT::scalar(64)};
1720 LLT S128{LLT::scalar(128)};
1721 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1722 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1723
1724 auto MIBMul32 =
1725 B.buildInstr(TargetOpcode::G_FMUL, {S32}, {MIBTrunc, MIBTrunc});
1726 auto MIBMul64 =
1727 B.buildInstr(TargetOpcode::G_FMUL, {S64}, {Copies[0], Copies[0]});
1728 auto MIBMul128 = B.buildInstr(TargetOpcode::G_FMUL, {S128}, {MIBExt, MIBExt});
1729
1730 AInfo Info(MF->getSubtarget());
1731 DummyGISelObserver Observer;
1732 LegalizerHelper Helper(*MF, Info, Observer, B);
1733
1734 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1735 Helper.libcall(*MIBMul32));
1736 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1737 Helper.libcall(*MIBMul64));
1738 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1739 Helper.libcall(*MIBMul128));
1740
1741 const auto *CheckStr = R"(
1742 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1743 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1744 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1745 CHECK: $s0 = COPY [[TRUNC]]
1746 CHECK: $s1 = COPY [[TRUNC]]
1747 CHECK: BL &__mulsf3
1748 CHECK: $d0 = COPY [[COPY]]
1749 CHECK: $d1 = COPY [[COPY]]
1750 CHECK: BL &__muldf3
1751 CHECK: $q0 = COPY [[ANYEXT]]
1752 CHECK: $q1 = COPY [[ANYEXT]]
1753 CHECK: BL &__multf3
1754 )";
1755
1756 // Check
1757 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1758 }
1759
TEST_F(AArch64GISelMITest,LibcallFDiv)1760 TEST_F(AArch64GISelMITest, LibcallFDiv) {
1761 setUp();
1762 if (!TM)
1763 return;
1764
1765 // Declare your legalization info
1766 DefineLegalizerInfo(A, {
1767 getActionDefinitionsBuilder(G_FDIV).libcallFor({s32, s64, s128});
1768 });
1769
1770 LLT S32{LLT::scalar(32)};
1771 LLT S64{LLT::scalar(64)};
1772 LLT S128{LLT::scalar(128)};
1773 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1774 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1775
1776 auto MIBDiv32 =
1777 B.buildInstr(TargetOpcode::G_FDIV, {S32}, {MIBTrunc, MIBTrunc});
1778 auto MIBDiv64 =
1779 B.buildInstr(TargetOpcode::G_FDIV, {S64}, {Copies[0], Copies[0]});
1780 auto MIBDiv128 = B.buildInstr(TargetOpcode::G_FDIV, {S128}, {MIBExt, MIBExt});
1781
1782 AInfo Info(MF->getSubtarget());
1783 DummyGISelObserver Observer;
1784 LegalizerHelper Helper(*MF, Info, Observer, B);
1785
1786 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1787 Helper.libcall(*MIBDiv32));
1788 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1789 Helper.libcall(*MIBDiv64));
1790 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1791 Helper.libcall(*MIBDiv128));
1792
1793 const auto *CheckStr = R"(
1794 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1795 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1796 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1797 CHECK: $s0 = COPY [[TRUNC]]
1798 CHECK: $s1 = COPY [[TRUNC]]
1799 CHECK: BL &__divsf3
1800 CHECK: $d0 = COPY [[COPY]]
1801 CHECK: $d1 = COPY [[COPY]]
1802 CHECK: BL &__divdf3
1803 CHECK: $q0 = COPY [[ANYEXT]]
1804 CHECK: $q1 = COPY [[ANYEXT]]
1805 CHECK: BL &__divtf3
1806 )";
1807
1808 // Check
1809 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1810 }
1811
TEST_F(AArch64GISelMITest,LibcallFExp)1812 TEST_F(AArch64GISelMITest, LibcallFExp) {
1813 setUp();
1814 if (!TM)
1815 return;
1816
1817 // Declare your legalization info
1818 DefineLegalizerInfo(A, {
1819 getActionDefinitionsBuilder(G_FEXP).libcallFor({s32, s64, s128});
1820 });
1821
1822 LLT S32{LLT::scalar(32)};
1823 LLT S64{LLT::scalar(64)};
1824 LLT S128{LLT::scalar(128)};
1825 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1826 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1827
1828 auto MIBExp32 = B.buildInstr(TargetOpcode::G_FEXP, {S32}, {MIBTrunc});
1829 auto MIBExp64 = B.buildInstr(TargetOpcode::G_FEXP, {S64}, {Copies[0]});
1830 auto MIBExp128 = B.buildInstr(TargetOpcode::G_FEXP, {S128}, {MIBExt});
1831
1832 AInfo Info(MF->getSubtarget());
1833 DummyGISelObserver Observer;
1834 LegalizerHelper Helper(*MF, Info, Observer, B);
1835
1836 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1837 Helper.libcall(*MIBExp32));
1838 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1839 Helper.libcall(*MIBExp64));
1840 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1841 Helper.libcall(*MIBExp128));
1842
1843 const auto *CheckStr = R"(
1844 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1845 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1846 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1847 CHECK: $s0 = COPY [[TRUNC]]
1848 CHECK: BL &expf
1849 CHECK: $d0 = COPY [[COPY]]
1850 CHECK: BL &exp
1851 CHECK: $q0 = COPY [[ANYEXT]]
1852 CHECK: BL &expl
1853 )";
1854
1855 // Check
1856 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1857 }
1858
TEST_F(AArch64GISelMITest,LibcallFExp2)1859 TEST_F(AArch64GISelMITest, LibcallFExp2) {
1860 setUp();
1861 if (!TM)
1862 return;
1863
1864 // Declare your legalization info
1865 DefineLegalizerInfo(A, {
1866 getActionDefinitionsBuilder(G_FEXP2).libcallFor({s32, s64, s128});
1867 });
1868
1869 LLT S32{LLT::scalar(32)};
1870 LLT S64{LLT::scalar(64)};
1871 LLT S128{LLT::scalar(128)};
1872 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1873 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1874
1875 auto MIBExp232 = B.buildInstr(TargetOpcode::G_FEXP2, {S32}, {MIBTrunc});
1876 auto MIBExp264 = B.buildInstr(TargetOpcode::G_FEXP2, {S64}, {Copies[0]});
1877 auto MIBExp2128 = B.buildInstr(TargetOpcode::G_FEXP2, {S128}, {MIBExt});
1878
1879 AInfo Info(MF->getSubtarget());
1880 DummyGISelObserver Observer;
1881 LegalizerHelper Helper(*MF, Info, Observer, B);
1882
1883 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1884 Helper.libcall(*MIBExp232));
1885 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1886 Helper.libcall(*MIBExp264));
1887 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1888 Helper.libcall(*MIBExp2128));
1889
1890 const auto *CheckStr = R"(
1891 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1892 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1893 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1894 CHECK: $s0 = COPY [[TRUNC]]
1895 CHECK: BL &exp2f
1896 CHECK: $d0 = COPY [[COPY]]
1897 CHECK: BL &exp2
1898 CHECK: $q0 = COPY [[ANYEXT]]
1899 CHECK: BL &exp2l
1900 )";
1901
1902 // Check
1903 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1904 }
1905
TEST_F(AArch64GISelMITest,LibcallFRem)1906 TEST_F(AArch64GISelMITest, LibcallFRem) {
1907 setUp();
1908 if (!TM)
1909 return;
1910
1911 // Declare your legalization info
1912 DefineLegalizerInfo(A, {
1913 getActionDefinitionsBuilder(G_FREM).libcallFor({s32, s64, s128});
1914 });
1915
1916 LLT S32{LLT::scalar(32)};
1917 LLT S64{LLT::scalar(64)};
1918 LLT S128{LLT::scalar(128)};
1919 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1920 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1921
1922 auto MIBFRem32 = B.buildInstr(TargetOpcode::G_FREM, {S32}, {MIBTrunc});
1923 auto MIBFRem64 = B.buildInstr(TargetOpcode::G_FREM, {S64}, {Copies[0]});
1924 auto MIBFRem128 = B.buildInstr(TargetOpcode::G_FREM, {S128}, {MIBExt});
1925
1926 AInfo Info(MF->getSubtarget());
1927 DummyGISelObserver Observer;
1928 LegalizerHelper Helper(*MF, Info, Observer, B);
1929
1930 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1931 Helper.libcall(*MIBFRem32));
1932 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1933 Helper.libcall(*MIBFRem64));
1934 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1935 Helper.libcall(*MIBFRem128));
1936
1937 const auto *CheckStr = R"(
1938 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1939 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1940 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1941 CHECK: $s0 = COPY [[TRUNC]]
1942 CHECK: BL &fmodf
1943 CHECK: $d0 = COPY [[COPY]]
1944 CHECK: BL &fmod
1945 CHECK: $q0 = COPY [[ANYEXT]]
1946 CHECK: BL &fmodl
1947 )";
1948
1949 // Check
1950 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1951 }
1952
TEST_F(AArch64GISelMITest,LibcallFPow)1953 TEST_F(AArch64GISelMITest, LibcallFPow) {
1954 setUp();
1955 if (!TM)
1956 return;
1957
1958 // Declare your legalization info
1959 DefineLegalizerInfo(A, {
1960 getActionDefinitionsBuilder(G_FPOW).libcallFor({s32, s64, s128});
1961 });
1962
1963 LLT S32{LLT::scalar(32)};
1964 LLT S64{LLT::scalar(64)};
1965 LLT S128{LLT::scalar(128)};
1966 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1967 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
1968
1969 auto MIBPow32 = B.buildInstr(TargetOpcode::G_FPOW, {S32}, {MIBTrunc});
1970 auto MIBPow64 = B.buildInstr(TargetOpcode::G_FPOW, {S64}, {Copies[0]});
1971 auto MIBPow128 = B.buildInstr(TargetOpcode::G_FPOW, {S128}, {MIBExt});
1972
1973 AInfo Info(MF->getSubtarget());
1974 DummyGISelObserver Observer;
1975 LegalizerHelper Helper(*MF, Info, Observer, B);
1976
1977 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1978 Helper.libcall(*MIBPow32));
1979 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1980 Helper.libcall(*MIBPow64));
1981 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1982 Helper.libcall(*MIBPow128));
1983
1984 const auto *CheckStr = R"(
1985 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
1986 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1987 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
1988 CHECK: $s0 = COPY [[TRUNC]]
1989 CHECK: BL &powf
1990 CHECK: $d0 = COPY [[COPY]]
1991 CHECK: BL &pow
1992 CHECK: $q0 = COPY [[ANYEXT]]
1993 CHECK: BL &powl
1994 )";
1995
1996 // Check
1997 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1998 }
1999
TEST_F(AArch64GISelMITest,LibcallFMa)2000 TEST_F(AArch64GISelMITest, LibcallFMa) {
2001 setUp();
2002 if (!TM)
2003 return;
2004
2005 // Declare your legalization info
2006 DefineLegalizerInfo(A, {
2007 getActionDefinitionsBuilder(G_FMA).libcallFor({s32, s64, s128});
2008 });
2009
2010 LLT S32{LLT::scalar(32)};
2011 LLT S64{LLT::scalar(64)};
2012 LLT S128{LLT::scalar(128)};
2013 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2014 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2015
2016 auto MIBMa32 = B.buildInstr(TargetOpcode::G_FMA, {S32}, {MIBTrunc, MIBTrunc});
2017 auto MIBMa64 =
2018 B.buildInstr(TargetOpcode::G_FMA, {S64}, {Copies[0], Copies[0]});
2019 auto MIBMa128 = B.buildInstr(TargetOpcode::G_FMA, {S128}, {MIBExt, MIBExt});
2020
2021 AInfo Info(MF->getSubtarget());
2022 DummyGISelObserver Observer;
2023 LegalizerHelper Helper(*MF, Info, Observer, B);
2024
2025 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2026 Helper.libcall(*MIBMa32));
2027 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2028 Helper.libcall(*MIBMa64));
2029 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2030 Helper.libcall(*MIBMa128));
2031
2032 const auto *CheckStr = R"(
2033 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2034 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2035 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2036 CHECK: $s0 = COPY [[TRUNC]]
2037 CHECK: BL &fmaf
2038 CHECK: $d0 = COPY [[COPY]]
2039 CHECK: BL &fma
2040 CHECK: $q0 = COPY [[ANYEXT]]
2041 CHECK: BL &fmal
2042 )";
2043
2044 // Check
2045 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2046 }
2047
TEST_F(AArch64GISelMITest,LibcallFCeil)2048 TEST_F(AArch64GISelMITest, LibcallFCeil) {
2049 setUp();
2050 if (!TM)
2051 return;
2052
2053 // Declare your legalization info
2054 DefineLegalizerInfo(A, {
2055 getActionDefinitionsBuilder(G_FCEIL).libcallFor({s32, s64, s128});
2056 });
2057
2058 LLT S32{LLT::scalar(32)};
2059 LLT S64{LLT::scalar(64)};
2060 LLT S128{LLT::scalar(128)};
2061 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2062 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2063
2064 auto MIBCeil32 = B.buildInstr(TargetOpcode::G_FCEIL, {S32}, {MIBTrunc});
2065 auto MIBCeil64 = B.buildInstr(TargetOpcode::G_FCEIL, {S64}, {Copies[0]});
2066 auto MIBCeil128 = B.buildInstr(TargetOpcode::G_FCEIL, {S128}, {MIBExt});
2067
2068 AInfo Info(MF->getSubtarget());
2069 DummyGISelObserver Observer;
2070 LegalizerHelper Helper(*MF, Info, Observer, B);
2071
2072 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2073 Helper.libcall(*MIBCeil32));
2074 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2075 Helper.libcall(*MIBCeil64));
2076 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2077 Helper.libcall(*MIBCeil128));
2078
2079 const auto *CheckStr = R"(
2080 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2081 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2082 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2083 CHECK: $s0 = COPY [[TRUNC]]
2084 CHECK: BL &ceilf
2085 CHECK: $d0 = COPY [[COPY]]
2086 CHECK: BL &ceil
2087 CHECK: $q0 = COPY [[ANYEXT]]
2088 CHECK: BL &ceill
2089 )";
2090
2091 // Check
2092 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2093 }
2094
TEST_F(AArch64GISelMITest,LibcallFFloor)2095 TEST_F(AArch64GISelMITest, LibcallFFloor) {
2096 setUp();
2097 if (!TM)
2098 return;
2099
2100 // Declare your legalization info
2101 DefineLegalizerInfo(A, {
2102 getActionDefinitionsBuilder(G_FFLOOR).libcallFor({s32, s64, s128});
2103 });
2104
2105 LLT S32{LLT::scalar(32)};
2106 LLT S64{LLT::scalar(64)};
2107 LLT S128{LLT::scalar(128)};
2108 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2109 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2110
2111 auto MIBFloor32 = B.buildInstr(TargetOpcode::G_FFLOOR, {S32}, {MIBTrunc});
2112 auto MIBFloor64 = B.buildInstr(TargetOpcode::G_FFLOOR, {S64}, {Copies[0]});
2113 auto MIBFloor128 = B.buildInstr(TargetOpcode::G_FFLOOR, {S128}, {MIBExt});
2114
2115 AInfo Info(MF->getSubtarget());
2116 DummyGISelObserver Observer;
2117 LegalizerHelper Helper(*MF, Info, Observer, B);
2118
2119 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2120 Helper.libcall(*MIBFloor32));
2121 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2122 Helper.libcall(*MIBFloor64));
2123 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2124 Helper.libcall(*MIBFloor128));
2125
2126 const auto *CheckStr = R"(
2127 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2128 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2129 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2130 CHECK: $s0 = COPY [[TRUNC]]
2131 CHECK: BL &floorf
2132 CHECK: $d0 = COPY [[COPY]]
2133 CHECK: BL &floor
2134 CHECK: $q0 = COPY [[ANYEXT]]
2135 CHECK: BL &floorl
2136 )";
2137
2138 // Check
2139 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2140 }
2141
TEST_F(AArch64GISelMITest,LibcallFMinNum)2142 TEST_F(AArch64GISelMITest, LibcallFMinNum) {
2143 setUp();
2144 if (!TM)
2145 return;
2146
2147 // Declare your legalization info
2148 DefineLegalizerInfo(A, {
2149 getActionDefinitionsBuilder(G_FMINNUM).libcallFor({s32, s64, s128});
2150 });
2151
2152 LLT S32{LLT::scalar(32)};
2153 LLT S64{LLT::scalar(64)};
2154 LLT S128{LLT::scalar(128)};
2155 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2156 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2157
2158 auto MIBMin32 = B.buildFMinNum(S32, MIBTrunc, MIBTrunc);
2159 auto MIBMin64 = B.buildFMinNum(S64, Copies[0], Copies[0]);
2160 auto MIBMin128 = B.buildFMinNum(S128, MIBExt, MIBExt);
2161
2162 AInfo Info(MF->getSubtarget());
2163 DummyGISelObserver Observer;
2164 LegalizerHelper Helper(*MF, Info, Observer, B);
2165
2166 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2167 Helper.libcall(*MIBMin32));
2168 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2169 Helper.libcall(*MIBMin64));
2170 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2171 Helper.libcall(*MIBMin128));
2172
2173 const auto *CheckStr = R"(
2174 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2175 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2176 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2177 CHECK: $s0 = COPY [[TRUNC]]
2178 CHECK: $s1 = COPY [[TRUNC]]
2179 CHECK: BL &fminf
2180 CHECK: $d0 = COPY [[COPY]]
2181 CHECK: $d1 = COPY [[COPY]]
2182 CHECK: BL &fmin
2183 CHECK: $q0 = COPY [[ANYEXT]]
2184 CHECK: $q1 = COPY [[ANYEXT]]
2185 CHECK: BL &fminl
2186 )";
2187
2188 // Check
2189 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2190 }
2191
TEST_F(AArch64GISelMITest,LibcallFMaxNum)2192 TEST_F(AArch64GISelMITest, LibcallFMaxNum) {
2193 setUp();
2194 if (!TM)
2195 return;
2196
2197 // Declare your legalization info
2198 DefineLegalizerInfo(A, {
2199 getActionDefinitionsBuilder(G_FMAXNUM).libcallFor({s32, s64, s128});
2200 });
2201
2202 LLT S32{LLT::scalar(32)};
2203 LLT S64{LLT::scalar(64)};
2204 LLT S128{LLT::scalar(128)};
2205 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2206 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2207
2208 auto MIBMax32 = B.buildFMaxNum(S32, MIBTrunc, MIBTrunc);
2209 auto MIBMax64 = B.buildFMaxNum(S64, Copies[0], Copies[0]);
2210 auto MIBMax128 = B.buildFMaxNum(S128, MIBExt, MIBExt);
2211
2212 AInfo Info(MF->getSubtarget());
2213 DummyGISelObserver Observer;
2214 LegalizerHelper Helper(*MF, Info, Observer, B);
2215
2216 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2217 Helper.libcall(*MIBMax32));
2218 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2219 Helper.libcall(*MIBMax64));
2220 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2221 Helper.libcall(*MIBMax128));
2222
2223 const auto *CheckStr = R"(
2224 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2225 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2226 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2227 CHECK: $s0 = COPY [[TRUNC]]
2228 CHECK: $s1 = COPY [[TRUNC]]
2229 CHECK: BL &fmaxf
2230 CHECK: $d0 = COPY [[COPY]]
2231 CHECK: $d1 = COPY [[COPY]]
2232 CHECK: BL &fmax
2233 CHECK: $q0 = COPY [[ANYEXT]]
2234 CHECK: $q1 = COPY [[ANYEXT]]
2235 CHECK: BL &fmaxl
2236 )";
2237
2238 // Check
2239 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2240 }
2241
TEST_F(AArch64GISelMITest,LibcallFSqrt)2242 TEST_F(AArch64GISelMITest, LibcallFSqrt) {
2243 setUp();
2244 if (!TM)
2245 return;
2246
2247 // Declare your legalization info
2248 DefineLegalizerInfo(A, {
2249 getActionDefinitionsBuilder(G_FSQRT).libcallFor({s32, s64, s128});
2250 });
2251
2252 LLT S32{LLT::scalar(32)};
2253 LLT S64{LLT::scalar(64)};
2254 LLT S128{LLT::scalar(128)};
2255 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2256 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2257
2258 auto MIBSqrt32 = B.buildInstr(TargetOpcode::G_FSQRT, {S32}, {MIBTrunc});
2259 auto MIBSqrt64 = B.buildInstr(TargetOpcode::G_FSQRT, {S64}, {Copies[0]});
2260 auto MIBSqrt128 = B.buildInstr(TargetOpcode::G_FSQRT, {S128}, {MIBExt});
2261
2262 AInfo Info(MF->getSubtarget());
2263 DummyGISelObserver Observer;
2264 LegalizerHelper Helper(*MF, Info, Observer, B);
2265
2266 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2267 Helper.libcall(*MIBSqrt32));
2268 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2269 Helper.libcall(*MIBSqrt64));
2270 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2271 Helper.libcall(*MIBSqrt128));
2272
2273 const auto *CheckStr = R"(
2274 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2275 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2276 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2277 CHECK: $s0 = COPY [[TRUNC]]
2278 CHECK: BL &sqrtf
2279 CHECK: $d0 = COPY [[COPY]]
2280 CHECK: BL &sqrt
2281 CHECK: $q0 = COPY [[ANYEXT]]
2282 CHECK: BL &sqrtl
2283 )";
2284
2285 // Check
2286 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2287 }
2288
TEST_F(AArch64GISelMITest,LibcallFRint)2289 TEST_F(AArch64GISelMITest, LibcallFRint) {
2290 setUp();
2291 if (!TM)
2292 return;
2293
2294 // Declare your legalization info
2295 DefineLegalizerInfo(A, {
2296 getActionDefinitionsBuilder(G_FRINT).libcallFor({s32, s64, s128});
2297 });
2298
2299 LLT S32{LLT::scalar(32)};
2300 LLT S64{LLT::scalar(64)};
2301 LLT S128{LLT::scalar(128)};
2302 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2303 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2304
2305 auto MIBRint32 = B.buildInstr(TargetOpcode::G_FRINT, {S32}, {MIBTrunc});
2306 auto MIBRint64 = B.buildInstr(TargetOpcode::G_FRINT, {S64}, {Copies[0]});
2307 auto MIBRint128 = B.buildInstr(TargetOpcode::G_FRINT, {S128}, {MIBExt});
2308
2309 AInfo Info(MF->getSubtarget());
2310 DummyGISelObserver Observer;
2311 LegalizerHelper Helper(*MF, Info, Observer, B);
2312
2313 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2314 Helper.libcall(*MIBRint32));
2315 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2316 Helper.libcall(*MIBRint64));
2317 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2318 Helper.libcall(*MIBRint128));
2319
2320 const auto *CheckStr = R"(
2321 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2322 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2323 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2324 CHECK: $s0 = COPY [[TRUNC]]
2325 CHECK: BL &rintf
2326 CHECK: $d0 = COPY [[COPY]]
2327 CHECK: BL &rint
2328 CHECK: $q0 = COPY [[ANYEXT]]
2329 CHECK: BL &rintl
2330 )";
2331
2332 // Check
2333 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2334 }
2335
TEST_F(AArch64GISelMITest,LibcallFNearbyInt)2336 TEST_F(AArch64GISelMITest, LibcallFNearbyInt) {
2337 setUp();
2338 if (!TM)
2339 return;
2340
2341 // Declare your legalization info
2342 DefineLegalizerInfo(A, {
2343 getActionDefinitionsBuilder(G_FNEARBYINT).libcallFor({s32, s64, s128});
2344 });
2345
2346 LLT S32{LLT::scalar(32)};
2347 LLT S64{LLT::scalar(64)};
2348 LLT S128{LLT::scalar(128)};
2349 auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2350 auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2351
2352 auto MIBNearbyInt32 =
2353 B.buildInstr(TargetOpcode::G_FNEARBYINT, {S32}, {MIBTrunc});
2354 auto MIBNearbyInt64 =
2355 B.buildInstr(TargetOpcode::G_FNEARBYINT, {S64}, {Copies[0]});
2356 auto MIBNearbyInt128 =
2357 B.buildInstr(TargetOpcode::G_FNEARBYINT, {S128}, {MIBExt});
2358
2359 AInfo Info(MF->getSubtarget());
2360 DummyGISelObserver Observer;
2361 LegalizerHelper Helper(*MF, Info, Observer, B);
2362
2363 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2364 Helper.libcall(*MIBNearbyInt32));
2365 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2366 Helper.libcall(*MIBNearbyInt64));
2367 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2368 Helper.libcall(*MIBNearbyInt128));
2369
2370 const auto *CheckStr = R"(
2371 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2372 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2373 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2374 CHECK: $s0 = COPY [[TRUNC]]
2375 CHECK: BL &nearbyintf
2376 CHECK: $d0 = COPY [[COPY]]
2377 CHECK: BL &nearbyint
2378 CHECK: $q0 = COPY [[ANYEXT]]
2379 CHECK: BL &nearbyintl
2380 )";
2381
2382 // Check
2383 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2384 }
2385
TEST_F(AArch64GISelMITest,NarrowScalarExtract)2386 TEST_F(AArch64GISelMITest, NarrowScalarExtract) {
2387 setUp();
2388 if (!TM)
2389 return;
2390
2391 // Declare your legalization info
2392 DefineLegalizerInfo(A, {
2393 getActionDefinitionsBuilder(G_UNMERGE_VALUES).legalFor({{s32, s64}});
2394 getActionDefinitionsBuilder(G_EXTRACT).legalForTypeWithAnyImm({{s16, s32}});
2395 });
2396
2397 LLT S16{LLT::scalar(16)};
2398 LLT S32{LLT::scalar(32)};
2399
2400 auto MIBExtractS32 = B.buildExtract(S32, Copies[1], 32);
2401 auto MIBExtractS16 = B.buildExtract(S16, Copies[1], 0);
2402
2403 AInfo Info(MF->getSubtarget());
2404 DummyGISelObserver Observer;
2405 LegalizerHelper Helper(*MF, Info, Observer, B);
2406
2407 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2408 Helper.narrowScalar(*MIBExtractS32, 1, S32));
2409
2410 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2411 Helper.narrowScalar(*MIBExtractS16, 1, S32));
2412
2413 const auto *CheckStr = R"(
2414 CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES
2415 CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY [[UV1]]
2416 CHECK: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES
2417 CHECK: [[EXTR:%[0-9]+]]:_(s16) = G_EXTRACT [[UV3]]:_(s32), 0
2418 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[EXTR]]
2419 )";
2420
2421 // Check
2422 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2423 }
2424
TEST_F(AArch64GISelMITest,LowerInsert)2425 TEST_F(AArch64GISelMITest, LowerInsert) {
2426 setUp();
2427 if (!TM)
2428 return;
2429
2430 // Declare your legalization info
2431 DefineLegalizerInfo(A, { getActionDefinitionsBuilder(G_INSERT).lower(); });
2432
2433 LLT S32{LLT::scalar(32)};
2434 LLT S64{LLT::scalar(64)};
2435 LLT P0{LLT::pointer(0, 64)};
2436 LLT P1{LLT::pointer(1, 32)};
2437 LLT V2S32{LLT::vector(2, 32)};
2438
2439 auto TruncS32 = B.buildTrunc(S32, Copies[0]);
2440 auto IntToPtrP0 = B.buildIntToPtr(P0, Copies[0]);
2441 auto IntToPtrP1 = B.buildIntToPtr(P1, TruncS32);
2442 auto BitcastV2S32 = B.buildBitcast(V2S32, Copies[0]);
2443
2444 auto InsertS64S32 = B.buildInsert(S64, Copies[0], TruncS32, 0);
2445 auto InsertS64P1 = B.buildInsert(S64, Copies[0], IntToPtrP1, 8);
2446 auto InsertP0S32 = B.buildInsert(P0, IntToPtrP0, TruncS32, 16);
2447 auto InsertP0P1 = B.buildInsert(P0, IntToPtrP0, IntToPtrP1, 4);
2448 auto InsertV2S32S32 = B.buildInsert(V2S32, BitcastV2S32, TruncS32, 32);
2449 auto InsertV2S32P1 = B.buildInsert(V2S32, BitcastV2S32, IntToPtrP1, 0);
2450
2451 AInfo Info(MF->getSubtarget());
2452 DummyGISelObserver Observer;
2453 LegalizerHelper Helper(*MF, Info, Observer, B);
2454
2455 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2456 Helper.lower(*InsertS64S32, 0, LLT{}));
2457
2458 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2459 Helper.lower(*InsertS64P1, 0, LLT{}));
2460
2461 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2462 Helper.lower(*InsertP0S32, 0, LLT{}));
2463
2464 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2465 Helper.lower(*InsertP0P1, 0, LLT{}));
2466
2467 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2468 Helper.lower(*InsertV2S32S32, 0, LLT{}));
2469
2470 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
2471 Helper.lower(*InsertV2S32P1, 0, LLT{}));
2472
2473 const auto *CheckStr = R"(
2474 CHECK: [[S64:%[0-9]+]]:_(s64) = COPY
2475 CHECK: [[S32:%[0-9]+]]:_(s32) = G_TRUNC [[S64]]
2476 CHECK: [[P0:%[0-9]+]]:_(p0) = G_INTTOPTR [[S64]]
2477 CHECK: [[P1:%[0-9]+]]:_(p1) = G_INTTOPTR [[S32]]
2478 CHECK: [[V2S32:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[S64]]
2479 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]]
2480 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
2481 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[S64]]:_, [[C]]:_
2482 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[ZEXT]]:_
2483
2484 CHECK: [[PTRTOINT:%[0-9]+]]:_(s32) = G_PTRTOINT [[P1]]
2485 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[PTRTOINT]]
2486 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
2487 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
2488 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
2489 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[S64]]:_, [[C]]:_
2490 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
2491
2492 CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[P0]]
2493 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]]
2494 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
2495 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
2496 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
2497 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[PTRTOINT]]:_, [[C]]:_
2498 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
2499 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]
2500
2501 CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[P0]]
2502 CHECK: [[PTRTOINT1:%[0-9]+]]:_(s32) = G_PTRTOINT [[P1]]
2503 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[PTRTOINT1]]
2504 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
2505 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
2506 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
2507 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[PTRTOINT]]:_, [[C]]:_
2508 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
2509 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]
2510
2511 CHECK: [[BITCAST:%[0-9]+]]:_(s64) = G_BITCAST [[V2S32]]
2512 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]]
2513 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
2514 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
2515 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
2516 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[BITCAST]]:_, [[C]]:_
2517 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
2518 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[OR]]
2519 )";
2520
2521 // Check
2522 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2523 }
2524
2525 // Test lowering of G_FFLOOR
TEST_F(AArch64GISelMITest,LowerFFloor)2526 TEST_F(AArch64GISelMITest, LowerFFloor) {
2527 setUp();
2528 if (!TM)
2529 return;
2530
2531 // Declare your legalization info
2532 DefineLegalizerInfo(A, {});
2533 // Build Instr
2534 auto Floor = B.buildFFloor(LLT::scalar(64), Copies[0], MachineInstr::MIFlag::FmNoInfs);
2535 AInfo Info(MF->getSubtarget());
2536 DummyGISelObserver Observer;
2537 LegalizerHelper Helper(*MF, Info, Observer, B);
2538 // Perform Legalization
2539 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2540 Helper.lower(*Floor, 0, LLT()));
2541
2542 auto CheckStr = R"(
2543 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2544 CHECK: [[TRUNC:%[0-9]+]]:_(s64) = ninf G_INTRINSIC_TRUNC [[COPY]]
2545 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_FCONSTANT double 0.000000e+00
2546 CHECK: [[CMP0:%[0-9]+]]:_(s1) = ninf G_FCMP floatpred(olt), [[COPY]]:_(s64), [[ZERO]]:_
2547 CHECK: [[CMP1:%[0-9]+]]:_(s1) = ninf G_FCMP floatpred(one), [[COPY]]:_(s64), [[TRUNC]]:_
2548 CHECK: [[AND:%[0-9]+]]:_(s1) = G_AND [[CMP0]]:_, [[CMP1]]:_
2549 CHECK: [[ITOFP:%[0-9]+]]:_(s64) = G_SITOFP [[AND]]
2550 = ninf G_FADD [[TRUNC]]:_, [[ITOFP]]:_
2551 )";
2552
2553 // Check
2554 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2555 }
2556
2557 // Test lowering of G_BSWAP
TEST_F(AArch64GISelMITest,LowerBSWAP)2558 TEST_F(AArch64GISelMITest, LowerBSWAP) {
2559 setUp();
2560 if (!TM)
2561 return;
2562
2563 DefineLegalizerInfo(A, {});
2564
2565 // Make sure vector lowering doesn't assert.
2566 auto Cast = B.buildBitcast(LLT::vector(2, 32), Copies[0]);
2567 auto BSwap = B.buildBSwap(LLT::vector(2, 32), Cast);
2568 AInfo Info(MF->getSubtarget());
2569 DummyGISelObserver Observer;
2570 LegalizerHelper Helper(*MF, Info, Observer, B);
2571 // Perform Legalization
2572 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2573 Helper.lower(*BSwap, 0, LLT()));
2574
2575 auto CheckStr = R"(
2576 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2577 CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
2578 CHECK: [[K24:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
2579 CHECK: [[SPLAT24:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[K24]]:_(s32), [[K24]]:_(s32)
2580 CHECK: [[SHL0:%[0-9]+]]:_(<2 x s32>) = G_SHL [[VEC]]:_, [[SPLAT24]]
2581 CHECK: [[SHR0:%[0-9]+]]:_(<2 x s32>) = G_LSHR [[VEC]]:_, [[SPLAT24]]
2582 CHECK: [[OR0:%[0-9]+]]:_(<2 x s32>) = G_OR [[SHR0]]:_, [[SHL0]]:_
2583 CHECK: [[KMASK:%[0-9]+]]:_(s32) = G_CONSTANT i32 65280
2584 CHECK: [[SPLATMASK:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[KMASK]]:_(s32), [[KMASK]]:_(s32)
2585 CHECK: [[K8:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
2586 CHECK: [[SPLAT8:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[K8]]:_(s32), [[K8]]:_(s32)
2587 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[VEC]]:_, [[SPLATMASK]]:_
2588 CHECK: [[SHL1:%[0-9]+]]:_(<2 x s32>) = G_SHL [[AND0]]:_, [[SPLAT8]]
2589 CHECK: [[OR1:%[0-9]+]]:_(<2 x s32>) = G_OR [[OR0]]:_, [[SHL1]]:_
2590 CHECK: [[SHR1:%[0-9]+]]:_(<2 x s32>) = G_LSHR [[VEC]]:_, [[SPLAT8]]
2591 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[SHR1]]:_, [[SPLATMASK]]:_
2592 CHECK: [[BSWAP:%[0-9]+]]:_(<2 x s32>) = G_OR [[OR1]]:_, [[AND1]]:_
2593 )";
2594
2595 // Check
2596 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2597 }
2598
2599 // Test widening of G_UNMERGE_VALUES
TEST_F(AArch64GISelMITest,WidenUnmerge)2600 TEST_F(AArch64GISelMITest, WidenUnmerge) {
2601 setUp();
2602 if (!TM)
2603 return;
2604
2605 DefineLegalizerInfo(A, {});
2606
2607 // Check that widening G_UNMERGE_VALUES to a larger type than the source type
2608 // works as expected
2609 LLT P0{LLT::pointer(0, 64)};
2610 LLT S32{LLT::scalar(32)};
2611 LLT S96{LLT::scalar(96)};
2612
2613 auto IntToPtr = B.buildIntToPtr(P0, Copies[0]);
2614 auto UnmergePtr = B.buildUnmerge(S32, IntToPtr);
2615 auto UnmergeScalar = B.buildUnmerge(S32, Copies[0]);
2616
2617 AInfo Info(MF->getSubtarget());
2618 DummyGISelObserver Observer;
2619 LegalizerHelper Helper(*MF, Info, Observer, B);
2620
2621 // Perform Legalization
2622 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2623 Helper.widenScalar(*UnmergePtr, 0, S96));
2624
2625 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2626 Helper.widenScalar(*UnmergeScalar, 0, S96));
2627
2628 const auto *CheckStr = R"(
2629 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2630 CHECK: [[PTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY]]
2631 CHECK: [[INT:%[0-9]+]]:_(s64) = G_PTRTOINT [[PTR]]
2632 CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[INT]]
2633 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]]
2634 CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32
2635 CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]]
2636 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]]
2637 CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY]]
2638 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]]
2639 CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32
2640 CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]]
2641 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]]
2642 )";
2643
2644 // Check
2645 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2646 }
2647
TEST_F(AArch64GISelMITest,BitcastLoad)2648 TEST_F(AArch64GISelMITest, BitcastLoad) {
2649 setUp();
2650 if (!TM)
2651 return;
2652
2653 LLT P0 = LLT::pointer(0, 64);
2654 LLT S32 = LLT::scalar(32);
2655 LLT V4S8 = LLT::vector(4, 8);
2656 auto Ptr = B.buildUndef(P0);
2657
2658 DefineLegalizerInfo(A, {});
2659
2660 MachineMemOperand *MMO = B.getMF().getMachineMemOperand(
2661 MachinePointerInfo(), MachineMemOperand::MOLoad, 4, Align(4));
2662 auto Load = B.buildLoad(V4S8, Ptr, *MMO);
2663
2664 AInfo Info(MF->getSubtarget());
2665 DummyGISelObserver Observer;
2666 B.setInsertPt(*EntryMBB, Load->getIterator());
2667 LegalizerHelper Helper(*MF, Info, Observer, B);
2668 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2669 Helper.bitcast(*Load, 0, S32));
2670
2671 auto CheckStr = R"(
2672 CHECK: [[PTR:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF
2673 CHECK: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD
2674 CHECK: [[CAST:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[LOAD]]
2675
2676 )";
2677
2678 // Check
2679 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2680 }
2681
TEST_F(AArch64GISelMITest,BitcastStore)2682 TEST_F(AArch64GISelMITest, BitcastStore) {
2683 setUp();
2684 if (!TM)
2685 return;
2686
2687 LLT P0 = LLT::pointer(0, 64);
2688 LLT S32 = LLT::scalar(32);
2689 LLT V4S8 = LLT::vector(4, 8);
2690 auto Ptr = B.buildUndef(P0);
2691
2692 DefineLegalizerInfo(A, {});
2693
2694 MachineMemOperand *MMO = B.getMF().getMachineMemOperand(
2695 MachinePointerInfo(), MachineMemOperand::MOStore, 4, Align(4));
2696 auto Val = B.buildUndef(V4S8);
2697 auto Store = B.buildStore(Val, Ptr, *MMO);
2698
2699 AInfo Info(MF->getSubtarget());
2700 DummyGISelObserver Observer;
2701 LegalizerHelper Helper(*MF, Info, Observer, B);
2702 B.setInsertPt(*EntryMBB, Store->getIterator());
2703 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2704 Helper.bitcast(*Store, 0, S32));
2705
2706 auto CheckStr = R"(
2707 CHECK: [[VAL:%[0-9]+]]:_(<4 x s8>) = G_IMPLICIT_DEF
2708 CHECK: [[CAST:%[0-9]+]]:_(s32) = G_BITCAST [[VAL]]
2709 CHECK: G_STORE [[CAST]]
2710 )";
2711
2712 // Check
2713 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2714 }
2715
TEST_F(AArch64GISelMITest,BitcastSelect)2716 TEST_F(AArch64GISelMITest, BitcastSelect) {
2717 setUp();
2718 if (!TM)
2719 return;
2720
2721 LLT S1 = LLT::scalar(1);
2722 LLT S32 = LLT::scalar(32);
2723 LLT V4S8 = LLT::vector(4, 8);
2724
2725 DefineLegalizerInfo(A, {});
2726
2727 auto Cond = B.buildUndef(S1);
2728 auto Val0 = B.buildConstant(V4S8, 123);
2729 auto Val1 = B.buildConstant(V4S8, 99);
2730
2731 auto Select = B.buildSelect(V4S8, Cond, Val0, Val1);
2732
2733 AInfo Info(MF->getSubtarget());
2734 DummyGISelObserver Observer;
2735 LegalizerHelper Helper(*MF, Info, Observer, B);
2736 B.setInsertPt(*EntryMBB, Select->getIterator());
2737 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2738 Helper.bitcast(*Select, 0, S32));
2739
2740 auto CheckStr = R"(
2741 CHECK: [[VAL0:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
2742 CHECK: [[VAL1:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
2743 CHECK: [[CAST0:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
2744 CHECK: [[CAST1:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
2745 CHECK: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT %{{[0-9]+}}:_(s1), [[CAST0]]:_, [[CAST1]]:_
2746 CHECK: [[CAST2:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[SELECT]]
2747 )";
2748
2749 // Check
2750 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2751
2752 // Doesn't make sense
2753 auto VCond = B.buildUndef(LLT::vector(4, 1));
2754 auto VSelect = B.buildSelect(V4S8, VCond, Val0, Val1);
2755
2756 B.setInsertPt(*EntryMBB, VSelect->getIterator());
2757 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
2758 Helper.bitcast(*VSelect, 0, S32));
2759 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
2760 Helper.bitcast(*VSelect, 1, LLT::scalar(4)));
2761 }
2762
TEST_F(AArch64GISelMITest,BitcastBitOps)2763 TEST_F(AArch64GISelMITest, BitcastBitOps) {
2764 setUp();
2765 if (!TM)
2766 return;
2767
2768 LLT S32 = LLT::scalar(32);
2769 LLT V4S8 = LLT::vector(4, 8);
2770
2771 DefineLegalizerInfo(A, {});
2772
2773 auto Val0 = B.buildConstant(V4S8, 123);
2774 auto Val1 = B.buildConstant(V4S8, 99);
2775 auto And = B.buildAnd(V4S8, Val0, Val1);
2776 auto Or = B.buildOr(V4S8, Val0, Val1);
2777 auto Xor = B.buildXor(V4S8, Val0, Val1);
2778
2779 AInfo Info(MF->getSubtarget());
2780 DummyGISelObserver Observer;
2781 LegalizerHelper Helper(*MF, Info, Observer, B);
2782 B.setInsertPt(*EntryMBB, And->getIterator());
2783 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2784 Helper.bitcast(*And, 0, S32));
2785
2786 B.setInsertPt(*EntryMBB, Or->getIterator());
2787 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2788 Helper.bitcast(*Or, 0, S32));
2789
2790 B.setInsertPt(*EntryMBB, Xor->getIterator());
2791 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2792 Helper.bitcast(*Xor, 0, S32));
2793
2794 auto CheckStr = R"(
2795 CHECK: [[VAL0:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
2796 CHECK: [[VAL1:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
2797 CHECK: [[CAST0:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
2798 CHECK: [[CAST1:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
2799 CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[CAST0]]:_, [[CAST1]]:_
2800 CHECK: [[CAST_AND:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[AND]]
2801 CHECK: [[CAST2:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
2802 CHECK: [[CAST3:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
2803 CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[CAST2]]:_, [[CAST3]]:_
2804 CHECK: [[CAST_OR:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[OR]]
2805 CHECK: [[CAST4:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
2806 CHECK: [[CAST5:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
2807 CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[CAST4]]:_, [[CAST5]]:_
2808 CHECK: [[CAST_XOR:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[XOR]]
2809 )";
2810
2811 // Check
2812 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2813 }
2814
TEST_F(AArch64GISelMITest,CreateLibcall)2815 TEST_F(AArch64GISelMITest, CreateLibcall) {
2816 setUp();
2817 if (!TM)
2818 return;
2819
2820 DefineLegalizerInfo(A, {});
2821
2822 AInfo Info(MF->getSubtarget());
2823 DummyGISelObserver Observer;
2824
2825 LLVMContext &Ctx = MF->getFunction().getContext();
2826 auto *RetTy = Type::getVoidTy(Ctx);
2827
2828 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2829 createLibcall(B, "abort", {{}, RetTy}, {}, CallingConv::C));
2830
2831 auto CheckStr = R"(
2832 CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
2833 CHECK: BL &abort
2834 CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
2835 )";
2836
2837 // Check
2838 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2839 }
2840
2841 // Test narrowing of G_IMPLICIT_DEF
TEST_F(AArch64GISelMITest,NarrowImplicitDef)2842 TEST_F(AArch64GISelMITest, NarrowImplicitDef) {
2843 setUp();
2844 if (!TM)
2845 return;
2846
2847 DefineLegalizerInfo(A, {});
2848
2849 // Make sure that G_IMPLICIT_DEF can be narrowed if the original size is not a
2850 // multiple of narrow size
2851 LLT S32{LLT::scalar(32)};
2852 LLT S48{LLT::scalar(48)};
2853 LLT S64{LLT::scalar(64)};
2854 LLT V2S64{{LLT::vector(2, 64)}};
2855
2856 auto Implicit1 = B.buildUndef(S64);
2857 auto Implicit2 = B.buildUndef(S64);
2858 auto Implicit3 = B.buildUndef(V2S64);
2859 auto Implicit4 = B.buildUndef(V2S64);
2860
2861 AInfo Info(MF->getSubtarget());
2862 DummyGISelObserver Observer;
2863 LegalizerHelper Helper(*MF, Info, Observer, B);
2864
2865 // Perform Legalization
2866
2867 B.setInsertPt(*EntryMBB, Implicit1->getIterator());
2868 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2869 Helper.narrowScalar(*Implicit1, 0, S48));
2870
2871 B.setInsertPt(*EntryMBB, Implicit2->getIterator());
2872 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2873 Helper.narrowScalar(*Implicit2, 0, S32));
2874
2875 B.setInsertPt(*EntryMBB, Implicit3->getIterator());
2876 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2877 Helper.narrowScalar(*Implicit3, 0, S48));
2878
2879 B.setInsertPt(*EntryMBB, Implicit4->getIterator());
2880 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2881 Helper.narrowScalar(*Implicit4, 0, S32));
2882
2883 const auto *CheckStr = R"(
2884 CHECK: [[DEF:%[0-9]+]]:_(s48) = G_IMPLICIT_DEF
2885 CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[DEF]]
2886
2887 CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
2888 CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
2889 CHECK: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[DEF]]:_(s32), [[DEF1]]
2890
2891 CHECK: [[DEF:%[0-9]+]]:_(<2 x s48>) = G_IMPLICIT_DEF
2892 CHECK: [[ANYEXT:%[0-9]+]]:_(<2 x s64>) = G_ANYEXT [[DEF]]
2893
2894 CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
2895 CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
2896 CHECK: [[DEF2:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
2897 CHECK: [[DEF3:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
2898 CHECK: [[BV:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[DEF]]:_(s32), [[DEF1]]:_(s32), [[DEF2]]:_(s32), [[DEF3]]:_(s32)
2899 )";
2900
2901 // Check
2902 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2903 }
2904
2905 // Test widening of G_FREEZE
TEST_F(AArch64GISelMITest,WidenFreeze)2906 TEST_F(AArch64GISelMITest, WidenFreeze) {
2907 setUp();
2908 if (!TM)
2909 return;
2910
2911 DefineLegalizerInfo(A, {});
2912
2913 // Make sure that G_FREEZE is widened with anyext
2914 LLT S64{LLT::scalar(64)};
2915 LLT S128{LLT::scalar(128)};
2916 LLT V2S32{LLT::vector(2, 32)};
2917 LLT V2S64{LLT::vector(2, 64)};
2918
2919 auto Vector = B.buildBitcast(V2S32, Copies[0]);
2920
2921 auto FreezeScalar = B.buildInstr(TargetOpcode::G_FREEZE, {S64}, {Copies[0]});
2922 auto FreezeVector = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector});
2923
2924 AInfo Info(MF->getSubtarget());
2925 DummyGISelObserver Observer;
2926 LegalizerHelper Helper(*MF, Info, Observer, B);
2927
2928 // Perform Legalization
2929
2930 B.setInsertPt(*EntryMBB, FreezeScalar->getIterator());
2931 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2932 Helper.widenScalar(*FreezeScalar, 0, S128));
2933
2934 B.setInsertPt(*EntryMBB, FreezeVector->getIterator());
2935 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2936 Helper.widenScalar(*FreezeVector, 0, V2S64));
2937
2938 const auto *CheckStr = R"(
2939 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2940 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
2941
2942 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT [[COPY]]
2943 CHECK: [[FREEZE:%[0-9]+]]:_(s128) = G_FREEZE [[ANYEXT]]
2944 CHECK: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[FREEZE]]
2945
2946 CHECK: [[ANYEXT1:%[0-9]+]]:_(<2 x s64>) = G_ANYEXT [[BITCAST]]
2947 CHECK: [[FREEZE1:%[0-9]+]]:_(<2 x s64>) = G_FREEZE [[ANYEXT1]]
2948 CHECK: [[TRUNC1:%[0-9]+]]:_(<2 x s32>) = G_TRUNC [[FREEZE1]]
2949 )";
2950
2951 // Check
2952 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2953 }
2954
2955 // Test narrowing of G_FREEZE
TEST_F(AArch64GISelMITest,NarrowFreeze)2956 TEST_F(AArch64GISelMITest, NarrowFreeze) {
2957 setUp();
2958 if (!TM)
2959 return;
2960
2961 DefineLegalizerInfo(A, {});
2962
2963 // Make sure that G_FREEZE is narrowed using unmerge/extract
2964 LLT S16{LLT::scalar(16)};
2965 LLT S32{LLT::scalar(32)};
2966 LLT S33{LLT::scalar(33)};
2967 LLT S64{LLT::scalar(64)};
2968 LLT V2S16{LLT::vector(2, 16)};
2969 LLT V2S32{LLT::vector(2, 32)};
2970
2971 auto Trunc = B.buildTrunc(S33, {Copies[0]});
2972 auto Vector = B.buildBitcast(V2S32, Copies[0]);
2973
2974 auto FreezeScalar = B.buildInstr(TargetOpcode::G_FREEZE, {S64}, {Copies[0]});
2975 auto FreezeOdd = B.buildInstr(TargetOpcode::G_FREEZE, {S33}, {Trunc});
2976 auto FreezeVector = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector});
2977 auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector});
2978
2979 AInfo Info(MF->getSubtarget());
2980 DummyGISelObserver Observer;
2981 LegalizerHelper Helper(*MF, Info, Observer, B);
2982
2983 // Perform Legalization
2984
2985 B.setInsertPt(*EntryMBB, FreezeScalar->getIterator());
2986 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2987 Helper.narrowScalar(*FreezeScalar, 0, S32));
2988
2989 B.setInsertPt(*EntryMBB, FreezeOdd->getIterator());
2990 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2991 Helper.narrowScalar(*FreezeOdd, 0, S32));
2992
2993 B.setInsertPt(*EntryMBB, FreezeVector->getIterator());
2994 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2995 Helper.narrowScalar(*FreezeVector, 0, V2S16));
2996
2997 B.setInsertPt(*EntryMBB, FreezeVector1->getIterator());
2998 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2999 Helper.narrowScalar(*FreezeVector1, 0, S16));
3000
3001 const auto *CheckStr = R"(
3002 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3003 CHECK: [[TRUNC:%[0-9]+]]:_(s33) = G_TRUNC [[COPY]]
3004 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3005
3006 CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]]
3007 CHECK: [[FREEZE:%[0-9]+]]:_(s32) = G_FREEZE [[UV]]
3008 CHECK: [[FREEZE1:%[0-9]+]]:_(s32) = G_FREEZE [[UV1]]
3009 CHECK: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[FREEZE]]:_(s32), [[FREEZE1]]
3010
3011 CHECK: (s1) = G_UNMERGE_VALUES [[TRUNC]]:_(s33)
3012 CHECK: [[UNDEF:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
3013 CHECK: [[MV1:%[0-9]+]]:_(s32) = G_MERGE_VALUES
3014 CHECK: [[MV2:%[0-9]+]]:_(s32) = G_MERGE_VALUES
3015 CHECK: [[UNDEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3016 CHECK: [[FREEZE2:%[0-9]+]]:_(s32) = G_FREEZE [[MV1]]
3017 CHECK: [[FREEZE3:%[0-9]+]]:_(s32) = G_FREEZE [[MV2]]
3018 CHECK: [[UNDEF2:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3019 CHECK: [[MV3:%[0-9]+]]:_(s1056) = G_MERGE_VALUES [[FREEZE2]]:_(s32), [[FREEZE3]]:_(s32), [[UNDEF2]]
3020 CHECK: [[TRUNC1:%[0-9]+]]:_(s33) = G_TRUNC [[MV3]]
3021
3022 CHECK: [[BITCAST1:%[0-9]+]]:_(s64) = G_BITCAST [[BITCAST]]
3023 CHECK: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST1]]
3024 CHECK: [[FREEZE4:%[0-9]+]]:_(s32) = G_FREEZE [[UV2]]
3025 CHECK: [[FREEZE5:%[0-9]+]]:_(s32) = G_FREEZE [[UV3]]
3026 CHECK: [[MV4:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[FREEZE4]]:_(s32), [[FREEZE5]]:_(s32)
3027 CHECK: [[BITCAST2:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[MV4]]
3028
3029 CHECK: [[BITCAST3:%[0-9]+]]:_(s64) = G_BITCAST [[BITCAST]]
3030 CHECK: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[BITCAST3]]
3031 CHECK: [[FREEZE6:%[0-9]+]]:_(s16) = G_FREEZE [[UV4]]
3032 CHECK: [[FREEZE7:%[0-9]+]]:_(s16) = G_FREEZE [[UV5]]
3033 CHECK: [[FREEZE8:%[0-9]+]]:_(s16) = G_FREEZE [[UV6]]
3034 CHECK: [[FREEZE9:%[0-9]+]]:_(s16) = G_FREEZE [[UV7]]
3035 CHECK: [[MV5:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[FREEZE6]]:_(s16), [[FREEZE7]]:_(s16), [[FREEZE8]]:_(s16), [[FREEZE9]]
3036 CHECK: [[BITCAST3:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[MV5]]
3037 )";
3038
3039 // Check
3040 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3041 }
3042
3043 // Test fewer elements of G_FREEZE
TEST_F(AArch64GISelMITest,FewerElementsFreeze)3044 TEST_F(AArch64GISelMITest, FewerElementsFreeze) {
3045 setUp();
3046 if (!TM)
3047 return;
3048
3049 DefineLegalizerInfo(A, {});
3050
3051 LLT S32{LLT::scalar(32)};
3052 LLT V2S16{LLT::vector(2, 16)};
3053 LLT V2S32{LLT::vector(2, 32)};
3054 LLT V4S16{LLT::vector(4, 16)};
3055
3056 auto Vector1 = B.buildBitcast(V2S32, Copies[0]);
3057 auto Vector2 = B.buildBitcast(V4S16, Copies[0]);
3058
3059 auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector1});
3060 auto FreezeVector2 = B.buildInstr(TargetOpcode::G_FREEZE, {V4S16}, {Vector2});
3061
3062 AInfo Info(MF->getSubtarget());
3063 DummyGISelObserver Observer;
3064 LegalizerHelper Helper(*MF, Info, Observer, B);
3065
3066 // Perform Legalization
3067
3068 B.setInsertPt(*EntryMBB, FreezeVector1->getIterator());
3069 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3070 Helper.fewerElementsVector(*FreezeVector1, 0, S32));
3071
3072 B.setInsertPt(*EntryMBB, FreezeVector2->getIterator());
3073 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3074 Helper.fewerElementsVector(*FreezeVector2, 0, V2S16));
3075
3076 const auto *CheckStr = R"(
3077 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3078 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3079 CHECK: [[BITCAST1:%[0-9]+]]:_(<4 x s16>) = G_BITCAST [[COPY]]
3080
3081 CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST]]
3082 CHECK: [[FREEZE:%[0-9]+]]:_(s32) = G_FREEZE [[UV]]
3083 CHECK: [[FREEZE1:%[0-9]+]]:_(s32) = G_FREEZE [[UV1]]
3084 CHECK: [[MV:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FREEZE]]:_(s32), [[FREEZE1]]
3085
3086 CHECK: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[BITCAST1]]
3087 CHECK: [[FREEZE2:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[UV]]
3088 CHECK: [[FREEZE3:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[UV1]]
3089 CHECK: [[MV:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[FREEZE2]]:_(<2 x s16>), [[FREEZE3]]
3090 )";
3091
3092 // Check
3093 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3094 }
3095
3096 // Test more elements of G_FREEZE
TEST_F(AArch64GISelMITest,MoreElementsFreeze)3097 TEST_F(AArch64GISelMITest, MoreElementsFreeze) {
3098 setUp();
3099 if (!TM)
3100 return;
3101
3102 DefineLegalizerInfo(A, {});
3103
3104 LLT V2S32{LLT::vector(2, 32)};
3105 LLT V4S32{LLT::vector(4, 32)};
3106
3107 auto Vector1 = B.buildBitcast(V2S32, Copies[0]);
3108 auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector1});
3109
3110 AInfo Info(MF->getSubtarget());
3111 DummyGISelObserver Observer;
3112 LegalizerHelper Helper(*MF, Info, Observer, B);
3113
3114 // Perform Legalization
3115 B.setInsertPt(*EntryMBB, FreezeVector1->getIterator());
3116 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3117 Helper.moreElementsVector(*FreezeVector1, 0, V4S32));
3118
3119 const auto *CheckStr = R"(
3120 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3121 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3122 CHECK: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
3123 CHECK: [[CV:%[0-9]+]]:_(<4 x s32>) = G_CONCAT_VECTORS [[BITCAST]]:_(<2 x s32>), [[UNDEF]]
3124 CHECK: [[FREEZE:%[0-9]+]]:_(<4 x s32>) = G_FREEZE [[CV]]
3125 CHECK: [[EXTR0:%[0-9]+]]:_(<2 x s32>), [[EXTR1:%[0-9]+]]:_(<2 x s32>) = G_UNMERGE_VALUES [[FREEZE]]:_(<4 x s32>)
3126 )";
3127
3128 // Check
3129 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3130 }
3131
3132 // Test fewer elements of G_INSERT_VECTOR_ELEMENT
TEST_F(AArch64GISelMITest,FewerElementsInsertVectorElt)3133 TEST_F(AArch64GISelMITest, FewerElementsInsertVectorElt) {
3134 setUp();
3135 if (!TM)
3136 return;
3137
3138 DefineLegalizerInfo(A, {});
3139
3140 LLT P0{LLT::pointer(0, 64)};
3141 LLT S64{LLT::scalar(64)};
3142 LLT S16{LLT::scalar(16)};
3143 LLT V2S16{LLT::vector(2, 16)};
3144 LLT V3S16{LLT::vector(3, 16)};
3145 LLT V8S16{LLT::vector(8, 16)};
3146
3147 auto Ptr0 = B.buildIntToPtr(P0, Copies[0]);
3148 auto VectorV8 = B.buildLoad(V8S16, Ptr0, MachinePointerInfo(), Align(8));
3149 auto Value = B.buildTrunc(S16, Copies[1]);
3150
3151 auto Seven = B.buildConstant(S64, 7);
3152 auto InsertV8Constant7_0 =
3153 B.buildInsertVectorElement(V8S16, VectorV8, Value, Seven);
3154 auto InsertV8Constant7_1 =
3155 B.buildInsertVectorElement(V8S16, VectorV8, Value, Seven);
3156
3157 B.buildStore(InsertV8Constant7_0, Ptr0, MachinePointerInfo(), Align(8),
3158 MachineMemOperand::MOVolatile);
3159 B.buildStore(InsertV8Constant7_1, Ptr0, MachinePointerInfo(), Align(8),
3160 MachineMemOperand::MOVolatile);
3161
3162 AInfo Info(MF->getSubtarget());
3163 DummyGISelObserver Observer;
3164 LegalizerHelper Helper(*MF, Info, Observer, B);
3165
3166 // Perform Legalization
3167 B.setInsertPt(*EntryMBB, InsertV8Constant7_0->getIterator());
3168
3169 // This should index the high element of the 4th piece of an unmerge.
3170 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3171 Helper.fewerElementsVector(*InsertV8Constant7_0, 0, V2S16));
3172
3173 // This case requires extracting an intermediate vector type into the target
3174 // v4s16.
3175 B.setInsertPt(*EntryMBB, InsertV8Constant7_1->getIterator());
3176 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3177 Helper.fewerElementsVector(*InsertV8Constant7_1, 0, V3S16));
3178
3179 const auto *CheckStr = R"(
3180 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
3181 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
3182 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY
3183 CHECK: [[PTR0:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY0]]
3184 CHECK: [[VEC8:%[0-9]+]]:_(<8 x s16>) = G_LOAD [[PTR0]]:_(p0) :: (load 16, align 8)
3185 CHECK: [[INSERT_VAL:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]]
3186
3187
3188 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]]
3189 CHECK: [[ONE:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
3190 CHECK: [[SUB_INSERT_7:%[0-9]+]]:_(<2 x s16>) = G_INSERT_VECTOR_ELT [[UNMERGE3]]:_, [[INSERT_VAL]]:_(s16), [[ONE]]
3191 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>)
3192
3193
3194 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>)
3195 CHECK: [[IMPDEF_S16:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
3196 CHECK: [[BUILD0:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_0]]:_(s16), [[UNMERGE1_1]]:_(s16), [[UNMERGE1_2]]:_(s16)
3197 CHECK: [[BUILD1:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_3]]:_(s16), [[UNMERGE1_4]]:_(s16), [[UNMERGE1_5]]:_(s16)
3198 CHECK: [[BUILD2:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_6]]:_(s16), [[UNMERGE1_7]]:_(s16), [[IMPDEF_S16]]:_(s16)
3199 CHECK: [[IMPDEF_V3S16:%[0-9]+]]:_(<3 x s16>) = G_IMPLICIT_DEF
3200 CHECK: [[ONE_1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
3201 CHECK: [[SUB_INSERT_7_V3S16:%[0-9]+]]:_(<3 x s16>) = G_INSERT_VECTOR_ELT [[BUILD2]]:_, [[INSERT_VAL]]:_(s16), [[ONE_1]]
3202
3203 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>)
3204 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>)
3205 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>)
3206
3207
3208 CHECK: G_STORE [[INSERT_V8_7_0]]
3209 CHECK: G_STORE [[INSERT_V8_7_1]]
3210 )";
3211
3212 // Check
3213 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3214 }
3215
3216 // Test widen scalar of G_UNMERGE_VALUES
TEST_F(AArch64GISelMITest,widenScalarUnmerge)3217 TEST_F(AArch64GISelMITest, widenScalarUnmerge) {
3218 setUp();
3219 if (!TM)
3220 return;
3221
3222 DefineLegalizerInfo(A, {});
3223
3224 LLT S96{LLT::scalar(96)};
3225 LLT S64{LLT::scalar(64)};
3226 LLT S48{LLT::scalar(48)};
3227
3228 auto Src = B.buildAnyExt(S96, Copies[0]);
3229 auto Unmerge = B.buildUnmerge(S48, Src);
3230
3231 AInfo Info(MF->getSubtarget());
3232 DummyGISelObserver Observer;
3233 LegalizerHelper Helper(*MF, Info, Observer, B);
3234
3235 // Perform Legalization
3236 B.setInsertPt(*EntryMBB, Unmerge->getIterator());
3237
3238 // This should create unmerges to a GCD type (S16), then remerge to S48
3239 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3240 Helper.widenScalar(*Unmerge, 0, S64));
3241
3242 const auto *CheckStr = R"(
3243 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
3244 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
3245 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY
3246 CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY0]]
3247 CHECK: [[ANYEXT1:%[0-9]+]]:_(s192) = G_ANYEXT [[ANYEXT]]
3248 CHECK: [[UNMERGE:%[0-9]+]]:_(s64), [[UNMERGE1:%[0-9]+]]:_(s64), [[UNMERGE2:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT1]]
3249 CHECK: [[UNMERGE3:%[0-9]+]]:_(s16), [[UNMERGE4:%[0-9]+]]:_(s16), [[UNMERGE5:%[0-9]+]]:_(s16), [[UNMERGE6:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE]]
3250 CHECK: [[UNMERGE7:%[0-9]+]]:_(s16), [[UNMERGE8:%[0-9]+]]:_(s16), [[UNMERGE9:%[0-9]+]]:_(s16), [[UNMERGE10:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE1]]
3251 CHECK: [[UNMERGE11:%[0-9]+]]:_(s16), [[UNMERGE12:%[0-9]+]]:_(s16), [[UNMERGE13:%[0-9]+]]:_(s16), [[UNMERGE14:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE2]]
3252 CHECK: [[MERGE:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE3]]:_(s16), [[UNMERGE4]]:_(s16), [[UNMERGE5]]:_(s16)
3253 CHECK: [[MERGE1:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE6]]:_(s16), [[UNMERGE7]]:_(s16), [[UNMERGE8]]:_(s16)
3254 )";
3255
3256 // Check
3257 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3258 }
3259
3260 } // namespace
3261