xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp (revision 5a321b899e7a10b45c3ee4003fb2a048f35074a9)
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 namespace {
13 
14 class DummyGISelObserver : public GISelChangeObserver {
15 public:
16   void changingInstr(MachineInstr &MI) override {}
17   void changedInstr(MachineInstr &MI) override {}
18   void createdInstr(MachineInstr &MI) override {}
19   void erasingInstr(MachineInstr &MI) override {}
20 };
21 
22 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom,
23 // in which case it becomes CTTZ_ZERO_UNDEF with select.
24 TEST_F(GISelMITest, LowerBitCountingCTTZ0) {
25   if (!TM)
26     return;
27 
28   // Declare your legalization info
29   DefineLegalizerInfo(A, {
30     getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s64, s64}});
31   });
32   // Build Instr
33   auto MIBCTTZ =
34       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
35   AInfo Info(MF->getSubtarget());
36   DummyGISelObserver Observer;
37   LegalizerHelper Helper(*MF, Info, Observer, B);
38   // Perform Legalization
39   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
40               LegalizerHelper::LegalizeResult::Legalized);
41 
42   auto CheckStr = R"(
43   CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF %0
44   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
45   CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
46   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
47   CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
48   )";
49 
50   // Check
51   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
52 }
53 
54 // CTTZ expansion in terms of CTLZ
55 TEST_F(GISelMITest, LowerBitCountingCTTZ1) {
56   if (!TM)
57     return;
58 
59   // Declare your legalization info
60   DefineLegalizerInfo(A, {
61     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}});
62   });
63   // Build Instr
64   auto MIBCTTZ =
65       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
66   AInfo Info(MF->getSubtarget());
67   DummyGISelObserver Observer;
68   LegalizerHelper Helper(*MF, Info, Observer, B);
69   // Perform Legalization
70   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
71               LegalizerHelper::LegalizeResult::Legalized);
72 
73   auto CheckStr = R"(
74   CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
75   CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
76   CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
77   CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
78   CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
79   CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_
80   CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_
81   )";
82 
83   // Check
84   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
85 }
86 
87 // CTTZ expansion in terms of CTPOP
88 TEST_F(GISelMITest, LowerBitCountingCTTZ2) {
89   if (!TM)
90     return;
91 
92   // Declare your legalization info
93   DefineLegalizerInfo(A, {
94     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}});
95   });
96   // Build
97   auto MIBCTTZ =
98       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
99   AInfo Info(MF->getSubtarget());
100   DummyGISelObserver Observer;
101   LegalizerHelper Helper(*MF, Info, Observer, B);
102   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
103               LegalizerHelper::LegalizeResult::Legalized);
104 
105   auto CheckStr = R"(
106   CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
107   CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
108   CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
109   CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
110   CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
111   )";
112 
113   // Check
114   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
115 }
116 
117 // CTPOP widening.
118 TEST_F(GISelMITest, WidenBitCountingCTPOP1) {
119   if (!TM)
120     return;
121 
122   // Declare your legalization info
123   DefineLegalizerInfo(A, {
124       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
125     });
126 
127   // Build
128   // Trunc it to s8.
129   LLT s8{LLT::scalar(8)};
130   LLT s16{LLT::scalar(16)};
131   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
132   auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc});
133   AInfo Info(MF->getSubtarget());
134   DummyGISelObserver Observer;
135   LegalizerHelper Helper(*MF, Info, Observer, B);
136   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
137             Helper.widenScalar(*MIBCTPOP, 1, s16));
138 
139   auto CheckStr = R"(
140   CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
141   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
142   CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
143   CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16)
144   )";
145 
146   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
147 }
148 
149 // Test a strange case where the result is wider than the source
150 TEST_F(GISelMITest, WidenBitCountingCTPOP2) {
151   if (!TM)
152     return;
153 
154   // Declare your legalization info
155   DefineLegalizerInfo(A, {
156       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}});
157     });
158 
159   // Build
160   // Trunc it to s8.
161   LLT s8{LLT::scalar(8)};
162   LLT s16{LLT::scalar(16)};
163   LLT s32{LLT::scalar(32)};
164   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
165   auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc});
166   AInfo Info(MF->getSubtarget());
167   DummyGISelObserver Observer;
168   LegalizerHelper Helper(*MF, Info, Observer, B);
169   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
170             Helper.widenScalar(*MIBCTPOP, 1, s16));
171 
172   auto CheckStr = R"(
173   CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
174   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
175   CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
176   CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16)
177   )";
178 
179   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
180 }
181 
182 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
183 TEST_F(GISelMITest, LowerBitCountingCTTZ3) {
184   if (!TM)
185     return;
186 
187   // Declare your legalization info
188   DefineLegalizerInfo(A, {
189     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
190   });
191   // Build
192   auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
193                               {LLT::scalar(64)}, {Copies[0]});
194   AInfo Info(MF->getSubtarget());
195   DummyGISelObserver Observer;
196   LegalizerHelper Helper(*MF, Info, Observer, B);
197   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
198               LegalizerHelper::LegalizeResult::Legalized);
199 
200   auto CheckStr = R"(
201   CHECK: CTTZ
202   )";
203 
204   // Check
205   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
206 }
207 
208 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
209 TEST_F(GISelMITest, LowerBitCountingCTLZ0) {
210   if (!TM)
211     return;
212 
213   // Declare your legalization info
214   DefineLegalizerInfo(A, {
215     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
216   });
217   // Build
218   auto MIBCTLZ =
219       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
220   AInfo Info(MF->getSubtarget());
221   DummyGISelObserver Observer;
222   LegalizerHelper Helper(*MF, Info, Observer, B);
223   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
224               LegalizerHelper::LegalizeResult::Legalized);
225 
226   auto CheckStr = R"(
227   CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
228   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
229   CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
230   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
231   CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
232   )";
233 
234   // Check
235   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
236 }
237 
238 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall
239 TEST_F(GISelMITest, LowerBitCountingCTLZLibcall) {
240   if (!TM)
241     return;
242 
243   // Declare your legalization info
244   DefineLegalizerInfo(A, {
245     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s64, s64}});
246   });
247   // Build
248   auto MIBCTLZ =
249       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
250   AInfo Info(MF->getSubtarget());
251   DummyGISelObserver Observer;
252   LegalizerHelper Helper(*MF, Info, Observer, B);
253   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
254               LegalizerHelper::LegalizeResult::Legalized);
255 
256   auto CheckStr = R"(
257   CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
258   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
259   CHECK: [[THIRTY2:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
260   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
261   CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]]
262   )";
263 
264   // Check
265   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
266 }
267 
268 // CTLZ expansion
269 TEST_F(GISelMITest, LowerBitCountingCTLZ1) {
270   if (!TM)
271     return;
272 
273   // Declare your legalization info
274   DefineLegalizerInfo(A, {
275     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
276   });
277   // Build
278   // Trunc it to s8.
279   LLT s8{LLT::scalar(8)};
280   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
281   auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
282   AInfo Info(MF->getSubtarget());
283   DummyGISelObserver Observer;
284   LegalizerHelper Helper(*MF, Info, Observer, B);
285   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
286               LegalizerHelper::LegalizeResult::Legalized);
287 
288   auto CheckStr = R"(
289   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
290   CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
291   CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
292   CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
293   CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
294   CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
295   CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
296   CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
297   CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
298   CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
299   CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
300   CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
301   CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
302   )";
303 
304   // Check
305   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
306 }
307 
308 // CTLZ widening.
309 TEST_F(GISelMITest, WidenBitCountingCTLZ) {
310   if (!TM)
311     return;
312 
313   // Declare your legalization info
314   DefineLegalizerInfo(A, {
315     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
316   });
317   // Build
318   // Trunc it to s8.
319   LLT s8{LLT::scalar(8)};
320   LLT s16{LLT::scalar(16)};
321   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
322   auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
323   AInfo Info(MF->getSubtarget());
324   DummyGISelObserver Observer;
325   LegalizerHelper Helper(*MF, Info, Observer, B);
326   EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) ==
327               LegalizerHelper::LegalizeResult::Legalized);
328 
329   auto CheckStr = R"(
330   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
331   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
332   CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
333   CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
334   CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
335   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
336   )";
337 
338   // Check
339   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
340 }
341 
342 // CTLZ_ZERO_UNDEF widening.
343 TEST_F(GISelMITest, WidenBitCountingCTLZZeroUndef) {
344   if (!TM)
345     return;
346 
347   // Declare your legalization info
348   DefineLegalizerInfo(A, {
349     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
350   });
351   // Build
352   // Trunc it to s8.
353   LLT s8{LLT::scalar(8)};
354   LLT s16{LLT::scalar(16)};
355   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
356   auto MIBCTLZ_ZU =
357       B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc});
358   AInfo Info(MF->getSubtarget());
359   DummyGISelObserver Observer;
360   LegalizerHelper Helper(*MF, Info, Observer, B);
361   EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) ==
362               LegalizerHelper::LegalizeResult::Legalized);
363 
364   auto CheckStr = R"(
365   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
366   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
367   CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
368   CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
369   CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
370   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
371   )";
372 
373   // Check
374   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
375 }
376 
377 // CTPOP widening.
378 TEST_F(GISelMITest, WidenBitCountingCTPOP) {
379   if (!TM)
380     return;
381 
382   // Declare your legalization info
383   DefineLegalizerInfo(A, {
384     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
385   });
386   // Build
387   // Trunc it to s8.
388   LLT s8{LLT::scalar(8)};
389   LLT s16{LLT::scalar(16)};
390   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
391   auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc});
392   AInfo Info(MF->getSubtarget());
393   DummyGISelObserver Observer;
394   LegalizerHelper Helper(*MF, Info, Observer, B);
395   EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) ==
396               LegalizerHelper::LegalizeResult::Legalized);
397 
398   auto CheckStr = R"(
399   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
400   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
401   CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
402   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
403   )";
404 
405   // Check
406   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
407 }
408 
409 // CTTZ_ZERO_UNDEF widening.
410 TEST_F(GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
411   if (!TM)
412     return;
413 
414   // Declare your legalization info
415   DefineLegalizerInfo(A, {
416     getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
417   });
418   // Build
419   // Trunc it to s8.
420   LLT s8{LLT::scalar(8)};
421   LLT s16{LLT::scalar(16)};
422   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
423   auto MIBCTTZ_ZERO_UNDEF =
424       B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc});
425   AInfo Info(MF->getSubtarget());
426   DummyGISelObserver Observer;
427   LegalizerHelper Helper(*MF, Info, Observer, B);
428   EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) ==
429               LegalizerHelper::LegalizeResult::Legalized);
430 
431   auto CheckStr = R"(
432   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
433   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
434   CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
435   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
436   )";
437 
438   // Check
439   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
440 }
441 
442 // CTTZ widening.
443 TEST_F(GISelMITest, WidenBitCountingCTTZ) {
444   if (!TM)
445     return;
446 
447   // Declare your legalization info
448   DefineLegalizerInfo(A, {
449     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
450   });
451   // Build
452   // Trunc it to s8.
453   LLT s8{LLT::scalar(8)};
454   LLT s16{LLT::scalar(16)};
455   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
456   auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc});
457   AInfo Info(MF->getSubtarget());
458   DummyGISelObserver Observer;
459   LegalizerHelper Helper(*MF, Info, Observer, B);
460   EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) ==
461               LegalizerHelper::LegalizeResult::Legalized);
462 
463   auto CheckStr = R"(
464   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
465   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
466   CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
467   CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
468   CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
469   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
470   )";
471 
472   // Check
473   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
474 }
475 // UADDO widening.
476 TEST_F(GISelMITest, WidenUADDO) {
477   if (!TM)
478     return;
479 
480   // Declare your legalization info
481   DefineLegalizerInfo(A, {
482     getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
483   });
484   // Build
485   // Trunc it to s8.
486   LLT s8{LLT::scalar(8)};
487   LLT s16{LLT::scalar(16)};
488   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
489   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
490   auto MIBUAddO =
491       B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
492   AInfo Info(MF->getSubtarget());
493   DummyGISelObserver Observer;
494   LegalizerHelper Helper(*MF, Info, Observer, B);
495   EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
496               LegalizerHelper::LegalizeResult::Legalized);
497 
498   auto CheckStr = R"(
499   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
500   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
501   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
502   CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
503   CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
504   CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_
505   CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_
506   CHECK: G_TRUNC [[ADD]]
507   )";
508 
509   // Check
510   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
511 }
512 
513 // USUBO widening.
514 TEST_F(GISelMITest, WidenUSUBO) {
515   if (!TM)
516     return;
517 
518   // Declare your legalization info
519   DefineLegalizerInfo(A, {
520     getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
521   });
522   // Build
523   // Trunc it to s8.
524   LLT s8{LLT::scalar(8)};
525   LLT s16{LLT::scalar(16)};
526   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
527   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
528   auto MIBUSUBO =
529       B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
530   AInfo Info(MF->getSubtarget());
531   DummyGISelObserver Observer;
532   LegalizerHelper Helper(*MF, Info, Observer, B);
533   EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
534               LegalizerHelper::LegalizeResult::Legalized);
535 
536   auto CheckStr = R"(
537   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
538   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
539   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
540   CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
541   CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
542   CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_
543   CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_
544   CHECK: G_TRUNC [[SUB]]
545   )";
546 
547   // Check
548   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
549 }
550 
551 TEST_F(GISelMITest, FewerElementsAnd) {
552   if (!TM)
553     return;
554 
555   const LLT V2S32 = LLT::vector(2, 32);
556   const LLT V5S32 = LLT::vector(5, 32);
557 
558   // Declare your legalization info
559   DefineLegalizerInfo(A, {
560     getActionDefinitionsBuilder(G_AND)
561       .legalFor({s32});
562   });
563 
564   auto Op0 = B.buildUndef(V5S32);
565   auto Op1 = B.buildUndef(V5S32);
566   auto And = B.buildAnd(V5S32, Op0, Op1);
567 
568   AInfo Info(MF->getSubtarget());
569   DummyGISelObserver Observer;
570   LegalizerHelper Helper(*MF, Info, Observer, B);
571   EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) ==
572               LegalizerHelper::LegalizeResult::Legalized);
573 
574   auto CheckStr = R"(
575   CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
576   CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
577   CHECK: [[IMP_DEF2:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
578   CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 0
579   CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 0
580   CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT0]]:_, [[EXTRACT1]]:_
581   CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[IMP_DEF2]]:_, [[AND0]]:_(<2 x s32>), 0
582 
583   CHECK: [[EXTRACT2:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 64
584   CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 64
585   CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT2]]:_, [[EXTRACT3]]:_
586   CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[AND1]]:_(<2 x s32>), 64
587 
588   CHECK: [[EXTRACT4:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 128
589   CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 128
590   CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[EXTRACT4]]:_, [[EXTRACT5]]:_
591   CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[AND2]]:_(s32), 128
592   )";
593 
594   // Check
595   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
596 }
597 
598 TEST_F(GISelMITest, MoreElementsAnd) {
599   if (!TM)
600     return;
601 
602   LLT s32 = LLT::scalar(32);
603   LLT v2s32 = LLT::vector(2, 32);
604   LLT v6s32 = LLT::vector(6, 32);
605 
606   LegalizerInfo LI;
607   LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
608     .legalFor({v6s32})
609     .clampMinNumElements(0, s32, 6);
610   LI.computeTables();
611 
612   DummyGISelObserver Observer;
613   LegalizerHelper Helper(*MF, LI, Observer, B);
614 
615   B.setInsertPt(*EntryMBB, EntryMBB->end());
616 
617   auto Val0 = B.buildBitcast(v2s32, Copies[0]);
618   auto Val1 = B.buildBitcast(v2s32, Copies[1]);
619 
620   auto And = B.buildAnd(v2s32, Val0, Val1);
621 
622   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
623             Helper.moreElementsVector(*And, 0, v6s32));
624 
625   auto CheckStr = R"(
626   CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
627   CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
628   CHECK: [[IMP_DEF0:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
629   CHECK: [[CONCAT0:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>)
630   CHECK: [[IMP_DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
631   CHECK: [[CONCAT1:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>)
632   CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[CONCAT0]]:_, [[CONCAT1]]:_
633   CHECK: (<2 x s32>) = G_EXTRACT [[AND]]:_(<6 x s32>), 0
634   )";
635 
636   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
637 }
638 
639 TEST_F(GISelMITest, FewerElementsPhi) {
640   if (!TM)
641     return;
642 
643   LLT s1 = LLT::scalar(1);
644   LLT s32 = LLT::scalar(32);
645   LLT s64 = LLT::scalar(64);
646   LLT v2s32 = LLT::vector(2, 32);
647   LLT v5s32 = LLT::vector(5, 32);
648 
649   LegalizerInfo LI;
650   LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
651     .legalFor({v2s32})
652     .clampMinNumElements(0, s32, 2);
653   LI.computeTables();
654 
655   LLT PhiTy = v5s32;
656   DummyGISelObserver Observer;
657   LegalizerHelper Helper(*MF, LI, Observer, B);
658   B.setMBB(*EntryMBB);
659 
660   MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock();
661   MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock();
662   MF->insert(MF->end(), MidMBB);
663   MF->insert(MF->end(), EndMBB);
664 
665   EntryMBB->addSuccessor(MidMBB);
666   EntryMBB->addSuccessor(EndMBB);
667   MidMBB->addSuccessor(EndMBB);
668 
669   auto InitVal = B.buildUndef(PhiTy);
670   auto InitOtherVal = B.buildConstant(s64, 999);
671 
672   auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
673   B.buildBrCond(ICmp.getReg(0), *MidMBB);
674   B.buildBr(*EndMBB);
675 
676 
677   B.setMBB(*MidMBB);
678   auto MidVal = B.buildUndef(PhiTy);
679   auto MidOtherVal = B.buildConstant(s64, 345);
680   B.buildBr(*EndMBB);
681 
682   B.setMBB(*EndMBB);
683   auto Phi = B.buildInstr(TargetOpcode::G_PHI)
684     .addDef(MRI->createGenericVirtualRegister(PhiTy))
685     .addUse(InitVal.getReg(0))
686     .addMBB(EntryMBB)
687     .addUse(MidVal.getReg(0))
688     .addMBB(MidMBB);
689 
690   // Insert another irrelevant phi to make sure the rebuild is inserted after
691   // it.
692   B.buildInstr(TargetOpcode::G_PHI)
693     .addDef(MRI->createGenericVirtualRegister(s64))
694     .addUse(InitOtherVal.getReg(0))
695     .addMBB(EntryMBB)
696     .addUse(MidOtherVal.getReg(0))
697     .addMBB(MidMBB);
698 
699   // Add some use instruction after the phis.
700   B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0));
701 
702   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
703             Helper.fewerElementsVector(*Phi, 0, v2s32));
704 
705   auto CheckStr = R"(
706   CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
707   CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 0
708   CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 64
709   CHECK: [[EXTRACT2:%[0-9]+]]:_(s32) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 128
710   CHECK: G_BRCOND
711 
712   CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
713   CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 0
714   CHECK: [[EXTRACT4:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 64
715   CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 128
716   CHECK: G_BR
717 
718   CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT0]]:_(<2 x s32>), %bb.0, [[EXTRACT3]]:_(<2 x s32>), %bb.1
719   CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT1]]:_(<2 x s32>), %bb.0, [[EXTRACT4]]:_(<2 x s32>), %bb.1
720   CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[EXTRACT2]]:_(s32), %bb.0, [[EXTRACT5]]:_(s32), %bb.1
721 
722   CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI
723   CHECK: [[REBUILD_VAL_IMPDEF:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
724   CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[REBUILD_VAL_IMPDEF]]:_, [[PHI0]]:_(<2 x s32>), 0
725   CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[PHI1]]:_(<2 x s32>), 64
726   CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[PHI2]]:_(s32), 128
727   CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[INSERT2]]:_, [[INSERT2]]:_
728   )";
729 
730   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
731 }
732 
733 // FNEG expansion in terms of FSUB
734 TEST_F(GISelMITest, LowerFNEG) {
735   if (!TM)
736     return;
737 
738   // Declare your legalization info
739   DefineLegalizerInfo(A, {
740     getActionDefinitionsBuilder(G_FSUB).legalFor({s64});
741   });
742 
743   // Build Instr. Make sure FMF are preserved.
744   auto FAdd =
745     B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]},
746                  MachineInstr::MIFlag::FmNsz);
747 
748   // Should not propagate the flags of src instruction.
749   auto FNeg0 =
750     B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)},
751                  {MachineInstr::MIFlag::FmArcp});
752 
753   // Preserve the one flag.
754   auto FNeg1 =
755     B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]},
756                  MachineInstr::MIFlag::FmNoInfs);
757 
758   AInfo Info(MF->getSubtarget());
759   DummyGISelObserver Observer;
760   LegalizerHelper Helper(*MF, Info, Observer, B);
761   // Perform Legalization
762   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
763             Helper.lower(*FNeg0, 0, LLT::scalar(64)));
764   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
765             Helper.lower(*FNeg1, 0, LLT::scalar(64)));
766 
767   auto CheckStr = R"(
768   CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_
769   CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
770   CHECK: [[FSUB0:%[0-9]+]]:_(s64) = arcp G_FSUB [[CONST0]]:_, [[FADD]]:_
771   CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
772   CHECK: [[FSUB1:%[0-9]+]]:_(s64) = ninf G_FSUB [[CONST1]]:_, %0:_
773   )";
774 
775   // Check
776   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
777 }
778 } // namespace
779