[ARM] MVE big endian bitcasts
[llvm-complete.git] / unittests / CodeGen / GlobalISel / LegalizerHelperTest.cpp
blobf3bee640b13c03915de0478137c02db12d4e916f
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 //===----------------------------------------------------------------------===//
10 #include "GISelMITest.h"
12 using namespace LegalizeActions;
13 using namespace LegalizeMutations;
14 using namespace LegalityPredicates;
16 namespace {
18 class DummyGISelObserver : public GISelChangeObserver {
19 public:
20 void changingInstr(MachineInstr &MI) override {}
21 void changedInstr(MachineInstr &MI) override {}
22 void createdInstr(MachineInstr &MI) override {}
23 void erasingInstr(MachineInstr &MI) override {}
26 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom,
27 // in which case it becomes CTTZ_ZERO_UNDEF with select.
28 TEST_F(GISelMITest, LowerBitCountingCTTZ0) {
29 if (!TM)
30 return;
32 // Declare your legalization info
33 DefineLegalizerInfo(A, {
34 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s64, s64}});
35 });
36 // Build Instr
37 auto MIBCTTZ =
38 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
39 AInfo Info(MF->getSubtarget());
40 DummyGISelObserver Observer;
41 LegalizerHelper Helper(*MF, Info, Observer, B);
42 // Perform Legalization
43 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
44 LegalizerHelper::LegalizeResult::Legalized);
46 auto CheckStr = R"(
47 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF %0
48 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
49 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
50 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
51 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
52 )";
54 // Check
55 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
58 // CTTZ expansion in terms of CTLZ
59 TEST_F(GISelMITest, LowerBitCountingCTTZ1) {
60 if (!TM)
61 return;
63 // Declare your legalization info
64 DefineLegalizerInfo(A, {
65 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}});
66 });
67 // Build Instr
68 auto MIBCTTZ =
69 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
70 AInfo Info(MF->getSubtarget());
71 DummyGISelObserver Observer;
72 LegalizerHelper Helper(*MF, Info, Observer, B);
73 // Perform Legalization
74 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
75 LegalizerHelper::LegalizeResult::Legalized);
77 auto CheckStr = R"(
78 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
79 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
80 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
81 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
82 CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
83 CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_
84 CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_
85 )";
87 // Check
88 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
91 // CTTZ expansion in terms of CTPOP
92 TEST_F(GISelMITest, LowerBitCountingCTTZ2) {
93 if (!TM)
94 return;
96 // Declare your legalization info
97 DefineLegalizerInfo(A, {
98 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}});
99 });
100 // Build
101 auto MIBCTTZ =
102 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
103 AInfo Info(MF->getSubtarget());
104 DummyGISelObserver Observer;
105 LegalizerHelper Helper(*MF, Info, Observer, B);
106 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
107 LegalizerHelper::LegalizeResult::Legalized);
109 auto CheckStr = R"(
110 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
111 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
112 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
113 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
114 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
117 // Check
118 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
121 // CTPOP widening.
122 TEST_F(GISelMITest, WidenBitCountingCTPOP1) {
123 if (!TM)
124 return;
126 // Declare your legalization info
127 DefineLegalizerInfo(A, {
128 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
131 // Build
132 // Trunc it to s8.
133 LLT s8{LLT::scalar(8)};
134 LLT s16{LLT::scalar(16)};
135 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
136 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc});
137 AInfo Info(MF->getSubtarget());
138 DummyGISelObserver Observer;
139 LegalizerHelper Helper(*MF, Info, Observer, B);
140 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
141 Helper.widenScalar(*MIBCTPOP, 1, s16));
143 auto CheckStr = R"(
144 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
145 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
146 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
147 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16)
150 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
153 // Test a strange case where the result is wider than the source
154 TEST_F(GISelMITest, WidenBitCountingCTPOP2) {
155 if (!TM)
156 return;
158 // Declare your legalization info
159 DefineLegalizerInfo(A, {
160 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}});
163 // Build
164 // Trunc it to s8.
165 LLT s8{LLT::scalar(8)};
166 LLT s16{LLT::scalar(16)};
167 LLT s32{LLT::scalar(32)};
168 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
169 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc});
170 AInfo Info(MF->getSubtarget());
171 DummyGISelObserver Observer;
172 LegalizerHelper Helper(*MF, Info, Observer, B);
173 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
174 Helper.widenScalar(*MIBCTPOP, 1, s16));
176 auto CheckStr = R"(
177 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
178 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
179 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
180 CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16)
183 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
186 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
187 TEST_F(GISelMITest, LowerBitCountingCTTZ3) {
188 if (!TM)
189 return;
191 // Declare your legalization info
192 DefineLegalizerInfo(A, {
193 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
195 // Build
196 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
197 {LLT::scalar(64)}, {Copies[0]});
198 AInfo Info(MF->getSubtarget());
199 DummyGISelObserver Observer;
200 LegalizerHelper Helper(*MF, Info, Observer, B);
201 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
202 LegalizerHelper::LegalizeResult::Legalized);
204 auto CheckStr = R"(
205 CHECK: CTTZ
208 // Check
209 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
212 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
213 TEST_F(GISelMITest, LowerBitCountingCTLZ0) {
214 if (!TM)
215 return;
217 // Declare your legalization info
218 DefineLegalizerInfo(A, {
219 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
221 // Build
222 auto MIBCTLZ =
223 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
224 AInfo Info(MF->getSubtarget());
225 DummyGISelObserver Observer;
226 LegalizerHelper Helper(*MF, Info, Observer, B);
227 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
228 LegalizerHelper::LegalizeResult::Legalized);
230 auto CheckStr = R"(
231 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
232 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
233 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
234 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
235 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
238 // Check
239 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
242 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall
243 TEST_F(GISelMITest, LowerBitCountingCTLZLibcall) {
244 if (!TM)
245 return;
247 // Declare your legalization info
248 DefineLegalizerInfo(A, {
249 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s64, s64}});
251 // Build
252 auto MIBCTLZ =
253 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
254 AInfo Info(MF->getSubtarget());
255 DummyGISelObserver Observer;
256 LegalizerHelper Helper(*MF, Info, Observer, B);
257 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
258 LegalizerHelper::LegalizeResult::Legalized);
260 auto CheckStr = R"(
261 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
262 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
263 CHECK: [[THIRTY2:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
264 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
265 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]]
268 // Check
269 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
272 // CTLZ expansion
273 TEST_F(GISelMITest, LowerBitCountingCTLZ1) {
274 if (!TM)
275 return;
277 // Declare your legalization info
278 DefineLegalizerInfo(A, {
279 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
281 // Build
282 // Trunc it to s8.
283 LLT s8{LLT::scalar(8)};
284 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
285 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
286 AInfo Info(MF->getSubtarget());
287 DummyGISelObserver Observer;
288 LegalizerHelper Helper(*MF, Info, Observer, B);
289 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
290 LegalizerHelper::LegalizeResult::Legalized);
292 auto CheckStr = R"(
293 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
294 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
295 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
296 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
297 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
298 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
299 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
300 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
301 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
302 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
303 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
304 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
305 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
308 // Check
309 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
312 // CTLZ widening.
313 TEST_F(GISelMITest, WidenBitCountingCTLZ) {
314 if (!TM)
315 return;
317 // Declare your legalization info
318 DefineLegalizerInfo(A, {
319 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
321 // Build
322 // Trunc it to s8.
323 LLT s8{LLT::scalar(8)};
324 LLT s16{LLT::scalar(16)};
325 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
326 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
327 AInfo Info(MF->getSubtarget());
328 DummyGISelObserver Observer;
329 LegalizerHelper Helper(*MF, Info, Observer, B);
330 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) ==
331 LegalizerHelper::LegalizeResult::Legalized);
333 auto CheckStr = R"(
334 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
335 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
336 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
337 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
338 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
339 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
342 // Check
343 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
346 // CTLZ_ZERO_UNDEF widening.
347 TEST_F(GISelMITest, WidenBitCountingCTLZZeroUndef) {
348 if (!TM)
349 return;
351 // Declare your legalization info
352 DefineLegalizerInfo(A, {
353 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
355 // Build
356 // Trunc it to s8.
357 LLT s8{LLT::scalar(8)};
358 LLT s16{LLT::scalar(16)};
359 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
360 auto MIBCTLZ_ZU =
361 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc});
362 AInfo Info(MF->getSubtarget());
363 DummyGISelObserver Observer;
364 LegalizerHelper Helper(*MF, Info, Observer, B);
365 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) ==
366 LegalizerHelper::LegalizeResult::Legalized);
368 auto CheckStr = R"(
369 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
370 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
371 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
372 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
373 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
374 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
377 // Check
378 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
381 // CTPOP widening.
382 TEST_F(GISelMITest, WidenBitCountingCTPOP) {
383 if (!TM)
384 return;
386 // Declare your legalization info
387 DefineLegalizerInfo(A, {
388 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
390 // Build
391 // Trunc it to s8.
392 LLT s8{LLT::scalar(8)};
393 LLT s16{LLT::scalar(16)};
394 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
395 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc});
396 AInfo Info(MF->getSubtarget());
397 DummyGISelObserver Observer;
398 LegalizerHelper Helper(*MF, Info, Observer, B);
399 EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) ==
400 LegalizerHelper::LegalizeResult::Legalized);
402 auto CheckStr = R"(
403 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
404 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
405 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
406 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
409 // Check
410 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
413 // CTTZ_ZERO_UNDEF widening.
414 TEST_F(GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
415 if (!TM)
416 return;
418 // Declare your legalization info
419 DefineLegalizerInfo(A, {
420 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
422 // Build
423 // Trunc it to s8.
424 LLT s8{LLT::scalar(8)};
425 LLT s16{LLT::scalar(16)};
426 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
427 auto MIBCTTZ_ZERO_UNDEF =
428 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc});
429 AInfo Info(MF->getSubtarget());
430 DummyGISelObserver Observer;
431 LegalizerHelper Helper(*MF, Info, Observer, B);
432 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) ==
433 LegalizerHelper::LegalizeResult::Legalized);
435 auto CheckStr = R"(
436 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
437 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
438 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
439 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
442 // Check
443 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
446 // CTTZ widening.
447 TEST_F(GISelMITest, WidenBitCountingCTTZ) {
448 if (!TM)
449 return;
451 // Declare your legalization info
452 DefineLegalizerInfo(A, {
453 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
455 // Build
456 // Trunc it to s8.
457 LLT s8{LLT::scalar(8)};
458 LLT s16{LLT::scalar(16)};
459 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
460 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc});
461 AInfo Info(MF->getSubtarget());
462 DummyGISelObserver Observer;
463 LegalizerHelper Helper(*MF, Info, Observer, B);
464 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) ==
465 LegalizerHelper::LegalizeResult::Legalized);
467 auto CheckStr = R"(
468 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
469 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
470 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
471 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
472 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
473 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
476 // Check
477 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
479 // UADDO widening.
480 TEST_F(GISelMITest, WidenUADDO) {
481 if (!TM)
482 return;
484 // Declare your legalization info
485 DefineLegalizerInfo(A, {
486 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
488 // Build
489 // Trunc it to s8.
490 LLT s8{LLT::scalar(8)};
491 LLT s16{LLT::scalar(16)};
492 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
493 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
494 auto MIBUAddO =
495 B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
496 AInfo Info(MF->getSubtarget());
497 DummyGISelObserver Observer;
498 LegalizerHelper Helper(*MF, Info, Observer, B);
499 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
500 LegalizerHelper::LegalizeResult::Legalized);
502 auto CheckStr = R"(
503 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
504 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
505 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
506 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
507 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
508 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_
509 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_
510 CHECK: G_TRUNC [[ADD]]
513 // Check
514 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
517 // USUBO widening.
518 TEST_F(GISelMITest, WidenUSUBO) {
519 if (!TM)
520 return;
522 // Declare your legalization info
523 DefineLegalizerInfo(A, {
524 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
526 // Build
527 // Trunc it to s8.
528 LLT s8{LLT::scalar(8)};
529 LLT s16{LLT::scalar(16)};
530 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
531 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
532 auto MIBUSUBO =
533 B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
534 AInfo Info(MF->getSubtarget());
535 DummyGISelObserver Observer;
536 LegalizerHelper Helper(*MF, Info, Observer, B);
537 EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
538 LegalizerHelper::LegalizeResult::Legalized);
540 auto CheckStr = R"(
541 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
542 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
543 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
544 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
545 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
546 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_
547 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_
548 CHECK: G_TRUNC [[SUB]]
551 // Check
552 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
555 TEST_F(GISelMITest, FewerElementsAnd) {
556 if (!TM)
557 return;
559 const LLT V2S32 = LLT::vector(2, 32);
560 const LLT V5S32 = LLT::vector(5, 32);
562 // Declare your legalization info
563 DefineLegalizerInfo(A, {
564 getActionDefinitionsBuilder(G_AND)
565 .legalFor({s32});
568 auto Op0 = B.buildUndef(V5S32);
569 auto Op1 = B.buildUndef(V5S32);
570 auto And = B.buildAnd(V5S32, Op0, Op1);
572 AInfo Info(MF->getSubtarget());
573 DummyGISelObserver Observer;
574 LegalizerHelper Helper(*MF, Info, Observer, B);
575 EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) ==
576 LegalizerHelper::LegalizeResult::Legalized);
578 auto CheckStr = R"(
579 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
580 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
581 CHECK: [[IMP_DEF2:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
582 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 0
583 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 0
584 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT0]]:_, [[EXTRACT1]]:_
585 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[IMP_DEF2]]:_, [[AND0]]:_(<2 x s32>), 0
587 CHECK: [[EXTRACT2:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 64
588 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 64
589 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT2]]:_, [[EXTRACT3]]:_
590 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[AND1]]:_(<2 x s32>), 64
592 CHECK: [[EXTRACT4:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 128
593 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 128
594 CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[EXTRACT4]]:_, [[EXTRACT5]]:_
595 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[AND2]]:_(s32), 128
598 // Check
599 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
602 TEST_F(GISelMITest, MoreElementsAnd) {
603 if (!TM)
604 return;
606 LLT s32 = LLT::scalar(32);
607 LLT v2s32 = LLT::vector(2, 32);
608 LLT v6s32 = LLT::vector(6, 32);
610 LegalizerInfo LI;
611 LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
612 .legalFor({v6s32})
613 .clampMinNumElements(0, s32, 6);
614 LI.computeTables();
616 DummyGISelObserver Observer;
617 LegalizerHelper Helper(*MF, LI, Observer, B);
619 B.setInsertPt(*EntryMBB, EntryMBB->end());
621 auto Val0 = B.buildBitcast(v2s32, Copies[0]);
622 auto Val1 = B.buildBitcast(v2s32, Copies[1]);
624 auto And = B.buildAnd(v2s32, Val0, Val1);
626 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
627 Helper.moreElementsVector(*And, 0, v6s32));
629 auto CheckStr = R"(
630 CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
631 CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
632 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
633 CHECK: [[CONCAT0:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>)
634 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
635 CHECK: [[CONCAT1:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>)
636 CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[CONCAT0]]:_, [[CONCAT1]]:_
637 CHECK: (<2 x s32>) = G_EXTRACT [[AND]]:_(<6 x s32>), 0
640 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
643 TEST_F(GISelMITest, FewerElementsPhi) {
644 if (!TM)
645 return;
647 LLT s1 = LLT::scalar(1);
648 LLT s32 = LLT::scalar(32);
649 LLT s64 = LLT::scalar(64);
650 LLT v2s32 = LLT::vector(2, 32);
651 LLT v5s32 = LLT::vector(5, 32);
653 LegalizerInfo LI;
654 LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
655 .legalFor({v2s32})
656 .clampMinNumElements(0, s32, 2);
657 LI.computeTables();
659 LLT PhiTy = v5s32;
660 DummyGISelObserver Observer;
661 LegalizerHelper Helper(*MF, LI, Observer, B);
662 B.setMBB(*EntryMBB);
664 MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock();
665 MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock();
666 MF->insert(MF->end(), MidMBB);
667 MF->insert(MF->end(), EndMBB);
669 EntryMBB->addSuccessor(MidMBB);
670 EntryMBB->addSuccessor(EndMBB);
671 MidMBB->addSuccessor(EndMBB);
673 auto InitVal = B.buildUndef(PhiTy);
674 auto InitOtherVal = B.buildConstant(s64, 999);
676 auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
677 B.buildBrCond(ICmp.getReg(0), *MidMBB);
678 B.buildBr(*EndMBB);
681 B.setMBB(*MidMBB);
682 auto MidVal = B.buildUndef(PhiTy);
683 auto MidOtherVal = B.buildConstant(s64, 345);
684 B.buildBr(*EndMBB);
686 B.setMBB(*EndMBB);
687 auto Phi = B.buildInstr(TargetOpcode::G_PHI)
688 .addDef(MRI->createGenericVirtualRegister(PhiTy))
689 .addUse(InitVal.getReg(0))
690 .addMBB(EntryMBB)
691 .addUse(MidVal.getReg(0))
692 .addMBB(MidMBB);
694 // Insert another irrelevant phi to make sure the rebuild is inserted after
695 // it.
696 B.buildInstr(TargetOpcode::G_PHI)
697 .addDef(MRI->createGenericVirtualRegister(s64))
698 .addUse(InitOtherVal.getReg(0))
699 .addMBB(EntryMBB)
700 .addUse(MidOtherVal.getReg(0))
701 .addMBB(MidMBB);
703 // Add some use instruction after the phis.
704 B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0));
706 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
707 Helper.fewerElementsVector(*Phi, 0, v2s32));
709 auto CheckStr = R"(
710 CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
711 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 0
712 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 64
713 CHECK: [[EXTRACT2:%[0-9]+]]:_(s32) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 128
714 CHECK: G_BRCOND
716 CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
717 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 0
718 CHECK: [[EXTRACT4:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 64
719 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 128
720 CHECK: G_BR
722 CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT0]]:_(<2 x s32>), %bb.0, [[EXTRACT3]]:_(<2 x s32>), %bb.1
723 CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT1]]:_(<2 x s32>), %bb.0, [[EXTRACT4]]:_(<2 x s32>), %bb.1
724 CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[EXTRACT2]]:_(s32), %bb.0, [[EXTRACT5]]:_(s32), %bb.1
726 CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI
727 CHECK: [[REBUILD_VAL_IMPDEF:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
728 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[REBUILD_VAL_IMPDEF]]:_, [[PHI0]]:_(<2 x s32>), 0
729 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[PHI1]]:_(<2 x s32>), 64
730 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[PHI2]]:_(s32), 128
731 CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[INSERT2]]:_, [[INSERT2]]:_
734 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
737 // FNEG expansion in terms of FSUB
738 TEST_F(GISelMITest, LowerFNEG) {
739 if (!TM)
740 return;
742 // Declare your legalization info
743 DefineLegalizerInfo(A, {
744 getActionDefinitionsBuilder(G_FSUB).legalFor({s64});
747 // Build Instr. Make sure FMF are preserved.
748 auto FAdd =
749 B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]},
750 MachineInstr::MIFlag::FmNsz);
752 // Should not propagate the flags of src instruction.
753 auto FNeg0 =
754 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)},
755 {MachineInstr::MIFlag::FmArcp});
757 // Preserve the one flag.
758 auto FNeg1 =
759 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]},
760 MachineInstr::MIFlag::FmNoInfs);
762 AInfo Info(MF->getSubtarget());
763 DummyGISelObserver Observer;
764 LegalizerHelper Helper(*MF, Info, Observer, B);
765 // Perform Legalization
766 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
767 Helper.lower(*FNeg0, 0, LLT::scalar(64)));
768 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
769 Helper.lower(*FNeg1, 0, LLT::scalar(64)));
771 auto CheckStr = R"(
772 CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_
773 CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
774 CHECK: [[FSUB0:%[0-9]+]]:_(s64) = arcp G_FSUB [[CONST0]]:_, [[FADD]]:_
775 CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
776 CHECK: [[FSUB1:%[0-9]+]]:_(s64) = ninf G_FSUB [[CONST1]]:_, %0:_
779 // Check
780 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
783 TEST_F(GISelMITest, LowerMinMax) {
784 if (!TM)
785 return;
787 LLT s64 = LLT::scalar(64);
788 LLT v2s32 = LLT::vector(2, 32);
790 DefineLegalizerInfo(A, {
791 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
792 .lowerFor({s64, LLT::vector(2, s32)});
795 auto SMin = B.buildSMin(s64, Copies[0], Copies[1]);
796 auto SMax = B.buildSMax(s64, Copies[0], Copies[1]);
797 auto UMin = B.buildUMin(s64, Copies[0], Copies[1]);
798 auto UMax = B.buildUMax(s64, Copies[0], Copies[1]);
800 auto VecVal0 = B.buildBitcast(v2s32, Copies[0]);
801 auto VecVal1 = B.buildBitcast(v2s32, Copies[1]);
803 auto SMinV = B.buildSMin(v2s32, VecVal0, VecVal1);
804 auto SMaxV = B.buildSMax(v2s32, VecVal0, VecVal1);
805 auto UMinV = B.buildUMin(v2s32, VecVal0, VecVal1);
806 auto UMaxV = B.buildUMax(v2s32, VecVal0, VecVal1);
808 AInfo Info(MF->getSubtarget());
809 DummyGISelObserver Observer;
810 LegalizerHelper Helper(*MF, Info, Observer, B);
811 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
812 Helper.lower(*SMin, 0, s64));
813 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
814 Helper.lower(*SMax, 0, s64));
815 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
816 Helper.lower(*UMin, 0, s64));
817 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
818 Helper.lower(*UMax, 0, s64));
820 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
821 Helper.lower(*SMinV, 0, v2s32));
822 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
823 Helper.lower(*SMaxV, 0, v2s32));
824 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
825 Helper.lower(*UMinV, 0, v2s32));
826 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
827 Helper.lower(*UMaxV, 0, v2s32));
829 auto CheckStr = R"(
830 CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_
831 CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_
833 CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_
834 CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_
836 CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_
837 CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_
839 CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_
840 CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_
842 CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
843 CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
845 CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
846 CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
848 CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
849 CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
851 CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
852 CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
854 CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
855 CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
858 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
861 TEST_F(GISelMITest, WidenScalarBuildVector) {
862 if (!TM)
863 return;
865 LLT S32 = LLT::scalar(32);
866 LLT S16 = LLT::scalar(16);
867 LLT V2S16 = LLT::vector(2, S16);
868 LLT V2S32 = LLT::vector(2, S32);
870 DefineLegalizerInfo(A, {
871 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
872 .lowerFor({s64, LLT::vector(2, s32)});
875 AInfo Info(MF->getSubtarget());
876 DummyGISelObserver Observer;
877 LegalizerHelper Helper(*MF, Info, Observer, B);
878 B.setInsertPt(*EntryMBB, EntryMBB->end());
880 Register Constant0 = B.buildConstant(S16, 1).getReg(0);
881 Register Constant1 = B.buildConstant(S16, 2).getReg(0);
882 auto BV0 = B.buildBuildVector(V2S16, {Constant0, Constant1});
883 auto BV1 = B.buildBuildVector(V2S16, {Constant0, Constant1});
885 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
886 Helper.widenScalar(*BV0, 0, V2S32));
887 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
888 Helper.widenScalar(*BV1, 1, S32));
890 auto CheckStr = R"(
891 CHECK: [[K0:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
892 CHECK-NEXT: [[K1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
893 CHECK-NEXT: [[EXT_K0_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
894 CHECK-NEXT: [[EXT_K1_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
895 CHECK-NEXT: [[BV0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[EXT_K0_0]]:_(s32), [[EXT_K1_0]]:_(s32)
896 CHECK-NEXT: [[BV0_TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BV0]]
898 CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
899 CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
901 CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32)
904 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
907 TEST_F(GISelMITest, LowerMergeValues) {
908 if (!TM)
909 return;
911 const LLT S32 = LLT::scalar(32);
912 const LLT S24 = LLT::scalar(24);
913 const LLT S21 = LLT::scalar(21);
914 const LLT S16 = LLT::scalar(16);
915 const LLT S9 = LLT::scalar(9);
916 const LLT S8 = LLT::scalar(8);
917 const LLT S3 = LLT::scalar(3);
919 DefineLegalizerInfo(A, {
920 getActionDefinitionsBuilder(G_UNMERGE_VALUES)
921 .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9)));
924 AInfo Info(MF->getSubtarget());
925 DummyGISelObserver Observer;
926 LegalizerHelper Helper(*MF, Info, Observer, B);
927 B.setInsertPt(*EntryMBB, EntryMBB->end());
929 // 24 = 3 3 3 3 3 3 3 3
930 // => 9
932 // This can do 3 merges, but need an extra implicit_def.
933 SmallVector<Register, 8> Merge0Ops;
934 for (int I = 0; I != 8; ++I)
935 Merge0Ops.push_back(B.buildConstant(S3, I).getReg(0));
937 auto Merge0 = B.buildMerge(S24, Merge0Ops);
939 // 21 = 3 3 3 3 3 3 3
940 // => 9, 2 extra implicit_def needed
942 SmallVector<Register, 8> Merge1Ops;
943 for (int I = 0; I != 7; ++I)
944 Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0));
946 auto Merge1 = B.buildMerge(S21, Merge1Ops);
948 SmallVector<Register, 8> Merge2Ops;
949 for (int I = 0; I != 2; ++I)
950 Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0));
952 auto Merge2 = B.buildMerge(S16, Merge2Ops);
954 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
955 Helper.widenScalar(*Merge0, 1, S9));
956 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
957 Helper.widenScalar(*Merge1, 1, S9));
959 // Request a source size greater than the original destination size.
960 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
961 Helper.widenScalar(*Merge2, 1, S32));
963 auto CheckStr = R"(
964 CHECK: [[K0:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
965 CHECK-NEXT: [[K1:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
966 CHECK-NEXT: [[K2:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
967 CHECK-NEXT: [[K3:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
968 CHECK-NEXT: [[K4:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
969 CHECK-NEXT: [[K5:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
970 CHECK-NEXT: [[K6:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
971 CHECK-NEXT: [[K7:%[0-9]+]]:_(s3) = G_CONSTANT i3 -1
972 CHECK-NEXT: [[IMPDEF0:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
973 CHECK-NEXT: [[MERGE0:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K0]]:_(s3), [[K1]]:_(s3), [[K2]]:_(s3)
974 CHECK-NEXT: [[MERGE1:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K3]]:_(s3), [[K4]]:_(s3), [[K5]]:_(s3)
975 CHECK-NEXT: [[MERGE2:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K6]]:_(s3), [[K7]]:_(s3), [[IMPDEF0]]:_(s3)
976 CHECK-NEXT: [[MERGE3:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE0]]:_(s9), [[MERGE1]]:_(s9), [[MERGE2]]:_(s9)
977 CHECK-NEXT: (s24) = G_TRUNC [[MERGE3]]:_(s27)
980 CHECK: [[K8:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
981 CHECK-NEXT: [[K9:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
982 CHECK-NEXT: [[K10:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
983 CHECK-NEXT: [[K11:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
984 CHECK-NEXT: [[K12:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
985 CHECK-NEXT: [[K13:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
986 CHECK-NEXT: [[K14:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
987 CHECK-NEXT: [[IMPDEF1:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
988 CHECK-NEXT: [[MERGE4:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K8]]:_(s3), [[K9]]:_(s3), [[K10]]:_(s3)
989 CHECK-NEXT: [[MERGE5:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K11]]:_(s3), [[K12]]:_(s3), [[K13]]:_(s3)
990 CHECK-NEXT: [[MERGE6:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K14]]:_(s3), [[IMPDEF1]]:_(s3), [[IMPDEF1]]:_(s3)
991 CHECK-NEXT: [[MERGE7:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE4]]:_(s9), [[MERGE5]]:_(s9), [[MERGE6]]:_(s9)
992 CHECK-NEXT: (s21) = G_TRUNC [[MERGE7]]:_(s27)
995 CHECK: [[K15:%[0-9]+]]:_(s8) = G_CONSTANT i8 0
996 CHECK-NEXT: [[K16:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
997 CHECK-NEXT: [[ZEXT_K15:[0-9]+]]:_(s32) = G_ZEXT [[K15]]:_(s8)
998 CHECK-NEXT: [[ZEXT_K16:[0-9]+]]:_(s32) = G_ZEXT [[K16]]:_(s8)
999 [[K16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1000 [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT_K16]]:_, [[K16]]:_(s32)
1001 [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT_K16]]:_, [[SHL]]:_
1002 (s16) = G_TRUNC [[OR]]:_(s32)
1005 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1008 TEST_F(GISelMITest, WidenScalarMergeValuesPointer) {
1009 if (!TM)
1010 return;
1012 DefineLegalizerInfo(A, {});
1014 AInfo Info(MF->getSubtarget());
1015 DummyGISelObserver Observer;
1016 LegalizerHelper Helper(*MF, Info, Observer, B);
1017 B.setInsertPt(*EntryMBB, EntryMBB->end());
1019 const LLT S32 = LLT::scalar(32);
1020 const LLT S64 = LLT::scalar(64);
1021 const LLT P0 = LLT::pointer(0, 64);
1023 auto Lo = B.buildTrunc(S32, Copies[0]);
1024 auto Hi = B.buildTrunc(S32, Copies[1]);
1026 auto Merge = B.buildMerge(P0, {Lo.getReg(0), Hi.getReg(0)});
1028 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1029 Helper.widenScalar(*Merge, 1, S64));
1031 auto CheckStr = R"(
1032 CHECK: [[TRUNC0:%[0-9]+]]:_(s32) = G_TRUNC
1033 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC
1034 CHECK: [[ZEXT_TRUNC0:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC0]]
1035 CHECK: [[ZEXT_TRUNC1:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC1]]
1036 CHECK: [[SHIFT_AMT:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
1037 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT_TRUNC1]]:_, [[SHIFT_AMT]]
1038 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[ZEXT_TRUNC0]]:_, [[SHL]]
1039 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]:_(s64)
1042 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1045 } // namespace