xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp (revision b3e86709dc76afac082bd3c7ed4c90ef9847f7b5)
1 //===- LegalizerHelperTest.cpp
2 //-----------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "GISelMITest.h"
11 
12 namespace {
13 
14 class DummyGISelObserver : public GISelChangeObserver {
15 public:
16   void changingInstr(MachineInstr &MI) override {}
17   void changedInstr(MachineInstr &MI) override {}
18   void createdInstr(MachineInstr &MI) override {}
19   void erasingInstr(MachineInstr &MI) override {}
20 };
21 
22 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom,
23 // in which case it becomes CTTZ_ZERO_UNDEF with select.
24 TEST_F(GISelMITest, LowerBitCountingCTTZ0) {
25   if (!TM)
26     return;
27 
28   // Declare your legalization info
29   DefineLegalizerInfo(A, {
30     getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s64, s64}});
31   });
32   // Build Instr
33   auto MIBCTTZ =
34       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
35   AInfo Info(MF->getSubtarget());
36   DummyGISelObserver Observer;
37   LegalizerHelper Helper(*MF, Info, Observer, B);
38   // Perform Legalization
39   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
40               LegalizerHelper::LegalizeResult::Legalized);
41 
42   auto CheckStr = R"(
43   CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF %0
44   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
45   CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
46   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
47   CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
48   )";
49 
50   // Check
51   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
52 }
53 
54 // CTTZ expansion in terms of CTLZ
55 TEST_F(GISelMITest, LowerBitCountingCTTZ1) {
56   if (!TM)
57     return;
58 
59   // Declare your legalization info
60   DefineLegalizerInfo(A, {
61     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}});
62   });
63   // Build Instr
64   auto MIBCTTZ =
65       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
66   AInfo Info(MF->getSubtarget());
67   DummyGISelObserver Observer;
68   LegalizerHelper Helper(*MF, Info, Observer, B);
69   // Perform Legalization
70   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
71               LegalizerHelper::LegalizeResult::Legalized);
72 
73   auto CheckStr = R"(
74   CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
75   CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
76   CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
77   CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
78   CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
79   CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_
80   CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_
81   )";
82 
83   // Check
84   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
85 }
86 
87 // CTTZ expansion in terms of CTPOP
88 TEST_F(GISelMITest, LowerBitCountingCTTZ2) {
89   if (!TM)
90     return;
91 
92   // Declare your legalization info
93   DefineLegalizerInfo(A, {
94     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}});
95   });
96   // Build
97   auto MIBCTTZ =
98       B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]});
99   AInfo Info(MF->getSubtarget());
100   DummyGISelObserver Observer;
101   LegalizerHelper Helper(*MF, Info, Observer, B);
102   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
103               LegalizerHelper::LegalizeResult::Legalized);
104 
105   auto CheckStr = R"(
106   CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
107   CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
108   CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
109   CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
110   CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
111   )";
112 
113   // Check
114   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
115 }
116 
117 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
118 TEST_F(GISelMITest, LowerBitCountingCTTZ3) {
119   if (!TM)
120     return;
121 
122   // Declare your legalization info
123   DefineLegalizerInfo(A, {
124     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}});
125   });
126   // Build
127   auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
128                               {LLT::scalar(64)}, {Copies[0]});
129   AInfo Info(MF->getSubtarget());
130   DummyGISelObserver Observer;
131   LegalizerHelper Helper(*MF, Info, Observer, B);
132   EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
133               LegalizerHelper::LegalizeResult::Legalized);
134 
135   auto CheckStr = R"(
136   CHECK: CTTZ
137   )";
138 
139   // Check
140   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
141 }
142 
143 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
144 TEST_F(GISelMITest, LowerBitCountingCTLZ0) {
145   if (!TM)
146     return;
147 
148   // Declare your legalization info
149   DefineLegalizerInfo(A, {
150     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}});
151   });
152   // Build
153   auto MIBCTLZ =
154       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
155   AInfo Info(MF->getSubtarget());
156   DummyGISelObserver Observer;
157   LegalizerHelper Helper(*MF, Info, Observer, B);
158   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
159               LegalizerHelper::LegalizeResult::Legalized);
160 
161   auto CheckStr = R"(
162   CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
163   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
164   CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
165   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
166   CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
167   )";
168 
169   // Check
170   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
171 }
172 
173 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall
174 TEST_F(GISelMITest, LowerBitCountingCTLZLibcall) {
175   if (!TM)
176     return;
177 
178   // Declare your legalization info
179   DefineLegalizerInfo(A, {
180     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s64, s64}});
181   });
182   // Build
183   auto MIBCTLZ =
184       B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]});
185   AInfo Info(MF->getSubtarget());
186   DummyGISelObserver Observer;
187   LegalizerHelper Helper(*MF, Info, Observer, B);
188   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
189               LegalizerHelper::LegalizeResult::Legalized);
190 
191   auto CheckStr = R"(
192   CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
193   CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
194   CHECK: [[THIRTY2:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
195   CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
196   CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]]
197   )";
198 
199   // Check
200   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
201 }
202 
203 // CTLZ expansion
204 TEST_F(GISelMITest, LowerBitCountingCTLZ1) {
205   if (!TM)
206     return;
207 
208   // Declare your legalization info
209   DefineLegalizerInfo(A, {
210     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}});
211   });
212   // Build
213   // Trunc it to s8.
214   LLT s8{LLT::scalar(8)};
215   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
216   auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
217   AInfo Info(MF->getSubtarget());
218   DummyGISelObserver Observer;
219   LegalizerHelper Helper(*MF, Info, Observer, B);
220   EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
221               LegalizerHelper::LegalizeResult::Legalized);
222 
223   auto CheckStr = R"(
224   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
225   CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
226   CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
227   CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
228   CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
229   CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
230   CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
231   CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
232   CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
233   CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
234   CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
235   CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
236   CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
237   )";
238 
239   // Check
240   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
241 }
242 
243 // CTLZ widening.
244 TEST_F(GISelMITest, WidenBitCountingCTLZ) {
245   if (!TM)
246     return;
247 
248   // Declare your legalization info
249   DefineLegalizerInfo(A, {
250     getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}});
251   });
252   // Build
253   // Trunc it to s8.
254   LLT s8{LLT::scalar(8)};
255   LLT s16{LLT::scalar(16)};
256   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
257   auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc});
258   AInfo Info(MF->getSubtarget());
259   DummyGISelObserver Observer;
260   LegalizerHelper Helper(*MF, Info, Observer, B);
261   EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) ==
262               LegalizerHelper::LegalizeResult::Legalized);
263 
264   auto CheckStr = R"(
265   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
266   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
267   CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
268   CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
269   CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
270   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
271   )";
272 
273   // Check
274   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
275 }
276 
277 // CTLZ_ZERO_UNDEF widening.
278 TEST_F(GISelMITest, WidenBitCountingCTLZZeroUndef) {
279   if (!TM)
280     return;
281 
282   // Declare your legalization info
283   DefineLegalizerInfo(A, {
284     getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}});
285   });
286   // Build
287   // Trunc it to s8.
288   LLT s8{LLT::scalar(8)};
289   LLT s16{LLT::scalar(16)};
290   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
291   auto MIBCTLZ_ZU =
292       B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc});
293   AInfo Info(MF->getSubtarget());
294   DummyGISelObserver Observer;
295   LegalizerHelper Helper(*MF, Info, Observer, B);
296   EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) ==
297               LegalizerHelper::LegalizeResult::Legalized);
298 
299   auto CheckStr = R"(
300   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
301   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
302   CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
303   CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
304   CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
305   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
306   )";
307 
308   // Check
309   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
310 }
311 
312 // CTPOP widening.
313 TEST_F(GISelMITest, WidenBitCountingCTPOP) {
314   if (!TM)
315     return;
316 
317   // Declare your legalization info
318   DefineLegalizerInfo(A, {
319     getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}});
320   });
321   // Build
322   // Trunc it to s8.
323   LLT s8{LLT::scalar(8)};
324   LLT s16{LLT::scalar(16)};
325   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
326   auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc});
327   AInfo Info(MF->getSubtarget());
328   DummyGISelObserver Observer;
329   LegalizerHelper Helper(*MF, Info, Observer, B);
330   EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) ==
331               LegalizerHelper::LegalizeResult::Legalized);
332 
333   auto CheckStr = R"(
334   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
335   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
336   CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
337   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
338   )";
339 
340   // Check
341   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
342 }
343 
344 // CTTZ_ZERO_UNDEF widening.
345 TEST_F(GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) {
346   if (!TM)
347     return;
348 
349   // Declare your legalization info
350   DefineLegalizerInfo(A, {
351     getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}});
352   });
353   // Build
354   // Trunc it to s8.
355   LLT s8{LLT::scalar(8)};
356   LLT s16{LLT::scalar(16)};
357   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
358   auto MIBCTTZ_ZERO_UNDEF =
359       B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc});
360   AInfo Info(MF->getSubtarget());
361   DummyGISelObserver Observer;
362   LegalizerHelper Helper(*MF, Info, Observer, B);
363   EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) ==
364               LegalizerHelper::LegalizeResult::Legalized);
365 
366   auto CheckStr = R"(
367   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
368   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
369   CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
370   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
371   )";
372 
373   // Check
374   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
375 }
376 
377 // CTTZ widening.
378 TEST_F(GISelMITest, WidenBitCountingCTTZ) {
379   if (!TM)
380     return;
381 
382   // Declare your legalization info
383   DefineLegalizerInfo(A, {
384     getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}});
385   });
386   // Build
387   // Trunc it to s8.
388   LLT s8{LLT::scalar(8)};
389   LLT s16{LLT::scalar(16)};
390   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
391   auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc});
392   AInfo Info(MF->getSubtarget());
393   DummyGISelObserver Observer;
394   LegalizerHelper Helper(*MF, Info, Observer, B);
395   EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) ==
396               LegalizerHelper::LegalizeResult::Legalized);
397 
398   auto CheckStr = R"(
399   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
400   CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
401   CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
402   CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
403   CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
404   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
405   )";
406 
407   // Check
408   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
409 }
410 // UADDO widening.
411 TEST_F(GISelMITest, WidenUADDO) {
412   if (!TM)
413     return;
414 
415   // Declare your legalization info
416   DefineLegalizerInfo(A, {
417     getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}});
418   });
419   // Build
420   // Trunc it to s8.
421   LLT s8{LLT::scalar(8)};
422   LLT s16{LLT::scalar(16)};
423   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
424   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
425   auto MIBUAddO =
426       B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
427   AInfo Info(MF->getSubtarget());
428   DummyGISelObserver Observer;
429   LegalizerHelper Helper(*MF, Info, Observer, B);
430   EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
431               LegalizerHelper::LegalizeResult::Legalized);
432 
433   auto CheckStr = R"(
434   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
435   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
436   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
437   CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
438   CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
439   CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_
440   CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_
441   CHECK: G_TRUNC [[ADD]]
442   )";
443 
444   // Check
445   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
446 }
447 
448 // USUBO widening.
449 TEST_F(GISelMITest, WidenUSUBO) {
450   if (!TM)
451     return;
452 
453   // Declare your legalization info
454   DefineLegalizerInfo(A, {
455     getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}});
456   });
457   // Build
458   // Trunc it to s8.
459   LLT s8{LLT::scalar(8)};
460   LLT s16{LLT::scalar(16)};
461   auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
462   unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
463   auto MIBUSUBO =
464       B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc});
465   AInfo Info(MF->getSubtarget());
466   DummyGISelObserver Observer;
467   LegalizerHelper Helper(*MF, Info, Observer, B);
468   EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
469               LegalizerHelper::LegalizeResult::Legalized);
470 
471   auto CheckStr = R"(
472   CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
473   CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
474   CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
475   CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
476   CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
477   CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_
478   CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_
479   CHECK: G_TRUNC [[SUB]]
480   )";
481 
482   // Check
483   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
484 }
485 } // namespace
486