[llvm-exegesis][NFC] Return many CodeTemplates instead of one.
[llvm-complete.git] / unittests / CodeGen / GlobalISel / LegalizerHelperTest.cpp
blob0cc989be3c091ce477094b127f33a76669c661f2
1 //===- PatternMatchTest.cpp -----------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
10 #include "LegalizerHelperTest.h"
12 namespace {
14 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom,
15 // in which case it becomes CTTZ_ZERO_UNDEF with select.
16 TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ0) {
17 if (!TM)
18 return;
20 // Declare your legalization info
21 DefineLegalizerInfo(
22 A, { getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({s64}); });
23 // Build Instr
24 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, LLT::scalar(64), Copies[0]);
25 AInfo Info(MF->getSubtarget());
26 LegalizerHelper Helper(*MF, Info);
27 // Perform Legalization
28 ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
29 LegalizerHelper::LegalizeResult::Legalized);
31 auto CheckStr = R"(
32 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF %0
33 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
34 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
35 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
36 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
37 )";
39 // Check
40 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
43 // CTTZ expansion in terms of CTLZ
44 TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ1) {
45 if (!TM)
46 return;
48 // Declare your legalization info
49 DefineLegalizerInfo(A,
50 { getActionDefinitionsBuilder(G_CTLZ).legalFor({s64}); });
51 // Build Instr
52 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, LLT::scalar(64), Copies[0]);
53 AInfo Info(MF->getSubtarget());
54 LegalizerHelper Helper(*MF, Info);
55 // Perform Legalization
56 ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
57 LegalizerHelper::LegalizeResult::Legalized);
59 auto CheckStr = R"(
60 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
61 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
62 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
63 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
64 CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
65 CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_
66 CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_
67 )";
69 // Check
70 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
73 // CTTZ expansion in terms of CTPOP
74 TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ2) {
75 if (!TM)
76 return;
78 // Declare your legalization info
79 DefineLegalizerInfo(
80 A, { getActionDefinitionsBuilder(G_CTPOP).legalFor({s64}); });
81 // Build
82 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, LLT::scalar(64), Copies[0]);
83 AInfo Info(MF->getSubtarget());
84 LegalizerHelper Helper(*MF, Info);
85 ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
86 LegalizerHelper::LegalizeResult::Legalized);
88 auto CheckStr = R"(
89 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
90 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
91 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
92 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
93 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
94 )";
96 // Check
97 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
100 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
101 TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ3) {
102 if (!TM)
103 return;
105 // Declare your legalization info
106 DefineLegalizerInfo(A,
107 { getActionDefinitionsBuilder(G_CTTZ).legalFor({s64}); });
108 // Build
109 auto MIBCTTZ =
110 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, LLT::scalar(64), Copies[0]);
111 AInfo Info(MF->getSubtarget());
112 LegalizerHelper Helper(*MF, Info);
113 ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) ==
114 LegalizerHelper::LegalizeResult::Legalized);
116 auto CheckStr = R"(
117 CHECK: CTTZ
120 // Check
121 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
124 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
125 TEST_F(LegalizerHelperTest, LowerBitCountingCTLZ0) {
126 if (!TM)
127 return;
129 // Declare your legalization info
130 DefineLegalizerInfo(
131 A, { getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({s64}); });
132 // Build
133 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, LLT::scalar(64), Copies[0]);
134 AInfo Info(MF->getSubtarget());
135 LegalizerHelper Helper(*MF, Info);
136 ASSERT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) ==
137 LegalizerHelper::LegalizeResult::Legalized);
139 auto CheckStr = R"(
140 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
141 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
142 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
143 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
144 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
147 // Check
148 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
151 // CTLZ expansion
152 TEST_F(LegalizerHelperTest, LowerBitCountingCTLZ1) {
153 if (!TM)
154 return;
156 // Declare your legalization info
157 DefineLegalizerInfo(A,
158 { getActionDefinitionsBuilder(G_CTPOP).legalFor({s8}); });
159 // Build
160 // Trunc it to s8.
161 LLT s8{LLT::scalar(8)};
162 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
163 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, s8, MIBTrunc);
164 AInfo Info(MF->getSubtarget());
165 LegalizerHelper Helper(*MF, Info);
166 ASSERT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) ==
167 LegalizerHelper::LegalizeResult::Legalized);
169 auto CheckStr = R"(
170 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
171 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
172 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
173 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
174 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
175 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
176 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
177 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
178 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
179 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
180 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
181 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
182 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
185 // Check
186 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
189 // CTLZ widening.
190 TEST_F(LegalizerHelperTest, WidenBitCountingCTLZ) {
191 if (!TM)
192 return;
194 // Declare your legalization info
195 DefineLegalizerInfo(A,
196 { getActionDefinitionsBuilder(G_CTLZ).legalFor({s16}); });
197 // Build
198 // Trunc it to s8.
199 LLT s8{LLT::scalar(8)};
200 LLT s16{LLT::scalar(16)};
201 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
202 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, s8, MIBTrunc);
203 AInfo Info(MF->getSubtarget());
204 LegalizerHelper Helper(*MF, Info);
205 ASSERT_TRUE(Helper.widenScalar(*MIBCTLZ, 0, s16) ==
206 LegalizerHelper::LegalizeResult::Legalized);
208 auto CheckStr = R"(
209 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
210 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
211 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
212 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
213 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
214 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
217 // Check
218 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
221 // CTLZ_ZERO_UNDEF widening.
222 TEST_F(LegalizerHelperTest, WidenBitCountingCTLZZeroUndef) {
223 if (!TM)
224 return;
226 // Declare your legalization info
227 DefineLegalizerInfo(
228 A, { getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({s16}); });
229 // Build
230 // Trunc it to s8.
231 LLT s8{LLT::scalar(8)};
232 LLT s16{LLT::scalar(16)};
233 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
234 auto MIBCTLZ_ZU = B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, s8, MIBTrunc);
235 AInfo Info(MF->getSubtarget());
236 LegalizerHelper Helper(*MF, Info);
237 ASSERT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 0, s16) ==
238 LegalizerHelper::LegalizeResult::Legalized);
240 auto CheckStr = R"(
241 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
242 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
243 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
244 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
245 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
246 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
249 // Check
250 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
253 // CTPOP widening.
254 TEST_F(LegalizerHelperTest, WidenBitCountingCTPOP) {
255 if (!TM)
256 return;
258 // Declare your legalization info
259 DefineLegalizerInfo(
260 A, { getActionDefinitionsBuilder(G_CTPOP).legalFor({s16}); });
261 // Build
262 // Trunc it to s8.
263 LLT s8{LLT::scalar(8)};
264 LLT s16{LLT::scalar(16)};
265 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
266 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, s8, MIBTrunc);
267 AInfo Info(MF->getSubtarget());
268 LegalizerHelper Helper(*MF, Info);
269 ASSERT_TRUE(Helper.widenScalar(*MIBCTPOP, 0, s16) ==
270 LegalizerHelper::LegalizeResult::Legalized);
272 auto CheckStr = R"(
273 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
274 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
275 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
276 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
279 // Check
280 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
283 // CTTZ_ZERO_UNDEF widening.
284 TEST_F(LegalizerHelperTest, WidenBitCountingCTTZ_ZERO_UNDEF) {
285 if (!TM)
286 return;
288 // Declare your legalization info
289 DefineLegalizerInfo(
290 A, { getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({s16}); });
291 // Build
292 // Trunc it to s8.
293 LLT s8{LLT::scalar(8)};
294 LLT s16{LLT::scalar(16)};
295 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
296 auto MIBCTTZ_ZERO_UNDEF =
297 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, s8, MIBTrunc);
298 AInfo Info(MF->getSubtarget());
299 LegalizerHelper Helper(*MF, Info);
300 ASSERT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 0, s16) ==
301 LegalizerHelper::LegalizeResult::Legalized);
303 auto CheckStr = R"(
304 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
305 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
306 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
307 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
310 // Check
311 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
314 // CTTZ widening.
315 TEST_F(LegalizerHelperTest, WidenBitCountingCTTZ) {
316 if (!TM)
317 return;
319 // Declare your legalization info
320 DefineLegalizerInfo(A,
321 { getActionDefinitionsBuilder(G_CTTZ).legalFor({s16}); });
322 // Build
323 // Trunc it to s8.
324 LLT s8{LLT::scalar(8)};
325 LLT s16{LLT::scalar(16)};
326 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
327 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, s8, MIBTrunc);
328 AInfo Info(MF->getSubtarget());
329 LegalizerHelper Helper(*MF, Info);
330 ASSERT_TRUE(Helper.widenScalar(*MIBCTTZ, 0, s16) ==
331 LegalizerHelper::LegalizeResult::Legalized);
333 auto CheckStr = R"(
334 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
335 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
336 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
337 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
338 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
339 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
342 // Check
343 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
345 // UADDO widening.
346 TEST_F(LegalizerHelperTest, WidenUADDO) {
347 if (!TM)
348 return;
350 // Declare your legalization info
351 DefineLegalizerInfo(A,
352 { getActionDefinitionsBuilder(G_ADD).legalFor({s16}); });
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 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
359 auto MIBUAddO = B.buildInstr(TargetOpcode::G_UADDO, s8)
360 .addDef(CarryReg)
361 .addUse(MIBTrunc->getOperand(0).getReg())
362 .addUse(MIBTrunc->getOperand(0).getReg());
363 AInfo Info(MF->getSubtarget());
364 LegalizerHelper Helper(*MF, Info);
365 ASSERT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) ==
366 LegalizerHelper::LegalizeResult::Legalized);
368 auto CheckStr = R"(
369 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
370 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
371 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
372 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
373 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
374 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_
375 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_
376 CHECK: G_TRUNC [[ADD]]
379 // Check
380 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
383 // USUBO widening.
384 TEST_F(LegalizerHelperTest, WidenUSUBO) {
385 if (!TM)
386 return;
388 // Declare your legalization info
389 DefineLegalizerInfo(A,
390 { getActionDefinitionsBuilder(G_SUB).legalFor({s16}); });
391 // Build
392 // Trunc it to s8.
393 LLT s8{LLT::scalar(8)};
394 LLT s16{LLT::scalar(16)};
395 auto MIBTrunc = B.buildTrunc(s8, Copies[0]);
396 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1));
397 auto MIBUSUBO = B.buildInstr(TargetOpcode::G_USUBO, s8)
398 .addDef(CarryReg)
399 .addUse(MIBTrunc->getOperand(0).getReg())
400 .addUse(MIBTrunc->getOperand(0).getReg());
401 AInfo Info(MF->getSubtarget());
402 LegalizerHelper Helper(*MF, Info);
403 ASSERT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) ==
404 LegalizerHelper::LegalizeResult::Legalized);
406 auto CheckStr = R"(
407 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
408 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
409 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
410 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
411 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
412 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_
413 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_
414 CHECK: G_TRUNC [[SUB]]
417 // Check
418 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr));
420 } // namespace