xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp (revision 6135f5eda48eb12a98f835d976e4916cfd44764c)
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({{s32, s64}});
36   });
37   // Build Instr
38   auto MIBCTTZ =
39       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]});
40   AInfo Info(MF->getSubtarget());
41   DummyGISelObserver Observer;
42   LegalizerHelper Helper(*MF, Info, Observer, B);
43   // Perform Legalization
44   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
45             Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)));
46 
47   auto CheckStr = R"(
48   CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF %0
49   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
50   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
51   CHECK: [[SIXTY4:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
52   CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
53   )";
54 
55   // Check
56   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
57 }
58 
59 // CTTZ expansion in terms of CTLZ
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 // CTLZ scalar narrowing
94 TEST_F(GISelMITest, NarrowScalarCTLZ) {
95   setUp();
96   if (!TM)
97     return;
98 
99   // Declare your legalization info
100   DefineLegalizerInfo(A, {
101     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s32, s32}});
102   });
103   // Build Instr
104   auto CTLZ =
105       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]});
106   AInfo Info(MF->getSubtarget());
107   DummyGISelObserver Observer;
108   LegalizerHelper Helper(*MF, Info, Observer, B);
109   // Perform Legalization
110   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
111             Helper.narrowScalar(*CTLZ, 1, LLT::scalar(32)));
112 
113   auto CheckStr = R"(
114   CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64)
115   CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
116   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_HI]]:_(s32), [[ZERO]]:_
117   CHECK: [[CTLZ_LO:%[0-9]+]]:_(s32) = G_CTLZ [[UNMERGE_LO]]:_(s32)
118   CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
119   CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTLZ_LO]]:_, [[THIRTYTWO]]:_
120   CHECK: [[CTLZ_HI:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[UNMERGE_HI]]:_(s32)
121   CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTLZ_HI]]:_
122   )";
123 
124   // Check
125   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
126 }
127 
128 // CTTZ scalar narrowing
129 TEST_F(GISelMITest, NarrowScalarCTTZ) {
130   setUp();
131   if (!TM)
132     return;
133 
134   // Declare your legalization info
135   DefineLegalizerInfo(A, {
136     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s32, s64}});
137   });
138   // Build Instr
139   auto CTTZ =
140       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]});
141   AInfo Info(MF->getSubtarget());
142   DummyGISelObserver Observer;
143   LegalizerHelper Helper(*MF, Info, Observer, B);
144   // Perform Legalization
145   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
146             Helper.narrowScalar(*CTTZ, 1, LLT::scalar(32)));
147 
148   auto CheckStr = R"(
149   CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64)
150   CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
151   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_LO]]:_(s32), [[ZERO]]:_
152   CHECK: [[CTTZ_HI:%[0-9]+]]:_(s32) = G_CTTZ [[UNMERGE_HI]]:_(s32)
153   CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
154   CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTTZ_HI]]:_, [[THIRTYTWO]]:_
155   CHECK: [[CTTZ_LO:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[UNMERGE_LO]]:_(s32)
156   CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTTZ_LO]]:_
157   )";
158 
159   // Check
160   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
161 }
162 
163 // CTTZ expansion in terms of CTPOP
164 TEST_F(GISelMITest, LowerBitCountingCTTZ2) {
165   setUp();
166   if (!TM)
167     return;
168 
169   // Declare your legalization info
170   DefineLegalizerInfo(A, {
171     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}});
172   });
173   // Build
174   auto MIBCTTZ =
175       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
176   AInfo Info(MF->getSubtarget());
177   DummyGISelObserver Observer;
178   LegalizerHelper Helper(*MF, Info, Observer, B);
179   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
180               LegalizerHelper::LegalizeResult::Legalized);
181 
182   auto CheckStr = R"(
183   CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
184   CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
185   CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
186   CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
187   CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
188   )";
189 
190   // Check
191   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
192 }
193 
194 // CTPOP widening.
195 TEST_F(GISelMITest, WidenBitCountingCTPOP1) {
196   if (!TM)
197     return;
198 
199   // Declare your legalization info
200   DefineLegalizerInfo(A, {
201       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
202     });
203 
204   // Build
205   // Trunc it to s8.
206   LLT s8{LLT::scalar(8)};
207   LLT s16{LLT::scalar(16)};
208   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
209   auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc});
210   AInfo Info(MF->getSubtarget());
211   DummyGISelObserver Observer;
212   LegalizerHelper Helper(*MF, Info, Observer, B);
213   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
214             Helper.widenScalar(*MIBCTPOP, 1, s16));
215 
216   auto CheckStr = R"(
217   CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
218   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
219   CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
220   CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16)
221   )";
222 
223   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
224 }
225 
226 // Test a strange case where the result is wider than the source
227 TEST_F(GISelMITest, WidenBitCountingCTPOP2) {
228   if (!TM)
229     return;
230 
231   // Declare your legalization info
232   DefineLegalizerInfo(A, {
233       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}});
234     });
235 
236   // Build
237   // Trunc it to s8.
238   LLT s8{LLT::scalar(8)};
239   LLT s16{LLT::scalar(16)};
240   LLT s32{LLT::scalar(32)};
241   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
242   auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc});
243   AInfo Info(MF->getSubtarget());
244   DummyGISelObserver Observer;
245   LegalizerHelper Helper(*MF, Info, Observer, B);
246   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
247             Helper.widenScalar(*MIBCTPOP, 1, s16));
248 
249   auto CheckStr = R"(
250   CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
251   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
252   CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
253   CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16)
254   )";
255 
256   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
257 }
258 
259 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
260 TEST_F(GISelMITest, LowerBitCountingCTTZ3) {
261   setUp();
262   if (!TM)
263     return;
264 
265   // Declare your legalization info
266   DefineLegalizerInfo(A, {
267     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
268   });
269   // Build
270   auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
271                               {LLT::scalar(64)}, {Copies[0]});
272   AInfo Info(MF->getSubtarget());
273   DummyGISelObserver Observer;
274   LegalizerHelper Helper(*MF, Info, Observer, B);
275   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
276               LegalizerHelper::LegalizeResult::Legalized);
277 
278   auto CheckStr = R"(
279   CHECK: CTTZ
280   )";
281 
282   // Check
283   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
284 }
285 
286 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
287 TEST_F(GISelMITest, LowerBitCountingCTLZ0) {
288   setUp();
289   if (!TM)
290     return;
291 
292   // Declare your legalization info
293   DefineLegalizerInfo(A, {
294     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
295   });
296   // Build
297   auto MIBCTLZ =
298       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
299   AInfo Info(MF->getSubtarget());
300   DummyGISelObserver Observer;
301   LegalizerHelper Helper(*MF, Info, Observer, B);
302   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
303               LegalizerHelper::LegalizeResult::Legalized);
304 
305   auto CheckStr = R"(
306   CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
307   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
308   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
309   CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
310   CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
311   )";
312 
313   // Check
314   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
315 }
316 
317 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall
318 TEST_F(GISelMITest, LowerBitCountingCTLZLibcall) {
319   setUp();
320   if (!TM)
321     return;
322 
323   // Declare your legalization info
324   DefineLegalizerInfo(A, {
325     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s32, s64}});
326   });
327   // Build
328   auto MIBCTLZ =
329       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]});
330   AInfo Info(MF->getSubtarget());
331   DummyGISelObserver Observer;
332   LegalizerHelper Helper(*MF, Info, Observer, B);
333   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
334             Helper.lower(*MIBCTLZ, 0, LLT::scalar(32)));
335 
336   auto CheckStr = R"(
337   CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF %0
338   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
339   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
340   CHECK: [[THIRTY2:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
341   CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]]
342   )";
343 
344   // Check
345   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
346 }
347 
348 // CTLZ expansion
349 TEST_F(GISelMITest, LowerBitCountingCTLZ1) {
350   setUp();
351   if (!TM)
352     return;
353 
354   // Declare your legalization info
355   DefineLegalizerInfo(A, {
356     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
357   });
358   // Build
359   // Trunc it to s8.
360   LLT s8{LLT::scalar(8)};
361   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
362   auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
363   AInfo Info(MF->getSubtarget());
364   DummyGISelObserver Observer;
365   LegalizerHelper Helper(*MF, Info, Observer, B);
366   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
367               LegalizerHelper::LegalizeResult::Legalized);
368 
369   auto CheckStr = R"(
370   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
371   CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
372   CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
373   CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
374   CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
375   CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
376   CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
377   CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
378   CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
379   CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
380   CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
381   CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
382   CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
383   )";
384 
385   // Check
386   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
387 }
388 
389 // CTLZ widening.
390 TEST_F(GISelMITest, WidenBitCountingCTLZ) {
391   setUp();
392   if (!TM)
393     return;
394 
395   // Declare your legalization info
396   DefineLegalizerInfo(A, {
397     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
398   });
399   // Build
400   // Trunc it to s8.
401   LLT s8{LLT::scalar(8)};
402   LLT s16{LLT::scalar(16)};
403   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
404   auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
405   AInfo Info(MF->getSubtarget());
406   DummyGISelObserver Observer;
407   LegalizerHelper Helper(*MF, Info, Observer, B);
408   EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) ==
409               LegalizerHelper::LegalizeResult::Legalized);
410 
411   auto CheckStr = R"(
412   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
413   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
414   CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
415   CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
416   CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
417   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
418   )";
419 
420   // Check
421   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
422 }
423 
424 // CTLZ_ZERO_UNDEF widening.
425 TEST_F(GISelMITest, WidenBitCountingCTLZZeroUndef) {
426   setUp();
427   if (!TM)
428     return;
429 
430   // Declare your legalization info
431   DefineLegalizerInfo(A, {
432     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
433   });
434   // Build
435   // Trunc it to s8.
436   LLT s8{LLT::scalar(8)};
437   LLT s16{LLT::scalar(16)};
438   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
439   auto MIBCTLZ_ZU =
440       B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc});
441   AInfo Info(MF->getSubtarget());
442   DummyGISelObserver Observer;
443   LegalizerHelper Helper(*MF, Info, Observer, B);
444   EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) ==
445               LegalizerHelper::LegalizeResult::Legalized);
446 
447   auto CheckStr = R"(
448   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
449   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
450   CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
451   CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
452   CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
453   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
454   )";
455 
456   // Check
457   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
458 }
459 
460 // CTPOP widening.
461 TEST_F(GISelMITest, WidenBitCountingCTPOP) {
462   setUp();
463   if (!TM)
464     return;
465 
466   // Declare your legalization info
467   DefineLegalizerInfo(A, {
468     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
469   });
470   // Build
471   // Trunc it to s8.
472   LLT s8{LLT::scalar(8)};
473   LLT s16{LLT::scalar(16)};
474   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
475   auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc});
476   AInfo Info(MF->getSubtarget());
477   DummyGISelObserver Observer;
478   LegalizerHelper Helper(*MF, Info, Observer, B);
479   EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) ==
480               LegalizerHelper::LegalizeResult::Legalized);
481 
482   auto CheckStr = R"(
483   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
484   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
485   CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
486   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
487   )";
488 
489   // Check
490   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
491 }
492 
493 // CTTZ_ZERO_UNDEF widening.
494 TEST_F(GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
495   setUp();
496   if (!TM)
497     return;
498 
499   // Declare your legalization info
500   DefineLegalizerInfo(A, {
501     getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
502   });
503   // Build
504   // Trunc it to s8.
505   LLT s8{LLT::scalar(8)};
506   LLT s16{LLT::scalar(16)};
507   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
508   auto MIBCTTZ_ZERO_UNDEF =
509       B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc});
510   AInfo Info(MF->getSubtarget());
511   DummyGISelObserver Observer;
512   LegalizerHelper Helper(*MF, Info, Observer, B);
513   EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) ==
514               LegalizerHelper::LegalizeResult::Legalized);
515 
516   auto CheckStr = R"(
517   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
518   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
519   CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
520   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
521   )";
522 
523   // Check
524   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
525 }
526 
527 // CTTZ widening.
528 TEST_F(GISelMITest, WidenBitCountingCTTZ) {
529   setUp();
530   if (!TM)
531     return;
532 
533   // Declare your legalization info
534   DefineLegalizerInfo(A, {
535     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
536   });
537   // Build
538   // Trunc it to s8.
539   LLT s8{LLT::scalar(8)};
540   LLT s16{LLT::scalar(16)};
541   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
542   auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc});
543   AInfo Info(MF->getSubtarget());
544   DummyGISelObserver Observer;
545   LegalizerHelper Helper(*MF, Info, Observer, B);
546   EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) ==
547               LegalizerHelper::LegalizeResult::Legalized);
548 
549   auto CheckStr = R"(
550   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
551   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
552   CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
553   CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
554   CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
555   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
556   )";
557 
558   // Check
559   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
560 }
561 // UADDO widening.
562 TEST_F(GISelMITest, WidenUADDO) {
563   setUp();
564   if (!TM)
565     return;
566 
567   // Declare your legalization info
568   DefineLegalizerInfo(A, {
569     getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
570   });
571   // Build
572   // Trunc it to s8.
573   LLT s8{LLT::scalar(8)};
574   LLT s16{LLT::scalar(16)};
575   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
576   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
577   auto MIBUAddO =
578       B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
579   AInfo Info(MF->getSubtarget());
580   DummyGISelObserver Observer;
581   LegalizerHelper Helper(*MF, Info, Observer, B);
582   EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
583               LegalizerHelper::LegalizeResult::Legalized);
584 
585   auto CheckStr = R"(
586   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
587   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
588   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
589   CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
590   CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
591   CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_
592   CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_
593   CHECK: G_TRUNC [[ADD]]
594   )";
595 
596   // Check
597   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
598 }
599 
600 // USUBO widening.
601 TEST_F(GISelMITest, WidenUSUBO) {
602   setUp();
603   if (!TM)
604     return;
605 
606   // Declare your legalization info
607   DefineLegalizerInfo(A, {
608     getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
609   });
610   // Build
611   // Trunc it to s8.
612   LLT s8{LLT::scalar(8)};
613   LLT s16{LLT::scalar(16)};
614   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
615   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
616   auto MIBUSUBO =
617       B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
618   AInfo Info(MF->getSubtarget());
619   DummyGISelObserver Observer;
620   LegalizerHelper Helper(*MF, Info, Observer, B);
621   EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
622               LegalizerHelper::LegalizeResult::Legalized);
623 
624   auto CheckStr = R"(
625   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
626   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
627   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
628   CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
629   CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
630   CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_
631   CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_
632   CHECK: G_TRUNC [[SUB]]
633   )";
634 
635   // Check
636   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
637 }
638 
639 TEST_F(GISelMITest, FewerElementsAnd) {
640   if (!TM)
641     return;
642 
643   const LLT V2S32 = LLT::vector(2, 32);
644   const LLT V5S32 = LLT::vector(5, 32);
645 
646   // Declare your legalization info
647   DefineLegalizerInfo(A, {
648     getActionDefinitionsBuilder(G_AND)
649       .legalFor({s32});
650   });
651 
652   auto Op0 = B.buildUndef(V5S32);
653   auto Op1 = B.buildUndef(V5S32);
654   auto And = B.buildAnd(V5S32, Op0, Op1);
655 
656   AInfo Info(MF->getSubtarget());
657   DummyGISelObserver Observer;
658   LegalizerHelper Helper(*MF, Info, Observer, B);
659   EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) ==
660               LegalizerHelper::LegalizeResult::Legalized);
661 
662   auto CheckStr = R"(
663   CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
664   CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
665   CHECK: [[IMP_DEF2:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
666   CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 0
667   CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 0
668   CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT0]]:_, [[EXTRACT1]]:_
669   CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[IMP_DEF2]]:_, [[AND0]]:_(<2 x s32>), 0
670 
671   CHECK: [[EXTRACT2:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 64
672   CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 64
673   CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT2]]:_, [[EXTRACT3]]:_
674   CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[AND1]]:_(<2 x s32>), 64
675 
676   CHECK: [[EXTRACT4:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 128
677   CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 128
678   CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[EXTRACT4]]:_, [[EXTRACT5]]:_
679   CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[AND2]]:_(s32), 128
680   )";
681 
682   // Check
683   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
684 }
685 
686 TEST_F(GISelMITest, MoreElementsAnd) {
687   if (!TM)
688     return;
689 
690   LLT s32 = LLT::scalar(32);
691   LLT v2s32 = LLT::vector(2, 32);
692   LLT v6s32 = LLT::vector(6, 32);
693 
694   LegalizerInfo LI;
695   LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
696     .legalFor({v6s32})
697     .clampMinNumElements(0, s32, 6);
698   LI.computeTables();
699 
700   DummyGISelObserver Observer;
701   LegalizerHelper Helper(*MF, LI, Observer, B);
702 
703   B.setInsertPt(*EntryMBB, EntryMBB->end());
704 
705   auto Val0 = B.buildBitcast(v2s32, Copies[0]);
706   auto Val1 = B.buildBitcast(v2s32, Copies[1]);
707 
708   auto And = B.buildAnd(v2s32, Val0, Val1);
709 
710   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
711             Helper.moreElementsVector(*And, 0, v6s32));
712 
713   auto CheckStr = R"(
714   CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
715   CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
716   CHECK: [[IMP_DEF0:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
717   CHECK: [[CONCAT0:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>)
718   CHECK: [[IMP_DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
719   CHECK: [[CONCAT1:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>)
720   CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[CONCAT0]]:_, [[CONCAT1]]:_
721   CHECK: (<2 x s32>) = G_EXTRACT [[AND]]:_(<6 x s32>), 0
722   )";
723 
724   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
725 }
726 
727 TEST_F(GISelMITest, FewerElementsPhi) {
728   if (!TM)
729     return;
730 
731   LLT s1 = LLT::scalar(1);
732   LLT s32 = LLT::scalar(32);
733   LLT s64 = LLT::scalar(64);
734   LLT v2s32 = LLT::vector(2, 32);
735   LLT v5s32 = LLT::vector(5, 32);
736 
737   LegalizerInfo LI;
738   LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
739     .legalFor({v2s32})
740     .clampMinNumElements(0, s32, 2);
741   LI.computeTables();
742 
743   LLT PhiTy = v5s32;
744   DummyGISelObserver Observer;
745   LegalizerHelper Helper(*MF, LI, Observer, B);
746   B.setMBB(*EntryMBB);
747 
748   MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock();
749   MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock();
750   MF->insert(MF->end(), MidMBB);
751   MF->insert(MF->end(), EndMBB);
752 
753   EntryMBB->addSuccessor(MidMBB);
754   EntryMBB->addSuccessor(EndMBB);
755   MidMBB->addSuccessor(EndMBB);
756 
757   auto InitVal = B.buildUndef(PhiTy);
758   auto InitOtherVal = B.buildConstant(s64, 999);
759 
760   auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
761   B.buildBrCond(ICmp.getReg(0), *MidMBB);
762   B.buildBr(*EndMBB);
763 
764 
765   B.setMBB(*MidMBB);
766   auto MidVal = B.buildUndef(PhiTy);
767   auto MidOtherVal = B.buildConstant(s64, 345);
768   B.buildBr(*EndMBB);
769 
770   B.setMBB(*EndMBB);
771   auto Phi = B.buildInstr(TargetOpcode::G_PHI)
772     .addDef(MRI->createGenericVirtualRegister(PhiTy))
773     .addUse(InitVal.getReg(0))
774     .addMBB(EntryMBB)
775     .addUse(MidVal.getReg(0))
776     .addMBB(MidMBB);
777 
778   // Insert another irrelevant phi to make sure the rebuild is inserted after
779   // it.
780   B.buildInstr(TargetOpcode::G_PHI)
781     .addDef(MRI->createGenericVirtualRegister(s64))
782     .addUse(InitOtherVal.getReg(0))
783     .addMBB(EntryMBB)
784     .addUse(MidOtherVal.getReg(0))
785     .addMBB(MidMBB);
786 
787   // Add some use instruction after the phis.
788   B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0));
789 
790   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
791             Helper.fewerElementsVector(*Phi, 0, v2s32));
792 
793   auto CheckStr = R"(
794   CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
795   CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 0
796   CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 64
797   CHECK: [[EXTRACT2:%[0-9]+]]:_(s32) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 128
798   CHECK: G_BRCOND
799 
800   CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
801   CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 0
802   CHECK: [[EXTRACT4:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 64
803   CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 128
804   CHECK: G_BR
805 
806   CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT0]]:_(<2 x s32>), %bb.0, [[EXTRACT3]]:_(<2 x s32>), %bb.1
807   CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT1]]:_(<2 x s32>), %bb.0, [[EXTRACT4]]:_(<2 x s32>), %bb.1
808   CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[EXTRACT2]]:_(s32), %bb.0, [[EXTRACT5]]:_(s32), %bb.1
809 
810   CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI
811   CHECK: [[REBUILD_VAL_IMPDEF:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
812   CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[REBUILD_VAL_IMPDEF]]:_, [[PHI0]]:_(<2 x s32>), 0
813   CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[PHI1]]:_(<2 x s32>), 64
814   CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[PHI2]]:_(s32), 128
815   CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[INSERT2]]:_, [[INSERT2]]:_
816   )";
817 
818   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
819 }
820 
821 // FNEG expansion in terms of FSUB
822 TEST_F(GISelMITest, LowerFNEG) {
823   if (!TM)
824     return;
825 
826   // Declare your legalization info
827   DefineLegalizerInfo(A, {
828     getActionDefinitionsBuilder(G_FSUB).legalFor({s64});
829   });
830 
831   // Build Instr. Make sure FMF are preserved.
832   auto FAdd =
833     B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]},
834                  MachineInstr::MIFlag::FmNsz);
835 
836   // Should not propagate the flags of src instruction.
837   auto FNeg0 =
838     B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)},
839                  {MachineInstr::MIFlag::FmArcp});
840 
841   // Preserve the one flag.
842   auto FNeg1 =
843     B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]},
844                  MachineInstr::MIFlag::FmNoInfs);
845 
846   AInfo Info(MF->getSubtarget());
847   DummyGISelObserver Observer;
848   LegalizerHelper Helper(*MF, Info, Observer, B);
849   // Perform Legalization
850   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
851             Helper.lower(*FNeg0, 0, LLT::scalar(64)));
852   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
853             Helper.lower(*FNeg1, 0, LLT::scalar(64)));
854 
855   auto CheckStr = R"(
856   CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_
857   CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
858   CHECK: [[FSUB0:%[0-9]+]]:_(s64) = arcp G_FSUB [[CONST0]]:_, [[FADD]]:_
859   CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
860   CHECK: [[FSUB1:%[0-9]+]]:_(s64) = ninf G_FSUB [[CONST1]]:_, %0:_
861   )";
862 
863   // Check
864   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
865 }
866 
867 TEST_F(GISelMITest, LowerMinMax) {
868   if (!TM)
869     return;
870 
871   LLT s64 = LLT::scalar(64);
872   LLT v2s32 = LLT::vector(2, 32);
873 
874   DefineLegalizerInfo(A, {
875     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
876       .lowerFor({s64, LLT::vector(2, s32)});
877   });
878 
879   auto SMin = B.buildSMin(s64, Copies[0], Copies[1]);
880   auto SMax = B.buildSMax(s64, Copies[0], Copies[1]);
881   auto UMin = B.buildUMin(s64, Copies[0], Copies[1]);
882   auto UMax = B.buildUMax(s64, Copies[0], Copies[1]);
883 
884   auto VecVal0 = B.buildBitcast(v2s32, Copies[0]);
885   auto VecVal1 = B.buildBitcast(v2s32, Copies[1]);
886 
887   auto SMinV = B.buildSMin(v2s32, VecVal0, VecVal1);
888   auto SMaxV = B.buildSMax(v2s32, VecVal0, VecVal1);
889   auto UMinV = B.buildUMin(v2s32, VecVal0, VecVal1);
890   auto UMaxV = B.buildUMax(v2s32, VecVal0, VecVal1);
891 
892   AInfo Info(MF->getSubtarget());
893   DummyGISelObserver Observer;
894   LegalizerHelper Helper(*MF, Info, Observer, B);
895   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
896             Helper.lower(*SMin, 0, s64));
897   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
898             Helper.lower(*SMax, 0, s64));
899   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
900             Helper.lower(*UMin, 0, s64));
901   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
902             Helper.lower(*UMax, 0, s64));
903 
904   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
905             Helper.lower(*SMinV, 0, v2s32));
906   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
907             Helper.lower(*SMaxV, 0, v2s32));
908   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
909             Helper.lower(*UMinV, 0, v2s32));
910   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
911             Helper.lower(*UMaxV, 0, v2s32));
912 
913   auto CheckStr = R"(
914   CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_
915   CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_
916 
917   CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_
918   CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_
919 
920   CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_
921   CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_
922 
923   CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_
924   CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_
925 
926   CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
927   CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
928 
929   CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
930   CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
931 
932   CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
933   CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
934 
935   CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
936   CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
937 
938   CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
939   CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
940   )";
941 
942   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
943 }
944 
945 TEST_F(GISelMITest, WidenScalarBuildVector) {
946   if (!TM)
947     return;
948 
949   LLT S32 = LLT::scalar(32);
950   LLT S16 = LLT::scalar(16);
951   LLT V2S16 = LLT::vector(2, S16);
952   LLT V2S32 = LLT::vector(2, S32);
953 
954   DefineLegalizerInfo(A, {
955     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
956       .lowerFor({s64, LLT::vector(2, s32)});
957   });
958 
959   AInfo Info(MF->getSubtarget());
960   DummyGISelObserver Observer;
961   LegalizerHelper Helper(*MF, Info, Observer, B);
962   B.setInsertPt(*EntryMBB, EntryMBB->end());
963 
964   Register Constant0 = B.buildConstant(S16, 1).getReg(0);
965   Register Constant1 = B.buildConstant(S16, 2).getReg(0);
966   auto BV0 = B.buildBuildVector(V2S16, {Constant0, Constant1});
967   auto BV1 = B.buildBuildVector(V2S16, {Constant0, Constant1});
968 
969   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
970             Helper.widenScalar(*BV0, 0, V2S32));
971   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
972             Helper.widenScalar(*BV1, 1, S32));
973 
974   auto CheckStr = R"(
975   CHECK: [[K0:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
976   CHECK-NEXT: [[K1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
977   CHECK-NEXT: [[EXT_K0_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
978   CHECK-NEXT: [[EXT_K1_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
979   CHECK-NEXT: [[BV0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[EXT_K0_0]]:_(s32), [[EXT_K1_0]]:_(s32)
980   CHECK-NEXT: [[BV0_TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BV0]]
981 
982   CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
983   CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
984 
985   CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32)
986   )";
987 
988   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
989 }
990 
991 TEST_F(GISelMITest, LowerMergeValues) {
992   if (!TM)
993     return;
994 
995   const LLT S32 = LLT::scalar(32);
996   const LLT S24 = LLT::scalar(24);
997   const LLT S21 = LLT::scalar(21);
998   const LLT S16 = LLT::scalar(16);
999   const LLT S9 = LLT::scalar(9);
1000   const LLT S8 = LLT::scalar(8);
1001   const LLT S3 = LLT::scalar(3);
1002 
1003   DefineLegalizerInfo(A, {
1004     getActionDefinitionsBuilder(G_UNMERGE_VALUES)
1005       .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9)));
1006   });
1007 
1008   AInfo Info(MF->getSubtarget());
1009   DummyGISelObserver Observer;
1010   LegalizerHelper Helper(*MF, Info, Observer, B);
1011   B.setInsertPt(*EntryMBB, EntryMBB->end());
1012 
1013   // 24 = 3 3 3   3 3 3   3 3
1014   //     => 9
1015   //
1016   // This can do 3 merges, but need an extra implicit_def.
1017   SmallVector<Register, 8> Merge0Ops;
1018   for (int I = 0; I != 8; ++I)
1019     Merge0Ops.push_back(B.buildConstant(S3, I).getReg(0));
1020 
1021   auto Merge0 = B.buildMerge(S24, Merge0Ops);
1022 
1023   // 21 = 3 3 3   3 3 3   3
1024   //     => 9, 2 extra implicit_def needed
1025   //
1026   SmallVector<Register, 8> Merge1Ops;
1027   for (int I = 0; I != 7; ++I)
1028     Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0));
1029 
1030   auto Merge1 = B.buildMerge(S21, Merge1Ops);
1031 
1032   SmallVector<Register, 8> Merge2Ops;
1033   for (int I = 0; I != 2; ++I)
1034     Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0));
1035 
1036   auto Merge2 = B.buildMerge(S16, Merge2Ops);
1037 
1038   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1039             Helper.widenScalar(*Merge0, 1, S9));
1040   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1041             Helper.widenScalar(*Merge1, 1, S9));
1042 
1043   // Request a source size greater than the original destination size.
1044   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1045             Helper.widenScalar(*Merge2, 1, S32));
1046 
1047   auto CheckStr = R"(
1048   CHECK: [[K0:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
1049   CHECK-NEXT: [[K1:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
1050   CHECK-NEXT: [[K2:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
1051   CHECK-NEXT: [[K3:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
1052   CHECK-NEXT: [[K4:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
1053   CHECK-NEXT: [[K5:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1054   CHECK-NEXT: [[K6:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1055   CHECK-NEXT: [[K7:%[0-9]+]]:_(s3) = G_CONSTANT i3 -1
1056   CHECK-NEXT: [[IMPDEF0:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1057   CHECK-NEXT: [[MERGE0:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K0]]:_(s3), [[K1]]:_(s3), [[K2]]:_(s3)
1058   CHECK-NEXT: [[MERGE1:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K3]]:_(s3), [[K4]]:_(s3), [[K5]]:_(s3)
1059   CHECK-NEXT: [[MERGE2:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K6]]:_(s3), [[K7]]:_(s3), [[IMPDEF0]]:_(s3)
1060   CHECK-NEXT: [[MERGE3:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE0]]:_(s9), [[MERGE1]]:_(s9), [[MERGE2]]:_(s9)
1061   CHECK-NEXT: (s24) = G_TRUNC [[MERGE3]]:_(s27)
1062 
1063 
1064   CHECK: [[K8:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
1065   CHECK-NEXT: [[K9:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
1066   CHECK-NEXT: [[K10:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
1067   CHECK-NEXT: [[K11:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
1068   CHECK-NEXT: [[K12:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
1069   CHECK-NEXT: [[K13:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1070   CHECK-NEXT: [[K14:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1071   CHECK-NEXT: [[IMPDEF1:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1072   CHECK-NEXT: [[MERGE4:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K8]]:_(s3), [[K9]]:_(s3), [[K10]]:_(s3)
1073   CHECK-NEXT: [[MERGE5:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K11]]:_(s3), [[K12]]:_(s3), [[K13]]:_(s3)
1074   CHECK-NEXT: [[MERGE6:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K14]]:_(s3), [[IMPDEF1]]:_(s3), [[IMPDEF1]]:_(s3)
1075   CHECK-NEXT: [[MERGE7:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE4]]:_(s9), [[MERGE5]]:_(s9), [[MERGE6]]:_(s9)
1076   CHECK-NEXT: (s21) = G_TRUNC [[MERGE7]]:_(s27)
1077 
1078 
1079   CHECK: [[K15:%[0-9]+]]:_(s8) = G_CONSTANT i8 0
1080   CHECK-NEXT: [[K16:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
1081   CHECK-NEXT: [[ZEXT_K15:[0-9]+]]:_(s32) = G_ZEXT [[K15]]:_(s8)
1082   CHECK-NEXT: [[ZEXT_K16:[0-9]+]]:_(s32) = G_ZEXT [[K16]]:_(s8)
1083   [[K16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1084   [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT_K16]]:_, [[K16]]:_(s32)
1085   [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT_K16]]:_, [[SHL]]:_
1086   (s16) = G_TRUNC [[OR]]:_(s32)
1087   )";
1088 
1089   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1090 }
1091 
1092 TEST_F(GISelMITest, WidenScalarMergeValuesPointer) {
1093   if (!TM)
1094     return;
1095 
1096   DefineLegalizerInfo(A, {});
1097 
1098   AInfo Info(MF->getSubtarget());
1099   DummyGISelObserver Observer;
1100   LegalizerHelper Helper(*MF, Info, Observer, B);
1101   B.setInsertPt(*EntryMBB, EntryMBB->end());
1102 
1103   const LLT S32 = LLT::scalar(32);
1104   const LLT S64 = LLT::scalar(64);
1105   const LLT P0 = LLT::pointer(0, 64);
1106 
1107   auto Lo = B.buildTrunc(S32, Copies[0]);
1108   auto Hi = B.buildTrunc(S32, Copies[1]);
1109 
1110   auto Merge = B.buildMerge(P0, {Lo, Hi});
1111 
1112   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1113             Helper.widenScalar(*Merge, 1, S64));
1114 
1115   auto CheckStr = R"(
1116    CHECK: [[TRUNC0:%[0-9]+]]:_(s32) = G_TRUNC
1117    CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC
1118    CHECK: [[ZEXT_TRUNC0:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC0]]
1119    CHECK: [[ZEXT_TRUNC1:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC1]]
1120    CHECK: [[SHIFT_AMT:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
1121    CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT_TRUNC1]]:_, [[SHIFT_AMT]]
1122    CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[ZEXT_TRUNC0]]:_, [[SHL]]
1123    CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]:_(s64)
1124   )";
1125 
1126   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1127 }
1128 
1129 TEST_F(GISelMITest, WidenSEXTINREG) {
1130   if (!TM)
1131     return;
1132 
1133   // Declare your legalization info
1134   DefineLegalizerInfo(A, {
1135     getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1136   });
1137   // Build Instr
1138   auto MIB = B.buildInstr(
1139       TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1140       {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1141        uint64_t(8)});
1142   AInfo Info(MF->getSubtarget());
1143   DummyGISelObserver Observer;
1144   LegalizerHelper Helper(*MF, Info, Observer, B);
1145   // Perform Legalization
1146   ASSERT_TRUE(Helper.widenScalar(*MIB, 0, LLT::scalar(64)) ==
1147               LegalizerHelper::LegalizeResult::Legalized);
1148 
1149   auto CheckStr = R"(
1150   CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1151   CHECK: [[T1:%[0-9]+]]:_(s64) = G_ANYEXT [[T0]]:_(s32)
1152   CHECK: [[T2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[T1]]:_, 8
1153   CHECK: [[T3:%[0-9]+]]:_(s32) = G_TRUNC [[T2]]:_(s64)
1154   )";
1155 
1156   // Check
1157   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1158 }
1159 
1160 TEST_F(GISelMITest, NarrowSEXTINREG) {
1161   if (!TM)
1162     return;
1163 
1164   // Declare your legalization info, these aren't actually relevant to the test.
1165   DefineLegalizerInfo(A, {
1166     getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1167   });
1168   // Build Instr
1169   auto MIB = B.buildInstr(
1170       TargetOpcode::G_SEXT_INREG, {LLT::scalar(16)},
1171       {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(16)}, {Copies[0]}),
1172        uint64_t(8)});
1173   AInfo Info(MF->getSubtarget());
1174   DummyGISelObserver Observer;
1175   LegalizerHelper Helper(*MF, Info, Observer, B);
1176   // Perform Legalization
1177   ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(10)) ==
1178               LegalizerHelper::LegalizeResult::Legalized);
1179 
1180   auto CheckStr = R"(
1181   CHECK: [[T0:%[0-9]+]]:_(s16) = G_TRUNC
1182   CHECK: [[T1:%[0-9]+]]:_(s10) = G_TRUNC [[T0]]:_(s16)
1183   CHECK: [[T2:%[0-9]+]]:_(s10) = G_SEXT_INREG [[T1]]:_, 8
1184   CHECK: [[T3:%[0-9]+]]:_(s16) = G_SEXT [[T2]]:_(s10)
1185   )";
1186 
1187   // Check
1188   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1189 }
1190 
1191 TEST_F(GISelMITest, NarrowSEXTINREG2) {
1192   if (!TM)
1193     return;
1194 
1195   // Declare your legalization info, these aren't actually relevant to the test.
1196   DefineLegalizerInfo(
1197       A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
1198   // Build Instr
1199   auto MIB = B.buildInstr(
1200       TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1201       {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1202        uint64_t(9)});
1203   AInfo Info(MF->getSubtarget());
1204   DummyGISelObserver Observer;
1205   LegalizerHelper Helper(*MF, Info, Observer, B);
1206   // Perform Legalization
1207   ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(8)) ==
1208               LegalizerHelper::LegalizeResult::Legalized);
1209 
1210   auto CheckStr = R"(
1211   CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1212   CHECK: [[T1:%[0-9]+]]:_(s8), [[T2:%[0-9]+]]:_(s8), [[T3:%[0-9]+]]:_(s8), [[T4:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[T0]]:_(s32)
1213   CHECK: [[CST2:%[0-9]+]]:_(s8) = G_CONSTANT i8 7
1214   CHECK: [[T5:%[0-9]+]]:_(s8) = G_SEXT_INREG [[T2]]:_, 1
1215   CHECK: [[T6:%[0-9]+]]:_(s8) = G_ASHR [[T5]]:_, [[CST2]]:_
1216   CHECK: [[T7:%[0-9]+]]:_(s32) = G_MERGE_VALUES [[T1]]:_(s8), [[T5]]:_(s8), [[T6]]:_(s8), [[T6]]:_(s8)
1217   )";
1218 
1219   // Check
1220   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1221 }
1222 
1223 TEST_F(GISelMITest, LowerSEXTINREG) {
1224   if (!TM)
1225     return;
1226 
1227   // Declare your legalization info, these aren't actually relevant to the test.
1228   DefineLegalizerInfo(
1229       A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
1230   // Build Instr
1231   auto MIB = B.buildInstr(
1232       TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1233       {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1234        uint64_t(8)});
1235   AInfo Info(MF->getSubtarget());
1236   DummyGISelObserver Observer;
1237   LegalizerHelper Helper(*MF, Info, Observer, B);
1238   // Perform Legalization
1239   ASSERT_TRUE(Helper.lower(*MIB, 0, LLT()) ==
1240               LegalizerHelper::LegalizeResult::Legalized);
1241 
1242   auto CheckStr = R"(
1243   CHECK: [[T1:%[0-9]+]]:_(s32) = G_TRUNC
1244   CHECK: [[CST:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
1245   CHECK: [[T2:%[0-9]+]]:_(s32) = G_SHL [[T1]]:_, [[CST]]:_
1246   CHECK: [[T3:%[0-9]+]]:_(s32) = G_ASHR [[T2]]:_, [[CST]]:_
1247   )";
1248 
1249   // Check
1250   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1251 }
1252 
1253 TEST_F(GISelMITest, LibcallFPExt) {
1254   setUp();
1255   if (!TM)
1256     return;
1257 
1258   // Declare your legalization info
1259   DefineLegalizerInfo(A, {
1260     getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s32, s16}, {s128, s64}});
1261   });
1262 
1263   LLT S16{LLT::scalar(16)};
1264   LLT S32{LLT::scalar(32)};
1265   LLT S128{LLT::scalar(128)};
1266   auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
1267   auto MIBFPExt1 =
1268       B.buildInstr(TargetOpcode::G_FPEXT, {S32}, {MIBTrunc});
1269 
1270   auto MIBFPExt2 =
1271       B.buildInstr(TargetOpcode::G_FPEXT, {S128}, {Copies[1]});
1272   AInfo Info(MF->getSubtarget());
1273   DummyGISelObserver Observer;
1274   LegalizerHelper Helper(*MF, Info, Observer, B);
1275   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1276               Helper.libcall(*MIBFPExt1));
1277 
1278   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1279               Helper.libcall(*MIBFPExt2));
1280   auto CheckStr = R"(
1281   CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC
1282   CHECK: $h0 = COPY [[TRUNC]]
1283   CHECK: BL &__gnu_h2f_ieee
1284   CHECK: $d0 = COPY
1285   CHECK: BL &__extenddftf2
1286   )";
1287 
1288   // Check
1289   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1290 }
1291 
1292 TEST_F(GISelMITest, LibcallFPTrunc) {
1293   setUp();
1294   if (!TM)
1295     return;
1296 
1297   // Declare your legalization info
1298   DefineLegalizerInfo(A, {
1299     getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s16, s32}, {s64, s128}});
1300   });
1301 
1302   LLT S16{LLT::scalar(16)};
1303   LLT S32{LLT::scalar(32)};
1304   LLT S64{LLT::scalar(64)};
1305   LLT S128{LLT::scalar(128)};
1306   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
1307   auto MIBFPTrunc1 =
1308       B.buildInstr(TargetOpcode::G_FPTRUNC, {S16}, {MIBTrunc});
1309 
1310   auto MIBMerge = B.buildMerge(S128, {Copies[1], Copies[2]});
1311 
1312   auto MIBFPTrunc2 =
1313       B.buildInstr(TargetOpcode::G_FPTRUNC, {S64}, {MIBMerge});
1314   AInfo Info(MF->getSubtarget());
1315   DummyGISelObserver Observer;
1316   LegalizerHelper Helper(*MF, Info, Observer, B);
1317   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1318             Helper.libcall(*MIBFPTrunc1));
1319 
1320   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1321             Helper.libcall(*MIBFPTrunc2));
1322   auto CheckStr = R"(
1323   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
1324   CHECK: $s0 = COPY [[TRUNC]]
1325   CHECK: BL &__gnu_f2h_ieee
1326   CHECK: $q0 = COPY
1327   CHECK: BL &__trunctfdf2
1328   )";
1329 
1330   // Check
1331   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1332 }
1333 
1334 TEST_F(GISelMITest, LibcallSimple) {
1335   setUp();
1336   if (!TM)
1337     return;
1338 
1339   // Declare your legalization info
1340   DefineLegalizerInfo(A, {
1341     getActionDefinitionsBuilder(G_FADD).libcallFor({s16});
1342   });
1343 
1344   LLT S16{LLT::scalar(16)};
1345   auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
1346   auto MIBFADD =
1347       B.buildInstr(TargetOpcode::G_FADD, {S16}, {MIBTrunc, MIBTrunc});
1348 
1349   AInfo Info(MF->getSubtarget());
1350   DummyGISelObserver Observer;
1351   LegalizerHelper Helper(*MF, Info, Observer, B);
1352   // Make sure we do not crash anymore
1353   EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
1354             Helper.libcall(*MIBFADD));
1355 }
1356 } // namespace
1357