xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp (revision 9ad917c2da729255aba68fe2c9359cb6e103eef7)
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:
20   void changingInstr(MachineInstr &MI) override {}
21   void changedInstr(MachineInstr &MI) override {}
22   void createdInstr(MachineInstr &MI) override {}
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.
28 TEST_F(GISelMITest, LowerBitCountingCTTZ0) {
29   if (!TM)
30     return;
31 
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);
45 
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   )";
53 
54   // Check
55   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
56 }
57 
58 // CTTZ expansion in terms of CTLZ
59 TEST_F(GISelMITest, LowerBitCountingCTTZ1) {
60   if (!TM)
61     return;
62 
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);
76 
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   )";
86 
87   // Check
88   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
89 }
90 
91 // CTTZ expansion in terms of CTPOP
92 TEST_F(GISelMITest, LowerBitCountingCTTZ2) {
93   if (!TM)
94     return;
95 
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);
108 
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]]
115   )";
116 
117   // Check
118   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
119 }
120 
121 // CTPOP widening.
122 TEST_F(GISelMITest, WidenBitCountingCTPOP1) {
123   if (!TM)
124     return;
125 
126   // Declare your legalization info
127   DefineLegalizerInfo(A, {
128       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
129     });
130 
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));
142 
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)
148   )";
149 
150   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
151 }
152 
153 // Test a strange case where the result is wider than the source
154 TEST_F(GISelMITest, WidenBitCountingCTPOP2) {
155   if (!TM)
156     return;
157 
158   // Declare your legalization info
159   DefineLegalizerInfo(A, {
160       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}});
161     });
162 
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));
175 
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)
181   )";
182 
183   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
184 }
185 
186 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
187 TEST_F(GISelMITest, LowerBitCountingCTTZ3) {
188   if (!TM)
189     return;
190 
191   // Declare your legalization info
192   DefineLegalizerInfo(A, {
193     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
194   });
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);
203 
204   auto CheckStr = R"(
205   CHECK: CTTZ
206   )";
207 
208   // Check
209   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
210 }
211 
212 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
213 TEST_F(GISelMITest, LowerBitCountingCTLZ0) {
214   if (!TM)
215     return;
216 
217   // Declare your legalization info
218   DefineLegalizerInfo(A, {
219     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
220   });
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);
229 
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]]
236   )";
237 
238   // Check
239   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
240 }
241 
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;
246 
247   // Declare your legalization info
248   DefineLegalizerInfo(A, {
249     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s64, s64}});
250   });
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);
259 
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]]
266   )";
267 
268   // Check
269   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
270 }
271 
272 // CTLZ expansion
273 TEST_F(GISelMITest, LowerBitCountingCTLZ1) {
274   if (!TM)
275     return;
276 
277   // Declare your legalization info
278   DefineLegalizerInfo(A, {
279     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
280   });
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);
291 
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]]:_
306   )";
307 
308   // Check
309   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
310 }
311 
312 // CTLZ widening.
313 TEST_F(GISelMITest, WidenBitCountingCTLZ) {
314   if (!TM)
315     return;
316 
317   // Declare your legalization info
318   DefineLegalizerInfo(A, {
319     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
320   });
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);
332 
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]]
340   )";
341 
342   // Check
343   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
344 }
345 
346 // CTLZ_ZERO_UNDEF widening.
347 TEST_F(GISelMITest, WidenBitCountingCTLZZeroUndef) {
348   if (!TM)
349     return;
350 
351   // Declare your legalization info
352   DefineLegalizerInfo(A, {
353     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
354   });
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);
367 
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]]
375   )";
376 
377   // Check
378   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
379 }
380 
381 // CTPOP widening.
382 TEST_F(GISelMITest, WidenBitCountingCTPOP) {
383   if (!TM)
384     return;
385 
386   // Declare your legalization info
387   DefineLegalizerInfo(A, {
388     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
389   });
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);
401 
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]]
407   )";
408 
409   // Check
410   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
411 }
412 
413 // CTTZ_ZERO_UNDEF widening.
414 TEST_F(GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
415   if (!TM)
416     return;
417 
418   // Declare your legalization info
419   DefineLegalizerInfo(A, {
420     getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
421   });
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);
434 
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]]
440   )";
441 
442   // Check
443   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
444 }
445 
446 // CTTZ widening.
447 TEST_F(GISelMITest, WidenBitCountingCTTZ) {
448   if (!TM)
449     return;
450 
451   // Declare your legalization info
452   DefineLegalizerInfo(A, {
453     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
454   });
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);
466 
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]]
474   )";
475 
476   // Check
477   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
478 }
479 // UADDO widening.
480 TEST_F(GISelMITest, WidenUADDO) {
481   if (!TM)
482     return;
483 
484   // Declare your legalization info
485   DefineLegalizerInfo(A, {
486     getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
487   });
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);
501 
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]]
511   )";
512 
513   // Check
514   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
515 }
516 
517 // USUBO widening.
518 TEST_F(GISelMITest, WidenUSUBO) {
519   if (!TM)
520     return;
521 
522   // Declare your legalization info
523   DefineLegalizerInfo(A, {
524     getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
525   });
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);
539 
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]]
549   )";
550 
551   // Check
552   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
553 }
554 
555 TEST_F(GISelMITest, FewerElementsAnd) {
556   if (!TM)
557     return;
558 
559   const LLT V2S32 = LLT::vector(2, 32);
560   const LLT V5S32 = LLT::vector(5, 32);
561 
562   // Declare your legalization info
563   DefineLegalizerInfo(A, {
564     getActionDefinitionsBuilder(G_AND)
565       .legalFor({s32});
566   });
567 
568   auto Op0 = B.buildUndef(V5S32);
569   auto Op1 = B.buildUndef(V5S32);
570   auto And = B.buildAnd(V5S32, Op0, Op1);
571 
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);
577 
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
586 
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
591 
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
596   )";
597 
598   // Check
599   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
600 }
601 
602 TEST_F(GISelMITest, MoreElementsAnd) {
603   if (!TM)
604     return;
605 
606   LLT s32 = LLT::scalar(32);
607   LLT v2s32 = LLT::vector(2, 32);
608   LLT v6s32 = LLT::vector(6, 32);
609 
610   LegalizerInfo LI;
611   LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
612     .legalFor({v6s32})
613     .clampMinNumElements(0, s32, 6);
614   LI.computeTables();
615 
616   DummyGISelObserver Observer;
617   LegalizerHelper Helper(*MF, LI, Observer, B);
618 
619   B.setInsertPt(*EntryMBB, EntryMBB->end());
620 
621   auto Val0 = B.buildBitcast(v2s32, Copies[0]);
622   auto Val1 = B.buildBitcast(v2s32, Copies[1]);
623 
624   auto And = B.buildAnd(v2s32, Val0, Val1);
625 
626   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
627             Helper.moreElementsVector(*And, 0, v6s32));
628 
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
638   )";
639 
640   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
641 }
642 
643 TEST_F(GISelMITest, FewerElementsPhi) {
644   if (!TM)
645     return;
646 
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);
652 
653   LegalizerInfo LI;
654   LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
655     .legalFor({v2s32})
656     .clampMinNumElements(0, s32, 2);
657   LI.computeTables();
658 
659   LLT PhiTy = v5s32;
660   DummyGISelObserver Observer;
661   LegalizerHelper Helper(*MF, LI, Observer, B);
662   B.setMBB(*EntryMBB);
663 
664   MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock();
665   MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock();
666   MF->insert(MF->end(), MidMBB);
667   MF->insert(MF->end(), EndMBB);
668 
669   EntryMBB->addSuccessor(MidMBB);
670   EntryMBB->addSuccessor(EndMBB);
671   MidMBB->addSuccessor(EndMBB);
672 
673   auto InitVal = B.buildUndef(PhiTy);
674   auto InitOtherVal = B.buildConstant(s64, 999);
675 
676   auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
677   B.buildBrCond(ICmp.getReg(0), *MidMBB);
678   B.buildBr(*EndMBB);
679 
680 
681   B.setMBB(*MidMBB);
682   auto MidVal = B.buildUndef(PhiTy);
683   auto MidOtherVal = B.buildConstant(s64, 345);
684   B.buildBr(*EndMBB);
685 
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);
693 
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);
702 
703   // Add some use instruction after the phis.
704   B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0));
705 
706   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
707             Helper.fewerElementsVector(*Phi, 0, v2s32));
708 
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
715 
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
721 
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
725 
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]]:_
732   )";
733 
734   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
735 }
736 
737 // FNEG expansion in terms of FSUB
738 TEST_F(GISelMITest, LowerFNEG) {
739   if (!TM)
740     return;
741 
742   // Declare your legalization info
743   DefineLegalizerInfo(A, {
744     getActionDefinitionsBuilder(G_FSUB).legalFor({s64});
745   });
746 
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);
751 
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});
756 
757   // Preserve the one flag.
758   auto FNeg1 =
759     B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]},
760                  MachineInstr::MIFlag::FmNoInfs);
761 
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)));
770 
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:_
777   )";
778 
779   // Check
780   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
781 }
782 
783 TEST_F(GISelMITest, LowerMinMax) {
784   if (!TM)
785     return;
786 
787   LLT s64 = LLT::scalar(64);
788   LLT v2s32 = LLT::vector(2, 32);
789 
790   DefineLegalizerInfo(A, {
791     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
792       .lowerFor({s64, LLT::vector(2, s32)});
793   });
794 
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]);
799 
800   auto VecVal0 = B.buildBitcast(v2s32, Copies[0]);
801   auto VecVal1 = B.buildBitcast(v2s32, Copies[1]);
802 
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);
807 
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));
819 
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));
828 
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:_
832 
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:_
835 
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:_
838 
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:_
841 
842   CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
843   CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
844 
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]]:_
847 
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]]:_
850 
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]]:_
853 
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]]:_
856   )";
857 
858   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
859 }
860 
861 TEST_F(GISelMITest, WidenScalarBuildVector) {
862   if (!TM)
863     return;
864 
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);
869 
870   DefineLegalizerInfo(A, {
871     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
872       .lowerFor({s64, LLT::vector(2, s32)});
873   });
874 
875   AInfo Info(MF->getSubtarget());
876   DummyGISelObserver Observer;
877   LegalizerHelper Helper(*MF, Info, Observer, B);
878   B.setInsertPt(*EntryMBB, EntryMBB->end());
879 
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});
884 
885   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
886             Helper.widenScalar(*BV0, 0, V2S32));
887   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
888             Helper.widenScalar(*BV1, 1, S32));
889 
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]]
897 
898   CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
899   CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
900 
901   CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32)
902   )";
903 
904   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
905 }
906 
907 TEST_F(GISelMITest, LowerMergeValues) {
908   if (!TM)
909     return;
910 
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);
918 
919   DefineLegalizerInfo(A, {
920     getActionDefinitionsBuilder(G_UNMERGE_VALUES)
921       .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9)));
922   });
923 
924   AInfo Info(MF->getSubtarget());
925   DummyGISelObserver Observer;
926   LegalizerHelper Helper(*MF, Info, Observer, B);
927   B.setInsertPt(*EntryMBB, EntryMBB->end());
928 
929   // 24 = 3 3 3   3 3 3   3 3
930   //     => 9
931   //
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));
936 
937   auto Merge0 = B.buildMerge(S24, Merge0Ops);
938 
939   // 21 = 3 3 3   3 3 3   3
940   //     => 9, 2 extra implicit_def needed
941   //
942   SmallVector<Register, 8> Merge1Ops;
943   for (int I = 0; I != 7; ++I)
944     Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0));
945 
946   auto Merge1 = B.buildMerge(S21, Merge1Ops);
947 
948   SmallVector<Register, 8> Merge2Ops;
949   for (int I = 0; I != 2; ++I)
950     Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0));
951 
952   auto Merge2 = B.buildMerge(S16, Merge2Ops);
953 
954   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
955             Helper.widenScalar(*Merge0, 1, S9));
956   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
957             Helper.widenScalar(*Merge1, 1, S9));
958 
959   // Request a source size greater than the original destination size.
960   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
961             Helper.widenScalar(*Merge2, 1, S32));
962 
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)
978 
979 
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)
993 
994 
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)
1003   )";
1004 
1005   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1006 }
1007 } // namespace
1008