xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp (revision 0a317df59f2392a2f1ba84e5def398e109d2e47f)
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   setUp();
30   if (!TM)
31     return;
32 
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);
46 
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   )";
54 
55   // Check
56   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
57 }
58 
59 // CTTZ expansion in terms of CTLZ
60 TEST_F(GISelMITest, LowerBitCountingCTTZ1) {
61   setUp();
62   if (!TM)
63     return;
64 
65   // Declare your legalization info
66   DefineLegalizerInfo(A, {
67     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}});
68   });
69   // Build Instr
70   auto MIBCTTZ =
71       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
72   AInfo Info(MF->getSubtarget());
73   DummyGISelObserver Observer;
74   LegalizerHelper Helper(*MF, Info, Observer, B);
75   // Perform Legalization
76   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
77               LegalizerHelper::LegalizeResult::Legalized);
78 
79   auto CheckStr = R"(
80   CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
81   CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
82   CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
83   CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
84   CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
85   CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_
86   CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_
87   )";
88 
89   // Check
90   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
91 }
92 
93 // CTTZ expansion in terms of CTPOP
94 TEST_F(GISelMITest, LowerBitCountingCTTZ2) {
95   setUp();
96   if (!TM)
97     return;
98 
99   // Declare your legalization info
100   DefineLegalizerInfo(A, {
101     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}});
102   });
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);
111 
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]]
118   )";
119 
120   // Check
121   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
122 }
123 
124 // CTPOP widening.
125 TEST_F(GISelMITest, WidenBitCountingCTPOP1) {
126   if (!TM)
127     return;
128 
129   // Declare your legalization info
130   DefineLegalizerInfo(A, {
131       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
132     });
133 
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));
145 
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)
151   )";
152 
153   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
154 }
155 
156 // Test a strange case where the result is wider than the source
157 TEST_F(GISelMITest, WidenBitCountingCTPOP2) {
158   if (!TM)
159     return;
160 
161   // Declare your legalization info
162   DefineLegalizerInfo(A, {
163       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}});
164     });
165 
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));
178 
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)
184   )";
185 
186   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
187 }
188 
189 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
190 TEST_F(GISelMITest, LowerBitCountingCTTZ3) {
191   setUp();
192   if (!TM)
193     return;
194 
195   // Declare your legalization info
196   DefineLegalizerInfo(A, {
197     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
198   });
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);
207 
208   auto CheckStr = R"(
209   CHECK: CTTZ
210   )";
211 
212   // Check
213   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
214 }
215 
216 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
217 TEST_F(GISelMITest, LowerBitCountingCTLZ0) {
218   setUp();
219   if (!TM)
220     return;
221 
222   // Declare your legalization info
223   DefineLegalizerInfo(A, {
224     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
225   });
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);
234 
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]]
241   )";
242 
243   // Check
244   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
245 }
246 
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;
252 
253   // Declare your legalization info
254   DefineLegalizerInfo(A, {
255     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s64, s64}});
256   });
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);
265 
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]]
272   )";
273 
274   // Check
275   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
276 }
277 
278 // CTLZ expansion
279 TEST_F(GISelMITest, LowerBitCountingCTLZ1) {
280   setUp();
281   if (!TM)
282     return;
283 
284   // Declare your legalization info
285   DefineLegalizerInfo(A, {
286     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
287   });
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);
298 
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]]:_
313   )";
314 
315   // Check
316   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
317 }
318 
319 // CTLZ widening.
320 TEST_F(GISelMITest, WidenBitCountingCTLZ) {
321   setUp();
322   if (!TM)
323     return;
324 
325   // Declare your legalization info
326   DefineLegalizerInfo(A, {
327     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
328   });
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);
340 
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]]
348   )";
349 
350   // Check
351   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
352 }
353 
354 // CTLZ_ZERO_UNDEF widening.
355 TEST_F(GISelMITest, WidenBitCountingCTLZZeroUndef) {
356   setUp();
357   if (!TM)
358     return;
359 
360   // Declare your legalization info
361   DefineLegalizerInfo(A, {
362     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
363   });
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);
376 
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]]
384   )";
385 
386   // Check
387   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
388 }
389 
390 // CTPOP widening.
391 TEST_F(GISelMITest, WidenBitCountingCTPOP) {
392   setUp();
393   if (!TM)
394     return;
395 
396   // Declare your legalization info
397   DefineLegalizerInfo(A, {
398     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
399   });
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);
411 
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]]
417   )";
418 
419   // Check
420   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
421 }
422 
423 // CTTZ_ZERO_UNDEF widening.
424 TEST_F(GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
425   setUp();
426   if (!TM)
427     return;
428 
429   // Declare your legalization info
430   DefineLegalizerInfo(A, {
431     getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
432   });
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);
445 
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]]
451   )";
452 
453   // Check
454   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
455 }
456 
457 // CTTZ widening.
458 TEST_F(GISelMITest, WidenBitCountingCTTZ) {
459   setUp();
460   if (!TM)
461     return;
462 
463   // Declare your legalization info
464   DefineLegalizerInfo(A, {
465     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
466   });
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);
478 
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]]
486   )";
487 
488   // Check
489   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
490 }
491 // UADDO widening.
492 TEST_F(GISelMITest, WidenUADDO) {
493   setUp();
494   if (!TM)
495     return;
496 
497   // Declare your legalization info
498   DefineLegalizerInfo(A, {
499     getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
500   });
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);
514 
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]]
524   )";
525 
526   // Check
527   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
528 }
529 
530 // USUBO widening.
531 TEST_F(GISelMITest, WidenUSUBO) {
532   setUp();
533   if (!TM)
534     return;
535 
536   // Declare your legalization info
537   DefineLegalizerInfo(A, {
538     getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
539   });
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);
553 
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]]
563   )";
564 
565   // Check
566   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
567 }
568 
569 TEST_F(GISelMITest, FewerElementsAnd) {
570   if (!TM)
571     return;
572 
573   const LLT V2S32 = LLT::vector(2, 32);
574   const LLT V5S32 = LLT::vector(5, 32);
575 
576   // Declare your legalization info
577   DefineLegalizerInfo(A, {
578     getActionDefinitionsBuilder(G_AND)
579       .legalFor({s32});
580   });
581 
582   auto Op0 = B.buildUndef(V5S32);
583   auto Op1 = B.buildUndef(V5S32);
584   auto And = B.buildAnd(V5S32, Op0, Op1);
585 
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);
591 
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
600 
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
605 
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
610   )";
611 
612   // Check
613   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
614 }
615 
616 TEST_F(GISelMITest, MoreElementsAnd) {
617   if (!TM)
618     return;
619 
620   LLT s32 = LLT::scalar(32);
621   LLT v2s32 = LLT::vector(2, 32);
622   LLT v6s32 = LLT::vector(6, 32);
623 
624   LegalizerInfo LI;
625   LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
626     .legalFor({v6s32})
627     .clampMinNumElements(0, s32, 6);
628   LI.computeTables();
629 
630   DummyGISelObserver Observer;
631   LegalizerHelper Helper(*MF, LI, Observer, B);
632 
633   B.setInsertPt(*EntryMBB, EntryMBB->end());
634 
635   auto Val0 = B.buildBitcast(v2s32, Copies[0]);
636   auto Val1 = B.buildBitcast(v2s32, Copies[1]);
637 
638   auto And = B.buildAnd(v2s32, Val0, Val1);
639 
640   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
641             Helper.moreElementsVector(*And, 0, v6s32));
642 
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
652   )";
653 
654   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
655 }
656 
657 TEST_F(GISelMITest, FewerElementsPhi) {
658   if (!TM)
659     return;
660 
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);
666 
667   LegalizerInfo LI;
668   LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
669     .legalFor({v2s32})
670     .clampMinNumElements(0, s32, 2);
671   LI.computeTables();
672 
673   LLT PhiTy = v5s32;
674   DummyGISelObserver Observer;
675   LegalizerHelper Helper(*MF, LI, Observer, B);
676   B.setMBB(*EntryMBB);
677 
678   MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock();
679   MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock();
680   MF->insert(MF->end(), MidMBB);
681   MF->insert(MF->end(), EndMBB);
682 
683   EntryMBB->addSuccessor(MidMBB);
684   EntryMBB->addSuccessor(EndMBB);
685   MidMBB->addSuccessor(EndMBB);
686 
687   auto InitVal = B.buildUndef(PhiTy);
688   auto InitOtherVal = B.buildConstant(s64, 999);
689 
690   auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
691   B.buildBrCond(ICmp.getReg(0), *MidMBB);
692   B.buildBr(*EndMBB);
693 
694 
695   B.setMBB(*MidMBB);
696   auto MidVal = B.buildUndef(PhiTy);
697   auto MidOtherVal = B.buildConstant(s64, 345);
698   B.buildBr(*EndMBB);
699 
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);
707 
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);
716 
717   // Add some use instruction after the phis.
718   B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0));
719 
720   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
721             Helper.fewerElementsVector(*Phi, 0, v2s32));
722 
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
729 
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
735 
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
739 
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]]:_
746   )";
747 
748   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
749 }
750 
751 // FNEG expansion in terms of FSUB
752 TEST_F(GISelMITest, LowerFNEG) {
753   if (!TM)
754     return;
755 
756   // Declare your legalization info
757   DefineLegalizerInfo(A, {
758     getActionDefinitionsBuilder(G_FSUB).legalFor({s64});
759   });
760 
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);
765 
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});
770 
771   // Preserve the one flag.
772   auto FNeg1 =
773     B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]},
774                  MachineInstr::MIFlag::FmNoInfs);
775 
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)));
784 
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:_
791   )";
792 
793   // Check
794   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
795 }
796 
797 TEST_F(GISelMITest, LowerMinMax) {
798   if (!TM)
799     return;
800 
801   LLT s64 = LLT::scalar(64);
802   LLT v2s32 = LLT::vector(2, 32);
803 
804   DefineLegalizerInfo(A, {
805     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
806       .lowerFor({s64, LLT::vector(2, s32)});
807   });
808 
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]);
813 
814   auto VecVal0 = B.buildBitcast(v2s32, Copies[0]);
815   auto VecVal1 = B.buildBitcast(v2s32, Copies[1]);
816 
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);
821 
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));
833 
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));
842 
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:_
846 
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:_
849 
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:_
852 
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:_
855 
856   CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
857   CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
858 
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]]:_
861 
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]]:_
864 
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]]:_
867 
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]]:_
870   )";
871 
872   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
873 }
874 
875 TEST_F(GISelMITest, WidenScalarBuildVector) {
876   if (!TM)
877     return;
878 
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);
883 
884   DefineLegalizerInfo(A, {
885     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
886       .lowerFor({s64, LLT::vector(2, s32)});
887   });
888 
889   AInfo Info(MF->getSubtarget());
890   DummyGISelObserver Observer;
891   LegalizerHelper Helper(*MF, Info, Observer, B);
892   B.setInsertPt(*EntryMBB, EntryMBB->end());
893 
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});
898 
899   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
900             Helper.widenScalar(*BV0, 0, V2S32));
901   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
902             Helper.widenScalar(*BV1, 1, S32));
903 
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]]
911 
912   CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
913   CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
914 
915   CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32)
916   )";
917 
918   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
919 }
920 
921 TEST_F(GISelMITest, LowerMergeValues) {
922   if (!TM)
923     return;
924 
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);
932 
933   DefineLegalizerInfo(A, {
934     getActionDefinitionsBuilder(G_UNMERGE_VALUES)
935       .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9)));
936   });
937 
938   AInfo Info(MF->getSubtarget());
939   DummyGISelObserver Observer;
940   LegalizerHelper Helper(*MF, Info, Observer, B);
941   B.setInsertPt(*EntryMBB, EntryMBB->end());
942 
943   // 24 = 3 3 3   3 3 3   3 3
944   //     => 9
945   //
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));
950 
951   auto Merge0 = B.buildMerge(S24, Merge0Ops);
952 
953   // 21 = 3 3 3   3 3 3   3
954   //     => 9, 2 extra implicit_def needed
955   //
956   SmallVector<Register, 8> Merge1Ops;
957   for (int I = 0; I != 7; ++I)
958     Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0));
959 
960   auto Merge1 = B.buildMerge(S21, Merge1Ops);
961 
962   SmallVector<Register, 8> Merge2Ops;
963   for (int I = 0; I != 2; ++I)
964     Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0));
965 
966   auto Merge2 = B.buildMerge(S16, Merge2Ops);
967 
968   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
969             Helper.widenScalar(*Merge0, 1, S9));
970   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
971             Helper.widenScalar(*Merge1, 1, S9));
972 
973   // Request a source size greater than the original destination size.
974   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
975             Helper.widenScalar(*Merge2, 1, S32));
976 
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)
992 
993 
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)
1007 
1008 
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)
1017   )";
1018 
1019   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1020 }
1021 
1022 TEST_F(GISelMITest, WidenScalarMergeValuesPointer) {
1023   if (!TM)
1024     return;
1025 
1026   DefineLegalizerInfo(A, {});
1027 
1028   AInfo Info(MF->getSubtarget());
1029   DummyGISelObserver Observer;
1030   LegalizerHelper Helper(*MF, Info, Observer, B);
1031   B.setInsertPt(*EntryMBB, EntryMBB->end());
1032 
1033   const LLT S32 = LLT::scalar(32);
1034   const LLT S64 = LLT::scalar(64);
1035   const LLT P0 = LLT::pointer(0, 64);
1036 
1037   auto Lo = B.buildTrunc(S32, Copies[0]);
1038   auto Hi = B.buildTrunc(S32, Copies[1]);
1039 
1040   auto Merge = B.buildMerge(P0, {Lo.getReg(0), Hi.getReg(0)});
1041 
1042   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1043             Helper.widenScalar(*Merge, 1, S64));
1044 
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)
1054   )";
1055 
1056   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1057 }
1058 
1059 TEST_F(GISelMITest, WidenSEXTINREG) {
1060   if (!TM)
1061     return;
1062 
1063   // Declare your legalization info
1064   DefineLegalizerInfo(A, {
1065     getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1066   });
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);
1078 
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)
1084   )";
1085 
1086   // Check
1087   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1088 }
1089 
1090 TEST_F(GISelMITest, NarrowSEXTINREG) {
1091   if (!TM)
1092     return;
1093 
1094   // Declare your legalization info, these aren't actually relevant to the test.
1095   DefineLegalizerInfo(A, {
1096     getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1097   });
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);
1109 
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)
1115   )";
1116 
1117   // Check
1118   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1119 }
1120 
1121 TEST_F(GISelMITest, NarrowSEXTINREG2) {
1122   if (!TM)
1123     return;
1124 
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);
1139 
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)
1147   )";
1148 
1149   // Check
1150   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1151 }
1152 
1153 TEST_F(GISelMITest, LowerSEXTINREG) {
1154   if (!TM)
1155     return;
1156 
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);
1171 
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]]:_
1177   )";
1178 
1179   // Check
1180   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1181 }
1182 } // namespace
1183