[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / unittests / CodeGen / GlobalISel / LegalizerHelperTest.cpp
blob4d3492fe99ef930ec93b53ddcb2facafcbcda85e
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 setUp();
30 if (!TM)
31 return;
33 // Declare your legalization info
34 DefineLegalizerInfo(A, {
35 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s64, s64}});
36 });
37 // Build Instr
38 auto MIBCTTZ =
39 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
40 AInfo Info(MF->getSubtarget());
41 DummyGISelObserver Observer;
42 LegalizerHelper Helper(*MF, Info, Observer, B);
43 // Perform Legalization
44 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
45 LegalizerHelper::LegalizeResult::Legalized);
47 auto CheckStr = R"(
48 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF %0
49 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
50 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
51 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
52 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
53 )";
55 // Check
56 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
59 // CTTZ expansion in terms of CTLZ
60 TEST_F(GISelMITest, LowerBitCountingCTTZ1) {
61 setUp();
62 if (!TM)
63 return;
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);
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 )";
89 // Check
90 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
93 // CTTZ expansion in terms of CTPOP
94 TEST_F(GISelMITest, LowerBitCountingCTTZ2) {
95 setUp();
96 if (!TM)
97 return;
99 // Declare your legalization info
100 DefineLegalizerInfo(A, {
101 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}});
103 // Build
104 auto MIBCTTZ =
105 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
106 AInfo Info(MF->getSubtarget());
107 DummyGISelObserver Observer;
108 LegalizerHelper Helper(*MF, Info, Observer, B);
109 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
110 LegalizerHelper::LegalizeResult::Legalized);
112 auto CheckStr = R"(
113 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
114 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
115 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
116 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
117 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
120 // Check
121 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
124 // CTPOP widening.
125 TEST_F(GISelMITest, WidenBitCountingCTPOP1) {
126 if (!TM)
127 return;
129 // Declare your legalization info
130 DefineLegalizerInfo(A, {
131 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
134 // Build
135 // Trunc it to s8.
136 LLT s8{LLT::scalar(8)};
137 LLT s16{LLT::scalar(16)};
138 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
139 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc});
140 AInfo Info(MF->getSubtarget());
141 DummyGISelObserver Observer;
142 LegalizerHelper Helper(*MF, Info, Observer, B);
143 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
144 Helper.widenScalar(*MIBCTPOP, 1, s16));
146 auto CheckStr = R"(
147 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
148 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
149 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
150 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16)
153 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
156 // Test a strange case where the result is wider than the source
157 TEST_F(GISelMITest, WidenBitCountingCTPOP2) {
158 if (!TM)
159 return;
161 // Declare your legalization info
162 DefineLegalizerInfo(A, {
163 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}});
166 // Build
167 // Trunc it to s8.
168 LLT s8{LLT::scalar(8)};
169 LLT s16{LLT::scalar(16)};
170 LLT s32{LLT::scalar(32)};
171 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
172 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc});
173 AInfo Info(MF->getSubtarget());
174 DummyGISelObserver Observer;
175 LegalizerHelper Helper(*MF, Info, Observer, B);
176 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
177 Helper.widenScalar(*MIBCTPOP, 1, s16));
179 auto CheckStr = R"(
180 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
181 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
182 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
183 CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16)
186 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
189 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
190 TEST_F(GISelMITest, LowerBitCountingCTTZ3) {
191 setUp();
192 if (!TM)
193 return;
195 // Declare your legalization info
196 DefineLegalizerInfo(A, {
197 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
199 // Build
200 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
201 {LLT::scalar(64)}, {Copies[0]});
202 AInfo Info(MF->getSubtarget());
203 DummyGISelObserver Observer;
204 LegalizerHelper Helper(*MF, Info, Observer, B);
205 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
206 LegalizerHelper::LegalizeResult::Legalized);
208 auto CheckStr = R"(
209 CHECK: CTTZ
212 // Check
213 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
216 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
217 TEST_F(GISelMITest, LowerBitCountingCTLZ0) {
218 setUp();
219 if (!TM)
220 return;
222 // Declare your legalization info
223 DefineLegalizerInfo(A, {
224 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
226 // Build
227 auto MIBCTLZ =
228 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
229 AInfo Info(MF->getSubtarget());
230 DummyGISelObserver Observer;
231 LegalizerHelper Helper(*MF, Info, Observer, B);
232 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
233 LegalizerHelper::LegalizeResult::Legalized);
235 auto CheckStr = R"(
236 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
237 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
238 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
239 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
240 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
243 // Check
244 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
247 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall
248 TEST_F(GISelMITest, LowerBitCountingCTLZLibcall) {
249 setUp();
250 if (!TM)
251 return;
253 // Declare your legalization info
254 DefineLegalizerInfo(A, {
255 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s64, s64}});
257 // Build
258 auto MIBCTLZ =
259 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
260 AInfo Info(MF->getSubtarget());
261 DummyGISelObserver Observer;
262 LegalizerHelper Helper(*MF, Info, Observer, B);
263 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
264 LegalizerHelper::LegalizeResult::Legalized);
266 auto CheckStr = R"(
267 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
268 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
269 CHECK: [[THIRTY2:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
270 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
271 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]]
274 // Check
275 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
278 // CTLZ expansion
279 TEST_F(GISelMITest, LowerBitCountingCTLZ1) {
280 setUp();
281 if (!TM)
282 return;
284 // Declare your legalization info
285 DefineLegalizerInfo(A, {
286 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
288 // Build
289 // Trunc it to s8.
290 LLT s8{LLT::scalar(8)};
291 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
292 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
293 AInfo Info(MF->getSubtarget());
294 DummyGISelObserver Observer;
295 LegalizerHelper Helper(*MF, Info, Observer, B);
296 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
297 LegalizerHelper::LegalizeResult::Legalized);
299 auto CheckStr = R"(
300 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
301 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
302 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
303 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
304 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
305 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
306 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
307 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
308 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
309 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
310 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
311 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
312 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
315 // Check
316 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
319 // CTLZ widening.
320 TEST_F(GISelMITest, WidenBitCountingCTLZ) {
321 setUp();
322 if (!TM)
323 return;
325 // Declare your legalization info
326 DefineLegalizerInfo(A, {
327 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
329 // Build
330 // Trunc it to s8.
331 LLT s8{LLT::scalar(8)};
332 LLT s16{LLT::scalar(16)};
333 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
334 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
335 AInfo Info(MF->getSubtarget());
336 DummyGISelObserver Observer;
337 LegalizerHelper Helper(*MF, Info, Observer, B);
338 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) ==
339 LegalizerHelper::LegalizeResult::Legalized);
341 auto CheckStr = R"(
342 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
343 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
344 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
345 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
346 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
347 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
350 // Check
351 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
354 // CTLZ_ZERO_UNDEF widening.
355 TEST_F(GISelMITest, WidenBitCountingCTLZZeroUndef) {
356 setUp();
357 if (!TM)
358 return;
360 // Declare your legalization info
361 DefineLegalizerInfo(A, {
362 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
364 // Build
365 // Trunc it to s8.
366 LLT s8{LLT::scalar(8)};
367 LLT s16{LLT::scalar(16)};
368 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
369 auto MIBCTLZ_ZU =
370 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc});
371 AInfo Info(MF->getSubtarget());
372 DummyGISelObserver Observer;
373 LegalizerHelper Helper(*MF, Info, Observer, B);
374 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) ==
375 LegalizerHelper::LegalizeResult::Legalized);
377 auto CheckStr = R"(
378 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
379 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
380 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
381 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
382 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
383 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
386 // Check
387 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
390 // CTPOP widening.
391 TEST_F(GISelMITest, WidenBitCountingCTPOP) {
392 setUp();
393 if (!TM)
394 return;
396 // Declare your legalization info
397 DefineLegalizerInfo(A, {
398 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
400 // Build
401 // Trunc it to s8.
402 LLT s8{LLT::scalar(8)};
403 LLT s16{LLT::scalar(16)};
404 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
405 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc});
406 AInfo Info(MF->getSubtarget());
407 DummyGISelObserver Observer;
408 LegalizerHelper Helper(*MF, Info, Observer, B);
409 EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) ==
410 LegalizerHelper::LegalizeResult::Legalized);
412 auto CheckStr = R"(
413 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
414 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
415 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
416 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
419 // Check
420 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
423 // CTTZ_ZERO_UNDEF widening.
424 TEST_F(GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
425 setUp();
426 if (!TM)
427 return;
429 // Declare your legalization info
430 DefineLegalizerInfo(A, {
431 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
433 // Build
434 // Trunc it to s8.
435 LLT s8{LLT::scalar(8)};
436 LLT s16{LLT::scalar(16)};
437 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
438 auto MIBCTTZ_ZERO_UNDEF =
439 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc});
440 AInfo Info(MF->getSubtarget());
441 DummyGISelObserver Observer;
442 LegalizerHelper Helper(*MF, Info, Observer, B);
443 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) ==
444 LegalizerHelper::LegalizeResult::Legalized);
446 auto CheckStr = R"(
447 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
448 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
449 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
450 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
453 // Check
454 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
457 // CTTZ widening.
458 TEST_F(GISelMITest, WidenBitCountingCTTZ) {
459 setUp();
460 if (!TM)
461 return;
463 // Declare your legalization info
464 DefineLegalizerInfo(A, {
465 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
467 // Build
468 // Trunc it to s8.
469 LLT s8{LLT::scalar(8)};
470 LLT s16{LLT::scalar(16)};
471 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
472 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc});
473 AInfo Info(MF->getSubtarget());
474 DummyGISelObserver Observer;
475 LegalizerHelper Helper(*MF, Info, Observer, B);
476 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) ==
477 LegalizerHelper::LegalizeResult::Legalized);
479 auto CheckStr = R"(
480 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
481 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
482 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
483 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
484 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
485 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
488 // Check
489 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
491 // UADDO widening.
492 TEST_F(GISelMITest, WidenUADDO) {
493 setUp();
494 if (!TM)
495 return;
497 // Declare your legalization info
498 DefineLegalizerInfo(A, {
499 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
501 // Build
502 // Trunc it to s8.
503 LLT s8{LLT::scalar(8)};
504 LLT s16{LLT::scalar(16)};
505 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
506 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
507 auto MIBUAddO =
508 B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
509 AInfo Info(MF->getSubtarget());
510 DummyGISelObserver Observer;
511 LegalizerHelper Helper(*MF, Info, Observer, B);
512 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
513 LegalizerHelper::LegalizeResult::Legalized);
515 auto CheckStr = R"(
516 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
517 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
518 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
519 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
520 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
521 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_
522 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_
523 CHECK: G_TRUNC [[ADD]]
526 // Check
527 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
530 // USUBO widening.
531 TEST_F(GISelMITest, WidenUSUBO) {
532 setUp();
533 if (!TM)
534 return;
536 // Declare your legalization info
537 DefineLegalizerInfo(A, {
538 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
540 // Build
541 // Trunc it to s8.
542 LLT s8{LLT::scalar(8)};
543 LLT s16{LLT::scalar(16)};
544 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
545 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
546 auto MIBUSUBO =
547 B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
548 AInfo Info(MF->getSubtarget());
549 DummyGISelObserver Observer;
550 LegalizerHelper Helper(*MF, Info, Observer, B);
551 EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
552 LegalizerHelper::LegalizeResult::Legalized);
554 auto CheckStr = R"(
555 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
556 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
557 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
558 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
559 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
560 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_
561 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_
562 CHECK: G_TRUNC [[SUB]]
565 // Check
566 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
569 TEST_F(GISelMITest, FewerElementsAnd) {
570 if (!TM)
571 return;
573 const LLT V2S32 = LLT::vector(2, 32);
574 const LLT V5S32 = LLT::vector(5, 32);
576 // Declare your legalization info
577 DefineLegalizerInfo(A, {
578 getActionDefinitionsBuilder(G_AND)
579 .legalFor({s32});
582 auto Op0 = B.buildUndef(V5S32);
583 auto Op1 = B.buildUndef(V5S32);
584 auto And = B.buildAnd(V5S32, Op0, Op1);
586 AInfo Info(MF->getSubtarget());
587 DummyGISelObserver Observer;
588 LegalizerHelper Helper(*MF, Info, Observer, B);
589 EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) ==
590 LegalizerHelper::LegalizeResult::Legalized);
592 auto CheckStr = R"(
593 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
594 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
595 CHECK: [[IMP_DEF2:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
596 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 0
597 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 0
598 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT0]]:_, [[EXTRACT1]]:_
599 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[IMP_DEF2]]:_, [[AND0]]:_(<2 x s32>), 0
601 CHECK: [[EXTRACT2:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 64
602 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 64
603 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT2]]:_, [[EXTRACT3]]:_
604 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[AND1]]:_(<2 x s32>), 64
606 CHECK: [[EXTRACT4:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 128
607 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 128
608 CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[EXTRACT4]]:_, [[EXTRACT5]]:_
609 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[AND2]]:_(s32), 128
612 // Check
613 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
616 TEST_F(GISelMITest, MoreElementsAnd) {
617 if (!TM)
618 return;
620 LLT s32 = LLT::scalar(32);
621 LLT v2s32 = LLT::vector(2, 32);
622 LLT v6s32 = LLT::vector(6, 32);
624 LegalizerInfo LI;
625 LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
626 .legalFor({v6s32})
627 .clampMinNumElements(0, s32, 6);
628 LI.computeTables();
630 DummyGISelObserver Observer;
631 LegalizerHelper Helper(*MF, LI, Observer, B);
633 B.setInsertPt(*EntryMBB, EntryMBB->end());
635 auto Val0 = B.buildBitcast(v2s32, Copies[0]);
636 auto Val1 = B.buildBitcast(v2s32, Copies[1]);
638 auto And = B.buildAnd(v2s32, Val0, Val1);
640 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
641 Helper.moreElementsVector(*And, 0, v6s32));
643 auto CheckStr = R"(
644 CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
645 CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
646 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
647 CHECK: [[CONCAT0:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>)
648 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
649 CHECK: [[CONCAT1:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>)
650 CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[CONCAT0]]:_, [[CONCAT1]]:_
651 CHECK: (<2 x s32>) = G_EXTRACT [[AND]]:_(<6 x s32>), 0
654 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
657 TEST_F(GISelMITest, FewerElementsPhi) {
658 if (!TM)
659 return;
661 LLT s1 = LLT::scalar(1);
662 LLT s32 = LLT::scalar(32);
663 LLT s64 = LLT::scalar(64);
664 LLT v2s32 = LLT::vector(2, 32);
665 LLT v5s32 = LLT::vector(5, 32);
667 LegalizerInfo LI;
668 LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
669 .legalFor({v2s32})
670 .clampMinNumElements(0, s32, 2);
671 LI.computeTables();
673 LLT PhiTy = v5s32;
674 DummyGISelObserver Observer;
675 LegalizerHelper Helper(*MF, LI, Observer, B);
676 B.setMBB(*EntryMBB);
678 MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock();
679 MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock();
680 MF->insert(MF->end(), MidMBB);
681 MF->insert(MF->end(), EndMBB);
683 EntryMBB->addSuccessor(MidMBB);
684 EntryMBB->addSuccessor(EndMBB);
685 MidMBB->addSuccessor(EndMBB);
687 auto InitVal = B.buildUndef(PhiTy);
688 auto InitOtherVal = B.buildConstant(s64, 999);
690 auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
691 B.buildBrCond(ICmp.getReg(0), *MidMBB);
692 B.buildBr(*EndMBB);
695 B.setMBB(*MidMBB);
696 auto MidVal = B.buildUndef(PhiTy);
697 auto MidOtherVal = B.buildConstant(s64, 345);
698 B.buildBr(*EndMBB);
700 B.setMBB(*EndMBB);
701 auto Phi = B.buildInstr(TargetOpcode::G_PHI)
702 .addDef(MRI->createGenericVirtualRegister(PhiTy))
703 .addUse(InitVal.getReg(0))
704 .addMBB(EntryMBB)
705 .addUse(MidVal.getReg(0))
706 .addMBB(MidMBB);
708 // Insert another irrelevant phi to make sure the rebuild is inserted after
709 // it.
710 B.buildInstr(TargetOpcode::G_PHI)
711 .addDef(MRI->createGenericVirtualRegister(s64))
712 .addUse(InitOtherVal.getReg(0))
713 .addMBB(EntryMBB)
714 .addUse(MidOtherVal.getReg(0))
715 .addMBB(MidMBB);
717 // Add some use instruction after the phis.
718 B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0));
720 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
721 Helper.fewerElementsVector(*Phi, 0, v2s32));
723 auto CheckStr = R"(
724 CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
725 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 0
726 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 64
727 CHECK: [[EXTRACT2:%[0-9]+]]:_(s32) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 128
728 CHECK: G_BRCOND
730 CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
731 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 0
732 CHECK: [[EXTRACT4:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 64
733 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 128
734 CHECK: G_BR
736 CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT0]]:_(<2 x s32>), %bb.0, [[EXTRACT3]]:_(<2 x s32>), %bb.1
737 CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT1]]:_(<2 x s32>), %bb.0, [[EXTRACT4]]:_(<2 x s32>), %bb.1
738 CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[EXTRACT2]]:_(s32), %bb.0, [[EXTRACT5]]:_(s32), %bb.1
740 CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI
741 CHECK: [[REBUILD_VAL_IMPDEF:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
742 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[REBUILD_VAL_IMPDEF]]:_, [[PHI0]]:_(<2 x s32>), 0
743 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[PHI1]]:_(<2 x s32>), 64
744 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[PHI2]]:_(s32), 128
745 CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[INSERT2]]:_, [[INSERT2]]:_
748 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
751 // FNEG expansion in terms of FSUB
752 TEST_F(GISelMITest, LowerFNEG) {
753 if (!TM)
754 return;
756 // Declare your legalization info
757 DefineLegalizerInfo(A, {
758 getActionDefinitionsBuilder(G_FSUB).legalFor({s64});
761 // Build Instr. Make sure FMF are preserved.
762 auto FAdd =
763 B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]},
764 MachineInstr::MIFlag::FmNsz);
766 // Should not propagate the flags of src instruction.
767 auto FNeg0 =
768 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)},
769 {MachineInstr::MIFlag::FmArcp});
771 // Preserve the one flag.
772 auto FNeg1 =
773 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]},
774 MachineInstr::MIFlag::FmNoInfs);
776 AInfo Info(MF->getSubtarget());
777 DummyGISelObserver Observer;
778 LegalizerHelper Helper(*MF, Info, Observer, B);
779 // Perform Legalization
780 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
781 Helper.lower(*FNeg0, 0, LLT::scalar(64)));
782 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
783 Helper.lower(*FNeg1, 0, LLT::scalar(64)));
785 auto CheckStr = R"(
786 CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_
787 CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
788 CHECK: [[FSUB0:%[0-9]+]]:_(s64) = arcp G_FSUB [[CONST0]]:_, [[FADD]]:_
789 CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
790 CHECK: [[FSUB1:%[0-9]+]]:_(s64) = ninf G_FSUB [[CONST1]]:_, %0:_
793 // Check
794 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
797 TEST_F(GISelMITest, LowerMinMax) {
798 if (!TM)
799 return;
801 LLT s64 = LLT::scalar(64);
802 LLT v2s32 = LLT::vector(2, 32);
804 DefineLegalizerInfo(A, {
805 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
806 .lowerFor({s64, LLT::vector(2, s32)});
809 auto SMin = B.buildSMin(s64, Copies[0], Copies[1]);
810 auto SMax = B.buildSMax(s64, Copies[0], Copies[1]);
811 auto UMin = B.buildUMin(s64, Copies[0], Copies[1]);
812 auto UMax = B.buildUMax(s64, Copies[0], Copies[1]);
814 auto VecVal0 = B.buildBitcast(v2s32, Copies[0]);
815 auto VecVal1 = B.buildBitcast(v2s32, Copies[1]);
817 auto SMinV = B.buildSMin(v2s32, VecVal0, VecVal1);
818 auto SMaxV = B.buildSMax(v2s32, VecVal0, VecVal1);
819 auto UMinV = B.buildUMin(v2s32, VecVal0, VecVal1);
820 auto UMaxV = B.buildUMax(v2s32, VecVal0, VecVal1);
822 AInfo Info(MF->getSubtarget());
823 DummyGISelObserver Observer;
824 LegalizerHelper Helper(*MF, Info, Observer, B);
825 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
826 Helper.lower(*SMin, 0, s64));
827 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
828 Helper.lower(*SMax, 0, s64));
829 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
830 Helper.lower(*UMin, 0, s64));
831 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
832 Helper.lower(*UMax, 0, s64));
834 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
835 Helper.lower(*SMinV, 0, v2s32));
836 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
837 Helper.lower(*SMaxV, 0, v2s32));
838 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
839 Helper.lower(*UMinV, 0, v2s32));
840 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
841 Helper.lower(*UMaxV, 0, v2s32));
843 auto CheckStr = R"(
844 CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_
845 CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_
847 CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_
848 CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_
850 CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_
851 CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_
853 CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_
854 CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_
856 CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
857 CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
859 CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
860 CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
862 CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
863 CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
865 CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
866 CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
868 CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
869 CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
872 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
875 TEST_F(GISelMITest, WidenScalarBuildVector) {
876 if (!TM)
877 return;
879 LLT S32 = LLT::scalar(32);
880 LLT S16 = LLT::scalar(16);
881 LLT V2S16 = LLT::vector(2, S16);
882 LLT V2S32 = LLT::vector(2, S32);
884 DefineLegalizerInfo(A, {
885 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
886 .lowerFor({s64, LLT::vector(2, s32)});
889 AInfo Info(MF->getSubtarget());
890 DummyGISelObserver Observer;
891 LegalizerHelper Helper(*MF, Info, Observer, B);
892 B.setInsertPt(*EntryMBB, EntryMBB->end());
894 Register Constant0 = B.buildConstant(S16, 1).getReg(0);
895 Register Constant1 = B.buildConstant(S16, 2).getReg(0);
896 auto BV0 = B.buildBuildVector(V2S16, {Constant0, Constant1});
897 auto BV1 = B.buildBuildVector(V2S16, {Constant0, Constant1});
899 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
900 Helper.widenScalar(*BV0, 0, V2S32));
901 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
902 Helper.widenScalar(*BV1, 1, S32));
904 auto CheckStr = R"(
905 CHECK: [[K0:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
906 CHECK-NEXT: [[K1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
907 CHECK-NEXT: [[EXT_K0_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
908 CHECK-NEXT: [[EXT_K1_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
909 CHECK-NEXT: [[BV0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[EXT_K0_0]]:_(s32), [[EXT_K1_0]]:_(s32)
910 CHECK-NEXT: [[BV0_TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BV0]]
912 CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
913 CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
915 CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32)
918 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
921 TEST_F(GISelMITest, LowerMergeValues) {
922 if (!TM)
923 return;
925 const LLT S32 = LLT::scalar(32);
926 const LLT S24 = LLT::scalar(24);
927 const LLT S21 = LLT::scalar(21);
928 const LLT S16 = LLT::scalar(16);
929 const LLT S9 = LLT::scalar(9);
930 const LLT S8 = LLT::scalar(8);
931 const LLT S3 = LLT::scalar(3);
933 DefineLegalizerInfo(A, {
934 getActionDefinitionsBuilder(G_UNMERGE_VALUES)
935 .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9)));
938 AInfo Info(MF->getSubtarget());
939 DummyGISelObserver Observer;
940 LegalizerHelper Helper(*MF, Info, Observer, B);
941 B.setInsertPt(*EntryMBB, EntryMBB->end());
943 // 24 = 3 3 3 3 3 3 3 3
944 // => 9
946 // This can do 3 merges, but need an extra implicit_def.
947 SmallVector<Register, 8> Merge0Ops;
948 for (int I = 0; I != 8; ++I)
949 Merge0Ops.push_back(B.buildConstant(S3, I).getReg(0));
951 auto Merge0 = B.buildMerge(S24, Merge0Ops);
953 // 21 = 3 3 3 3 3 3 3
954 // => 9, 2 extra implicit_def needed
956 SmallVector<Register, 8> Merge1Ops;
957 for (int I = 0; I != 7; ++I)
958 Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0));
960 auto Merge1 = B.buildMerge(S21, Merge1Ops);
962 SmallVector<Register, 8> Merge2Ops;
963 for (int I = 0; I != 2; ++I)
964 Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0));
966 auto Merge2 = B.buildMerge(S16, Merge2Ops);
968 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
969 Helper.widenScalar(*Merge0, 1, S9));
970 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
971 Helper.widenScalar(*Merge1, 1, S9));
973 // Request a source size greater than the original destination size.
974 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
975 Helper.widenScalar(*Merge2, 1, S32));
977 auto CheckStr = R"(
978 CHECK: [[K0:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
979 CHECK-NEXT: [[K1:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
980 CHECK-NEXT: [[K2:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
981 CHECK-NEXT: [[K3:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
982 CHECK-NEXT: [[K4:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
983 CHECK-NEXT: [[K5:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
984 CHECK-NEXT: [[K6:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
985 CHECK-NEXT: [[K7:%[0-9]+]]:_(s3) = G_CONSTANT i3 -1
986 CHECK-NEXT: [[IMPDEF0:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
987 CHECK-NEXT: [[MERGE0:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K0]]:_(s3), [[K1]]:_(s3), [[K2]]:_(s3)
988 CHECK-NEXT: [[MERGE1:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K3]]:_(s3), [[K4]]:_(s3), [[K5]]:_(s3)
989 CHECK-NEXT: [[MERGE2:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K6]]:_(s3), [[K7]]:_(s3), [[IMPDEF0]]:_(s3)
990 CHECK-NEXT: [[MERGE3:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE0]]:_(s9), [[MERGE1]]:_(s9), [[MERGE2]]:_(s9)
991 CHECK-NEXT: (s24) = G_TRUNC [[MERGE3]]:_(s27)
994 CHECK: [[K8:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
995 CHECK-NEXT: [[K9:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
996 CHECK-NEXT: [[K10:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
997 CHECK-NEXT: [[K11:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
998 CHECK-NEXT: [[K12:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
999 CHECK-NEXT: [[K13:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1000 CHECK-NEXT: [[K14:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1001 CHECK-NEXT: [[IMPDEF1:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1002 CHECK-NEXT: [[MERGE4:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K8]]:_(s3), [[K9]]:_(s3), [[K10]]:_(s3)
1003 CHECK-NEXT: [[MERGE5:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K11]]:_(s3), [[K12]]:_(s3), [[K13]]:_(s3)
1004 CHECK-NEXT: [[MERGE6:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K14]]:_(s3), [[IMPDEF1]]:_(s3), [[IMPDEF1]]:_(s3)
1005 CHECK-NEXT: [[MERGE7:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE4]]:_(s9), [[MERGE5]]:_(s9), [[MERGE6]]:_(s9)
1006 CHECK-NEXT: (s21) = G_TRUNC [[MERGE7]]:_(s27)
1009 CHECK: [[K15:%[0-9]+]]:_(s8) = G_CONSTANT i8 0
1010 CHECK-NEXT: [[K16:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
1011 CHECK-NEXT: [[ZEXT_K15:[0-9]+]]:_(s32) = G_ZEXT [[K15]]:_(s8)
1012 CHECK-NEXT: [[ZEXT_K16:[0-9]+]]:_(s32) = G_ZEXT [[K16]]:_(s8)
1013 [[K16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1014 [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT_K16]]:_, [[K16]]:_(s32)
1015 [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT_K16]]:_, [[SHL]]:_
1016 (s16) = G_TRUNC [[OR]]:_(s32)
1019 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1022 TEST_F(GISelMITest, WidenScalarMergeValuesPointer) {
1023 if (!TM)
1024 return;
1026 DefineLegalizerInfo(A, {});
1028 AInfo Info(MF->getSubtarget());
1029 DummyGISelObserver Observer;
1030 LegalizerHelper Helper(*MF, Info, Observer, B);
1031 B.setInsertPt(*EntryMBB, EntryMBB->end());
1033 const LLT S32 = LLT::scalar(32);
1034 const LLT S64 = LLT::scalar(64);
1035 const LLT P0 = LLT::pointer(0, 64);
1037 auto Lo = B.buildTrunc(S32, Copies[0]);
1038 auto Hi = B.buildTrunc(S32, Copies[1]);
1040 auto Merge = B.buildMerge(P0, {Lo.getReg(0), Hi.getReg(0)});
1042 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1043 Helper.widenScalar(*Merge, 1, S64));
1045 auto CheckStr = R"(
1046 CHECK: [[TRUNC0:%[0-9]+]]:_(s32) = G_TRUNC
1047 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC
1048 CHECK: [[ZEXT_TRUNC0:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC0]]
1049 CHECK: [[ZEXT_TRUNC1:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC1]]
1050 CHECK: [[SHIFT_AMT:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
1051 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT_TRUNC1]]:_, [[SHIFT_AMT]]
1052 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[ZEXT_TRUNC0]]:_, [[SHL]]
1053 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]:_(s64)
1056 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1059 TEST_F(GISelMITest, WidenSEXTINREG) {
1060 if (!TM)
1061 return;
1063 // Declare your legalization info
1064 DefineLegalizerInfo(A, {
1065 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1067 // Build Instr
1068 auto MIB = B.buildInstr(
1069 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1070 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1071 uint64_t(8)});
1072 AInfo Info(MF->getSubtarget());
1073 DummyGISelObserver Observer;
1074 LegalizerHelper Helper(*MF, Info, Observer, B);
1075 // Perform Legalization
1076 ASSERT_TRUE(Helper.widenScalar(*MIB, 0, LLT::scalar(64)) ==
1077 LegalizerHelper::LegalizeResult::Legalized);
1079 auto CheckStr = R"(
1080 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1081 CHECK: [[T1:%[0-9]+]]:_(s64) = G_ANYEXT [[T0]]:_(s32)
1082 CHECK: [[T2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[T1]]:_, 8
1083 CHECK: [[T3:%[0-9]+]]:_(s32) = G_TRUNC [[T2]]:_(s64)
1086 // Check
1087 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1090 TEST_F(GISelMITest, NarrowSEXTINREG) {
1091 if (!TM)
1092 return;
1094 // Declare your legalization info, these aren't actually relevant to the test.
1095 DefineLegalizerInfo(A, {
1096 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1098 // Build Instr
1099 auto MIB = B.buildInstr(
1100 TargetOpcode::G_SEXT_INREG, {LLT::scalar(16)},
1101 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(16)}, {Copies[0]}),
1102 uint64_t(8)});
1103 AInfo Info(MF->getSubtarget());
1104 DummyGISelObserver Observer;
1105 LegalizerHelper Helper(*MF, Info, Observer, B);
1106 // Perform Legalization
1107 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(10)) ==
1108 LegalizerHelper::LegalizeResult::Legalized);
1110 auto CheckStr = R"(
1111 CHECK: [[T0:%[0-9]+]]:_(s16) = G_TRUNC
1112 CHECK: [[T1:%[0-9]+]]:_(s10) = G_TRUNC [[T0]]:_(s16)
1113 CHECK: [[T2:%[0-9]+]]:_(s10) = G_SEXT_INREG [[T1]]:_, 8
1114 CHECK: [[T3:%[0-9]+]]:_(s16) = G_SEXT [[T2]]:_(s10)
1117 // Check
1118 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1121 TEST_F(GISelMITest, NarrowSEXTINREG2) {
1122 if (!TM)
1123 return;
1125 // Declare your legalization info, these aren't actually relevant to the test.
1126 DefineLegalizerInfo(
1127 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
1128 // Build Instr
1129 auto MIB = B.buildInstr(
1130 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1131 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1132 uint64_t(9)});
1133 AInfo Info(MF->getSubtarget());
1134 DummyGISelObserver Observer;
1135 LegalizerHelper Helper(*MF, Info, Observer, B);
1136 // Perform Legalization
1137 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(8)) ==
1138 LegalizerHelper::LegalizeResult::Legalized);
1140 auto CheckStr = R"(
1141 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1142 CHECK: [[T1:%[0-9]+]]:_(s8), [[T2:%[0-9]+]]:_(s8), [[T3:%[0-9]+]]:_(s8), [[T4:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[T0]]:_(s32)
1143 CHECK: [[CST2:%[0-9]+]]:_(s8) = G_CONSTANT i8 7
1144 CHECK: [[T5:%[0-9]+]]:_(s8) = G_SEXT_INREG [[T2]]:_, 1
1145 CHECK: [[T6:%[0-9]+]]:_(s8) = G_ASHR [[T5]]:_, [[CST2]]:_
1146 CHECK: [[T7:%[0-9]+]]:_(s32) = G_MERGE_VALUES [[T1]]:_(s8), [[T5]]:_(s8), [[T6]]:_(s8), [[T6]]:_(s8)
1149 // Check
1150 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1153 TEST_F(GISelMITest, LowerSEXTINREG) {
1154 if (!TM)
1155 return;
1157 // Declare your legalization info, these aren't actually relevant to the test.
1158 DefineLegalizerInfo(
1159 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
1160 // Build Instr
1161 auto MIB = B.buildInstr(
1162 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1163 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1164 uint64_t(8)});
1165 AInfo Info(MF->getSubtarget());
1166 DummyGISelObserver Observer;
1167 LegalizerHelper Helper(*MF, Info, Observer, B);
1168 // Perform Legalization
1169 ASSERT_TRUE(Helper.lower(*MIB, 0, LLT()) ==
1170 LegalizerHelper::LegalizeResult::Legalized);
1172 auto CheckStr = R"(
1173 CHECK: [[T1:%[0-9]+]]:_(s32) = G_TRUNC
1174 CHECK: [[CST:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
1175 CHECK: [[T2:%[0-9]+]]:_(s32) = G_SHL [[T1]]:_, [[CST]]:_
1176 CHECK: [[T3:%[0-9]+]]:_(s32) = G_ASHR [[T2]]:_, [[CST]]:_
1179 // Check
1180 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1182 } // namespace