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