xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp (revision d5e14ba88cbf353236faa45caf626c2a30a1cb0c)
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 #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
12 
13 using namespace LegalizeActions;
14 using namespace LegalizeMutations;
15 using namespace LegalityPredicates;
16 
17 namespace {
18 
19 class DummyGISelObserver : public GISelChangeObserver {
20 public:
21   void changingInstr(MachineInstr &MI) override {}
22   void changedInstr(MachineInstr &MI) override {}
23   void createdInstr(MachineInstr &MI) override {}
24   void erasingInstr(MachineInstr &MI) override {}
25 };
26 
27 // Test G_ROTL/G_ROTR lowering.
28 TEST_F(AArch64GISelMITest, LowerRotates) {
29   setUp();
30   if (!TM)
31     return;
32 
33   // Declare your legalization info
34   DefineLegalizerInfo(A, {
35     getActionDefinitionsBuilder({G_ROTR, G_ROTL}).lower(); });
36 
37   LLT S32 = LLT::scalar(32);
38   auto Src = B.buildTrunc(S32, Copies[0]);
39   auto Amt = B.buildTrunc(S32, Copies[1]);
40   auto ROTR = B.buildInstr(TargetOpcode::G_ROTR, {S32}, {Src, Amt});
41   auto ROTL = B.buildInstr(TargetOpcode::G_ROTL, {S32}, {Src, Amt});
42 
43   AInfo Info(MF->getSubtarget());
44   DummyGISelObserver Observer;
45   LegalizerHelper Helper(*MF, Info, Observer, B);
46   // Perform Legalization
47   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
48             Helper.lower(*ROTR, 0, S32));
49   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
50             Helper.lower(*ROTL, 0, S32));
51 
52   auto CheckStr = R"(
53   ; Check G_ROTR
54   CHECK: [[SRC:%[0-9]+]]:_(s32) = G_TRUNC
55   CHECK: [[AMT:%[0-9]+]]:_(s32) = G_TRUNC
56   CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
57   CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
58   CHECK: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]]:_, [[AMT]]:_
59   CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMT]]:_, [[C1]]:_
60   CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[SRC]]:_, [[AND]]:_(s32)
61   CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[SUB]]:_, [[C1]]:_
62   CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SRC]]:_, [[AND1]]:_(s32)
63   CHECK: G_OR [[LSHR]]:_, [[SHL]]:_
64 
65   ; Check G_ROTL
66   CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
67   CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
68   CHECK: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]]:_, [[AMT]]:_
69   CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMT]]:_, [[C1]]:_
70   CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SRC]]:_, [[AND]]:_(s32)
71   CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[SUB]]:_, [[C1]]:_
72   CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[SRC]]:_, [[AND1]]:_(s32)
73   CHECK: G_OR [[SHL]]:_, [[LSHR]]:_
74   )";
75 
76   // Check
77   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
78 }
79 
80 // Test G_ROTL/G_ROTR non-pow2 lowering.
81 TEST_F(AArch64GISelMITest, LowerRotatesNonPow2) {
82   setUp();
83   if (!TM)
84     return;
85 
86   // Declare your legalization info
87   DefineLegalizerInfo(A, {
88     getActionDefinitionsBuilder({G_ROTR, G_ROTL}).lower(); });
89 
90   LLT S24 = LLT::scalar(24);
91   auto Src = B.buildTrunc(S24, Copies[0]);
92   auto Amt = B.buildTrunc(S24, Copies[1]);
93   auto ROTR = B.buildInstr(TargetOpcode::G_ROTR, {S24}, {Src, Amt});
94   auto ROTL = B.buildInstr(TargetOpcode::G_ROTL, {S24}, {Src, Amt});
95 
96   AInfo Info(MF->getSubtarget());
97   DummyGISelObserver Observer;
98   LegalizerHelper Helper(*MF, Info, Observer, B);
99   // Perform Legalization
100   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
101             Helper.lower(*ROTR, 0, S24));
102   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
103             Helper.lower(*ROTL, 0, S24));
104 
105   auto CheckStr = R"(
106   ; Check G_ROTR
107   CHECK: [[SRC:%[0-9]+]]:_(s24) = G_TRUNC
108   CHECK: [[AMT:%[0-9]+]]:_(s24) = G_TRUNC
109   CHECK: [[C:%[0-9]+]]:_(s24) = G_CONSTANT i24 0
110   CHECK: [[C1:%[0-9]+]]:_(s24) = G_CONSTANT i24 23
111   CHECK: [[C2:%[0-9]+]]:_(s24) = G_CONSTANT i24 24
112   CHECK: [[UREM:%[0-9]+]]:_(s24) = G_UREM [[AMT]]:_, [[C2]]:_
113   CHECK: [[LSHR:%[0-9]+]]:_(s24) = G_LSHR [[SRC]]:_, [[UREM]]:_(s24)
114   CHECK: [[SUB:%[0-9]+]]:_(s24) = G_SUB [[C1]]:_, [[UREM]]:_
115   CHECK: [[C4:%[0-9]+]]:_(s24) = G_CONSTANT i24 1
116   CHECK: [[SHL:%[0-9]+]]:_(s24) = G_SHL [[SRC]]:_, [[C4]]:_(s24)
117   CHECK: [[SHL2:%[0-9]+]]:_(s24) = G_SHL [[SHL]]:_, [[SUB]]:_(s24)
118   CHECK: G_OR [[LSHR]]:_, [[SHL2]]:_
119 
120   ; Check G_ROTL
121   CHECK: [[C:%[0-9]+]]:_(s24) = G_CONSTANT i24 0
122   CHECK: [[C1:%[0-9]+]]:_(s24) = G_CONSTANT i24 23
123   CHECK: [[C2:%[0-9]+]]:_(s24) = G_CONSTANT i24 24
124   CHECK: [[UREM:%[0-9]+]]:_(s24) = G_UREM [[AMT]]:_, [[C2]]:_
125   CHECK: [[SHL:%[0-9]+]]:_(s24) = G_SHL [[SRC]]:_, [[UREM]]:_(s24)
126   CHECK: [[SUB:%[0-9]+]]:_(s24) = G_SUB [[C1]]:_, [[UREM]]:_
127   CHECK: [[C4:%[0-9]+]]:_(s24) = G_CONSTANT i24 1
128   CHECK: [[LSHR:%[0-9]+]]:_(s24) = G_LSHR [[SRC]]:_, [[C4]]:_(s24)
129   CHECK: [[LSHR2:%[0-9]+]]:_(s24) = G_LSHR [[LSHR]]:_, [[SUB]]:_(s24)
130   CHECK: G_OR [[SHL]]:_, [[LSHR2]]:_
131   )";
132 
133   // Check
134   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
135 }
136 
137 // Test vector G_ROTR lowering.
138 TEST_F(AArch64GISelMITest, LowerRotatesVector) {
139   setUp();
140   if (!TM)
141     return;
142 
143   // Declare your legalization info
144   DefineLegalizerInfo(A, {
145     getActionDefinitionsBuilder({G_ROTR, G_ROTL}).lower(); });
146 
147   LLT S32 = LLT::scalar(32);
148   LLT V4S32 = LLT::fixed_vector(4, S32);
149   auto SrcTrunc = B.buildTrunc(S32, Copies[0]);
150   auto Src = B.buildSplatVector(V4S32, SrcTrunc);
151   auto AmtTrunc = B.buildTrunc(S32, Copies[1]);
152   auto Amt = B.buildSplatVector(V4S32, AmtTrunc);
153   auto ROTR = B.buildInstr(TargetOpcode::G_ROTR, {V4S32}, {Src, Amt});
154 
155   AInfo Info(MF->getSubtarget());
156   DummyGISelObserver Observer;
157   LegalizerHelper Helper(*MF, Info, Observer, B);
158   // Perform Legalization
159   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
160             Helper.lower(*ROTR, 0, V4S32));
161 
162   auto CheckStr = R"(
163   CHECK: [[SRCTRUNC:%[0-9]+]]:_(s32) = G_TRUNC
164   CHECK: [[SRC:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[SRCTRUNC]]
165   CHECK: [[AMTTRUNC:%[0-9]+]]:_(s32) = G_TRUNC
166   CHECK: [[AMT:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[AMTTRUNC]]
167   CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
168   CHECK: [[ZERO:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]]
169   CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
170   CHECK: [[VEC31:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]]
171   CHECK: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB [[ZERO]]:_, [[AMT]]:_
172   CHECK: [[AND:%[0-9]+]]:_(<4 x s32>) = G_AND [[AMT]]:_, [[VEC31]]:_
173   CHECK: [[LSHR:%[0-9]+]]:_(<4 x s32>) = G_LSHR [[SRC]]:_, [[AND]]:_(<4 x s32>)
174   CHECK: [[AND1:%[0-9]+]]:_(<4 x s32>) = G_AND [[SUB]]:_, [[VEC31]]:_
175   CHECK: [[SHL:%[0-9]+]]:_(<4 x s32>) = G_SHL [[SRC]]:_, [[AND1]]:_(<4 x s32>)
176   CHECK: G_OR [[LSHR]]:_, [[SHL]]:_
177   )";
178 
179   // Check
180   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
181 }
182 
183 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom,
184 // in which case it becomes CTTZ_ZERO_UNDEF with select.
185 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ0) {
186   setUp();
187   if (!TM)
188     return;
189 
190   // Declare your legalization info
191   DefineLegalizerInfo(A, {
192     getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s32, s64}});
193   });
194   // Build Instr
195   auto MIBCTTZ =
196       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]});
197   AInfo Info(MF->getSubtarget());
198   DummyGISelObserver Observer;
199   LegalizerHelper Helper(*MF, Info, Observer, B);
200   // Perform Legalization
201   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
202             Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)));
203 
204   auto CheckStr = R"(
205   CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF %0
206   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
207   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
208   CHECK: [[SIXTY4:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
209   CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
210   )";
211 
212   // Check
213   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
214 }
215 
216 // CTTZ expansion in terms of CTLZ
217 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ1) {
218   setUp();
219   if (!TM)
220     return;
221 
222   // Declare your legalization info
223   DefineLegalizerInfo(A, {
224     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}});
225   });
226   // Build Instr
227   auto MIBCTTZ =
228       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
229   AInfo Info(MF->getSubtarget());
230   DummyGISelObserver Observer;
231   LegalizerHelper Helper(*MF, Info, Observer, B);
232   // Perform Legalization
233   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
234               LegalizerHelper::LegalizeResult::Legalized);
235 
236   auto CheckStr = R"(
237   CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
238   CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
239   CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
240   CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
241   CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
242   CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_
243   CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_
244   )";
245 
246   // Check
247   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
248 }
249 
250 // CTLZ scalar narrowing
251 TEST_F(AArch64GISelMITest, NarrowScalarCTLZ) {
252   setUp();
253   if (!TM)
254     return;
255 
256   // Declare your legalization info
257   DefineLegalizerInfo(A, {
258     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s32, s32}});
259   });
260   // Build Instr
261   auto CTLZ =
262       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]});
263   AInfo Info(MF->getSubtarget());
264   DummyGISelObserver Observer;
265   LegalizerHelper Helper(*MF, Info, Observer, B);
266   // Perform Legalization
267   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
268             Helper.narrowScalar(*CTLZ, 1, LLT::scalar(32)));
269 
270   auto CheckStr = R"(
271   CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64)
272   CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
273   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_HI]]:_(s32), [[ZERO]]:_
274   CHECK: [[CTLZ_LO:%[0-9]+]]:_(s32) = G_CTLZ [[UNMERGE_LO]]:_(s32)
275   CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
276   CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTLZ_LO]]:_, [[THIRTYTWO]]:_
277   CHECK: [[CTLZ_HI:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[UNMERGE_HI]]:_(s32)
278   CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTLZ_HI]]:_
279   )";
280 
281   // Check
282   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
283 }
284 
285 // CTTZ scalar narrowing
286 TEST_F(AArch64GISelMITest, NarrowScalarCTTZ) {
287   setUp();
288   if (!TM)
289     return;
290 
291   // Declare your legalization info
292   DefineLegalizerInfo(A, {
293     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s32, s64}});
294   });
295   // Build Instr
296   auto CTTZ =
297       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]});
298   AInfo Info(MF->getSubtarget());
299   DummyGISelObserver Observer;
300   LegalizerHelper Helper(*MF, Info, Observer, B);
301   // Perform Legalization
302   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
303             Helper.narrowScalar(*CTTZ, 1, LLT::scalar(32)));
304 
305   auto CheckStr = R"(
306   CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64)
307   CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
308   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_LO]]:_(s32), [[ZERO]]:_
309   CHECK: [[CTTZ_HI:%[0-9]+]]:_(s32) = G_CTTZ [[UNMERGE_HI]]:_(s32)
310   CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
311   CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTTZ_HI]]:_, [[THIRTYTWO]]:_
312   CHECK: [[CTTZ_LO:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[UNMERGE_LO]]:_(s32)
313   CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTTZ_LO]]:_
314   )";
315 
316   // Check
317   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
318 }
319 
320 // CTTZ expansion in terms of CTPOP
321 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ2) {
322   setUp();
323   if (!TM)
324     return;
325 
326   // Declare your legalization info
327   DefineLegalizerInfo(A, {
328     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}});
329   });
330   // Build
331   auto MIBCTTZ =
332       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
333   AInfo Info(MF->getSubtarget());
334   DummyGISelObserver Observer;
335   LegalizerHelper Helper(*MF, Info, Observer, B);
336 
337   B.setInsertPt(*EntryMBB, MIBCTTZ->getIterator());
338   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
339               LegalizerHelper::LegalizeResult::Legalized);
340 
341   auto CheckStr = R"(
342   CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
343   CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
344   CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
345   CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
346   CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
347   )";
348 
349   // Check
350   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
351 }
352 
353 // CTPOP widening.
354 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP1) {
355   setUp();
356   if (!TM)
357     return;
358 
359   // Declare your legalization info
360   DefineLegalizerInfo(A, {
361       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
362     });
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 MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc});
370   AInfo Info(MF->getSubtarget());
371   DummyGISelObserver Observer;
372   LegalizerHelper Helper(*MF, Info, Observer, B);
373   B.setInstr(*MIBCTPOP);
374   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
375             Helper.widenScalar(*MIBCTPOP, 1, s16));
376 
377   auto CheckStr = R"(
378   CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
379   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
380   CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
381   CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16)
382   )";
383 
384   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
385 }
386 
387 // Test a strange case where the result is wider than the source
388 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP2) {
389   setUp();
390   if (!TM)
391     return;
392 
393   // Declare your legalization info
394   DefineLegalizerInfo(A, {
395       getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}});
396     });
397 
398   // Build
399   // Trunc it to s8.
400   LLT s8{LLT::scalar(8)};
401   LLT s16{LLT::scalar(16)};
402   LLT s32{LLT::scalar(32)};
403   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
404   auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc});
405   AInfo Info(MF->getSubtarget());
406   DummyGISelObserver Observer;
407   LegalizerHelper Helper(*MF, Info, Observer, B);
408   B.setInstr(*MIBCTPOP);
409   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
410             Helper.widenScalar(*MIBCTPOP, 1, s16));
411 
412   auto CheckStr = R"(
413   CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
414   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
415   CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
416   CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16)
417   )";
418 
419   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
420 }
421 
422 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
423 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ3) {
424   setUp();
425   if (!TM)
426     return;
427 
428   // Declare your legalization info
429   DefineLegalizerInfo(A, {
430     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
431   });
432   // Build
433   auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
434                               {LLT::scalar(64)}, {Copies[0]});
435   AInfo Info(MF->getSubtarget());
436   DummyGISelObserver Observer;
437   LegalizerHelper Helper(*MF, Info, Observer, B);
438   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
439               LegalizerHelper::LegalizeResult::Legalized);
440 
441   auto CheckStr = R"(
442   CHECK: CTTZ
443   )";
444 
445   // Check
446   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
447 }
448 
449 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
450 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZ0) {
451   setUp();
452   if (!TM)
453     return;
454 
455   // Declare your legalization info
456   DefineLegalizerInfo(A, {
457     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
458   });
459   // Build
460   auto MIBCTLZ =
461       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
462   AInfo Info(MF->getSubtarget());
463   DummyGISelObserver Observer;
464   LegalizerHelper Helper(*MF, Info, Observer, B);
465   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
466               LegalizerHelper::LegalizeResult::Legalized);
467 
468   auto CheckStr = R"(
469   CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
470   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
471   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
472   CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
473   CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
474   )";
475 
476   // Check
477   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
478 }
479 
480 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall
481 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZLibcall) {
482   setUp();
483   if (!TM)
484     return;
485 
486   // Declare your legalization info
487   DefineLegalizerInfo(A, {
488     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s32, s64}});
489   });
490   // Build
491   auto MIBCTLZ =
492       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]});
493   AInfo Info(MF->getSubtarget());
494   DummyGISelObserver Observer;
495   LegalizerHelper Helper(*MF, Info, Observer, B);
496   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
497             Helper.lower(*MIBCTLZ, 0, LLT::scalar(32)));
498 
499   auto CheckStr = R"(
500   CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF %0
501   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
502   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
503   CHECK: [[THIRTY2:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
504   CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]]
505   )";
506 
507   // Check
508   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
509 }
510 
511 // CTLZ expansion
512 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZ1) {
513   setUp();
514   if (!TM)
515     return;
516 
517   // Declare your legalization info
518   DefineLegalizerInfo(A, {
519     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
520   });
521   // Build
522   // Trunc it to s8.
523   LLT s8{LLT::scalar(8)};
524   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
525   auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
526   AInfo Info(MF->getSubtarget());
527   DummyGISelObserver Observer;
528   LegalizerHelper Helper(*MF, Info, Observer, B);
529   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
530               LegalizerHelper::LegalizeResult::Legalized);
531 
532   auto CheckStr = R"(
533   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
534   CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
535   CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
536   CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
537   CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
538   CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
539   CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
540   CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
541   CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
542   CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
543   CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
544   CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
545   CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
546   )";
547 
548   // Check
549   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
550 }
551 
552 // CTLZ widening.
553 TEST_F(AArch64GISelMITest, WidenBitCountingCTLZ) {
554   setUp();
555   if (!TM)
556     return;
557 
558   // Declare your legalization info
559   DefineLegalizerInfo(A, {
560     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
561   });
562   // Build
563   // Trunc it to s8.
564   LLT s8{LLT::scalar(8)};
565   LLT s16{LLT::scalar(16)};
566   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
567   auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
568   AInfo Info(MF->getSubtarget());
569   DummyGISelObserver Observer;
570   LegalizerHelper Helper(*MF, Info, Observer, B);
571   EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) ==
572               LegalizerHelper::LegalizeResult::Legalized);
573 
574   auto CheckStr = R"(
575   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
576   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
577   CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
578   CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
579   CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
580   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
581   )";
582 
583   // Check
584   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
585 }
586 
587 // CTLZ_ZERO_UNDEF widening.
588 TEST_F(AArch64GISelMITest, WidenBitCountingCTLZZeroUndef) {
589   setUp();
590   if (!TM)
591     return;
592 
593   // Declare your legalization info
594   DefineLegalizerInfo(A, {
595     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
596   });
597   // Build
598   // Trunc it to s8.
599   LLT s8{LLT::scalar(8)};
600   LLT s16{LLT::scalar(16)};
601   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
602   auto MIBCTLZ_ZU =
603       B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc});
604   AInfo Info(MF->getSubtarget());
605   DummyGISelObserver Observer;
606   LegalizerHelper Helper(*MF, Info, Observer, B);
607   EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) ==
608               LegalizerHelper::LegalizeResult::Legalized);
609 
610   auto CheckStr = R"(
611   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
612   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
613   CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
614   CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
615   CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
616   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
617   )";
618 
619   // Check
620   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
621 }
622 
623 // CTPOP widening.
624 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP) {
625   setUp();
626   if (!TM)
627     return;
628 
629   // Declare your legalization info
630   DefineLegalizerInfo(A, {
631     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
632   });
633   // Build
634   // Trunc it to s8.
635   LLT s8{LLT::scalar(8)};
636   LLT s16{LLT::scalar(16)};
637   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
638   auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc});
639   AInfo Info(MF->getSubtarget());
640   DummyGISelObserver Observer;
641   LegalizerHelper Helper(*MF, Info, Observer, B);
642   EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) ==
643               LegalizerHelper::LegalizeResult::Legalized);
644 
645   auto CheckStr = R"(
646   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
647   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
648   CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
649   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
650   )";
651 
652   // Check
653   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
654 }
655 
656 // CTTZ_ZERO_UNDEF widening.
657 TEST_F(AArch64GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
658   setUp();
659   if (!TM)
660     return;
661 
662   // Declare your legalization info
663   DefineLegalizerInfo(A, {
664     getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
665   });
666   // Build
667   // Trunc it to s8.
668   LLT s8{LLT::scalar(8)};
669   LLT s16{LLT::scalar(16)};
670   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
671   auto MIBCTTZ_ZERO_UNDEF =
672       B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc});
673   AInfo Info(MF->getSubtarget());
674   DummyGISelObserver Observer;
675   LegalizerHelper Helper(*MF, Info, Observer, B);
676   EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) ==
677               LegalizerHelper::LegalizeResult::Legalized);
678 
679   auto CheckStr = R"(
680   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
681   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
682   CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
683   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
684   )";
685 
686   // Check
687   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
688 }
689 
690 // CTTZ widening.
691 TEST_F(AArch64GISelMITest, WidenBitCountingCTTZ) {
692   setUp();
693   if (!TM)
694     return;
695 
696   // Declare your legalization info
697   DefineLegalizerInfo(A, {
698     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
699   });
700   // Build
701   // Trunc it to s8.
702   LLT s8{LLT::scalar(8)};
703   LLT s16{LLT::scalar(16)};
704   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
705   auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc});
706   AInfo Info(MF->getSubtarget());
707   DummyGISelObserver Observer;
708   LegalizerHelper Helper(*MF, Info, Observer, B);
709   EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) ==
710               LegalizerHelper::LegalizeResult::Legalized);
711 
712   auto CheckStr = R"(
713   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
714   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
715   CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
716   CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
717   CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
718   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
719   )";
720 
721   // Check
722   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
723 }
724 // UADDO widening.
725 TEST_F(AArch64GISelMITest, WidenUADDO) {
726   setUp();
727   if (!TM)
728     return;
729 
730   // Declare your legalization info
731   DefineLegalizerInfo(A, {
732     getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
733   });
734   // Build
735   // Trunc it to s8.
736   LLT s8{LLT::scalar(8)};
737   LLT s16{LLT::scalar(16)};
738   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
739   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
740   auto MIBUAddO =
741       B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
742   AInfo Info(MF->getSubtarget());
743   DummyGISelObserver Observer;
744   LegalizerHelper Helper(*MF, Info, Observer, B);
745   EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
746               LegalizerHelper::LegalizeResult::Legalized);
747 
748   auto CheckStr = R"(
749   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
750   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
751   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
752   CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
753   CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ADD]]
754   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
755   CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[ZEXT]]:_
756   CHECK: G_TRUNC [[ADD]]
757   )";
758 
759   // Check
760   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
761 }
762 
763 // USUBO widening.
764 TEST_F(AArch64GISelMITest, WidenUSUBO) {
765   setUp();
766   if (!TM)
767     return;
768 
769   // Declare your legalization info
770   DefineLegalizerInfo(A, {
771     getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
772   });
773   // Build
774   // Trunc it to s8.
775   LLT s8{LLT::scalar(8)};
776   LLT s16{LLT::scalar(16)};
777   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
778   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
779   auto MIBUSUBO =
780       B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
781   AInfo Info(MF->getSubtarget());
782   DummyGISelObserver Observer;
783   LegalizerHelper Helper(*MF, Info, Observer, B);
784   EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
785               LegalizerHelper::LegalizeResult::Legalized);
786 
787   auto CheckStr = R"(
788   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
789   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
790   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
791   CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
792   CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SUB]]
793   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
794   CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[ZEXT]]:_
795   CHECK: G_TRUNC [[SUB]]
796   )";
797 
798   // Check
799   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
800 }
801 
802 // SADDO widening.
803 TEST_F(AArch64GISelMITest, WidenSADDO) {
804   setUp();
805   if (!TM)
806     return;
807 
808   // Declare your legalization info
809   DefineLegalizerInfo(A, {
810     getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
811   });
812   // Build
813   // Trunc it to s8.
814   LLT s8{LLT::scalar(8)};
815   LLT s16{LLT::scalar(16)};
816   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
817   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
818   auto MIBSAddO =
819       B.buildInstr(TargetOpcode::G_SADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
820   AInfo Info(MF->getSubtarget());
821   DummyGISelObserver Observer;
822   LegalizerHelper Helper(*MF, Info, Observer, B);
823   EXPECT_TRUE(Helper.widenScalar(*MIBSAddO, 0, s16) ==
824               LegalizerHelper::LegalizeResult::Legalized);
825 
826   auto CheckStr = R"(
827   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
828   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
829   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
830   CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
831   CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ADD]]
832   CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
833   CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[SEXT]]:_
834   CHECK: G_TRUNC [[ADD]]
835   )";
836 
837   // Check
838   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
839 }
840 
841 // SSUBO widening.
842 TEST_F(AArch64GISelMITest, WidenSSUBO) {
843   setUp();
844   if (!TM)
845     return;
846 
847   // Declare your legalization info
848   DefineLegalizerInfo(A, {
849     getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
850   });
851   // Build
852   // Trunc it to s8.
853   LLT s8{LLT::scalar(8)};
854   LLT s16{LLT::scalar(16)};
855   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
856   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
857   auto MIBSSUBO =
858       B.buildInstr(TargetOpcode::G_SSUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
859   AInfo Info(MF->getSubtarget());
860   DummyGISelObserver Observer;
861   LegalizerHelper Helper(*MF, Info, Observer, B);
862   EXPECT_TRUE(Helper.widenScalar(*MIBSSUBO, 0, s16) ==
863               LegalizerHelper::LegalizeResult::Legalized);
864 
865   auto CheckStr = R"(
866   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
867   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
868   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
869   CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
870   CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SUB]]
871   CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
872   CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[SEXT]]:_
873   CHECK: G_TRUNC [[SUB]]
874   )";
875 
876   // Check
877   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
878 }
879 
880 TEST_F(AArch64GISelMITest, WidenUADDE) {
881   setUp();
882   if (!TM)
883     return;
884 
885   // Declare your legalization info
886   DefineLegalizerInfo(A, {
887     getActionDefinitionsBuilder(G_UADDE).legalFor({{s16, s16}});
888   });
889   // Build
890   // Trunc it to s8.
891   LLT s8{LLT::scalar(8)};
892   LLT s16{LLT::scalar(16)};
893   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
894   auto CarryIn = B.buildUndef(LLT::scalar(1));
895   Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
896   auto MIBUAddO = B.buildInstr(TargetOpcode::G_UADDE, {s8, CarryReg},
897                                {MIBTrunc, MIBTrunc, CarryIn});
898   AInfo Info(MF->getSubtarget());
899   DummyGISelObserver Observer;
900   LegalizerHelper Helper(*MF, Info, Observer, B);
901   EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
902               LegalizerHelper::LegalizeResult::Legalized);
903 
904   const char *CheckStr = R"(
905   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
906   CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
907   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
908   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
909   CHECK: [[UADDE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_UADDE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_
910   CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[UADDE]]
911   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
912   CHECK: G_ICMP intpred(ne), [[UADDE]]:_(s16), [[ZEXT]]:_
913   CHECK: G_TRUNC [[UADDE]]
914   )";
915 
916   // Check
917   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
918 }
919 
920 TEST_F(AArch64GISelMITest, WidenUSUBE) {
921   setUp();
922   if (!TM)
923     return;
924 
925   // Declare your legalization info
926   DefineLegalizerInfo(A, {
927     getActionDefinitionsBuilder(G_USUBE).legalFor({{s16, s16}});
928   });
929   // Build
930   // Trunc it to s8.
931   LLT s8{LLT::scalar(8)};
932   LLT s16{LLT::scalar(16)};
933   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
934   auto CarryIn = B.buildUndef(LLT::scalar(1));
935   Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
936   auto MIBUSUBE = B.buildInstr(TargetOpcode::G_USUBE, {s8, CarryReg},
937                                {MIBTrunc, MIBTrunc, CarryIn});
938   AInfo Info(MF->getSubtarget());
939   DummyGISelObserver Observer;
940   LegalizerHelper Helper(*MF, Info, Observer, B);
941   EXPECT_TRUE(Helper.widenScalar(*MIBUSUBE, 0, s16) ==
942               LegalizerHelper::LegalizeResult::Legalized);
943 
944   const char *CheckStr = R"(
945   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
946   CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
947   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
948   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
949   CHECK: [[USUBE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_USUBE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_
950   CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[USUBE]]
951   CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]]
952   CHECK: G_ICMP intpred(ne), [[USUBE]]:_(s16), [[ZEXT]]:_
953   CHECK: G_TRUNC [[USUBE]]
954   )";
955 
956   // Check
957   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
958 }
959 
960 TEST_F(AArch64GISelMITest, WidenSADDE) {
961   setUp();
962   if (!TM)
963     return;
964 
965   // Declare your legalization info
966   DefineLegalizerInfo(A, {
967     getActionDefinitionsBuilder({G_SADDE, G_UADDE}).legalFor({{s16, s16}});
968   });
969   // Build
970   // Trunc it to s8.
971   LLT s8{LLT::scalar(8)};
972   LLT s16{LLT::scalar(16)};
973   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
974   auto CarryIn = B.buildUndef(LLT::scalar(1));
975   Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
976   auto MIBUAddO = B.buildInstr(TargetOpcode::G_SADDE, {s8, CarryReg},
977                                {MIBTrunc, MIBTrunc, CarryIn});
978   AInfo Info(MF->getSubtarget());
979   DummyGISelObserver Observer;
980   LegalizerHelper Helper(*MF, Info, Observer, B);
981   EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
982               LegalizerHelper::LegalizeResult::Legalized);
983 
984   const char *CheckStr = R"(
985   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
986   CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
987   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
988   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
989   CHECK: [[SADDE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_UADDE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_
990   CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SADDE]]
991   CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
992   CHECK: G_ICMP intpred(ne), [[SADDE]]:_(s16), [[SEXT]]:_
993   CHECK: G_TRUNC [[SADDE]]
994   )";
995 
996   // Check
997   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
998 }
999 
1000 TEST_F(AArch64GISelMITest, WidenSSUBE) {
1001   setUp();
1002   if (!TM)
1003     return;
1004 
1005   // Declare your legalization info
1006   DefineLegalizerInfo(A, {
1007     getActionDefinitionsBuilder({G_SSUBE, G_USUBE}).legalFor({{s16, s16}});
1008   });
1009   // Build
1010   // Trunc it to s8.
1011   LLT s8{LLT::scalar(8)};
1012   LLT s16{LLT::scalar(16)};
1013   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
1014   auto CarryIn = B.buildUndef(LLT::scalar(1));
1015   Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
1016   auto MIBSSUBE = B.buildInstr(TargetOpcode::G_SSUBE, {s8, CarryReg},
1017                                {MIBTrunc, MIBTrunc, CarryIn});
1018   AInfo Info(MF->getSubtarget());
1019   DummyGISelObserver Observer;
1020   LegalizerHelper Helper(*MF, Info, Observer, B);
1021   EXPECT_TRUE(Helper.widenScalar(*MIBSSUBE, 0, s16) ==
1022               LegalizerHelper::LegalizeResult::Legalized);
1023 
1024   const char *CheckStr = R"(
1025   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
1026   CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1027   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
1028   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]]
1029   CHECK: [[SSUBE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_USUBE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_
1030   CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SSUBE]]
1031   CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]]
1032   CHECK: G_ICMP intpred(ne), [[SSUBE]]:_(s16), [[SEXT]]:_
1033   CHECK: G_TRUNC [[SSUBE]]
1034   )";
1035 
1036   // Check
1037   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1038 }
1039 
1040 TEST_F(AArch64GISelMITest, NarrowUADDO) {
1041   setUp();
1042   if (!TM)
1043     return;
1044 
1045   LLT S1 = LLT::scalar(1);
1046   LLT S32 = LLT::scalar(32);
1047   LLT S96 = LLT::scalar(96);
1048   DefineLegalizerInfo(A, {
1049     getActionDefinitionsBuilder({G_UADDO, G_UADDE})
1050         .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1051   });
1052 
1053   auto Op0 = B.buildUndef(S96);
1054   auto Op1 = B.buildUndef(S96);
1055   auto UADDO = B.buildUAddo(S96, S1, Op0, Op1);
1056 
1057   AInfo Info(MF->getSubtarget());
1058   DummyGISelObserver Observer;
1059   LegalizerHelper Helper(*MF, Info, Observer, B);
1060   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1061             Helper.narrowScalar(*UADDO, 0, S32));
1062 
1063   const char *CheckStr = R"(
1064   CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1065   CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1066   CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1067   CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1068   CHECK: [[UADDO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDO [[OP0_0]]:_, [[OP1_0]]:_
1069   CHECK: [[UADDO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1070   CHECK: [[UADDO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_UADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1071   CHECK: [[UADDO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[UADDO0]]:_(s32), [[UADDO1]]:_(s32), [[UADDO2]]:_(s32)
1072   )";
1073 
1074   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1075 }
1076 
1077 TEST_F(AArch64GISelMITest, NarrowUSUBO) {
1078   setUp();
1079   if (!TM)
1080     return;
1081 
1082   LLT S1 = LLT::scalar(1);
1083   LLT S32 = LLT::scalar(32);
1084   LLT S96 = LLT::scalar(96);
1085   DefineLegalizerInfo(A, {
1086     getActionDefinitionsBuilder({G_USUBO, G_USUBE})
1087         .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1088   });
1089 
1090   auto Op0 = B.buildUndef(S96);
1091   auto Op1 = B.buildUndef(S96);
1092   auto USUBO = B.buildUSubo(S96, S1, Op0, Op1);
1093 
1094   AInfo Info(MF->getSubtarget());
1095   DummyGISelObserver Observer;
1096   LegalizerHelper Helper(*MF, Info, Observer, B);
1097   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1098             Helper.narrowScalar(*USUBO, 0, S32));
1099 
1100   const char *CheckStr = R"(
1101   CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1102   CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1103   CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1104   CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1105   CHECK: [[USUBO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBO [[OP0_0]]:_, [[OP1_0]]:_
1106   CHECK: [[USUBO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1107   CHECK: [[USUBO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_USUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1108   CHECK: [[USUBO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[USUBO0]]:_(s32), [[USUBO1]]:_(s32), [[USUBO2]]:_(s32)
1109   )";
1110 
1111   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1112 }
1113 
1114 TEST_F(AArch64GISelMITest, NarrowSADDO) {
1115   setUp();
1116   if (!TM)
1117     return;
1118 
1119   LLT S1 = LLT::scalar(1);
1120   LLT S32 = LLT::scalar(32);
1121   LLT S96 = LLT::scalar(96);
1122   DefineLegalizerInfo(A, {
1123     getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_SADDE})
1124         .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1125   });
1126 
1127   auto Op0 = B.buildUndef(S96);
1128   auto Op1 = B.buildUndef(S96);
1129   auto SADDO = B.buildSAddo(S96, S1, Op0, Op1);
1130 
1131   AInfo Info(MF->getSubtarget());
1132   DummyGISelObserver Observer;
1133   LegalizerHelper Helper(*MF, Info, Observer, B);
1134   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1135             Helper.narrowScalar(*SADDO, 0, S32));
1136 
1137   const char *CheckStr = R"(
1138   CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1139   CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1140   CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1141   CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1142   CHECK: [[SADDO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDO [[OP0_0]]:_, [[OP1_0]]:_
1143   CHECK: [[SADDO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1144   CHECK: [[SADDO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1145   CHECK: [[SADDO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SADDO0]]:_(s32), [[SADDO1]]:_(s32), [[SADDO2]]:_(s32)
1146   )";
1147 
1148   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1149 }
1150 
1151 TEST_F(AArch64GISelMITest, NarrowSSUBO) {
1152   setUp();
1153   if (!TM)
1154     return;
1155 
1156   LLT S1 = LLT::scalar(1);
1157   LLT S32 = LLT::scalar(32);
1158   LLT S96 = LLT::scalar(96);
1159   DefineLegalizerInfo(A, {
1160     getActionDefinitionsBuilder({G_USUBO, G_USUBE, G_SSUBE})
1161         .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1162   });
1163 
1164   auto Op0 = B.buildUndef(S96);
1165   auto Op1 = B.buildUndef(S96);
1166   auto SSUBO = B.buildSSubo(S96, S1, Op0, Op1);
1167 
1168   AInfo Info(MF->getSubtarget());
1169   DummyGISelObserver Observer;
1170   LegalizerHelper Helper(*MF, Info, Observer, B);
1171   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1172             Helper.narrowScalar(*SSUBO, 0, S32));
1173 
1174   const char *CheckStr = R"(
1175   CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1176   CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1177   CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1178   CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1179   CHECK: [[SSUBO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBO [[OP0_0]]:_, [[OP1_0]]:_
1180   CHECK: [[SSUBO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1181   CHECK: [[SSUBO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SSUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1182   CHECK: [[SSUBO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SSUBO0]]:_(s32), [[SSUBO1]]:_(s32), [[SSUBO2]]:_(s32)
1183   )";
1184 
1185   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1186 }
1187 
1188 TEST_F(AArch64GISelMITest, NarrowUADDE) {
1189   setUp();
1190   if (!TM)
1191     return;
1192 
1193   LLT S1 = LLT::scalar(1);
1194   LLT S32 = LLT::scalar(32);
1195   LLT S96 = LLT::scalar(96);
1196   DefineLegalizerInfo(A, {
1197     getActionDefinitionsBuilder(G_UADDE).legalFor(
1198         {{LLT::scalar(32), LLT::scalar(1)}});
1199   });
1200 
1201   auto Op0 = B.buildUndef(S96);
1202   auto Op1 = B.buildUndef(S96);
1203   auto Op2 = B.buildUndef(S1);
1204   auto UADDE = B.buildUAdde(S96, S1, Op0, Op1, Op2);
1205 
1206   AInfo Info(MF->getSubtarget());
1207   DummyGISelObserver Observer;
1208   LegalizerHelper Helper(*MF, Info, Observer, B);
1209   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1210             Helper.narrowScalar(*UADDE, 0, S32));
1211 
1212   const char *CheckStr = R"(
1213   CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1214   CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1215   CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1216   CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1217   CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1218   CHECK: [[UADDE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_
1219   CHECK: [[UADDE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1220   CHECK: [[UADDE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_UADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1221   CHECK: [[UADDE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[UADDE0]]:_(s32), [[UADDE1]]:_(s32), [[UADDE2]]:_(s32)
1222   )";
1223 
1224   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1225 }
1226 
1227 TEST_F(AArch64GISelMITest, NarrowUSUBE) {
1228   setUp();
1229   if (!TM)
1230     return;
1231 
1232   LLT S1 = LLT::scalar(1);
1233   LLT S32 = LLT::scalar(32);
1234   LLT S96 = LLT::scalar(96);
1235   DefineLegalizerInfo(A, {
1236     getActionDefinitionsBuilder(G_USUBE).legalFor(
1237         {{LLT::scalar(32), LLT::scalar(1)}});
1238   });
1239 
1240   auto Op0 = B.buildUndef(S96);
1241   auto Op1 = B.buildUndef(S96);
1242   auto Op2 = B.buildUndef(S1);
1243   auto USUBE = B.buildUSube(S96, S1, Op0, Op1, Op2);
1244 
1245   AInfo Info(MF->getSubtarget());
1246   DummyGISelObserver Observer;
1247   LegalizerHelper Helper(*MF, Info, Observer, B);
1248   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1249             Helper.narrowScalar(*USUBE, 0, S32));
1250 
1251   const char *CheckStr = R"(
1252   CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1253   CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1254   CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1255   CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1256   CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1257   CHECK: [[USUBE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_
1258   CHECK: [[USUBE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1259   CHECK: [[USUBE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_USUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1260   CHECK: [[USUBE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[USUBE0]]:_(s32), [[USUBE1]]:_(s32), [[USUBE2]]:_(s32)
1261   )";
1262 
1263   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1264 }
1265 
1266 TEST_F(AArch64GISelMITest, NarrowSADDE) {
1267   setUp();
1268   if (!TM)
1269     return;
1270 
1271   LLT S1 = LLT::scalar(1);
1272   LLT S32 = LLT::scalar(32);
1273   LLT S96 = LLT::scalar(96);
1274   DefineLegalizerInfo(A, {
1275     getActionDefinitionsBuilder({G_SADDE, G_UADDE})
1276         .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1277   });
1278 
1279   auto Op0 = B.buildUndef(S96);
1280   auto Op1 = B.buildUndef(S96);
1281   auto Op2 = B.buildUndef(S1);
1282   auto SADDE = B.buildSAdde(S96, S1, Op0, Op1, Op2);
1283 
1284   AInfo Info(MF->getSubtarget());
1285   DummyGISelObserver Observer;
1286   LegalizerHelper Helper(*MF, Info, Observer, B);
1287   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1288             Helper.narrowScalar(*SADDE, 0, S32));
1289 
1290   const char *CheckStr = R"(
1291   CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1292   CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1293   CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1294   CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1295   CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1296   CHECK: [[SADDE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_
1297   CHECK: [[SADDE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1298   CHECK: [[SADDE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1299   CHECK: [[SADDE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SADDE0]]:_(s32), [[SADDE1]]:_(s32), [[SADDE2]]:_(s32)
1300   )";
1301 
1302   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1303 }
1304 
1305 TEST_F(AArch64GISelMITest, NarrowSSUBE) {
1306   setUp();
1307   if (!TM)
1308     return;
1309 
1310   LLT S1 = LLT::scalar(1);
1311   LLT S32 = LLT::scalar(32);
1312   LLT S96 = LLT::scalar(96);
1313   DefineLegalizerInfo(A, {
1314     getActionDefinitionsBuilder({G_SSUBE, G_USUBE})
1315         .legalFor({{LLT::scalar(32), LLT::scalar(1)}});
1316   });
1317 
1318   auto Op0 = B.buildUndef(S96);
1319   auto Op1 = B.buildUndef(S96);
1320   auto Op2 = B.buildUndef(S1);
1321   auto SSUBE = B.buildSSube(S96, S1, Op0, Op1, Op2);
1322 
1323   AInfo Info(MF->getSubtarget());
1324   DummyGISelObserver Observer;
1325   LegalizerHelper Helper(*MF, Info, Observer, B);
1326   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1327             Helper.narrowScalar(*SSUBE, 0, S32));
1328 
1329   const char *CheckStr = R"(
1330   CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1331   CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF
1332   CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
1333   CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]
1334   CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]
1335   CHECK: [[SSUBE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_
1336   CHECK: [[SSUBE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_
1337   CHECK: [[SSUBE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SSUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_
1338   CHECK: [[SSUBE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SSUBE0]]:_(s32), [[SSUBE1]]:_(s32), [[SSUBE2]]:_(s32)
1339   )";
1340 
1341   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1342 }
1343 
1344 TEST_F(AArch64GISelMITest, FewerElementsAnd) {
1345   setUp();
1346   if (!TM)
1347     return;
1348 
1349   const LLT V2S32 = LLT::fixed_vector(2, 32);
1350   const LLT V5S32 = LLT::fixed_vector(5, 32);
1351 
1352   // Declare your legalization info
1353   DefineLegalizerInfo(A, {
1354     getActionDefinitionsBuilder(G_AND)
1355       .legalFor({s32});
1356   });
1357 
1358   auto Op0 = B.buildUndef(V5S32);
1359   auto Op1 = B.buildUndef(V5S32);
1360   auto And = B.buildAnd(V5S32, Op0, Op1);
1361 
1362   AInfo Info(MF->getSubtarget());
1363   DummyGISelObserver Observer;
1364   LegalizerHelper Helper(*MF, Info, Observer, B);
1365   B.setInstr(*And);
1366   EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) ==
1367               LegalizerHelper::LegalizeResult::Legalized);
1368 
1369   auto CheckStr = R"(
1370   CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
1371   CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
1372   CHECK: [[VALUE0:%[0-9]+]]:_(s32), [[VALUE1:%[0-9]+]]:_(s32), [[VALUE2:%[0-9]+]]:_(s32), [[VALUE3:%[0-9]+]]:_(s32), [[VALUE4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]:_(<5 x s32>)
1373   CHECK: [[IMP_DEF2:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
1374   CHECK: [[VECTOR0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE0]]:_(s32), [[VALUE1]]:_(s32)
1375   CHECK: [[VECTOR1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE2]]:_(s32), [[VALUE3]]:_(s32)
1376   CHECK: [[VECTOR2:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE4]]:_(s32), [[IMP_DEF2]]:_(s32)
1377   CHECK: [[IMP_DEF3:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
1378   CHECK: [[VALUE5:%[0-9]+]]:_(s32), [[VALUE6:%[0-9]+]]:_(s32), [[VALUE7:%[0-9]+]]:_(s32), [[VALUE8:%[0-9]+]]:_(s32), [[VALUE9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]:_(<5 x s32>)
1379   CHECK: [[IMP_DEF4:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
1380   CHECK: [[VECTOR3:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE5]]:_(s32), [[VALUE6]]:_(s32)
1381   CHECK: [[VECTOR4:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE7]]:_(s32), [[VALUE8]]:_(s32)
1382   CHECK: [[VECTOR5:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE9]]:_(s32), [[IMP_DEF4]]:_(s32)
1383   CHECK: [[IMP_DEF5:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
1384 
1385   CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[VECTOR0]]:_, [[VECTOR3]]:_
1386   CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[VECTOR1]]:_, [[VECTOR4]]:_
1387   CHECK: [[AND2:%[0-9]+]]:_(<2 x s32>) = G_AND [[VECTOR2]]:_, [[VECTOR5]]:_
1388   CHECK: [[IMP_DEF6:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
1389 
1390   CHECK: [[VECTOR6:%[0-9]+]]:_(<10 x s32>) = G_CONCAT_VECTORS [[AND0]]:_(<2 x s32>), [[AND1]]:_(<2 x s32>), [[AND2]]:_(<2 x s32>), [[IMP_DEF6]]:_(<2 x s32>), [[IMP_DEF6]]:_(<2 x s32>)
1391   CHECK: [[VECTOR7:%[0-9]+]]:_(<10 x s32>) = G_CONCAT_VECTORS [[AND0]]:_(<2 x s32>), [[AND1]]:_(<2 x s32>), [[AND2]]:_(<2 x s32>), [[IMP_DEF6]]:_(<2 x s32>), [[IMP_DEF6]]:_(<2 x s32>)
1392   CHECK: [[VECTOR8:%[0-9]+]]:_(<5 x s32>), [[VECTOR9:%[0-9]+]]:_(<5 x s32>) = G_UNMERGE_VALUES [[VECTOR7]]:_(<10 x s32>)
1393   )";
1394 
1395   // Check
1396   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1397 }
1398 
1399 TEST_F(AArch64GISelMITest, MoreElementsAnd) {
1400   setUp();
1401   if (!TM)
1402     return;
1403 
1404   LLT s32 = LLT::scalar(32);
1405   LLT v2s32 = LLT::fixed_vector(2, 32);
1406   LLT v6s32 = LLT::fixed_vector(6, 32);
1407 
1408   LegalizerInfo LI;
1409   LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
1410     .legalFor({v6s32})
1411     .clampMinNumElements(0, s32, 6);
1412   LI.getLegacyLegalizerInfo().computeTables();
1413 
1414   DummyGISelObserver Observer;
1415   LegalizerHelper Helper(*MF, LI, Observer, B);
1416 
1417   B.setInsertPt(*EntryMBB, EntryMBB->end());
1418 
1419   auto Val0 = B.buildBitcast(v2s32, Copies[0]);
1420   auto Val1 = B.buildBitcast(v2s32, Copies[1]);
1421 
1422   auto And = B.buildAnd(v2s32, Val0, Val1);
1423 
1424   B.setInstr(*And);
1425   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1426             Helper.moreElementsVector(*And, 0, v6s32));
1427 
1428   auto CheckStr = R"(
1429   CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
1430   CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
1431   CHECK: [[IMP_DEF0:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
1432   CHECK: [[CONCAT0:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>)
1433   CHECK: [[IMP_DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
1434   CHECK: [[CONCAT1:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>)
1435   CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[CONCAT0]]:_, [[CONCAT1]]:_
1436   CHECK: (<2 x s32>) = G_UNMERGE_VALUES [[AND]]:_(<6 x s32>)
1437   )";
1438 
1439   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1440 }
1441 
1442 TEST_F(AArch64GISelMITest, FewerElementsPhi) {
1443   setUp();
1444   if (!TM)
1445     return;
1446 
1447   LLT s1 = LLT::scalar(1);
1448   LLT s32 = LLT::scalar(32);
1449   LLT s64 = LLT::scalar(64);
1450   LLT v2s32 = LLT::fixed_vector(2, 32);
1451   LLT v5s32 = LLT::fixed_vector(5, 32);
1452 
1453   LegalizerInfo LI;
1454   LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
1455     .legalFor({v2s32})
1456     .clampMinNumElements(0, s32, 2);
1457   LI.getLegacyLegalizerInfo().computeTables();
1458 
1459   LLT PhiTy = v5s32;
1460   DummyGISelObserver Observer;
1461   LegalizerHelper Helper(*MF, LI, Observer, B);
1462   B.setMBB(*EntryMBB);
1463 
1464   MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock();
1465   MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock();
1466   MF->insert(MF->end(), MidMBB);
1467   MF->insert(MF->end(), EndMBB);
1468 
1469   EntryMBB->addSuccessor(MidMBB);
1470   EntryMBB->addSuccessor(EndMBB);
1471   MidMBB->addSuccessor(EndMBB);
1472 
1473   auto InitVal = B.buildUndef(PhiTy);
1474   auto InitOtherVal = B.buildConstant(s64, 999);
1475 
1476   auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
1477   B.buildBrCond(ICmp.getReg(0), *MidMBB);
1478   B.buildBr(*EndMBB);
1479 
1480 
1481   B.setMBB(*MidMBB);
1482   auto MidVal = B.buildUndef(PhiTy);
1483   auto MidOtherVal = B.buildConstant(s64, 345);
1484   B.buildBr(*EndMBB);
1485 
1486   B.setMBB(*EndMBB);
1487   auto Phi = B.buildInstr(TargetOpcode::G_PHI)
1488     .addDef(MRI->createGenericVirtualRegister(PhiTy))
1489     .addUse(InitVal.getReg(0))
1490     .addMBB(EntryMBB)
1491     .addUse(MidVal.getReg(0))
1492     .addMBB(MidMBB);
1493 
1494   // Insert another irrelevant phi to make sure the rebuild is inserted after
1495   // it.
1496   B.buildInstr(TargetOpcode::G_PHI)
1497     .addDef(MRI->createGenericVirtualRegister(s64))
1498     .addUse(InitOtherVal.getReg(0))
1499     .addMBB(EntryMBB)
1500     .addUse(MidOtherVal.getReg(0))
1501     .addMBB(MidMBB);
1502 
1503   // Add some use instruction after the phis.
1504   B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0));
1505 
1506   B.setInstr(*Phi);
1507   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1508             Helper.fewerElementsVector(*Phi, 0, v2s32));
1509 
1510   auto CheckStr = R"(
1511   CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
1512   CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 0
1513   CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 64
1514   CHECK: [[EXTRACT2:%[0-9]+]]:_(s32) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 128
1515   CHECK: G_BRCOND
1516 
1517   CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
1518   CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 0
1519   CHECK: [[EXTRACT4:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 64
1520   CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 128
1521   CHECK: G_BR
1522 
1523   CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT0]]:_(<2 x s32>), %bb.0, [[EXTRACT3]]:_(<2 x s32>), %bb.1
1524   CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT1]]:_(<2 x s32>), %bb.0, [[EXTRACT4]]:_(<2 x s32>), %bb.1
1525   CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[EXTRACT2]]:_(s32), %bb.0, [[EXTRACT5]]:_(s32), %bb.1
1526 
1527   CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI
1528 
1529   CHECK: [[UNMERGE0:%[0-9]+]]:_(s32), [[UNMERGE1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[PHI0]]:_(<2 x s32>)
1530   CHECK: [[UNMERGE2:%[0-9]+]]:_(s32), [[UNMERGE3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[PHI1]]:_(<2 x s32>)
1531   CHECK: [[BV:%[0-9]+]]:_(<5 x s32>) = G_BUILD_VECTOR [[UNMERGE0]]:_(s32), [[UNMERGE1]]:_(s32), [[UNMERGE2]]:_(s32), [[UNMERGE3]]:_(s32), [[PHI2]]:_(s32)
1532   CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[BV]]:_, [[BV]]:_
1533   )";
1534 
1535   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1536 }
1537 
1538 // FNEG expansion in terms of XOR
1539 TEST_F(AArch64GISelMITest, LowerFNEG) {
1540   setUp();
1541   if (!TM)
1542     return;
1543 
1544   // Declare your legalization info
1545   DefineLegalizerInfo(A, {
1546     getActionDefinitionsBuilder(G_FSUB).legalFor({s64});
1547   });
1548 
1549   // Build Instr. Make sure FMF are preserved.
1550   auto FAdd =
1551     B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]},
1552                  MachineInstr::MIFlag::FmNsz);
1553 
1554   // Should not propagate the flags of src instruction.
1555   auto FNeg0 =
1556     B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)},
1557                  {MachineInstr::MIFlag::FmArcp});
1558 
1559   // Preserve the one flag.
1560   auto FNeg1 =
1561     B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]},
1562                  MachineInstr::MIFlag::FmNoInfs);
1563 
1564   AInfo Info(MF->getSubtarget());
1565   DummyGISelObserver Observer;
1566   LegalizerHelper Helper(*MF, Info, Observer, B);
1567   // Perform Legalization
1568   B.setInstr(*FNeg0);
1569   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1570             Helper.lower(*FNeg0, 0, LLT::scalar(64)));
1571   B.setInstr(*FNeg1);
1572   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1573             Helper.lower(*FNeg1, 0, LLT::scalar(64)));
1574 
1575   auto CheckStr = R"(
1576   CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_
1577   CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808
1578   CHECK: [[FSUB0:%[0-9]+]]:_(s64) = G_XOR [[FADD]]:_, [[CONST0]]:_
1579   CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808
1580   CHECK: [[FSUB1:%[0-9]+]]:_(s64) = G_XOR %0:_, [[CONST1]]:_
1581   )";
1582 
1583   // Check
1584   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1585 }
1586 
1587 TEST_F(AArch64GISelMITest, LowerMinMax) {
1588   setUp();
1589   if (!TM)
1590     return;
1591 
1592   LLT s64 = LLT::scalar(64);
1593   LLT v2s32 = LLT::fixed_vector(2, 32);
1594 
1595   DefineLegalizerInfo(A, {
1596     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1597         .lowerFor({s64, LLT::fixed_vector(2, s32)});
1598   });
1599 
1600   auto SMin = B.buildSMin(s64, Copies[0], Copies[1]);
1601   auto SMax = B.buildSMax(s64, Copies[0], Copies[1]);
1602   auto UMin = B.buildUMin(s64, Copies[0], Copies[1]);
1603   auto UMax = B.buildUMax(s64, Copies[0], Copies[1]);
1604 
1605   auto VecVal0 = B.buildBitcast(v2s32, Copies[0]);
1606   auto VecVal1 = B.buildBitcast(v2s32, Copies[1]);
1607 
1608   auto SMinV = B.buildSMin(v2s32, VecVal0, VecVal1);
1609   auto SMaxV = B.buildSMax(v2s32, VecVal0, VecVal1);
1610   auto UMinV = B.buildUMin(v2s32, VecVal0, VecVal1);
1611   auto UMaxV = B.buildUMax(v2s32, VecVal0, VecVal1);
1612 
1613   AInfo Info(MF->getSubtarget());
1614   DummyGISelObserver Observer;
1615   LegalizerHelper Helper(*MF, Info, Observer, B);
1616   B.setInstr(*SMin);
1617   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1618             Helper.lower(*SMin, 0, s64));
1619   B.setInstr(*SMax);
1620   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1621             Helper.lower(*SMax, 0, s64));
1622   B.setInstr(*UMin);
1623   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1624             Helper.lower(*UMin, 0, s64));
1625   B.setInstr(*UMax);
1626   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1627             Helper.lower(*UMax, 0, s64));
1628 
1629   B.setInstr(*SMinV);
1630   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1631             Helper.lower(*SMinV, 0, v2s32));
1632   B.setInstr(*SMaxV);
1633   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1634             Helper.lower(*SMaxV, 0, v2s32));
1635   B.setInstr(*UMinV);
1636   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1637             Helper.lower(*UMinV, 0, v2s32));
1638   B.setInstr(*UMaxV);
1639   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1640             Helper.lower(*UMaxV, 0, v2s32));
1641 
1642   auto CheckStr = R"(
1643   CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_
1644   CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_
1645 
1646   CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_
1647   CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_
1648 
1649   CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_
1650   CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_
1651 
1652   CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_
1653   CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_
1654 
1655   CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
1656   CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
1657 
1658   CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1659   CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1660 
1661   CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1662   CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1663 
1664   CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1665   CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1666 
1667   CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
1668   CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
1669   )";
1670 
1671   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1672 }
1673 
1674 TEST_F(AArch64GISelMITest, WidenScalarBuildVector) {
1675   setUp();
1676   if (!TM)
1677     return;
1678 
1679   LLT S32 = LLT::scalar(32);
1680   LLT S16 = LLT::scalar(16);
1681   LLT V2S16 = LLT::fixed_vector(2, S16);
1682   LLT V2S32 = LLT::fixed_vector(2, S32);
1683 
1684   DefineLegalizerInfo(A, {
1685     getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX})
1686         .lowerFor({s64, LLT::fixed_vector(2, s32)});
1687   });
1688 
1689   AInfo Info(MF->getSubtarget());
1690   DummyGISelObserver Observer;
1691   LegalizerHelper Helper(*MF, Info, Observer, B);
1692   B.setInsertPt(*EntryMBB, EntryMBB->end());
1693 
1694   Register Constant0 = B.buildConstant(S16, 1).getReg(0);
1695   Register Constant1 = B.buildConstant(S16, 2).getReg(0);
1696   auto BV0 = B.buildBuildVector(V2S16, {Constant0, Constant1});
1697   auto BV1 = B.buildBuildVector(V2S16, {Constant0, Constant1});
1698 
1699   B.setInstr(*BV0);
1700   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1701             Helper.widenScalar(*BV0, 0, V2S32));
1702   B.setInstr(*BV1);
1703   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1704             Helper.widenScalar(*BV1, 1, S32));
1705 
1706   auto CheckStr = R"(
1707   CHECK: [[K0:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
1708   CHECK-NEXT: [[K1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
1709   CHECK-NEXT: [[EXT_K0_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
1710   CHECK-NEXT: [[EXT_K1_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
1711   CHECK-NEXT: [[BV0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[EXT_K0_0]]:_(s32), [[EXT_K1_0]]:_(s32)
1712   CHECK-NEXT: [[BV0_TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BV0]]
1713 
1714   CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
1715   CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
1716 
1717   CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32)
1718   )";
1719 
1720   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1721 }
1722 
1723 TEST_F(AArch64GISelMITest, LowerMergeValues) {
1724   setUp();
1725   if (!TM)
1726     return;
1727 
1728   const LLT S32 = LLT::scalar(32);
1729   const LLT S24 = LLT::scalar(24);
1730   const LLT S21 = LLT::scalar(21);
1731   const LLT S16 = LLT::scalar(16);
1732   const LLT S9 = LLT::scalar(9);
1733   const LLT S8 = LLT::scalar(8);
1734   const LLT S3 = LLT::scalar(3);
1735 
1736   DefineLegalizerInfo(A, {
1737     getActionDefinitionsBuilder(G_UNMERGE_VALUES)
1738       .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9)));
1739   });
1740 
1741   AInfo Info(MF->getSubtarget());
1742   DummyGISelObserver Observer;
1743   LegalizerHelper Helper(*MF, Info, Observer, B);
1744   B.setInsertPt(*EntryMBB, EntryMBB->end());
1745 
1746   // 24 = 3 3 3   3 3 3   3 3
1747   //     => 9
1748   //
1749   // This can do 3 merges, but need an extra implicit_def.
1750   SmallVector<Register, 8> Merge0Ops;
1751   for (int I = 0; I != 8; ++I)
1752     Merge0Ops.push_back(B.buildConstant(S3, I).getReg(0));
1753 
1754   auto Merge0 = B.buildMerge(S24, Merge0Ops);
1755 
1756   // 21 = 3 3 3   3 3 3   3
1757   //     => 9, 2 extra implicit_def needed
1758   //
1759   SmallVector<Register, 8> Merge1Ops;
1760   for (int I = 0; I != 7; ++I)
1761     Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0));
1762 
1763   auto Merge1 = B.buildMerge(S21, Merge1Ops);
1764 
1765   SmallVector<Register, 8> Merge2Ops;
1766   for (int I = 0; I != 2; ++I)
1767     Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0));
1768 
1769   auto Merge2 = B.buildMerge(S16, Merge2Ops);
1770 
1771   B.setInstr(*Merge0);
1772   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1773             Helper.widenScalar(*Merge0, 1, S9));
1774   B.setInstr(*Merge1);
1775   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1776             Helper.widenScalar(*Merge1, 1, S9));
1777 
1778   // Request a source size greater than the original destination size.
1779   B.setInstr(*Merge2);
1780   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1781             Helper.widenScalar(*Merge2, 1, S32));
1782 
1783   auto CheckStr = R"(
1784   CHECK: [[K0:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
1785   CHECK-NEXT: [[K1:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
1786   CHECK-NEXT: [[K2:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
1787   CHECK-NEXT: [[K3:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
1788   CHECK-NEXT: [[K4:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
1789   CHECK-NEXT: [[K5:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1790   CHECK-NEXT: [[K6:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1791   CHECK-NEXT: [[K7:%[0-9]+]]:_(s3) = G_CONSTANT i3 -1
1792   CHECK-NEXT: [[IMPDEF0:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1793   CHECK-NEXT: [[MERGE0:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K0]]:_(s3), [[K1]]:_(s3), [[K2]]:_(s3)
1794   CHECK-NEXT: [[MERGE1:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K3]]:_(s3), [[K4]]:_(s3), [[K5]]:_(s3)
1795   CHECK-NEXT: [[MERGE2:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K6]]:_(s3), [[K7]]:_(s3), [[IMPDEF0]]:_(s3)
1796   CHECK-NEXT: [[MERGE3:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE0]]:_(s9), [[MERGE1]]:_(s9), [[MERGE2]]:_(s9)
1797   CHECK-NEXT: (s24) = G_TRUNC [[MERGE3]]:_(s27)
1798 
1799 
1800   CHECK: [[K8:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
1801   CHECK-NEXT: [[K9:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
1802   CHECK-NEXT: [[K10:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
1803   CHECK-NEXT: [[K11:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
1804   CHECK-NEXT: [[K12:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
1805   CHECK-NEXT: [[K13:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1806   CHECK-NEXT: [[K14:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1807   CHECK-NEXT: [[IMPDEF1:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1808   CHECK-NEXT: [[MERGE4:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K8]]:_(s3), [[K9]]:_(s3), [[K10]]:_(s3)
1809   CHECK-NEXT: [[MERGE5:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K11]]:_(s3), [[K12]]:_(s3), [[K13]]:_(s3)
1810   CHECK-NEXT: [[MERGE6:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K14]]:_(s3), [[IMPDEF1]]:_(s3), [[IMPDEF1]]:_(s3)
1811   CHECK-NEXT: [[MERGE7:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE4]]:_(s9), [[MERGE5]]:_(s9), [[MERGE6]]:_(s9)
1812   CHECK-NEXT: (s21) = G_TRUNC [[MERGE7]]:_(s27)
1813 
1814 
1815   CHECK: [[K15:%[0-9]+]]:_(s8) = G_CONSTANT i8 0
1816   CHECK-NEXT: [[K16:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
1817   CHECK-NEXT: [[ZEXT_K15:[0-9]+]]:_(s32) = G_ZEXT [[K15]]:_(s8)
1818   CHECK-NEXT: [[ZEXT_K16:[0-9]+]]:_(s32) = G_ZEXT [[K16]]:_(s8)
1819   [[K16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1820   [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT_K16]]:_, [[K16]]:_(s32)
1821   [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT_K16]]:_, [[SHL]]:_
1822   (s16) = G_TRUNC [[OR]]:_(s32)
1823   )";
1824 
1825   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1826 }
1827 
1828 TEST_F(AArch64GISelMITest, WidenScalarMergeValuesPointer) {
1829   setUp();
1830   if (!TM)
1831     return;
1832 
1833   DefineLegalizerInfo(A, {});
1834 
1835   AInfo Info(MF->getSubtarget());
1836   DummyGISelObserver Observer;
1837   LegalizerHelper Helper(*MF, Info, Observer, B);
1838   B.setInsertPt(*EntryMBB, EntryMBB->end());
1839 
1840   const LLT S32 = LLT::scalar(32);
1841   const LLT S64 = LLT::scalar(64);
1842   const LLT P0 = LLT::pointer(0, 64);
1843 
1844   auto Lo = B.buildTrunc(S32, Copies[0]);
1845   auto Hi = B.buildTrunc(S32, Copies[1]);
1846 
1847   auto Merge = B.buildMerge(P0, {Lo, Hi});
1848 
1849   B.setInstr(*Merge);
1850   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
1851             Helper.widenScalar(*Merge, 1, S64));
1852 
1853   auto CheckStr = R"(
1854    CHECK: [[TRUNC0:%[0-9]+]]:_(s32) = G_TRUNC
1855    CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC
1856    CHECK: [[ZEXT_TRUNC0:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC0]]
1857    CHECK: [[ZEXT_TRUNC1:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC1]]
1858    CHECK: [[SHIFT_AMT:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
1859    CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT_TRUNC1]]:_, [[SHIFT_AMT]]
1860    CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[ZEXT_TRUNC0]]:_, [[SHL]]
1861    CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]:_(s64)
1862   )";
1863 
1864   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1865 }
1866 
1867 TEST_F(AArch64GISelMITest, WidenSEXTINREG) {
1868   setUp();
1869   if (!TM)
1870     return;
1871 
1872   // Declare your legalization info
1873   DefineLegalizerInfo(A, {
1874     getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1875   });
1876   // Build Instr
1877   auto MIB = B.buildInstr(
1878       TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1879       {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1880        uint64_t(8)});
1881   AInfo Info(MF->getSubtarget());
1882   DummyGISelObserver Observer;
1883   LegalizerHelper Helper(*MF, Info, Observer, B);
1884   // Perform Legalization
1885   B.setInstr(*MIB);
1886   ASSERT_TRUE(Helper.widenScalar(*MIB, 0, LLT::scalar(64)) ==
1887               LegalizerHelper::LegalizeResult::Legalized);
1888 
1889   auto CheckStr = R"(
1890   CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1891   CHECK: [[T1:%[0-9]+]]:_(s64) = G_ANYEXT [[T0]]:_(s32)
1892   CHECK: [[T2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[T1]]:_, 8
1893   CHECK: [[T3:%[0-9]+]]:_(s32) = G_TRUNC [[T2]]:_(s64)
1894   )";
1895 
1896   // Check
1897   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1898 }
1899 
1900 TEST_F(AArch64GISelMITest, NarrowSEXTINREG) {
1901   setUp();
1902   if (!TM)
1903     return;
1904 
1905   // Declare your legalization info, these aren't actually relevant to the test.
1906   DefineLegalizerInfo(A, {
1907     getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64});
1908   });
1909   // Build Instr
1910   auto MIB = B.buildInstr(
1911       TargetOpcode::G_SEXT_INREG, {LLT::scalar(16)},
1912       {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(16)}, {Copies[0]}),
1913        uint64_t(8)});
1914   AInfo Info(MF->getSubtarget());
1915   DummyGISelObserver Observer;
1916   LegalizerHelper Helper(*MF, Info, Observer, B);
1917   // Perform Legalization
1918   B.setInstr(*MIB);
1919   ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(10)) ==
1920               LegalizerHelper::LegalizeResult::Legalized);
1921 
1922   auto CheckStr = R"(
1923   CHECK: [[T0:%[0-9]+]]:_(s16) = G_TRUNC
1924   CHECK: [[T1:%[0-9]+]]:_(s10) = G_TRUNC [[T0]]:_(s16)
1925   CHECK: [[T2:%[0-9]+]]:_(s10) = G_SEXT_INREG [[T1]]:_, 8
1926   CHECK: [[T3:%[0-9]+]]:_(s16) = G_SEXT [[T2]]:_(s10)
1927   )";
1928 
1929   // Check
1930   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
1931 }
1932 
1933 TEST_F(AArch64GISelMITest, NarrowSEXTINREG2) {
1934   setUp();
1935   if (!TM)
1936     return;
1937 
1938   // Declare your legalization info, these aren't actually relevant to the test.
1939   DefineLegalizerInfo(
1940       A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
1941   // Build Instr
1942   auto MIB = B.buildInstr(
1943       TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1944       {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1945        uint64_t(9)});
1946   AInfo Info(MF->getSubtarget());
1947   DummyGISelObserver Observer;
1948   LegalizerHelper Helper(*MF, Info, Observer, B);
1949   // Perform Legalization
1950   B.setInstr(*MIB);
1951   ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(8)) ==
1952               LegalizerHelper::LegalizeResult::Legalized);
1953 
1954   auto CheckStr = R"(
1955   CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1956   CHECK: [[T1:%[0-9]+]]:_(s8), [[T2:%[0-9]+]]:_(s8), [[T3:%[0-9]+]]:_(s8), [[T4:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[T0]]:_(s32)
1957   CHECK: [[CST2:%[0-9]+]]:_(s8) = G_CONSTANT i8 7
1958   CHECK: [[T5:%[0-9]+]]:_(s8) = G_SEXT_INREG [[T2]]:_, 1
1959   CHECK: [[T6:%[0-9]+]]:_(s8) = G_ASHR [[T5]]:_, [[CST2]]:_
1960   CHECK: [[T7:%[0-9]+]]:_(s32) = G_MERGE_VALUES [[T1]]:_(s8), [[T5]]:_(s8), [[T6]]:_(s8), [[T6]]:_(s8)
1961   )";
1962 
1963   // Check
1964   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1965 }
1966 
1967 TEST_F(AArch64GISelMITest, LowerSEXTINREG) {
1968   setUp();
1969   if (!TM)
1970     return;
1971 
1972   // Declare your legalization info, these aren't actually relevant to the test.
1973   DefineLegalizerInfo(
1974       A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); });
1975   // Build Instr
1976   auto MIB = B.buildInstr(
1977       TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)},
1978       {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}),
1979        uint64_t(8)});
1980   AInfo Info(MF->getSubtarget());
1981   DummyGISelObserver Observer;
1982   LegalizerHelper Helper(*MF, Info, Observer, B);
1983   // Perform Legalization
1984   B.setInstr(*MIB);
1985   ASSERT_TRUE(Helper.lower(*MIB, 0, LLT()) ==
1986               LegalizerHelper::LegalizeResult::Legalized);
1987 
1988   auto CheckStr = R"(
1989   CHECK: [[T1:%[0-9]+]]:_(s32) = G_TRUNC
1990   CHECK: [[CST:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
1991   CHECK: [[T2:%[0-9]+]]:_(s32) = G_SHL [[T1]]:_, [[CST]]:_
1992   CHECK: [[T3:%[0-9]+]]:_(s32) = G_ASHR [[T2]]:_, [[CST]]:_
1993   )";
1994 
1995   // Check
1996   ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
1997 }
1998 
1999 TEST_F(AArch64GISelMITest, LibcallFPExt) {
2000   setUp();
2001   if (!TM)
2002     return;
2003 
2004   // Declare your legalization info
2005   DefineLegalizerInfo(A, {
2006     getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s32, s16}, {s128, s64}});
2007   });
2008 
2009   LLT S16{LLT::scalar(16)};
2010   LLT S32{LLT::scalar(32)};
2011   LLT S128{LLT::scalar(128)};
2012   auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
2013   auto MIBFPExt1 =
2014       B.buildInstr(TargetOpcode::G_FPEXT, {S32}, {MIBTrunc});
2015 
2016   auto MIBFPExt2 =
2017       B.buildInstr(TargetOpcode::G_FPEXT, {S128}, {Copies[1]});
2018   AInfo Info(MF->getSubtarget());
2019   DummyGISelObserver Observer;
2020   LegalizerHelper Helper(*MF, Info, Observer, B);
2021   LostDebugLocObserver DummyLocObserver("");
2022   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2023               Helper.libcall(*MIBFPExt1, DummyLocObserver));
2024 
2025   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2026               Helper.libcall(*MIBFPExt2, DummyLocObserver));
2027   auto CheckStr = R"(
2028   CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC
2029   CHECK: $h0 = COPY [[TRUNC]]
2030   CHECK: BL &__gnu_h2f_ieee
2031   CHECK: $d0 = COPY
2032   CHECK: BL &__extenddftf2
2033   )";
2034 
2035   // Check
2036   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2037 }
2038 
2039 TEST_F(AArch64GISelMITest, LibcallFPTrunc) {
2040   setUp();
2041   if (!TM)
2042     return;
2043 
2044   // Declare your legalization info
2045   DefineLegalizerInfo(A, {
2046     getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s16, s32}, {s64, s128}});
2047   });
2048 
2049   LLT S16{LLT::scalar(16)};
2050   LLT S32{LLT::scalar(32)};
2051   LLT S64{LLT::scalar(64)};
2052   LLT S128{LLT::scalar(128)};
2053   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2054   auto MIBFPTrunc1 =
2055       B.buildInstr(TargetOpcode::G_FPTRUNC, {S16}, {MIBTrunc});
2056 
2057   auto MIBMerge = B.buildMerge(S128, {Copies[1], Copies[2]});
2058 
2059   auto MIBFPTrunc2 =
2060       B.buildInstr(TargetOpcode::G_FPTRUNC, {S64}, {MIBMerge});
2061   AInfo Info(MF->getSubtarget());
2062   DummyGISelObserver Observer;
2063   LostDebugLocObserver DummyLocObserver("");
2064   LegalizerHelper Helper(*MF, Info, Observer, B);
2065   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2066             Helper.libcall(*MIBFPTrunc1, DummyLocObserver));
2067 
2068   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2069             Helper.libcall(*MIBFPTrunc2, DummyLocObserver));
2070   auto CheckStr = R"(
2071   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2072   CHECK: $s0 = COPY [[TRUNC]]
2073   CHECK: BL &__gnu_f2h_ieee
2074   CHECK: $q0 = COPY
2075   CHECK: BL &__trunctfdf2
2076   )";
2077 
2078   // Check
2079   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2080 }
2081 
2082 TEST_F(AArch64GISelMITest, LibcallSimple) {
2083   setUp();
2084   if (!TM)
2085     return;
2086 
2087   // Declare your legalization info
2088   DefineLegalizerInfo(A, {
2089     getActionDefinitionsBuilder(G_FADD).libcallFor({s16});
2090   });
2091 
2092   LLT S16{LLT::scalar(16)};
2093   auto MIBTrunc = B.buildTrunc(S16, Copies[0]);
2094   auto MIBFADD =
2095       B.buildInstr(TargetOpcode::G_FADD, {S16}, {MIBTrunc, MIBTrunc});
2096 
2097   AInfo Info(MF->getSubtarget());
2098   DummyGISelObserver Observer;
2099   LostDebugLocObserver DummyLocObserver("");
2100   LegalizerHelper Helper(*MF, Info, Observer, B);
2101   // Make sure we do not crash anymore
2102   EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
2103             Helper.libcall(*MIBFADD, DummyLocObserver));
2104 }
2105 
2106 TEST_F(AArch64GISelMITest, LibcallSRem) {
2107   setUp();
2108   if (!TM)
2109     return;
2110 
2111   // Declare your legalization info
2112   DefineLegalizerInfo(A, {
2113     getActionDefinitionsBuilder(G_SREM).libcallFor({s32, s64, s128});
2114   });
2115 
2116   LLT S32{LLT::scalar(32)};
2117   LLT S64{LLT::scalar(64)};
2118   LLT S128{LLT::scalar(128)};
2119   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2120   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2121 
2122   auto MIBSRem32 =
2123       B.buildInstr(TargetOpcode::G_SREM, {S32}, {MIBTrunc, MIBTrunc});
2124   auto MIBSRem64 =
2125       B.buildInstr(TargetOpcode::G_SREM, {S64}, {Copies[0], Copies[0]});
2126   auto MIBSRem128 =
2127       B.buildInstr(TargetOpcode::G_SREM, {S128}, {MIBExt, MIBExt});
2128 
2129   AInfo Info(MF->getSubtarget());
2130   DummyGISelObserver Observer;
2131   LostDebugLocObserver DummyLocObserver("");
2132   LegalizerHelper Helper(*MF, Info, Observer, B);
2133 
2134   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2135             Helper.libcall(*MIBSRem32, DummyLocObserver));
2136   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2137             Helper.libcall(*MIBSRem64, DummyLocObserver));
2138   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2139             Helper.libcall(*MIBSRem128, DummyLocObserver));
2140 
2141   auto CheckStr = R"(
2142   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2143   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2144   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2145   CHECK: $w0 = COPY [[TRUNC]]
2146   CHECK: $w1 = COPY [[TRUNC]]
2147   CHECK: BL &__modsi3
2148   CHECK: $x0 = COPY [[COPY]]
2149   CHECK: $x1 = COPY [[COPY]]
2150   CHECK: BL &__moddi3
2151   CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2152   CHECK: $x0 = COPY [[UV]]
2153   CHECK: $x1 = COPY [[UV1]]
2154   CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2155   CHECK: $x2 = COPY [[UV2]]
2156   CHECK: $x3 = COPY [[UV3]]
2157   CHECK: BL &__modti3
2158   )";
2159 
2160   // Check
2161   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2162 }
2163 
2164 TEST_F(AArch64GISelMITest, LibcallURem) {
2165   setUp();
2166   if (!TM)
2167     return;
2168 
2169   // Declare your legalization info
2170   DefineLegalizerInfo(A, {
2171     getActionDefinitionsBuilder(G_UREM).libcallFor({s32, s64, s128});
2172   });
2173 
2174   LLT S32{LLT::scalar(32)};
2175   LLT S64{LLT::scalar(64)};
2176   LLT S128{LLT::scalar(128)};
2177   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2178   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2179 
2180   auto MIBURem32 =
2181       B.buildInstr(TargetOpcode::G_UREM, {S32}, {MIBTrunc, MIBTrunc});
2182   auto MIBURem64 =
2183       B.buildInstr(TargetOpcode::G_UREM, {S64}, {Copies[0], Copies[0]});
2184   auto MIBURem128 =
2185       B.buildInstr(TargetOpcode::G_UREM, {S128}, {MIBExt, MIBExt});
2186 
2187   AInfo Info(MF->getSubtarget());
2188   DummyGISelObserver Observer;
2189   LostDebugLocObserver DummyLocObserver("");
2190   LegalizerHelper Helper(*MF, Info, Observer, B);
2191 
2192   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2193             Helper.libcall(*MIBURem32, DummyLocObserver));
2194   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2195             Helper.libcall(*MIBURem64, DummyLocObserver));
2196   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2197             Helper.libcall(*MIBURem128, DummyLocObserver));
2198 
2199   const auto *CheckStr = R"(
2200   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2201   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2202   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2203   CHECK: $w0 = COPY [[TRUNC]]
2204   CHECK: $w1 = COPY [[TRUNC]]
2205   CHECK: BL &__umodsi3
2206   CHECK: $x0 = COPY [[COPY]]
2207   CHECK: $x1 = COPY [[COPY]]
2208   CHECK: BL &__umoddi3
2209   CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2210   CHECK: $x0 = COPY [[UV]]
2211   CHECK: $x1 = COPY [[UV1]]
2212   CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2213   CHECK: $x2 = COPY [[UV2]]
2214   CHECK: $x3 = COPY [[UV3]]
2215   CHECK: BL &__umodti3
2216   )";
2217 
2218   // Check
2219   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2220 }
2221 
2222 TEST_F(AArch64GISelMITest, LibcallCtlzZeroUndef) {
2223   setUp();
2224   if (!TM)
2225     return;
2226 
2227   // Declare your legalization info
2228   DefineLegalizerInfo(A, {
2229     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF)
2230         .libcallFor({{s32, s32}, {s64, s64}, {s128, s128}});
2231   });
2232 
2233   LLT S32{LLT::scalar(32)};
2234   LLT S64{LLT::scalar(64)};
2235   LLT S128{LLT::scalar(128)};
2236   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2237   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2238 
2239   auto MIBCtlz32 =
2240       B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S32}, {MIBTrunc});
2241   auto MIBCtlz64 =
2242       B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S64}, {Copies[0]});
2243   auto MIBCtlz128 =
2244       B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S128}, {MIBExt});
2245 
2246   AInfo Info(MF->getSubtarget());
2247   DummyGISelObserver Observer;
2248   LostDebugLocObserver DummyLocObserver("");
2249   LegalizerHelper Helper(*MF, Info, Observer, B);
2250 
2251   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2252             Helper.libcall(*MIBCtlz32, DummyLocObserver));
2253   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2254             Helper.libcall(*MIBCtlz64, DummyLocObserver));
2255   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2256             Helper.libcall(*MIBCtlz128, DummyLocObserver));
2257 
2258   const auto *CheckStr = R"(
2259   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2260   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2261   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2262   CHECK: $w0 = COPY [[TRUNC]]
2263   CHECK: BL &__clzsi2
2264   CHECK: $x0 = COPY [[COPY]]
2265   CHECK: BL &__clzdi2
2266   CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]]
2267   CHECK: $x0 = COPY [[UV]]
2268   CHECK: $x1 = COPY [[UV1]]
2269   CHECK: BL &__clzti2
2270   )";
2271 
2272   // Check
2273   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2274 }
2275 
2276 TEST_F(AArch64GISelMITest, LibcallFAdd) {
2277   setUp();
2278   if (!TM)
2279     return;
2280 
2281   // Declare your legalization info
2282   DefineLegalizerInfo(A, {
2283     getActionDefinitionsBuilder(G_FADD).libcallFor({s32, s64, s128});
2284   });
2285 
2286   LLT S32{LLT::scalar(32)};
2287   LLT S64{LLT::scalar(64)};
2288   LLT S128{LLT::scalar(128)};
2289   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2290   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2291 
2292   auto MIBAdd32 =
2293       B.buildInstr(TargetOpcode::G_FADD, {S32}, {MIBTrunc, MIBTrunc});
2294   auto MIBAdd64 =
2295       B.buildInstr(TargetOpcode::G_FADD, {S64}, {Copies[0], Copies[0]});
2296   auto MIBAdd128 = B.buildInstr(TargetOpcode::G_FADD, {S128}, {MIBExt, MIBExt});
2297 
2298   AInfo Info(MF->getSubtarget());
2299   DummyGISelObserver Observer;
2300   LostDebugLocObserver DummyLocObserver("");
2301   LegalizerHelper Helper(*MF, Info, Observer, B);
2302 
2303   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2304             Helper.libcall(*MIBAdd32, DummyLocObserver));
2305   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2306             Helper.libcall(*MIBAdd64, DummyLocObserver));
2307   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2308             Helper.libcall(*MIBAdd128, DummyLocObserver));
2309 
2310   const auto *CheckStr = R"(
2311   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2312   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2313   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2314   CHECK: $s0 = COPY [[TRUNC]]
2315   CHECK: $s1 = COPY [[TRUNC]]
2316   CHECK: BL &__addsf3
2317   CHECK: $d0 = COPY [[COPY]]
2318   CHECK: $d1 = COPY [[COPY]]
2319   CHECK: BL &__adddf3
2320   CHECK: $q0 = COPY [[ANYEXT]]
2321   CHECK: $q1 = COPY [[ANYEXT]]
2322   CHECK: BL &__addtf3
2323   )";
2324 
2325   // Check
2326   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2327 }
2328 
2329 TEST_F(AArch64GISelMITest, LibcallFSub) {
2330   setUp();
2331   if (!TM)
2332     return;
2333 
2334   // Declare your legalization info
2335   DefineLegalizerInfo(A, {
2336     getActionDefinitionsBuilder(G_FSUB).libcallFor({s32, s64, s128});
2337   });
2338 
2339   LLT S32{LLT::scalar(32)};
2340   LLT S64{LLT::scalar(64)};
2341   LLT S128{LLT::scalar(128)};
2342   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2343   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2344 
2345   auto MIBSub32 =
2346       B.buildInstr(TargetOpcode::G_FSUB, {S32}, {MIBTrunc, MIBTrunc});
2347   auto MIBSub64 =
2348       B.buildInstr(TargetOpcode::G_FSUB, {S64}, {Copies[0], Copies[0]});
2349   auto MIBSub128 = B.buildInstr(TargetOpcode::G_FSUB, {S128}, {MIBExt, MIBExt});
2350 
2351   AInfo Info(MF->getSubtarget());
2352   DummyGISelObserver Observer;
2353   LostDebugLocObserver DummyLocObserver("");
2354   LegalizerHelper Helper(*MF, Info, Observer, B);
2355 
2356   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2357             Helper.libcall(*MIBSub32, DummyLocObserver));
2358   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2359             Helper.libcall(*MIBSub64, DummyLocObserver));
2360   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2361             Helper.libcall(*MIBSub128, DummyLocObserver));
2362 
2363   const auto *CheckStr = R"(
2364   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2365   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2366   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2367   CHECK: $s0 = COPY [[TRUNC]]
2368   CHECK: $s1 = COPY [[TRUNC]]
2369   CHECK: BL &__subsf3
2370   CHECK: $d0 = COPY [[COPY]]
2371   CHECK: $d1 = COPY [[COPY]]
2372   CHECK: BL &__subdf3
2373   CHECK: $q0 = COPY [[ANYEXT]]
2374   CHECK: $q1 = COPY [[ANYEXT]]
2375   CHECK: BL &__subtf3
2376   )";
2377 
2378   // Check
2379   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2380 }
2381 
2382 TEST_F(AArch64GISelMITest, LibcallFMul) {
2383   setUp();
2384   if (!TM)
2385     return;
2386 
2387   // Declare your legalization info
2388   DefineLegalizerInfo(A, {
2389     getActionDefinitionsBuilder(G_FMUL).libcallFor({s32, s64, s128});
2390   });
2391 
2392   LLT S32{LLT::scalar(32)};
2393   LLT S64{LLT::scalar(64)};
2394   LLT S128{LLT::scalar(128)};
2395   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2396   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2397 
2398   auto MIBMul32 =
2399       B.buildInstr(TargetOpcode::G_FMUL, {S32}, {MIBTrunc, MIBTrunc});
2400   auto MIBMul64 =
2401       B.buildInstr(TargetOpcode::G_FMUL, {S64}, {Copies[0], Copies[0]});
2402   auto MIBMul128 = B.buildInstr(TargetOpcode::G_FMUL, {S128}, {MIBExt, MIBExt});
2403 
2404   AInfo Info(MF->getSubtarget());
2405   DummyGISelObserver Observer;
2406   LegalizerHelper Helper(*MF, Info, Observer, B);
2407   LostDebugLocObserver DummyLocObserver("");
2408 
2409   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2410             Helper.libcall(*MIBMul32, DummyLocObserver));
2411   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2412             Helper.libcall(*MIBMul64, DummyLocObserver));
2413   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2414             Helper.libcall(*MIBMul128, DummyLocObserver));
2415 
2416   const auto *CheckStr = R"(
2417   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2418   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2419   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2420   CHECK: $s0 = COPY [[TRUNC]]
2421   CHECK: $s1 = COPY [[TRUNC]]
2422   CHECK: BL &__mulsf3
2423   CHECK: $d0 = COPY [[COPY]]
2424   CHECK: $d1 = COPY [[COPY]]
2425   CHECK: BL &__muldf3
2426   CHECK: $q0 = COPY [[ANYEXT]]
2427   CHECK: $q1 = COPY [[ANYEXT]]
2428   CHECK: BL &__multf3
2429   )";
2430 
2431   // Check
2432   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2433 }
2434 
2435 TEST_F(AArch64GISelMITest, LibcallFDiv) {
2436   setUp();
2437   if (!TM)
2438     return;
2439 
2440   // Declare your legalization info
2441   DefineLegalizerInfo(A, {
2442     getActionDefinitionsBuilder(G_FDIV).libcallFor({s32, s64, s128});
2443   });
2444 
2445   LLT S32{LLT::scalar(32)};
2446   LLT S64{LLT::scalar(64)};
2447   LLT S128{LLT::scalar(128)};
2448   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2449   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2450 
2451   auto MIBDiv32 =
2452       B.buildInstr(TargetOpcode::G_FDIV, {S32}, {MIBTrunc, MIBTrunc});
2453   auto MIBDiv64 =
2454       B.buildInstr(TargetOpcode::G_FDIV, {S64}, {Copies[0], Copies[0]});
2455   auto MIBDiv128 = B.buildInstr(TargetOpcode::G_FDIV, {S128}, {MIBExt, MIBExt});
2456 
2457   AInfo Info(MF->getSubtarget());
2458   DummyGISelObserver Observer;
2459   LostDebugLocObserver DummyLocObserver("");
2460   LegalizerHelper Helper(*MF, Info, Observer, B);
2461 
2462   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2463             Helper.libcall(*MIBDiv32, DummyLocObserver));
2464   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2465             Helper.libcall(*MIBDiv64, DummyLocObserver));
2466   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2467             Helper.libcall(*MIBDiv128, DummyLocObserver));
2468 
2469   const auto *CheckStr = R"(
2470   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2471   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2472   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2473   CHECK: $s0 = COPY [[TRUNC]]
2474   CHECK: $s1 = COPY [[TRUNC]]
2475   CHECK: BL &__divsf3
2476   CHECK: $d0 = COPY [[COPY]]
2477   CHECK: $d1 = COPY [[COPY]]
2478   CHECK: BL &__divdf3
2479   CHECK: $q0 = COPY [[ANYEXT]]
2480   CHECK: $q1 = COPY [[ANYEXT]]
2481   CHECK: BL &__divtf3
2482   )";
2483 
2484   // Check
2485   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2486 }
2487 
2488 TEST_F(AArch64GISelMITest, LibcallFExp) {
2489   setUp();
2490   if (!TM)
2491     return;
2492 
2493   // Declare your legalization info
2494   DefineLegalizerInfo(A, {
2495     getActionDefinitionsBuilder(G_FEXP).libcallFor({s32, s64, s128});
2496   });
2497 
2498   LLT S32{LLT::scalar(32)};
2499   LLT S64{LLT::scalar(64)};
2500   LLT S128{LLT::scalar(128)};
2501   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2502   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2503 
2504   auto MIBExp32 = B.buildInstr(TargetOpcode::G_FEXP, {S32}, {MIBTrunc});
2505   auto MIBExp64 = B.buildInstr(TargetOpcode::G_FEXP, {S64}, {Copies[0]});
2506   auto MIBExp128 = B.buildInstr(TargetOpcode::G_FEXP, {S128}, {MIBExt});
2507 
2508   AInfo Info(MF->getSubtarget());
2509   DummyGISelObserver Observer;
2510   LostDebugLocObserver DummyLocObserver("");
2511   LegalizerHelper Helper(*MF, Info, Observer, B);
2512 
2513   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2514             Helper.libcall(*MIBExp32, DummyLocObserver));
2515   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2516             Helper.libcall(*MIBExp64, DummyLocObserver));
2517   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2518             Helper.libcall(*MIBExp128, DummyLocObserver));
2519 
2520   const auto *CheckStr = R"(
2521   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2522   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2523   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2524   CHECK: $s0 = COPY [[TRUNC]]
2525   CHECK: BL &expf
2526   CHECK: $d0 = COPY [[COPY]]
2527   CHECK: BL &exp
2528   CHECK: $q0 = COPY [[ANYEXT]]
2529   CHECK: BL &expl
2530   )";
2531 
2532   // Check
2533   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2534 }
2535 
2536 TEST_F(AArch64GISelMITest, LibcallFExp2) {
2537   setUp();
2538   if (!TM)
2539     return;
2540 
2541   // Declare your legalization info
2542   DefineLegalizerInfo(A, {
2543     getActionDefinitionsBuilder(G_FEXP2).libcallFor({s32, s64, s128});
2544   });
2545 
2546   LLT S32{LLT::scalar(32)};
2547   LLT S64{LLT::scalar(64)};
2548   LLT S128{LLT::scalar(128)};
2549   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2550   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2551 
2552   auto MIBExp232 = B.buildInstr(TargetOpcode::G_FEXP2, {S32}, {MIBTrunc});
2553   auto MIBExp264 = B.buildInstr(TargetOpcode::G_FEXP2, {S64}, {Copies[0]});
2554   auto MIBExp2128 = B.buildInstr(TargetOpcode::G_FEXP2, {S128}, {MIBExt});
2555 
2556   AInfo Info(MF->getSubtarget());
2557   DummyGISelObserver Observer;
2558   LostDebugLocObserver DummyLocObserver("");
2559   LegalizerHelper Helper(*MF, Info, Observer, B);
2560 
2561   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2562             Helper.libcall(*MIBExp232, DummyLocObserver));
2563   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2564             Helper.libcall(*MIBExp264, DummyLocObserver));
2565   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2566             Helper.libcall(*MIBExp2128, DummyLocObserver));
2567 
2568   const auto *CheckStr = R"(
2569   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2570   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2571   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2572   CHECK: $s0 = COPY [[TRUNC]]
2573   CHECK: BL &exp2f
2574   CHECK: $d0 = COPY [[COPY]]
2575   CHECK: BL &exp2
2576   CHECK: $q0 = COPY [[ANYEXT]]
2577   CHECK: BL &exp2l
2578   )";
2579 
2580   // Check
2581   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2582 }
2583 
2584 TEST_F(AArch64GISelMITest, LibcallFRem) {
2585   setUp();
2586   if (!TM)
2587     return;
2588 
2589   // Declare your legalization info
2590   DefineLegalizerInfo(A, {
2591     getActionDefinitionsBuilder(G_FREM).libcallFor({s32, s64, s128});
2592   });
2593 
2594   LLT S32{LLT::scalar(32)};
2595   LLT S64{LLT::scalar(64)};
2596   LLT S128{LLT::scalar(128)};
2597   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2598   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2599 
2600   auto MIBFRem32 = B.buildInstr(TargetOpcode::G_FREM, {S32}, {MIBTrunc});
2601   auto MIBFRem64 = B.buildInstr(TargetOpcode::G_FREM, {S64}, {Copies[0]});
2602   auto MIBFRem128 = B.buildInstr(TargetOpcode::G_FREM, {S128}, {MIBExt});
2603 
2604   AInfo Info(MF->getSubtarget());
2605   DummyGISelObserver Observer;
2606   LostDebugLocObserver DummyLocObserver("");
2607   LegalizerHelper Helper(*MF, Info, Observer, B);
2608 
2609   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2610             Helper.libcall(*MIBFRem32, DummyLocObserver));
2611   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2612             Helper.libcall(*MIBFRem64, DummyLocObserver));
2613   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2614             Helper.libcall(*MIBFRem128, DummyLocObserver));
2615 
2616   const auto *CheckStr = R"(
2617   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2618   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2619   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2620   CHECK: $s0 = COPY [[TRUNC]]
2621   CHECK: BL &fmodf
2622   CHECK: $d0 = COPY [[COPY]]
2623   CHECK: BL &fmod
2624   CHECK: $q0 = COPY [[ANYEXT]]
2625   CHECK: BL &fmodl
2626   )";
2627 
2628   // Check
2629   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2630 }
2631 
2632 TEST_F(AArch64GISelMITest, LibcallFPow) {
2633   setUp();
2634   if (!TM)
2635     return;
2636 
2637   // Declare your legalization info
2638   DefineLegalizerInfo(A, {
2639     getActionDefinitionsBuilder(G_FPOW).libcallFor({s32, s64, s128});
2640   });
2641 
2642   LLT S32{LLT::scalar(32)};
2643   LLT S64{LLT::scalar(64)};
2644   LLT S128{LLT::scalar(128)};
2645   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2646   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2647 
2648   auto MIBPow32 = B.buildInstr(TargetOpcode::G_FPOW, {S32}, {MIBTrunc});
2649   auto MIBPow64 = B.buildInstr(TargetOpcode::G_FPOW, {S64}, {Copies[0]});
2650   auto MIBPow128 = B.buildInstr(TargetOpcode::G_FPOW, {S128}, {MIBExt});
2651 
2652   AInfo Info(MF->getSubtarget());
2653   DummyGISelObserver Observer;
2654   LostDebugLocObserver DummyLocObserver("");
2655   LegalizerHelper Helper(*MF, Info, Observer, B);
2656 
2657   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2658             Helper.libcall(*MIBPow32, DummyLocObserver));
2659   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2660             Helper.libcall(*MIBPow64, DummyLocObserver));
2661   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2662             Helper.libcall(*MIBPow128, DummyLocObserver));
2663 
2664   const auto *CheckStr = R"(
2665   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2666   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2667   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2668   CHECK: $s0 = COPY [[TRUNC]]
2669   CHECK: BL &powf
2670   CHECK: $d0 = COPY [[COPY]]
2671   CHECK: BL &pow
2672   CHECK: $q0 = COPY [[ANYEXT]]
2673   CHECK: BL &powl
2674   )";
2675 
2676   // Check
2677   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2678 }
2679 
2680 TEST_F(AArch64GISelMITest, LibcallFMa) {
2681   setUp();
2682   if (!TM)
2683     return;
2684 
2685   // Declare your legalization info
2686   DefineLegalizerInfo(A, {
2687     getActionDefinitionsBuilder(G_FMA).libcallFor({s32, s64, s128});
2688   });
2689 
2690   LLT S32{LLT::scalar(32)};
2691   LLT S64{LLT::scalar(64)};
2692   LLT S128{LLT::scalar(128)};
2693   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2694   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2695 
2696   auto MIBMa32 = B.buildInstr(TargetOpcode::G_FMA, {S32}, {MIBTrunc, MIBTrunc});
2697   auto MIBMa64 =
2698       B.buildInstr(TargetOpcode::G_FMA, {S64}, {Copies[0], Copies[0]});
2699   auto MIBMa128 = B.buildInstr(TargetOpcode::G_FMA, {S128}, {MIBExt, MIBExt});
2700 
2701   AInfo Info(MF->getSubtarget());
2702   DummyGISelObserver Observer;
2703   LostDebugLocObserver DummyLocObserver("");
2704   LegalizerHelper Helper(*MF, Info, Observer, B);
2705 
2706   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2707             Helper.libcall(*MIBMa32, DummyLocObserver));
2708   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2709             Helper.libcall(*MIBMa64, DummyLocObserver));
2710   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2711             Helper.libcall(*MIBMa128, DummyLocObserver));
2712 
2713   const auto *CheckStr = R"(
2714   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2715   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2716   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2717   CHECK: $s0 = COPY [[TRUNC]]
2718   CHECK: BL &fmaf
2719   CHECK: $d0 = COPY [[COPY]]
2720   CHECK: BL &fma
2721   CHECK: $q0 = COPY [[ANYEXT]]
2722   CHECK: BL &fmal
2723   )";
2724 
2725   // Check
2726   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2727 }
2728 
2729 TEST_F(AArch64GISelMITest, LibcallFCeil) {
2730   setUp();
2731   if (!TM)
2732     return;
2733 
2734   // Declare your legalization info
2735   DefineLegalizerInfo(A, {
2736     getActionDefinitionsBuilder(G_FCEIL).libcallFor({s32, s64, s128});
2737   });
2738 
2739   LLT S32{LLT::scalar(32)};
2740   LLT S64{LLT::scalar(64)};
2741   LLT S128{LLT::scalar(128)};
2742   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2743   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2744 
2745   auto MIBCeil32 = B.buildInstr(TargetOpcode::G_FCEIL, {S32}, {MIBTrunc});
2746   auto MIBCeil64 = B.buildInstr(TargetOpcode::G_FCEIL, {S64}, {Copies[0]});
2747   auto MIBCeil128 = B.buildInstr(TargetOpcode::G_FCEIL, {S128}, {MIBExt});
2748 
2749   AInfo Info(MF->getSubtarget());
2750   DummyGISelObserver Observer;
2751   LegalizerHelper Helper(*MF, Info, Observer, B);
2752   LostDebugLocObserver DummyLocObserver("");
2753 
2754   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2755             Helper.libcall(*MIBCeil32, DummyLocObserver));
2756   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2757             Helper.libcall(*MIBCeil64, DummyLocObserver));
2758   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2759             Helper.libcall(*MIBCeil128, DummyLocObserver));
2760 
2761   const auto *CheckStr = R"(
2762   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2763   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2764   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2765   CHECK: $s0 = COPY [[TRUNC]]
2766   CHECK: BL &ceilf
2767   CHECK: $d0 = COPY [[COPY]]
2768   CHECK: BL &ceil
2769   CHECK: $q0 = COPY [[ANYEXT]]
2770   CHECK: BL &ceill
2771   )";
2772 
2773   // Check
2774   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2775 }
2776 
2777 TEST_F(AArch64GISelMITest, LibcallFFloor) {
2778   setUp();
2779   if (!TM)
2780     return;
2781 
2782   // Declare your legalization info
2783   DefineLegalizerInfo(A, {
2784     getActionDefinitionsBuilder(G_FFLOOR).libcallFor({s32, s64, s128});
2785   });
2786 
2787   LLT S32{LLT::scalar(32)};
2788   LLT S64{LLT::scalar(64)};
2789   LLT S128{LLT::scalar(128)};
2790   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2791   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2792 
2793   auto MIBFloor32 = B.buildInstr(TargetOpcode::G_FFLOOR, {S32}, {MIBTrunc});
2794   auto MIBFloor64 = B.buildInstr(TargetOpcode::G_FFLOOR, {S64}, {Copies[0]});
2795   auto MIBFloor128 = B.buildInstr(TargetOpcode::G_FFLOOR, {S128}, {MIBExt});
2796 
2797   AInfo Info(MF->getSubtarget());
2798   DummyGISelObserver Observer;
2799   LegalizerHelper Helper(*MF, Info, Observer, B);
2800   LostDebugLocObserver DummyLocObserver("");
2801 
2802   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2803             Helper.libcall(*MIBFloor32, DummyLocObserver));
2804   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2805             Helper.libcall(*MIBFloor64, DummyLocObserver));
2806   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2807             Helper.libcall(*MIBFloor128, DummyLocObserver));
2808 
2809   const auto *CheckStr = R"(
2810   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2811   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2812   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2813   CHECK: $s0 = COPY [[TRUNC]]
2814   CHECK: BL &floorf
2815   CHECK: $d0 = COPY [[COPY]]
2816   CHECK: BL &floor
2817   CHECK: $q0 = COPY [[ANYEXT]]
2818   CHECK: BL &floorl
2819   )";
2820 
2821   // Check
2822   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2823 }
2824 
2825 TEST_F(AArch64GISelMITest, LibcallFMinNum) {
2826   setUp();
2827   if (!TM)
2828     return;
2829 
2830   // Declare your legalization info
2831   DefineLegalizerInfo(A, {
2832     getActionDefinitionsBuilder(G_FMINNUM).libcallFor({s32, s64, s128});
2833   });
2834 
2835   LLT S32{LLT::scalar(32)};
2836   LLT S64{LLT::scalar(64)};
2837   LLT S128{LLT::scalar(128)};
2838   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2839   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2840 
2841   auto MIBMin32 = B.buildFMinNum(S32, MIBTrunc, MIBTrunc);
2842   auto MIBMin64 = B.buildFMinNum(S64, Copies[0], Copies[0]);
2843   auto MIBMin128 = B.buildFMinNum(S128, MIBExt, MIBExt);
2844 
2845   AInfo Info(MF->getSubtarget());
2846   DummyGISelObserver Observer;
2847   LegalizerHelper Helper(*MF, Info, Observer, B);
2848   LostDebugLocObserver DummyLocObserver("");
2849 
2850   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2851             Helper.libcall(*MIBMin32, DummyLocObserver));
2852   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2853             Helper.libcall(*MIBMin64, DummyLocObserver));
2854   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2855             Helper.libcall(*MIBMin128, DummyLocObserver));
2856 
2857   const auto *CheckStr = R"(
2858   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2859   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2860   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2861   CHECK: $s0 = COPY [[TRUNC]]
2862   CHECK: $s1 = COPY [[TRUNC]]
2863   CHECK: BL &fminf
2864   CHECK: $d0 = COPY [[COPY]]
2865   CHECK: $d1 = COPY [[COPY]]
2866   CHECK: BL &fmin
2867   CHECK: $q0 = COPY [[ANYEXT]]
2868   CHECK: $q1 = COPY [[ANYEXT]]
2869   CHECK: BL &fminl
2870   )";
2871 
2872   // Check
2873   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2874 }
2875 
2876 TEST_F(AArch64GISelMITest, LibcallFMaxNum) {
2877   setUp();
2878   if (!TM)
2879     return;
2880 
2881   // Declare your legalization info
2882   DefineLegalizerInfo(A, {
2883     getActionDefinitionsBuilder(G_FMAXNUM).libcallFor({s32, s64, s128});
2884   });
2885 
2886   LLT S32{LLT::scalar(32)};
2887   LLT S64{LLT::scalar(64)};
2888   LLT S128{LLT::scalar(128)};
2889   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2890   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2891 
2892   auto MIBMax32 = B.buildFMaxNum(S32, MIBTrunc, MIBTrunc);
2893   auto MIBMax64 = B.buildFMaxNum(S64, Copies[0], Copies[0]);
2894   auto MIBMax128 = B.buildFMaxNum(S128, MIBExt, MIBExt);
2895 
2896   AInfo Info(MF->getSubtarget());
2897   DummyGISelObserver Observer;
2898   LegalizerHelper Helper(*MF, Info, Observer, B);
2899   LostDebugLocObserver DummyLocObserver("");
2900 
2901   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2902             Helper.libcall(*MIBMax32, DummyLocObserver));
2903   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2904             Helper.libcall(*MIBMax64, DummyLocObserver));
2905   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2906             Helper.libcall(*MIBMax128, DummyLocObserver));
2907 
2908   const auto *CheckStr = R"(
2909   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2910   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2911   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2912   CHECK: $s0 = COPY [[TRUNC]]
2913   CHECK: $s1 = COPY [[TRUNC]]
2914   CHECK: BL &fmaxf
2915   CHECK: $d0 = COPY [[COPY]]
2916   CHECK: $d1 = COPY [[COPY]]
2917   CHECK: BL &fmax
2918   CHECK: $q0 = COPY [[ANYEXT]]
2919   CHECK: $q1 = COPY [[ANYEXT]]
2920   CHECK: BL &fmaxl
2921   )";
2922 
2923   // Check
2924   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2925 }
2926 
2927 TEST_F(AArch64GISelMITest, LibcallFSqrt) {
2928   setUp();
2929   if (!TM)
2930     return;
2931 
2932   // Declare your legalization info
2933   DefineLegalizerInfo(A, {
2934     getActionDefinitionsBuilder(G_FSQRT).libcallFor({s32, s64, s128});
2935   });
2936 
2937   LLT S32{LLT::scalar(32)};
2938   LLT S64{LLT::scalar(64)};
2939   LLT S128{LLT::scalar(128)};
2940   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2941   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2942 
2943   auto MIBSqrt32 = B.buildInstr(TargetOpcode::G_FSQRT, {S32}, {MIBTrunc});
2944   auto MIBSqrt64 = B.buildInstr(TargetOpcode::G_FSQRT, {S64}, {Copies[0]});
2945   auto MIBSqrt128 = B.buildInstr(TargetOpcode::G_FSQRT, {S128}, {MIBExt});
2946 
2947   AInfo Info(MF->getSubtarget());
2948   DummyGISelObserver Observer;
2949   LegalizerHelper Helper(*MF, Info, Observer, B);
2950   LostDebugLocObserver DummyLocObserver("");
2951 
2952   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2953             Helper.libcall(*MIBSqrt32, DummyLocObserver));
2954   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2955             Helper.libcall(*MIBSqrt64, DummyLocObserver));
2956   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
2957             Helper.libcall(*MIBSqrt128, DummyLocObserver));
2958 
2959   const auto *CheckStr = R"(
2960   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
2961   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
2962   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
2963   CHECK: $s0 = COPY [[TRUNC]]
2964   CHECK: BL &sqrtf
2965   CHECK: $d0 = COPY [[COPY]]
2966   CHECK: BL &sqrt
2967   CHECK: $q0 = COPY [[ANYEXT]]
2968   CHECK: BL &sqrtl
2969   )";
2970 
2971   // Check
2972   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
2973 }
2974 
2975 TEST_F(AArch64GISelMITest, LibcallFRint) {
2976   setUp();
2977   if (!TM)
2978     return;
2979 
2980   // Declare your legalization info
2981   DefineLegalizerInfo(A, {
2982     getActionDefinitionsBuilder(G_FRINT).libcallFor({s32, s64, s128});
2983   });
2984 
2985   LLT S32{LLT::scalar(32)};
2986   LLT S64{LLT::scalar(64)};
2987   LLT S128{LLT::scalar(128)};
2988   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
2989   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
2990 
2991   auto MIBRint32 = B.buildInstr(TargetOpcode::G_FRINT, {S32}, {MIBTrunc});
2992   auto MIBRint64 = B.buildInstr(TargetOpcode::G_FRINT, {S64}, {Copies[0]});
2993   auto MIBRint128 = B.buildInstr(TargetOpcode::G_FRINT, {S128}, {MIBExt});
2994 
2995   AInfo Info(MF->getSubtarget());
2996   DummyGISelObserver Observer;
2997   LegalizerHelper Helper(*MF, Info, Observer, B);
2998   LostDebugLocObserver DummyLocObserver("");
2999 
3000   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3001             Helper.libcall(*MIBRint32, DummyLocObserver));
3002   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3003             Helper.libcall(*MIBRint64, DummyLocObserver));
3004   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3005             Helper.libcall(*MIBRint128, DummyLocObserver));
3006 
3007   const auto *CheckStr = R"(
3008   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3009   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
3010   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
3011   CHECK: $s0 = COPY [[TRUNC]]
3012   CHECK: BL &rintf
3013   CHECK: $d0 = COPY [[COPY]]
3014   CHECK: BL &rint
3015   CHECK: $q0 = COPY [[ANYEXT]]
3016   CHECK: BL &rintl
3017   )";
3018 
3019   // Check
3020   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3021 }
3022 
3023 TEST_F(AArch64GISelMITest, LibcallFNearbyInt) {
3024   setUp();
3025   if (!TM)
3026     return;
3027 
3028   // Declare your legalization info
3029   DefineLegalizerInfo(A, {
3030     getActionDefinitionsBuilder(G_FNEARBYINT).libcallFor({s32, s64, s128});
3031   });
3032 
3033   LLT S32{LLT::scalar(32)};
3034   LLT S64{LLT::scalar(64)};
3035   LLT S128{LLT::scalar(128)};
3036   auto MIBTrunc = B.buildTrunc(S32, Copies[0]);
3037   auto MIBExt = B.buildAnyExt(S128, Copies[0]);
3038 
3039   auto MIBNearbyInt32 =
3040       B.buildInstr(TargetOpcode::G_FNEARBYINT, {S32}, {MIBTrunc});
3041   auto MIBNearbyInt64 =
3042       B.buildInstr(TargetOpcode::G_FNEARBYINT, {S64}, {Copies[0]});
3043   auto MIBNearbyInt128 =
3044       B.buildInstr(TargetOpcode::G_FNEARBYINT, {S128}, {MIBExt});
3045 
3046   AInfo Info(MF->getSubtarget());
3047   DummyGISelObserver Observer;
3048   LegalizerHelper Helper(*MF, Info, Observer, B);
3049   LostDebugLocObserver DummyLocObserver("");
3050 
3051   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3052             Helper.libcall(*MIBNearbyInt32, DummyLocObserver));
3053   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3054             Helper.libcall(*MIBNearbyInt64, DummyLocObserver));
3055   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3056             Helper.libcall(*MIBNearbyInt128, DummyLocObserver));
3057 
3058   const auto *CheckStr = R"(
3059   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3060   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC
3061   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT
3062   CHECK: $s0 = COPY [[TRUNC]]
3063   CHECK: BL &nearbyintf
3064   CHECK: $d0 = COPY [[COPY]]
3065   CHECK: BL &nearbyint
3066   CHECK: $q0 = COPY [[ANYEXT]]
3067   CHECK: BL &nearbyintl
3068   )";
3069 
3070   // Check
3071   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3072 }
3073 
3074 TEST_F(AArch64GISelMITest, NarrowScalarExtract) {
3075   setUp();
3076   if (!TM)
3077     return;
3078 
3079   // Declare your legalization info
3080   DefineLegalizerInfo(A, {
3081     getActionDefinitionsBuilder(G_UNMERGE_VALUES).legalFor({{s32, s64}});
3082     getActionDefinitionsBuilder(G_EXTRACT).legalForTypeWithAnyImm({{s16, s32}});
3083   });
3084 
3085   LLT S16{LLT::scalar(16)};
3086   LLT S32{LLT::scalar(32)};
3087 
3088   auto MIBExtractS32 = B.buildExtract(S32, Copies[1], 32);
3089   auto MIBExtractS16 = B.buildExtract(S16, Copies[1], 0);
3090 
3091   AInfo Info(MF->getSubtarget());
3092   DummyGISelObserver Observer;
3093   LegalizerHelper Helper(*MF, Info, Observer, B);
3094 
3095   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3096             Helper.narrowScalar(*MIBExtractS32, 1, S32));
3097 
3098   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3099             Helper.narrowScalar(*MIBExtractS16, 1, S32));
3100 
3101   const auto *CheckStr = R"(
3102   CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES
3103   CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY [[UV1]]
3104   CHECK: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES
3105   CHECK: [[EXTR:%[0-9]+]]:_(s16) = G_EXTRACT [[UV3]]:_(s32), 0
3106   CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[EXTR]]
3107   )";
3108 
3109   // Check
3110   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3111 }
3112 
3113 TEST_F(AArch64GISelMITest, LowerInsert) {
3114   setUp();
3115   if (!TM)
3116     return;
3117 
3118   // Declare your legalization info
3119   DefineLegalizerInfo(A, { getActionDefinitionsBuilder(G_INSERT).lower(); });
3120 
3121   LLT S32{LLT::scalar(32)};
3122   LLT S64{LLT::scalar(64)};
3123   LLT P0{LLT::pointer(0, 64)};
3124   LLT P1{LLT::pointer(1, 32)};
3125   LLT V2S32{LLT::fixed_vector(2, 32)};
3126 
3127   auto TruncS32 = B.buildTrunc(S32, Copies[0]);
3128   auto IntToPtrP0 = B.buildIntToPtr(P0, Copies[0]);
3129   auto IntToPtrP1 = B.buildIntToPtr(P1, TruncS32);
3130   auto BitcastV2S32 = B.buildBitcast(V2S32, Copies[0]);
3131 
3132   auto InsertS64S32 = B.buildInsert(S64, Copies[0], TruncS32, 0);
3133   auto InsertS64P1 = B.buildInsert(S64, Copies[0], IntToPtrP1, 8);
3134   auto InsertP0S32 = B.buildInsert(P0, IntToPtrP0, TruncS32, 16);
3135   auto InsertP0P1 = B.buildInsert(P0, IntToPtrP0, IntToPtrP1, 4);
3136   auto InsertV2S32S32 = B.buildInsert(V2S32, BitcastV2S32, TruncS32, 32);
3137   auto InsertV2S32P1 = B.buildInsert(V2S32, BitcastV2S32, IntToPtrP1, 0);
3138 
3139   AInfo Info(MF->getSubtarget());
3140   DummyGISelObserver Observer;
3141   LegalizerHelper Helper(*MF, Info, Observer, B);
3142 
3143   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3144             Helper.lower(*InsertS64S32, 0, LLT{}));
3145 
3146   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3147             Helper.lower(*InsertS64P1, 0, LLT{}));
3148 
3149   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3150             Helper.lower(*InsertP0S32, 0, LLT{}));
3151 
3152   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3153             Helper.lower(*InsertP0P1, 0, LLT{}));
3154 
3155   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3156             Helper.lower(*InsertV2S32S32, 0, LLT{}));
3157 
3158   EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
3159             Helper.lower(*InsertV2S32P1, 0, LLT{}));
3160 
3161   const auto *CheckStr = R"(
3162   CHECK: [[S64:%[0-9]+]]:_(s64) = COPY
3163   CHECK: [[S32:%[0-9]+]]:_(s32) = G_TRUNC [[S64]]
3164   CHECK: [[P0:%[0-9]+]]:_(p0) = G_INTTOPTR [[S64]]
3165   CHECK: [[P1:%[0-9]+]]:_(p1) = G_INTTOPTR [[S32]]
3166   CHECK: [[V2S32:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[S64]]
3167   CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]]
3168   CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3169   CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[S64]]:_, [[C]]:_
3170   CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[ZEXT]]:_
3171 
3172   CHECK: [[PTRTOINT:%[0-9]+]]:_(s32) = G_PTRTOINT [[P1]]
3173   CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[PTRTOINT]]
3174   CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3175   CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
3176   CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3177   CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[S64]]:_, [[C]]:_
3178   CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
3179 
3180   CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[P0]]
3181   CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]]
3182   CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3183   CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
3184   CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3185   CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[PTRTOINT]]:_, [[C]]:_
3186   CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
3187   CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]
3188 
3189   CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[P0]]
3190   CHECK: [[PTRTOINT1:%[0-9]+]]:_(s32) = G_PTRTOINT [[P1]]
3191   CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[PTRTOINT1]]
3192   CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3193   CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
3194   CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3195   CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[PTRTOINT]]:_, [[C]]:_
3196   CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
3197   CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]
3198 
3199   CHECK: [[BITCAST:%[0-9]+]]:_(s64) = G_BITCAST [[V2S32]]
3200   CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]]
3201   CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3202   CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64)
3203   CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT
3204   CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[BITCAST]]:_, [[C]]:_
3205   CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_
3206   CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[OR]]
3207   )";
3208 
3209   // Check
3210   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3211 }
3212 
3213 // Test lowering of G_FFLOOR
3214 TEST_F(AArch64GISelMITest, LowerFFloor) {
3215   setUp();
3216   if (!TM)
3217     return;
3218 
3219   // Declare your legalization info
3220   DefineLegalizerInfo(A, {});
3221   // Build Instr
3222   auto Floor = B.buildFFloor(LLT::scalar(64), Copies[0], MachineInstr::MIFlag::FmNoInfs);
3223   AInfo Info(MF->getSubtarget());
3224   DummyGISelObserver Observer;
3225   LegalizerHelper Helper(*MF, Info, Observer, B);
3226   // Perform Legalization
3227   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3228             Helper.lower(*Floor, 0, LLT()));
3229 
3230   auto CheckStr = R"(
3231   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3232   CHECK: [[TRUNC:%[0-9]+]]:_(s64) = ninf G_INTRINSIC_TRUNC [[COPY]]
3233   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_FCONSTANT double 0.000000e+00
3234   CHECK: [[CMP0:%[0-9]+]]:_(s1) = ninf G_FCMP floatpred(olt), [[COPY]]:_(s64), [[ZERO]]:_
3235   CHECK: [[CMP1:%[0-9]+]]:_(s1) = ninf G_FCMP floatpred(one), [[COPY]]:_(s64), [[TRUNC]]:_
3236   CHECK: [[AND:%[0-9]+]]:_(s1) = G_AND [[CMP0]]:_, [[CMP1]]:_
3237   CHECK: [[ITOFP:%[0-9]+]]:_(s64) = G_SITOFP [[AND]]
3238   = ninf G_FADD [[TRUNC]]:_, [[ITOFP]]:_
3239   )";
3240 
3241   // Check
3242   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3243 }
3244 
3245 // Test lowering of G_BSWAP
3246 TEST_F(AArch64GISelMITest, LowerBSWAP) {
3247   setUp();
3248   if (!TM)
3249     return;
3250 
3251   DefineLegalizerInfo(A, {});
3252 
3253   // Make sure vector lowering doesn't assert.
3254   auto Cast = B.buildBitcast(LLT::fixed_vector(2, 32), Copies[0]);
3255   auto BSwap = B.buildBSwap(LLT::fixed_vector(2, 32), Cast);
3256   AInfo Info(MF->getSubtarget());
3257   DummyGISelObserver Observer;
3258   LegalizerHelper Helper(*MF, Info, Observer, B);
3259   // Perform Legalization
3260   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3261             Helper.lower(*BSwap, 0, LLT()));
3262 
3263   auto CheckStr = R"(
3264   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3265   CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3266   CHECK: [[K24:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
3267   CHECK: [[SPLAT24:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[K24]]:_(s32), [[K24]]:_(s32)
3268   CHECK: [[SHL0:%[0-9]+]]:_(<2 x s32>) = G_SHL [[VEC]]:_, [[SPLAT24]]
3269   CHECK: [[SHR0:%[0-9]+]]:_(<2 x s32>) = G_LSHR [[VEC]]:_, [[SPLAT24]]
3270   CHECK: [[OR0:%[0-9]+]]:_(<2 x s32>) = G_OR [[SHR0]]:_, [[SHL0]]:_
3271   CHECK: [[KMASK:%[0-9]+]]:_(s32) = G_CONSTANT i32 65280
3272   CHECK: [[SPLATMASK:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[KMASK]]:_(s32), [[KMASK]]:_(s32)
3273   CHECK: [[K8:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
3274   CHECK: [[SPLAT8:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[K8]]:_(s32), [[K8]]:_(s32)
3275   CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[VEC]]:_, [[SPLATMASK]]:_
3276   CHECK: [[SHL1:%[0-9]+]]:_(<2 x s32>) = G_SHL [[AND0]]:_, [[SPLAT8]]
3277   CHECK: [[OR1:%[0-9]+]]:_(<2 x s32>) = G_OR [[OR0]]:_, [[SHL1]]:_
3278   CHECK: [[SHR1:%[0-9]+]]:_(<2 x s32>) = G_LSHR [[VEC]]:_, [[SPLAT8]]
3279   CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[SHR1]]:_, [[SPLATMASK]]:_
3280   CHECK: [[BSWAP:%[0-9]+]]:_(<2 x s32>) = G_OR [[OR1]]:_, [[AND1]]:_
3281   )";
3282 
3283   // Check
3284   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3285 }
3286 
3287 // Test lowering of G_SDIVREM into G_SDIV and G_SREM
3288 TEST_F(AArch64GISelMITest, LowerSDIVREM) {
3289   setUp();
3290   if (!TM)
3291     return;
3292 
3293   // Declare your legalization info
3294   DefineLegalizerInfo(
3295       A, { getActionDefinitionsBuilder(G_SDIVREM).lowerFor({s64}); });
3296 
3297   LLT S64{LLT::scalar(64)};
3298 
3299   // Build Instr
3300   auto SDivrem =
3301       B.buildInstr(TargetOpcode::G_SDIVREM, {S64, S64}, {Copies[0], Copies[1]});
3302   AInfo Info(MF->getSubtarget());
3303   DummyGISelObserver Observer;
3304   LegalizerHelper Helper(*MF, Info, Observer, B);
3305   // Perform Legalization
3306   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3307             Helper.lower(*SDivrem, 0, S64));
3308 
3309   const auto *CheckStr = R"(
3310   CHECK: [[DIV:%[0-9]+]]:_(s64) = G_SDIV %0:_, %1:_
3311   CHECK: [[REM:%[0-9]+]]:_(s64) = G_SREM %0:_, %1:_
3312   )";
3313 
3314   // Check
3315   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3316 }
3317 
3318 // Test lowering of G_UDIVREM into G_UDIV and G_UREM
3319 TEST_F(AArch64GISelMITest, LowerUDIVREM) {
3320   setUp();
3321   if (!TM)
3322     return;
3323 
3324   // Declare your legalization info
3325   DefineLegalizerInfo(
3326       A, { getActionDefinitionsBuilder(G_UDIVREM).lowerFor({s64}); });
3327 
3328   LLT S64{LLT::scalar(64)};
3329 
3330   // Build Instr
3331   auto UDivrem =
3332       B.buildInstr(TargetOpcode::G_UDIVREM, {S64, S64}, {Copies[0], Copies[1]});
3333   AInfo Info(MF->getSubtarget());
3334   DummyGISelObserver Observer;
3335   LegalizerHelper Helper(*MF, Info, Observer, B);
3336   // Perform Legalization
3337   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3338             Helper.lower(*UDivrem, 0, S64));
3339 
3340   const auto *CheckStr = R"(
3341   CHECK: [[DIV:%[0-9]+]]:_(s64) = G_UDIV %0:_, %1:_
3342   CHECK: [[REM:%[0-9]+]]:_(s64) = G_UREM %0:_, %1:_
3343   )";
3344 
3345   // Check
3346   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3347 }
3348 
3349 // Test widening of G_UNMERGE_VALUES
3350 TEST_F(AArch64GISelMITest, WidenUnmerge) {
3351   setUp();
3352   if (!TM)
3353     return;
3354 
3355   DefineLegalizerInfo(A, {});
3356 
3357   // Check that widening G_UNMERGE_VALUES to a larger type than the source type
3358   // works as expected
3359   LLT P0{LLT::pointer(0, 64)};
3360   LLT S32{LLT::scalar(32)};
3361   LLT S96{LLT::scalar(96)};
3362 
3363   auto IntToPtr = B.buildIntToPtr(P0, Copies[0]);
3364   auto UnmergePtr = B.buildUnmerge(S32, IntToPtr);
3365   auto UnmergeScalar = B.buildUnmerge(S32, Copies[0]);
3366 
3367   AInfo Info(MF->getSubtarget());
3368   DummyGISelObserver Observer;
3369   LegalizerHelper Helper(*MF, Info, Observer, B);
3370 
3371   // Perform Legalization
3372   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3373             Helper.widenScalar(*UnmergePtr, 0, S96));
3374 
3375   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3376             Helper.widenScalar(*UnmergeScalar, 0, S96));
3377 
3378   const auto *CheckStr = R"(
3379   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3380   CHECK: [[PTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY]]
3381   CHECK: [[INT:%[0-9]+]]:_(s64) = G_PTRTOINT [[PTR]]
3382   CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[INT]]
3383   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]]
3384   CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32
3385   CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]]
3386   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]]
3387   CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY]]
3388   CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]]
3389   CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32
3390   CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]]
3391   CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]]
3392   )";
3393 
3394   // Check
3395   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3396 }
3397 
3398 TEST_F(AArch64GISelMITest, BitcastLoad) {
3399   setUp();
3400   if (!TM)
3401     return;
3402 
3403   LLT P0 = LLT::pointer(0, 64);
3404   LLT S32 = LLT::scalar(32);
3405   LLT V4S8 = LLT::fixed_vector(4, 8);
3406   auto Ptr = B.buildUndef(P0);
3407 
3408   DefineLegalizerInfo(A, {});
3409 
3410   MachineMemOperand *MMO = B.getMF().getMachineMemOperand(
3411       MachinePointerInfo(), MachineMemOperand::MOLoad, 4, Align(4));
3412   auto Load = B.buildLoad(V4S8, Ptr, *MMO);
3413 
3414   AInfo Info(MF->getSubtarget());
3415   DummyGISelObserver Observer;
3416   B.setInsertPt(*EntryMBB, Load->getIterator());
3417   LegalizerHelper Helper(*MF, Info, Observer, B);
3418   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3419             Helper.bitcast(*Load, 0, S32));
3420 
3421   auto CheckStr = R"(
3422   CHECK: [[PTR:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF
3423   CHECK: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD
3424   CHECK: [[CAST:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[LOAD]]
3425 
3426   )";
3427 
3428   // Check
3429   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3430 }
3431 
3432 TEST_F(AArch64GISelMITest, BitcastStore) {
3433   setUp();
3434   if (!TM)
3435     return;
3436 
3437   LLT P0 = LLT::pointer(0, 64);
3438   LLT S32 = LLT::scalar(32);
3439   LLT V4S8 = LLT::fixed_vector(4, 8);
3440   auto Ptr = B.buildUndef(P0);
3441 
3442   DefineLegalizerInfo(A, {});
3443 
3444   MachineMemOperand *MMO = B.getMF().getMachineMemOperand(
3445       MachinePointerInfo(), MachineMemOperand::MOStore, 4, Align(4));
3446   auto Val = B.buildUndef(V4S8);
3447   auto Store = B.buildStore(Val, Ptr, *MMO);
3448 
3449   AInfo Info(MF->getSubtarget());
3450   DummyGISelObserver Observer;
3451   LegalizerHelper Helper(*MF, Info, Observer, B);
3452   B.setInsertPt(*EntryMBB, Store->getIterator());
3453   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3454             Helper.bitcast(*Store, 0, S32));
3455 
3456   auto CheckStr = R"(
3457   CHECK: [[VAL:%[0-9]+]]:_(<4 x s8>) = G_IMPLICIT_DEF
3458   CHECK: [[CAST:%[0-9]+]]:_(s32) = G_BITCAST [[VAL]]
3459   CHECK: G_STORE [[CAST]]
3460   )";
3461 
3462   // Check
3463   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3464 }
3465 
3466 TEST_F(AArch64GISelMITest, BitcastSelect) {
3467   setUp();
3468   if (!TM)
3469     return;
3470 
3471   LLT S1 = LLT::scalar(1);
3472   LLT S32 = LLT::scalar(32);
3473   LLT V4S8 = LLT::fixed_vector(4, 8);
3474 
3475   DefineLegalizerInfo(A, {});
3476 
3477   auto Cond = B.buildUndef(S1);
3478   auto Val0 = B.buildConstant(V4S8, 123);
3479   auto Val1 = B.buildConstant(V4S8, 99);
3480 
3481   auto Select = B.buildSelect(V4S8, Cond, Val0, Val1);
3482 
3483   AInfo Info(MF->getSubtarget());
3484   DummyGISelObserver Observer;
3485   LegalizerHelper Helper(*MF, Info, Observer, B);
3486   B.setInsertPt(*EntryMBB, Select->getIterator());
3487   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3488             Helper.bitcast(*Select, 0, S32));
3489 
3490   auto CheckStr = R"(
3491   CHECK: [[VAL0:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
3492   CHECK: [[VAL1:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
3493   CHECK: [[CAST0:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
3494   CHECK: [[CAST1:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
3495   CHECK: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT %{{[0-9]+}}:_(s1), [[CAST0]]:_, [[CAST1]]:_
3496   CHECK: [[CAST2:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[SELECT]]
3497   )";
3498 
3499   // Check
3500   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3501 
3502   // Doesn't make sense
3503   auto VCond = B.buildUndef(LLT::fixed_vector(4, 1));
3504   auto VSelect = B.buildSelect(V4S8, VCond, Val0, Val1);
3505 
3506   B.setInsertPt(*EntryMBB, VSelect->getIterator());
3507   EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
3508             Helper.bitcast(*VSelect, 0, S32));
3509   EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize,
3510             Helper.bitcast(*VSelect, 1, LLT::scalar(4)));
3511 }
3512 
3513 TEST_F(AArch64GISelMITest, BitcastBitOps) {
3514   setUp();
3515   if (!TM)
3516     return;
3517 
3518   LLT S32 = LLT::scalar(32);
3519   LLT V4S8 = LLT::fixed_vector(4, 8);
3520 
3521   DefineLegalizerInfo(A, {});
3522 
3523   auto Val0 = B.buildConstant(V4S8, 123);
3524   auto Val1 = B.buildConstant(V4S8, 99);
3525   auto And = B.buildAnd(V4S8, Val0, Val1);
3526   auto Or = B.buildOr(V4S8, Val0, Val1);
3527   auto Xor = B.buildXor(V4S8, Val0, Val1);
3528 
3529   AInfo Info(MF->getSubtarget());
3530   DummyGISelObserver Observer;
3531   LegalizerHelper Helper(*MF, Info, Observer, B);
3532   B.setInsertPt(*EntryMBB, And->getIterator());
3533   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3534             Helper.bitcast(*And, 0, S32));
3535 
3536   B.setInsertPt(*EntryMBB, Or->getIterator());
3537   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3538             Helper.bitcast(*Or, 0, S32));
3539 
3540   B.setInsertPt(*EntryMBB, Xor->getIterator());
3541   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3542             Helper.bitcast(*Xor, 0, S32));
3543 
3544   auto CheckStr = R"(
3545   CHECK: [[VAL0:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
3546   CHECK: [[VAL1:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR
3547   CHECK: [[CAST0:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
3548   CHECK: [[CAST1:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
3549   CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[CAST0]]:_, [[CAST1]]:_
3550   CHECK: [[CAST_AND:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[AND]]
3551   CHECK: [[CAST2:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
3552   CHECK: [[CAST3:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
3553   CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[CAST2]]:_, [[CAST3]]:_
3554   CHECK: [[CAST_OR:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[OR]]
3555   CHECK: [[CAST4:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]]
3556   CHECK: [[CAST5:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]]
3557   CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[CAST4]]:_, [[CAST5]]:_
3558   CHECK: [[CAST_XOR:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[XOR]]
3559   )";
3560 
3561   // Check
3562   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3563 }
3564 
3565 TEST_F(AArch64GISelMITest, CreateLibcall) {
3566   setUp();
3567   if (!TM)
3568     return;
3569 
3570   DefineLegalizerInfo(A, {});
3571 
3572   AInfo Info(MF->getSubtarget());
3573   DummyGISelObserver Observer;
3574 
3575   LLVMContext &Ctx = MF->getFunction().getContext();
3576   auto *RetTy = Type::getVoidTy(Ctx);
3577 
3578   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3579             createLibcall(B, "abort", {{}, RetTy}, {}, CallingConv::C));
3580 
3581   auto CheckStr = R"(
3582   CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
3583   CHECK: BL &abort
3584   CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
3585   )";
3586 
3587   // Check
3588   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3589 }
3590 
3591 // Test narrowing of G_IMPLICIT_DEF
3592 TEST_F(AArch64GISelMITest, NarrowImplicitDef) {
3593   setUp();
3594   if (!TM)
3595     return;
3596 
3597   DefineLegalizerInfo(A, {});
3598 
3599   // Make sure that G_IMPLICIT_DEF can be narrowed if the original size is not a
3600   // multiple of narrow size
3601   LLT S32{LLT::scalar(32)};
3602   LLT S48{LLT::scalar(48)};
3603   LLT S64{LLT::scalar(64)};
3604   LLT V2S64{{LLT::fixed_vector(2, 64)}};
3605 
3606   auto Implicit1 = B.buildUndef(S64);
3607   auto Implicit2 = B.buildUndef(S64);
3608   auto Implicit3 = B.buildUndef(V2S64);
3609   auto Implicit4 = B.buildUndef(V2S64);
3610 
3611   AInfo Info(MF->getSubtarget());
3612   DummyGISelObserver Observer;
3613   LegalizerHelper Helper(*MF, Info, Observer, B);
3614 
3615   // Perform Legalization
3616 
3617   B.setInsertPt(*EntryMBB, Implicit1->getIterator());
3618   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3619             Helper.narrowScalar(*Implicit1, 0, S48));
3620 
3621   B.setInsertPt(*EntryMBB, Implicit2->getIterator());
3622   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3623             Helper.narrowScalar(*Implicit2, 0, S32));
3624 
3625   B.setInsertPt(*EntryMBB, Implicit3->getIterator());
3626   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3627             Helper.narrowScalar(*Implicit3, 0, S48));
3628 
3629   B.setInsertPt(*EntryMBB, Implicit4->getIterator());
3630   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3631             Helper.narrowScalar(*Implicit4, 0, S32));
3632 
3633   const auto *CheckStr = R"(
3634   CHECK: [[DEF:%[0-9]+]]:_(s48) = G_IMPLICIT_DEF
3635   CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[DEF]]
3636 
3637   CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3638   CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3639   CHECK: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[DEF]]:_(s32), [[DEF1]]
3640 
3641   CHECK: [[DEF:%[0-9]+]]:_(<2 x s48>) = G_IMPLICIT_DEF
3642   CHECK: [[ANYEXT:%[0-9]+]]:_(<2 x s64>) = G_ANYEXT [[DEF]]
3643 
3644   CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3645   CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3646   CHECK: [[DEF2:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3647   CHECK: [[DEF3:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3648   CHECK: [[BV:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[DEF]]:_(s32), [[DEF1]]:_(s32), [[DEF2]]:_(s32), [[DEF3]]:_(s32)
3649   )";
3650 
3651   // Check
3652   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3653 }
3654 
3655 // Test widening of G_FREEZE
3656 TEST_F(AArch64GISelMITest, WidenFreeze) {
3657   setUp();
3658   if (!TM)
3659     return;
3660 
3661   DefineLegalizerInfo(A, {});
3662 
3663   // Make sure that G_FREEZE is widened with anyext
3664   LLT S64{LLT::scalar(64)};
3665   LLT S128{LLT::scalar(128)};
3666   LLT V2S32{LLT::fixed_vector(2, 32)};
3667   LLT V2S64{LLT::fixed_vector(2, 64)};
3668 
3669   auto Vector = B.buildBitcast(V2S32, Copies[0]);
3670 
3671   auto FreezeScalar = B.buildInstr(TargetOpcode::G_FREEZE, {S64}, {Copies[0]});
3672   auto FreezeVector = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector});
3673 
3674   AInfo Info(MF->getSubtarget());
3675   DummyGISelObserver Observer;
3676   LegalizerHelper Helper(*MF, Info, Observer, B);
3677 
3678   // Perform Legalization
3679 
3680   B.setInsertPt(*EntryMBB, FreezeScalar->getIterator());
3681   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3682             Helper.widenScalar(*FreezeScalar, 0, S128));
3683 
3684   B.setInsertPt(*EntryMBB, FreezeVector->getIterator());
3685   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3686             Helper.widenScalar(*FreezeVector, 0, V2S64));
3687 
3688   const auto *CheckStr = R"(
3689   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3690   CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3691 
3692   CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT [[COPY]]
3693   CHECK: [[FREEZE:%[0-9]+]]:_(s128) = G_FREEZE [[ANYEXT]]
3694   CHECK: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[FREEZE]]
3695 
3696   CHECK: [[ANYEXT1:%[0-9]+]]:_(<2 x s64>) = G_ANYEXT [[BITCAST]]
3697   CHECK: [[FREEZE1:%[0-9]+]]:_(<2 x s64>) = G_FREEZE [[ANYEXT1]]
3698   CHECK: [[TRUNC1:%[0-9]+]]:_(<2 x s32>) = G_TRUNC [[FREEZE1]]
3699   )";
3700 
3701   // Check
3702   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3703 }
3704 
3705 // Test narrowing of G_FREEZE
3706 TEST_F(AArch64GISelMITest, NarrowFreeze) {
3707   setUp();
3708   if (!TM)
3709     return;
3710 
3711   DefineLegalizerInfo(A, {});
3712 
3713   // Make sure that G_FREEZE is narrowed using unmerge/extract
3714   LLT S16{LLT::scalar(16)};
3715   LLT S32{LLT::scalar(32)};
3716   LLT S33{LLT::scalar(33)};
3717   LLT S64{LLT::scalar(64)};
3718   LLT V2S16{LLT::fixed_vector(2, 16)};
3719   LLT V2S32{LLT::fixed_vector(2, 32)};
3720 
3721   auto Trunc = B.buildTrunc(S33, {Copies[0]});
3722   auto Vector = B.buildBitcast(V2S32, Copies[0]);
3723 
3724   auto FreezeScalar = B.buildInstr(TargetOpcode::G_FREEZE, {S64}, {Copies[0]});
3725   auto FreezeOdd = B.buildInstr(TargetOpcode::G_FREEZE, {S33}, {Trunc});
3726   auto FreezeVector = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector});
3727   auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector});
3728 
3729   AInfo Info(MF->getSubtarget());
3730   DummyGISelObserver Observer;
3731   LegalizerHelper Helper(*MF, Info, Observer, B);
3732 
3733   // Perform Legalization
3734 
3735   B.setInsertPt(*EntryMBB, FreezeScalar->getIterator());
3736   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3737             Helper.narrowScalar(*FreezeScalar, 0, S32));
3738 
3739   B.setInsertPt(*EntryMBB, FreezeOdd->getIterator());
3740   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3741             Helper.narrowScalar(*FreezeOdd, 0, S32));
3742 
3743   B.setInsertPt(*EntryMBB, FreezeVector->getIterator());
3744   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3745             Helper.narrowScalar(*FreezeVector, 0, V2S16));
3746 
3747   B.setInsertPt(*EntryMBB, FreezeVector1->getIterator());
3748   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3749             Helper.narrowScalar(*FreezeVector1, 0, S16));
3750 
3751   const auto *CheckStr = R"(
3752   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3753   CHECK: [[TRUNC:%[0-9]+]]:_(s33) = G_TRUNC [[COPY]]
3754   CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3755 
3756   CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]]
3757   CHECK: [[FREEZE:%[0-9]+]]:_(s32) = G_FREEZE [[UV]]
3758   CHECK: [[FREEZE1:%[0-9]+]]:_(s32) = G_FREEZE [[UV1]]
3759   CHECK: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[FREEZE]]:_(s32), [[FREEZE1]]
3760 
3761   CHECK: (s1) = G_UNMERGE_VALUES [[TRUNC]]:_(s33)
3762   CHECK: [[UNDEF:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
3763   CHECK: [[MV1:%[0-9]+]]:_(s32) = G_MERGE_VALUES
3764   CHECK: [[MV2:%[0-9]+]]:_(s32) = G_MERGE_VALUES
3765   CHECK: [[UNDEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3766   CHECK: [[FREEZE2:%[0-9]+]]:_(s32) = G_FREEZE [[MV1]]
3767   CHECK: [[FREEZE3:%[0-9]+]]:_(s32) = G_FREEZE [[MV2]]
3768   CHECK: [[UNDEF2:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
3769   CHECK: [[MV3:%[0-9]+]]:_(s1056) = G_MERGE_VALUES [[FREEZE2]]:_(s32), [[FREEZE3]]:_(s32), [[UNDEF2]]
3770   CHECK: [[TRUNC1:%[0-9]+]]:_(s33) = G_TRUNC [[MV3]]
3771 
3772   CHECK: [[BITCAST1:%[0-9]+]]:_(s64) = G_BITCAST [[BITCAST]]
3773   CHECK: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST1]]
3774   CHECK: [[FREEZE4:%[0-9]+]]:_(s32) = G_FREEZE [[UV2]]
3775   CHECK: [[FREEZE5:%[0-9]+]]:_(s32) = G_FREEZE [[UV3]]
3776   CHECK: [[MV4:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[FREEZE4]]:_(s32), [[FREEZE5]]:_(s32)
3777   CHECK: [[BITCAST2:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[MV4]]
3778 
3779   CHECK: [[BITCAST3:%[0-9]+]]:_(s64) = G_BITCAST [[BITCAST]]
3780   CHECK: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[BITCAST3]]
3781   CHECK: [[FREEZE6:%[0-9]+]]:_(s16) = G_FREEZE [[UV4]]
3782   CHECK: [[FREEZE7:%[0-9]+]]:_(s16) = G_FREEZE [[UV5]]
3783   CHECK: [[FREEZE8:%[0-9]+]]:_(s16) = G_FREEZE [[UV6]]
3784   CHECK: [[FREEZE9:%[0-9]+]]:_(s16) = G_FREEZE [[UV7]]
3785   CHECK: [[MV5:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[FREEZE6]]:_(s16), [[FREEZE7]]:_(s16), [[FREEZE8]]:_(s16), [[FREEZE9]]
3786   CHECK: [[BITCAST3:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[MV5]]
3787   )";
3788 
3789   // Check
3790   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3791 }
3792 
3793 // Test fewer elements of G_FREEZE
3794 TEST_F(AArch64GISelMITest, FewerElementsFreeze) {
3795   setUp();
3796   if (!TM)
3797     return;
3798 
3799   DefineLegalizerInfo(A, {});
3800 
3801   LLT S32{LLT::scalar(32)};
3802   LLT V2S16{LLT::fixed_vector(2, 16)};
3803   LLT V2S32{LLT::fixed_vector(2, 32)};
3804   LLT V4S16{LLT::fixed_vector(4, 16)};
3805 
3806   auto Vector1 = B.buildBitcast(V2S32, Copies[0]);
3807   auto Vector2 = B.buildBitcast(V4S16, Copies[0]);
3808 
3809   auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector1});
3810   auto FreezeVector2 = B.buildInstr(TargetOpcode::G_FREEZE, {V4S16}, {Vector2});
3811 
3812   AInfo Info(MF->getSubtarget());
3813   DummyGISelObserver Observer;
3814   LegalizerHelper Helper(*MF, Info, Observer, B);
3815 
3816   // Perform Legalization
3817 
3818   B.setInsertPt(*EntryMBB, FreezeVector1->getIterator());
3819   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3820             Helper.fewerElementsVector(*FreezeVector1, 0, S32));
3821 
3822   B.setInsertPt(*EntryMBB, FreezeVector2->getIterator());
3823   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3824             Helper.fewerElementsVector(*FreezeVector2, 0, V2S16));
3825 
3826   const auto *CheckStr = R"(
3827   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3828   CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3829   CHECK: [[BITCAST1:%[0-9]+]]:_(<4 x s16>) = G_BITCAST [[COPY]]
3830 
3831   CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST]]
3832   CHECK: [[FREEZE:%[0-9]+]]:_(s32) = G_FREEZE [[UV]]
3833   CHECK: [[FREEZE1:%[0-9]+]]:_(s32) = G_FREEZE [[UV1]]
3834   CHECK: [[MV:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FREEZE]]:_(s32), [[FREEZE1]]
3835 
3836   CHECK: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[BITCAST1]]
3837   CHECK: [[FREEZE2:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[UV]]
3838   CHECK: [[FREEZE3:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[UV1]]
3839   CHECK: [[MV:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[FREEZE2]]:_(<2 x s16>), [[FREEZE3]]
3840   )";
3841 
3842   // Check
3843   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3844 }
3845 
3846 // Test more elements of G_FREEZE
3847 TEST_F(AArch64GISelMITest, MoreElementsFreeze) {
3848   setUp();
3849   if (!TM)
3850     return;
3851 
3852   DefineLegalizerInfo(A, {});
3853 
3854   LLT V2S32{LLT::fixed_vector(2, 32)};
3855   LLT V4S32{LLT::fixed_vector(4, 32)};
3856 
3857   auto Vector1 = B.buildBitcast(V2S32, Copies[0]);
3858   auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector1});
3859 
3860   AInfo Info(MF->getSubtarget());
3861   DummyGISelObserver Observer;
3862   LegalizerHelper Helper(*MF, Info, Observer, B);
3863 
3864   // Perform Legalization
3865   B.setInsertPt(*EntryMBB, FreezeVector1->getIterator());
3866   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3867             Helper.moreElementsVector(*FreezeVector1, 0, V4S32));
3868 
3869   const auto *CheckStr = R"(
3870   CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY
3871   CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]]
3872   CHECK: [[UNDEF:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
3873   CHECK: [[CV:%[0-9]+]]:_(<4 x s32>) = G_CONCAT_VECTORS [[BITCAST]]:_(<2 x s32>), [[UNDEF]]
3874   CHECK: [[FREEZE:%[0-9]+]]:_(<4 x s32>) = G_FREEZE [[CV]]
3875   CHECK: [[EXTR0:%[0-9]+]]:_(<2 x s32>), [[EXTR1:%[0-9]+]]:_(<2 x s32>) = G_UNMERGE_VALUES [[FREEZE]]:_(<4 x s32>)
3876   )";
3877 
3878   // Check
3879   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3880 }
3881 
3882 // Test fewer elements of G_INSERT_VECTOR_ELEMENT
3883 TEST_F(AArch64GISelMITest, FewerElementsInsertVectorElt) {
3884   setUp();
3885   if (!TM)
3886     return;
3887 
3888   DefineLegalizerInfo(A, {});
3889 
3890   LLT P0{LLT::pointer(0, 64)};
3891   LLT S64{LLT::scalar(64)};
3892   LLT S16{LLT::scalar(16)};
3893   LLT V2S16{LLT::fixed_vector(2, 16)};
3894   LLT V3S16{LLT::fixed_vector(3, 16)};
3895   LLT V8S16{LLT::fixed_vector(8, 16)};
3896 
3897   auto Ptr0 = B.buildIntToPtr(P0, Copies[0]);
3898   auto VectorV8 = B.buildLoad(V8S16, Ptr0, MachinePointerInfo(), Align(8));
3899   auto Value = B.buildTrunc(S16, Copies[1]);
3900 
3901   auto Seven = B.buildConstant(S64, 7);
3902   auto InsertV8Constant7_0 =
3903       B.buildInsertVectorElement(V8S16, VectorV8, Value, Seven);
3904   auto InsertV8Constant7_1 =
3905       B.buildInsertVectorElement(V8S16, VectorV8, Value, Seven);
3906 
3907   B.buildStore(InsertV8Constant7_0, Ptr0, MachinePointerInfo(), Align(8),
3908                MachineMemOperand::MOVolatile);
3909   B.buildStore(InsertV8Constant7_1, Ptr0, MachinePointerInfo(), Align(8),
3910                MachineMemOperand::MOVolatile);
3911 
3912   AInfo Info(MF->getSubtarget());
3913   DummyGISelObserver Observer;
3914   LegalizerHelper Helper(*MF, Info, Observer, B);
3915 
3916   // Perform Legalization
3917   B.setInsertPt(*EntryMBB, InsertV8Constant7_0->getIterator());
3918 
3919   // This should index the high element of the 4th piece of an unmerge.
3920   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3921             Helper.fewerElementsVector(*InsertV8Constant7_0, 0, V2S16));
3922 
3923   // This case requires extracting an intermediate vector type into the target
3924   // v4s16.
3925   B.setInsertPt(*EntryMBB, InsertV8Constant7_1->getIterator());
3926   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3927             Helper.fewerElementsVector(*InsertV8Constant7_1, 0, V3S16));
3928 
3929   const auto *CheckStr = R"(
3930   CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
3931   CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
3932   CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY
3933   CHECK: [[PTR0:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY0]]
3934   CHECK: [[VEC8:%[0-9]+]]:_(<8 x s16>) = G_LOAD [[PTR0]]:_(p0) :: (load 16, align 8)
3935   CHECK: [[INSERT_VAL:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]]
3936 
3937 
3938   CHECK: [[UNMERGE0:%[0-9]+]]:_(<2 x s16>), [[UNMERGE1:%[0-9]+]]:_(<2 x s16>), [[UNMERGE2:%[0-9]+]]:_(<2 x s16>), [[UNMERGE3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[VEC8]]
3939   CHECK: [[ONE:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
3940   CHECK: [[SUB_INSERT_7:%[0-9]+]]:_(<2 x s16>) = G_INSERT_VECTOR_ELT [[UNMERGE3]]:_, [[INSERT_VAL]]:_(s16), [[ONE]]
3941   CHECK: [[INSERT_V8_7_0:%[0-9]+]]:_(<8 x s16>) = G_CONCAT_VECTORS [[UNMERGE0]]:_(<2 x s16>), [[UNMERGE1]]:_(<2 x s16>), [[UNMERGE2]]:_(<2 x s16>), [[SUB_INSERT_7]]:_(<2 x s16>)
3942 
3943 
3944   CHECK: [[UNMERGE1_0:%[0-9]+]]:_(s16), [[UNMERGE1_1:%[0-9]+]]:_(s16), [[UNMERGE1_2:%[0-9]+]]:_(s16), [[UNMERGE1_3:%[0-9]+]]:_(s16), [[UNMERGE1_4:%[0-9]+]]:_(s16), [[UNMERGE1_5:%[0-9]+]]:_(s16), [[UNMERGE1_6:%[0-9]+]]:_(s16), [[UNMERGE1_7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[VEC8]]:_(<8 x s16>)
3945   CHECK: [[IMPDEF_S16:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
3946   CHECK: [[BUILD0:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_0]]:_(s16), [[UNMERGE1_1]]:_(s16), [[UNMERGE1_2]]:_(s16)
3947   CHECK: [[BUILD1:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_3]]:_(s16), [[UNMERGE1_4]]:_(s16), [[UNMERGE1_5]]:_(s16)
3948   CHECK: [[BUILD2:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_6]]:_(s16), [[UNMERGE1_7]]:_(s16), [[IMPDEF_S16]]:_(s16)
3949   CHECK: [[IMPDEF_V3S16:%[0-9]+]]:_(<3 x s16>) = G_IMPLICIT_DEF
3950   CHECK: [[ONE_1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
3951   CHECK: [[SUB_INSERT_7_V3S16:%[0-9]+]]:_(<3 x s16>) = G_INSERT_VECTOR_ELT [[BUILD2]]:_, [[INSERT_VAL]]:_(s16), [[ONE_1]]
3952 
3953   CHECK: [[WIDE_CONCAT_DEAD:%[0-9]+]]:_(<24 x s16>) = G_CONCAT_VECTORS [[BUILD0]]:_(<3 x s16>), [[BUILD1]]:_(<3 x s16>), [[SUB_INSERT_7_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>)
3954   CHECK: [[WIDE_CONCAT:%[0-9]+]]:_(<24 x s16>) = G_CONCAT_VECTORS [[BUILD0]]:_(<3 x s16>), [[BUILD1]]:_(<3 x s16>), [[SUB_INSERT_7_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>)
3955   CHECK: [[INSERT_V8_7_1:%[0-9]+]]:_(<8 x s16>), %{{[0-9]+}}:_(<8 x s16>), %{{[0-9]+}}:_(<8 x s16>) = G_UNMERGE_VALUES [[WIDE_CONCAT]]:_(<24 x s16>)
3956 
3957 
3958   CHECK: G_STORE [[INSERT_V8_7_0]]
3959   CHECK: G_STORE [[INSERT_V8_7_1]]
3960   )";
3961 
3962   // Check
3963   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3964 }
3965 
3966 // Test widen scalar of G_UNMERGE_VALUES
3967 TEST_F(AArch64GISelMITest, widenScalarUnmerge) {
3968   setUp();
3969   if (!TM)
3970     return;
3971 
3972   DefineLegalizerInfo(A, {});
3973 
3974   LLT S96{LLT::scalar(96)};
3975   LLT S64{LLT::scalar(64)};
3976   LLT S48{LLT::scalar(48)};
3977 
3978   auto Src = B.buildAnyExt(S96, Copies[0]);
3979   auto Unmerge = B.buildUnmerge(S48, Src);
3980 
3981   AInfo Info(MF->getSubtarget());
3982   DummyGISelObserver Observer;
3983   LegalizerHelper Helper(*MF, Info, Observer, B);
3984 
3985   // Perform Legalization
3986   B.setInsertPt(*EntryMBB, Unmerge->getIterator());
3987 
3988   // This should create unmerges to a GCD type (S16), then remerge to S48
3989   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
3990             Helper.widenScalar(*Unmerge, 0, S64));
3991 
3992   const auto *CheckStr = R"(
3993   CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY
3994   CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY
3995   CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY
3996   CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY0]]
3997   CHECK: [[ANYEXT1:%[0-9]+]]:_(s192) = G_ANYEXT [[ANYEXT]]
3998   CHECK: [[UNMERGE:%[0-9]+]]:_(s64), [[UNMERGE1:%[0-9]+]]:_(s64), [[UNMERGE2:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT1]]
3999   CHECK: [[UNMERGE3:%[0-9]+]]:_(s16), [[UNMERGE4:%[0-9]+]]:_(s16), [[UNMERGE5:%[0-9]+]]:_(s16), [[UNMERGE6:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE]]
4000   CHECK: [[UNMERGE7:%[0-9]+]]:_(s16), [[UNMERGE8:%[0-9]+]]:_(s16), [[UNMERGE9:%[0-9]+]]:_(s16), [[UNMERGE10:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE1]]
4001   CHECK: [[UNMERGE11:%[0-9]+]]:_(s16), [[UNMERGE12:%[0-9]+]]:_(s16), [[UNMERGE13:%[0-9]+]]:_(s16), [[UNMERGE14:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE2]]
4002   CHECK: [[MERGE:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE3]]:_(s16), [[UNMERGE4]]:_(s16), [[UNMERGE5]]:_(s16)
4003   CHECK: [[MERGE1:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE6]]:_(s16), [[UNMERGE7]]:_(s16), [[UNMERGE8]]:_(s16)
4004   )";
4005 
4006   // Check
4007   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
4008 }
4009 
4010 } // namespace
4011