1 //===- LegalizerHelperTest.cpp
2 //-----------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #include "GISelMITest.h"
12 using namespace LegalizeActions
;
13 using namespace LegalizeMutations
;
14 using namespace LegalityPredicates
;
18 class DummyGISelObserver
: public GISelChangeObserver
{
20 void changingInstr(MachineInstr
&MI
) override
{}
21 void changedInstr(MachineInstr
&MI
) override
{}
22 void createdInstr(MachineInstr
&MI
) override
{}
23 void erasingInstr(MachineInstr
&MI
) override
{}
26 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom,
27 // in which case it becomes CTTZ_ZERO_UNDEF with select.
28 TEST_F(GISelMITest
, LowerBitCountingCTTZ0
) {
33 // Declare your legalization info
34 DefineLegalizerInfo(A
, {
35 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF
).legalFor({{s64
, s64
}});
39 B
.buildInstr(TargetOpcode::G_CTTZ
, {LLT::scalar(64)}, {Copies
[0]});
40 AInfo
Info(MF
->getSubtarget());
41 DummyGISelObserver Observer
;
42 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
43 // Perform Legalization
44 EXPECT_TRUE(Helper
.lower(*MIBCTTZ
, 0, LLT::scalar(64)) ==
45 LegalizerHelper::LegalizeResult::Legalized
);
48 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF %0
49 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
50 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
51 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
52 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
56 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
59 // CTTZ expansion in terms of CTLZ
60 TEST_F(GISelMITest
, LowerBitCountingCTTZ1
) {
65 // Declare your legalization info
66 DefineLegalizerInfo(A
, {
67 getActionDefinitionsBuilder(G_CTLZ
).legalFor({{s64
, s64
}});
71 B
.buildInstr(TargetOpcode::G_CTTZ
, {LLT::scalar(64)}, {Copies
[0]});
72 AInfo
Info(MF
->getSubtarget());
73 DummyGISelObserver Observer
;
74 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
75 // Perform Legalization
76 EXPECT_TRUE(Helper
.lower(*MIBCTTZ
, 0, LLT::scalar(64)) ==
77 LegalizerHelper::LegalizeResult::Legalized
);
80 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
81 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
82 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
83 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
84 CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
85 CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_
86 CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_
90 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
93 // CTTZ expansion in terms of CTPOP
94 TEST_F(GISelMITest
, LowerBitCountingCTTZ2
) {
99 // Declare your legalization info
100 DefineLegalizerInfo(A
, {
101 getActionDefinitionsBuilder(G_CTPOP
).legalFor({{s64
, s64
}});
105 B
.buildInstr(TargetOpcode::G_CTTZ
, {LLT::scalar(64)}, {Copies
[0]});
106 AInfo
Info(MF
->getSubtarget());
107 DummyGISelObserver Observer
;
108 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
109 EXPECT_TRUE(Helper
.lower(*MIBCTTZ
, 0, LLT::scalar(64)) ==
110 LegalizerHelper::LegalizeResult::Legalized
);
113 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
114 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]]
115 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]]
116 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_
117 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]]
121 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
125 TEST_F(GISelMITest
, WidenBitCountingCTPOP1
) {
129 // Declare your legalization info
130 DefineLegalizerInfo(A
, {
131 getActionDefinitionsBuilder(G_CTPOP
).legalFor({{s16
, s16
}});
136 LLT s8
{LLT::scalar(8)};
137 LLT s16
{LLT::scalar(16)};
138 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
139 auto MIBCTPOP
= B
.buildInstr(TargetOpcode::G_CTPOP
, {s16
}, {MIBTrunc
});
140 AInfo
Info(MF
->getSubtarget());
141 DummyGISelObserver Observer
;
142 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
143 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
144 Helper
.widenScalar(*MIBCTPOP
, 1, s16
));
147 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
148 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
149 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
150 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16)
153 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
156 // Test a strange case where the result is wider than the source
157 TEST_F(GISelMITest
, WidenBitCountingCTPOP2
) {
161 // Declare your legalization info
162 DefineLegalizerInfo(A
, {
163 getActionDefinitionsBuilder(G_CTPOP
).legalFor({{s32
, s16
}});
168 LLT s8
{LLT::scalar(8)};
169 LLT s16
{LLT::scalar(16)};
170 LLT s32
{LLT::scalar(32)};
171 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
172 auto MIBCTPOP
= B
.buildInstr(TargetOpcode::G_CTPOP
, {s32
}, {MIBTrunc
});
173 AInfo
Info(MF
->getSubtarget());
174 DummyGISelObserver Observer
;
175 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
176 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
177 Helper
.widenScalar(*MIBCTPOP
, 1, s16
));
180 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64)
181 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8)
182 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]]
183 CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16)
186 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
189 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ
190 TEST_F(GISelMITest
, LowerBitCountingCTTZ3
) {
195 // Declare your legalization info
196 DefineLegalizerInfo(A
, {
197 getActionDefinitionsBuilder(G_CTTZ
).legalFor({{s64
, s64
}});
200 auto MIBCTTZ
= B
.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF
,
201 {LLT::scalar(64)}, {Copies
[0]});
202 AInfo
Info(MF
->getSubtarget());
203 DummyGISelObserver Observer
;
204 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
205 EXPECT_TRUE(Helper
.lower(*MIBCTTZ
, 0, LLT::scalar(64)) ==
206 LegalizerHelper::LegalizeResult::Legalized
);
213 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
216 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF
217 TEST_F(GISelMITest
, LowerBitCountingCTLZ0
) {
222 // Declare your legalization info
223 DefineLegalizerInfo(A
, {
224 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF
).legalFor({{s64
, s64
}});
228 B
.buildInstr(TargetOpcode::G_CTLZ
, {LLT::scalar(64)}, {Copies
[0]});
229 AInfo
Info(MF
->getSubtarget());
230 DummyGISelObserver Observer
;
231 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
232 EXPECT_TRUE(Helper
.lower(*MIBCTLZ
, 0, LLT::scalar(64)) ==
233 LegalizerHelper::LegalizeResult::Legalized
);
236 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
237 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
238 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
239 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
240 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]]
244 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
247 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall
248 TEST_F(GISelMITest
, LowerBitCountingCTLZLibcall
) {
253 // Declare your legalization info
254 DefineLegalizerInfo(A
, {
255 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF
).libcallFor({{s64
, s64
}});
259 B
.buildInstr(TargetOpcode::G_CTLZ
, {LLT::scalar(64)}, {Copies
[0]});
260 AInfo
Info(MF
->getSubtarget());
261 DummyGISelObserver Observer
;
262 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
263 EXPECT_TRUE(Helper
.lower(*MIBCTLZ
, 0, LLT::scalar(64)) ==
264 LegalizerHelper::LegalizeResult::Legalized
);
267 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0
268 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
269 CHECK: [[THIRTY2:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
270 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]]
271 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]]
275 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
279 TEST_F(GISelMITest
, LowerBitCountingCTLZ1
) {
284 // Declare your legalization info
285 DefineLegalizerInfo(A
, {
286 getActionDefinitionsBuilder(G_CTPOP
).legalFor({{s8
, s8
}});
290 LLT s8
{LLT::scalar(8)};
291 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
292 auto MIBCTLZ
= B
.buildInstr(TargetOpcode::G_CTLZ
, {s8
}, {MIBTrunc
});
293 AInfo
Info(MF
->getSubtarget());
294 DummyGISelObserver Observer
;
295 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
296 EXPECT_TRUE(Helper
.lower(*MIBCTLZ
, 0, s8
) ==
297 LegalizerHelper::LegalizeResult::Legalized
);
300 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
301 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
302 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_
303 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_
304 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
305 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_
306 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_
307 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4
308 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_
309 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_
310 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_
311 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
312 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_
316 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
320 TEST_F(GISelMITest
, WidenBitCountingCTLZ
) {
325 // Declare your legalization info
326 DefineLegalizerInfo(A
, {
327 getActionDefinitionsBuilder(G_CTLZ
).legalFor({{s16
, s16
}});
331 LLT s8
{LLT::scalar(8)};
332 LLT s16
{LLT::scalar(16)};
333 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
334 auto MIBCTLZ
= B
.buildInstr(TargetOpcode::G_CTLZ
, {s8
}, {MIBTrunc
});
335 AInfo
Info(MF
->getSubtarget());
336 DummyGISelObserver Observer
;
337 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
338 EXPECT_TRUE(Helper
.widenScalar(*MIBCTLZ
, 1, s16
) ==
339 LegalizerHelper::LegalizeResult::Legalized
);
342 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
343 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
344 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]]
345 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
346 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_
347 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
351 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
354 // CTLZ_ZERO_UNDEF widening.
355 TEST_F(GISelMITest
, WidenBitCountingCTLZZeroUndef
) {
360 // Declare your legalization info
361 DefineLegalizerInfo(A
, {
362 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF
).legalFor({{s16
, s16
}});
366 LLT s8
{LLT::scalar(8)};
367 LLT s16
{LLT::scalar(16)};
368 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
370 B
.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF
, {s8
}, {MIBTrunc
});
371 AInfo
Info(MF
->getSubtarget());
372 DummyGISelObserver Observer
;
373 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
374 EXPECT_TRUE(Helper
.widenScalar(*MIBCTLZ_ZU
, 1, s16
) ==
375 LegalizerHelper::LegalizeResult::Legalized
);
378 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
379 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
380 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]]
381 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8
382 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_
383 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]]
387 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
391 TEST_F(GISelMITest
, WidenBitCountingCTPOP
) {
396 // Declare your legalization info
397 DefineLegalizerInfo(A
, {
398 getActionDefinitionsBuilder(G_CTPOP
).legalFor({{s16
, s16
}});
402 LLT s8
{LLT::scalar(8)};
403 LLT s16
{LLT::scalar(16)};
404 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
405 auto MIBCTPOP
= B
.buildInstr(TargetOpcode::G_CTPOP
, {s8
}, {MIBTrunc
});
406 AInfo
Info(MF
->getSubtarget());
407 DummyGISelObserver Observer
;
408 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
409 EXPECT_TRUE(Helper
.widenScalar(*MIBCTPOP
, 1, s16
) ==
410 LegalizerHelper::LegalizeResult::Legalized
);
413 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
414 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
415 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]]
416 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]]
420 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
423 // CTTZ_ZERO_UNDEF widening.
424 TEST_F(GISelMITest
, WidenBitCountingCTTZ_ZERO_UNDEF
) {
429 // Declare your legalization info
430 DefineLegalizerInfo(A
, {
431 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF
).legalFor({{s16
, s16
}});
435 LLT s8
{LLT::scalar(8)};
436 LLT s16
{LLT::scalar(16)};
437 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
438 auto MIBCTTZ_ZERO_UNDEF
=
439 B
.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF
, {s8
}, {MIBTrunc
});
440 AInfo
Info(MF
->getSubtarget());
441 DummyGISelObserver Observer
;
442 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
443 EXPECT_TRUE(Helper
.widenScalar(*MIBCTTZ_ZERO_UNDEF
, 1, s16
) ==
444 LegalizerHelper::LegalizeResult::Legalized
);
447 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
448 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
449 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]]
450 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]]
454 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
458 TEST_F(GISelMITest
, WidenBitCountingCTTZ
) {
463 // Declare your legalization info
464 DefineLegalizerInfo(A
, {
465 getActionDefinitionsBuilder(G_CTTZ
).legalFor({{s16
, s16
}});
469 LLT s8
{LLT::scalar(8)};
470 LLT s16
{LLT::scalar(16)};
471 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
472 auto MIBCTTZ
= B
.buildInstr(TargetOpcode::G_CTTZ
, {s8
}, {MIBTrunc
});
473 AInfo
Info(MF
->getSubtarget());
474 DummyGISelObserver Observer
;
475 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
476 EXPECT_TRUE(Helper
.widenScalar(*MIBCTTZ
, 1, s16
) ==
477 LegalizerHelper::LegalizeResult::Legalized
);
480 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
481 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
482 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256
483 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]]
484 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]]
485 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]]
489 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
492 TEST_F(GISelMITest
, WidenUADDO
) {
497 // Declare your legalization info
498 DefineLegalizerInfo(A
, {
499 getActionDefinitionsBuilder(G_ADD
).legalFor({{s16
, s16
}});
503 LLT s8
{LLT::scalar(8)};
504 LLT s16
{LLT::scalar(16)};
505 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
506 unsigned CarryReg
= MRI
->createGenericVirtualRegister(LLT::scalar(1));
508 B
.buildInstr(TargetOpcode::G_UADDO
, {s8
, CarryReg
}, {MIBTrunc
, MIBTrunc
});
509 AInfo
Info(MF
->getSubtarget());
510 DummyGISelObserver Observer
;
511 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
512 EXPECT_TRUE(Helper
.widenScalar(*MIBUAddO
, 0, s16
) ==
513 LegalizerHelper::LegalizeResult::Legalized
);
516 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
517 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
518 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
519 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_
520 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
521 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_
522 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_
523 CHECK: G_TRUNC [[ADD]]
527 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
531 TEST_F(GISelMITest
, WidenUSUBO
) {
536 // Declare your legalization info
537 DefineLegalizerInfo(A
, {
538 getActionDefinitionsBuilder(G_SUB
).legalFor({{s16
, s16
}});
542 LLT s8
{LLT::scalar(8)};
543 LLT s16
{LLT::scalar(16)};
544 auto MIBTrunc
= B
.buildTrunc(s8
, Copies
[0]);
545 unsigned CarryReg
= MRI
->createGenericVirtualRegister(LLT::scalar(1));
547 B
.buildInstr(TargetOpcode::G_USUBO
, {s8
, CarryReg
}, {MIBTrunc
, MIBTrunc
});
548 AInfo
Info(MF
->getSubtarget());
549 DummyGISelObserver Observer
;
550 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
551 EXPECT_TRUE(Helper
.widenScalar(*MIBUSUBO
, 0, s16
) ==
552 LegalizerHelper::LegalizeResult::Legalized
);
555 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC
556 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
557 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]]
558 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_
559 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255
560 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_
561 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_
562 CHECK: G_TRUNC [[SUB]]
566 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
569 TEST_F(GISelMITest
, FewerElementsAnd
) {
573 const LLT V2S32
= LLT::vector(2, 32);
574 const LLT V5S32
= LLT::vector(5, 32);
576 // Declare your legalization info
577 DefineLegalizerInfo(A
, {
578 getActionDefinitionsBuilder(G_AND
)
582 auto Op0
= B
.buildUndef(V5S32
);
583 auto Op1
= B
.buildUndef(V5S32
);
584 auto And
= B
.buildAnd(V5S32
, Op0
, Op1
);
586 AInfo
Info(MF
->getSubtarget());
587 DummyGISelObserver Observer
;
588 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
589 EXPECT_TRUE(Helper
.fewerElementsVector(*And
, 0, V2S32
) ==
590 LegalizerHelper::LegalizeResult::Legalized
);
593 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
594 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
595 CHECK: [[IMP_DEF2:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
596 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 0
597 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 0
598 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT0]]:_, [[EXTRACT1]]:_
599 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[IMP_DEF2]]:_, [[AND0]]:_(<2 x s32>), 0
601 CHECK: [[EXTRACT2:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 64
602 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 64
603 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT2]]:_, [[EXTRACT3]]:_
604 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[AND1]]:_(<2 x s32>), 64
606 CHECK: [[EXTRACT4:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 128
607 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 128
608 CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[EXTRACT4]]:_, [[EXTRACT5]]:_
609 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[AND2]]:_(s32), 128
613 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
616 TEST_F(GISelMITest
, MoreElementsAnd
) {
620 LLT s32
= LLT::scalar(32);
621 LLT v2s32
= LLT::vector(2, 32);
622 LLT v6s32
= LLT::vector(6, 32);
625 LI
.getActionDefinitionsBuilder(TargetOpcode::G_AND
)
627 .clampMinNumElements(0, s32
, 6);
630 DummyGISelObserver Observer
;
631 LegalizerHelper
Helper(*MF
, LI
, Observer
, B
);
633 B
.setInsertPt(*EntryMBB
, EntryMBB
->end());
635 auto Val0
= B
.buildBitcast(v2s32
, Copies
[0]);
636 auto Val1
= B
.buildBitcast(v2s32
, Copies
[1]);
638 auto And
= B
.buildAnd(v2s32
, Val0
, Val1
);
640 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
641 Helper
.moreElementsVector(*And
, 0, v6s32
));
644 CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
645 CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST
646 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
647 CHECK: [[CONCAT0:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>)
648 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
649 CHECK: [[CONCAT1:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>)
650 CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[CONCAT0]]:_, [[CONCAT1]]:_
651 CHECK: (<2 x s32>) = G_EXTRACT [[AND]]:_(<6 x s32>), 0
654 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
657 TEST_F(GISelMITest
, FewerElementsPhi
) {
661 LLT s1
= LLT::scalar(1);
662 LLT s32
= LLT::scalar(32);
663 LLT s64
= LLT::scalar(64);
664 LLT v2s32
= LLT::vector(2, 32);
665 LLT v5s32
= LLT::vector(5, 32);
668 LI
.getActionDefinitionsBuilder(TargetOpcode::G_PHI
)
670 .clampMinNumElements(0, s32
, 2);
674 DummyGISelObserver Observer
;
675 LegalizerHelper
Helper(*MF
, LI
, Observer
, B
);
678 MachineBasicBlock
*MidMBB
= MF
->CreateMachineBasicBlock();
679 MachineBasicBlock
*EndMBB
= MF
->CreateMachineBasicBlock();
680 MF
->insert(MF
->end(), MidMBB
);
681 MF
->insert(MF
->end(), EndMBB
);
683 EntryMBB
->addSuccessor(MidMBB
);
684 EntryMBB
->addSuccessor(EndMBB
);
685 MidMBB
->addSuccessor(EndMBB
);
687 auto InitVal
= B
.buildUndef(PhiTy
);
688 auto InitOtherVal
= B
.buildConstant(s64
, 999);
690 auto ICmp
= B
.buildICmp(CmpInst::ICMP_EQ
, s1
, Copies
[0], Copies
[1]);
691 B
.buildBrCond(ICmp
.getReg(0), *MidMBB
);
696 auto MidVal
= B
.buildUndef(PhiTy
);
697 auto MidOtherVal
= B
.buildConstant(s64
, 345);
701 auto Phi
= B
.buildInstr(TargetOpcode::G_PHI
)
702 .addDef(MRI
->createGenericVirtualRegister(PhiTy
))
703 .addUse(InitVal
.getReg(0))
705 .addUse(MidVal
.getReg(0))
708 // Insert another irrelevant phi to make sure the rebuild is inserted after
710 B
.buildInstr(TargetOpcode::G_PHI
)
711 .addDef(MRI
->createGenericVirtualRegister(s64
))
712 .addUse(InitOtherVal
.getReg(0))
714 .addUse(MidOtherVal
.getReg(0))
717 // Add some use instruction after the phis.
718 B
.buildAnd(PhiTy
, Phi
.getReg(0), Phi
.getReg(0));
720 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
721 Helper
.fewerElementsVector(*Phi
, 0, v2s32
));
724 CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
725 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 0
726 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 64
727 CHECK: [[EXTRACT2:%[0-9]+]]:_(s32) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 128
730 CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
731 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 0
732 CHECK: [[EXTRACT4:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 64
733 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 128
736 CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT0]]:_(<2 x s32>), %bb.0, [[EXTRACT3]]:_(<2 x s32>), %bb.1
737 CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT1]]:_(<2 x s32>), %bb.0, [[EXTRACT4]]:_(<2 x s32>), %bb.1
738 CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[EXTRACT2]]:_(s32), %bb.0, [[EXTRACT5]]:_(s32), %bb.1
740 CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI
741 CHECK: [[REBUILD_VAL_IMPDEF:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF
742 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[REBUILD_VAL_IMPDEF]]:_, [[PHI0]]:_(<2 x s32>), 0
743 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[PHI1]]:_(<2 x s32>), 64
744 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[PHI2]]:_(s32), 128
745 CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[INSERT2]]:_, [[INSERT2]]:_
748 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
751 // FNEG expansion in terms of FSUB
752 TEST_F(GISelMITest
, LowerFNEG
) {
756 // Declare your legalization info
757 DefineLegalizerInfo(A
, {
758 getActionDefinitionsBuilder(G_FSUB
).legalFor({s64
});
761 // Build Instr. Make sure FMF are preserved.
763 B
.buildInstr(TargetOpcode::G_FADD
, {LLT::scalar(64)}, {Copies
[0], Copies
[1]},
764 MachineInstr::MIFlag::FmNsz
);
766 // Should not propagate the flags of src instruction.
768 B
.buildInstr(TargetOpcode::G_FNEG
, {LLT::scalar(64)}, {FAdd
.getReg(0)},
769 {MachineInstr::MIFlag::FmArcp
});
771 // Preserve the one flag.
773 B
.buildInstr(TargetOpcode::G_FNEG
, {LLT::scalar(64)}, {Copies
[0]},
774 MachineInstr::MIFlag::FmNoInfs
);
776 AInfo
Info(MF
->getSubtarget());
777 DummyGISelObserver Observer
;
778 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
779 // Perform Legalization
780 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
781 Helper
.lower(*FNeg0
, 0, LLT::scalar(64)));
782 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
783 Helper
.lower(*FNeg1
, 0, LLT::scalar(64)));
786 CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_
787 CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
788 CHECK: [[FSUB0:%[0-9]+]]:_(s64) = arcp G_FSUB [[CONST0]]:_, [[FADD]]:_
789 CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00
790 CHECK: [[FSUB1:%[0-9]+]]:_(s64) = ninf G_FSUB [[CONST1]]:_, %0:_
794 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
797 TEST_F(GISelMITest
, LowerMinMax
) {
801 LLT s64
= LLT::scalar(64);
802 LLT v2s32
= LLT::vector(2, 32);
804 DefineLegalizerInfo(A
, {
805 getActionDefinitionsBuilder({G_SMIN
, G_SMAX
, G_UMIN
, G_UMAX
})
806 .lowerFor({s64
, LLT::vector(2, s32
)});
809 auto SMin
= B
.buildSMin(s64
, Copies
[0], Copies
[1]);
810 auto SMax
= B
.buildSMax(s64
, Copies
[0], Copies
[1]);
811 auto UMin
= B
.buildUMin(s64
, Copies
[0], Copies
[1]);
812 auto UMax
= B
.buildUMax(s64
, Copies
[0], Copies
[1]);
814 auto VecVal0
= B
.buildBitcast(v2s32
, Copies
[0]);
815 auto VecVal1
= B
.buildBitcast(v2s32
, Copies
[1]);
817 auto SMinV
= B
.buildSMin(v2s32
, VecVal0
, VecVal1
);
818 auto SMaxV
= B
.buildSMax(v2s32
, VecVal0
, VecVal1
);
819 auto UMinV
= B
.buildUMin(v2s32
, VecVal0
, VecVal1
);
820 auto UMaxV
= B
.buildUMax(v2s32
, VecVal0
, VecVal1
);
822 AInfo
Info(MF
->getSubtarget());
823 DummyGISelObserver Observer
;
824 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
825 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
826 Helper
.lower(*SMin
, 0, s64
));
827 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
828 Helper
.lower(*SMax
, 0, s64
));
829 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
830 Helper
.lower(*UMin
, 0, s64
));
831 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
832 Helper
.lower(*UMax
, 0, s64
));
834 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
835 Helper
.lower(*SMinV
, 0, v2s32
));
836 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
837 Helper
.lower(*SMaxV
, 0, v2s32
));
838 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
839 Helper
.lower(*UMinV
, 0, v2s32
));
840 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
841 Helper
.lower(*UMaxV
, 0, v2s32
));
844 CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_
845 CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_
847 CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_
848 CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_
850 CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_
851 CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_
853 CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_
854 CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_
856 CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64)
857 CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64)
859 CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
860 CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
862 CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
863 CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
865 CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
866 CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
868 CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_
869 CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_
872 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
875 TEST_F(GISelMITest
, WidenScalarBuildVector
) {
879 LLT S32
= LLT::scalar(32);
880 LLT S16
= LLT::scalar(16);
881 LLT V2S16
= LLT::vector(2, S16
);
882 LLT V2S32
= LLT::vector(2, S32
);
884 DefineLegalizerInfo(A
, {
885 getActionDefinitionsBuilder({G_SMIN
, G_SMAX
, G_UMIN
, G_UMAX
})
886 .lowerFor({s64
, LLT::vector(2, s32
)});
889 AInfo
Info(MF
->getSubtarget());
890 DummyGISelObserver Observer
;
891 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
892 B
.setInsertPt(*EntryMBB
, EntryMBB
->end());
894 Register Constant0
= B
.buildConstant(S16
, 1).getReg(0);
895 Register Constant1
= B
.buildConstant(S16
, 2).getReg(0);
896 auto BV0
= B
.buildBuildVector(V2S16
, {Constant0
, Constant1
});
897 auto BV1
= B
.buildBuildVector(V2S16
, {Constant0
, Constant1
});
899 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
900 Helper
.widenScalar(*BV0
, 0, V2S32
));
901 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
902 Helper
.widenScalar(*BV1
, 1, S32
));
905 CHECK: [[K0:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
906 CHECK-NEXT: [[K1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
907 CHECK-NEXT: [[EXT_K0_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
908 CHECK-NEXT: [[EXT_K1_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
909 CHECK-NEXT: [[BV0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[EXT_K0_0]]:_(s32), [[EXT_K1_0]]:_(s32)
910 CHECK-NEXT: [[BV0_TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BV0]]
912 CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]]
913 CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]]
915 CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32)
918 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
921 TEST_F(GISelMITest
, LowerMergeValues
) {
925 const LLT S32
= LLT::scalar(32);
926 const LLT S24
= LLT::scalar(24);
927 const LLT S21
= LLT::scalar(21);
928 const LLT S16
= LLT::scalar(16);
929 const LLT S9
= LLT::scalar(9);
930 const LLT S8
= LLT::scalar(8);
931 const LLT S3
= LLT::scalar(3);
933 DefineLegalizerInfo(A
, {
934 getActionDefinitionsBuilder(G_UNMERGE_VALUES
)
935 .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9)));
938 AInfo
Info(MF
->getSubtarget());
939 DummyGISelObserver Observer
;
940 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
941 B
.setInsertPt(*EntryMBB
, EntryMBB
->end());
943 // 24 = 3 3 3 3 3 3 3 3
946 // This can do 3 merges, but need an extra implicit_def.
947 SmallVector
<Register
, 8> Merge0Ops
;
948 for (int I
= 0; I
!= 8; ++I
)
949 Merge0Ops
.push_back(B
.buildConstant(S3
, I
).getReg(0));
951 auto Merge0
= B
.buildMerge(S24
, Merge0Ops
);
953 // 21 = 3 3 3 3 3 3 3
954 // => 9, 2 extra implicit_def needed
956 SmallVector
<Register
, 8> Merge1Ops
;
957 for (int I
= 0; I
!= 7; ++I
)
958 Merge1Ops
.push_back(B
.buildConstant(S3
, I
).getReg(0));
960 auto Merge1
= B
.buildMerge(S21
, Merge1Ops
);
962 SmallVector
<Register
, 8> Merge2Ops
;
963 for (int I
= 0; I
!= 2; ++I
)
964 Merge2Ops
.push_back(B
.buildConstant(S8
, I
).getReg(0));
966 auto Merge2
= B
.buildMerge(S16
, Merge2Ops
);
968 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
969 Helper
.widenScalar(*Merge0
, 1, S9
));
970 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
971 Helper
.widenScalar(*Merge1
, 1, S9
));
973 // Request a source size greater than the original destination size.
974 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
975 Helper
.widenScalar(*Merge2
, 1, S32
));
978 CHECK: [[K0:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
979 CHECK-NEXT: [[K1:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
980 CHECK-NEXT: [[K2:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
981 CHECK-NEXT: [[K3:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
982 CHECK-NEXT: [[K4:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
983 CHECK-NEXT: [[K5:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
984 CHECK-NEXT: [[K6:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
985 CHECK-NEXT: [[K7:%[0-9]+]]:_(s3) = G_CONSTANT i3 -1
986 CHECK-NEXT: [[IMPDEF0:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
987 CHECK-NEXT: [[MERGE0:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K0]]:_(s3), [[K1]]:_(s3), [[K2]]:_(s3)
988 CHECK-NEXT: [[MERGE1:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K3]]:_(s3), [[K4]]:_(s3), [[K5]]:_(s3)
989 CHECK-NEXT: [[MERGE2:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K6]]:_(s3), [[K7]]:_(s3), [[IMPDEF0]]:_(s3)
990 CHECK-NEXT: [[MERGE3:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE0]]:_(s9), [[MERGE1]]:_(s9), [[MERGE2]]:_(s9)
991 CHECK-NEXT: (s24) = G_TRUNC [[MERGE3]]:_(s27)
994 CHECK: [[K8:%[0-9]+]]:_(s3) = G_CONSTANT i3 0
995 CHECK-NEXT: [[K9:%[0-9]+]]:_(s3) = G_CONSTANT i3 1
996 CHECK-NEXT: [[K10:%[0-9]+]]:_(s3) = G_CONSTANT i3 2
997 CHECK-NEXT: [[K11:%[0-9]+]]:_(s3) = G_CONSTANT i3 3
998 CHECK-NEXT: [[K12:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4
999 CHECK-NEXT: [[K13:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3
1000 CHECK-NEXT: [[K14:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2
1001 CHECK-NEXT: [[IMPDEF1:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF
1002 CHECK-NEXT: [[MERGE4:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K8]]:_(s3), [[K9]]:_(s3), [[K10]]:_(s3)
1003 CHECK-NEXT: [[MERGE5:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K11]]:_(s3), [[K12]]:_(s3), [[K13]]:_(s3)
1004 CHECK-NEXT: [[MERGE6:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K14]]:_(s3), [[IMPDEF1]]:_(s3), [[IMPDEF1]]:_(s3)
1005 CHECK-NEXT: [[MERGE7:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE4]]:_(s9), [[MERGE5]]:_(s9), [[MERGE6]]:_(s9)
1006 CHECK-NEXT: (s21) = G_TRUNC [[MERGE7]]:_(s27)
1009 CHECK: [[K15:%[0-9]+]]:_(s8) = G_CONSTANT i8 0
1010 CHECK-NEXT: [[K16:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
1011 CHECK-NEXT: [[ZEXT_K15:[0-9]+]]:_(s32) = G_ZEXT [[K15]]:_(s8)
1012 CHECK-NEXT: [[ZEXT_K16:[0-9]+]]:_(s32) = G_ZEXT [[K16]]:_(s8)
1013 [[K16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1014 [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT_K16]]:_, [[K16]]:_(s32)
1015 [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT_K16]]:_, [[SHL]]:_
1016 (s16) = G_TRUNC [[OR]]:_(s32)
1019 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
1022 TEST_F(GISelMITest
, WidenScalarMergeValuesPointer
) {
1026 DefineLegalizerInfo(A
, {});
1028 AInfo
Info(MF
->getSubtarget());
1029 DummyGISelObserver Observer
;
1030 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
1031 B
.setInsertPt(*EntryMBB
, EntryMBB
->end());
1033 const LLT S32
= LLT::scalar(32);
1034 const LLT S64
= LLT::scalar(64);
1035 const LLT P0
= LLT::pointer(0, 64);
1037 auto Lo
= B
.buildTrunc(S32
, Copies
[0]);
1038 auto Hi
= B
.buildTrunc(S32
, Copies
[1]);
1040 auto Merge
= B
.buildMerge(P0
, {Lo
.getReg(0), Hi
.getReg(0)});
1042 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized
,
1043 Helper
.widenScalar(*Merge
, 1, S64
));
1046 CHECK: [[TRUNC0:%[0-9]+]]:_(s32) = G_TRUNC
1047 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC
1048 CHECK: [[ZEXT_TRUNC0:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC0]]
1049 CHECK: [[ZEXT_TRUNC1:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC1]]
1050 CHECK: [[SHIFT_AMT:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
1051 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT_TRUNC1]]:_, [[SHIFT_AMT]]
1052 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[ZEXT_TRUNC0]]:_, [[SHL]]
1053 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]:_(s64)
1056 EXPECT_TRUE(CheckMachineFunction(*MF
, CheckStr
)) << *MF
;
1059 TEST_F(GISelMITest
, WidenSEXTINREG
) {
1063 // Declare your legalization info
1064 DefineLegalizerInfo(A
, {
1065 getActionDefinitionsBuilder(G_SEXT_INREG
).legalForTypeWithAnyImm({s64
});
1068 auto MIB
= B
.buildInstr(
1069 TargetOpcode::G_SEXT_INREG
, {LLT::scalar(32)},
1070 {B
.buildInstr(TargetOpcode::G_TRUNC
, {LLT::scalar(32)}, {Copies
[0]}),
1072 AInfo
Info(MF
->getSubtarget());
1073 DummyGISelObserver Observer
;
1074 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
1075 // Perform Legalization
1076 ASSERT_TRUE(Helper
.widenScalar(*MIB
, 0, LLT::scalar(64)) ==
1077 LegalizerHelper::LegalizeResult::Legalized
);
1080 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1081 CHECK: [[T1:%[0-9]+]]:_(s64) = G_ANYEXT [[T0]]:_(s32)
1082 CHECK: [[T2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[T1]]:_, 8
1083 CHECK: [[T3:%[0-9]+]]:_(s32) = G_TRUNC [[T2]]:_(s64)
1087 ASSERT_TRUE(CheckMachineFunction(*MF
, CheckStr
));
1090 TEST_F(GISelMITest
, NarrowSEXTINREG
) {
1094 // Declare your legalization info, these aren't actually relevant to the test.
1095 DefineLegalizerInfo(A
, {
1096 getActionDefinitionsBuilder(G_SEXT_INREG
).legalForTypeWithAnyImm({s64
});
1099 auto MIB
= B
.buildInstr(
1100 TargetOpcode::G_SEXT_INREG
, {LLT::scalar(16)},
1101 {B
.buildInstr(TargetOpcode::G_TRUNC
, {LLT::scalar(16)}, {Copies
[0]}),
1103 AInfo
Info(MF
->getSubtarget());
1104 DummyGISelObserver Observer
;
1105 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
1106 // Perform Legalization
1107 ASSERT_TRUE(Helper
.narrowScalar(*MIB
, 0, LLT::scalar(10)) ==
1108 LegalizerHelper::LegalizeResult::Legalized
);
1111 CHECK: [[T0:%[0-9]+]]:_(s16) = G_TRUNC
1112 CHECK: [[T1:%[0-9]+]]:_(s10) = G_TRUNC [[T0]]:_(s16)
1113 CHECK: [[T2:%[0-9]+]]:_(s10) = G_SEXT_INREG [[T1]]:_, 8
1114 CHECK: [[T3:%[0-9]+]]:_(s16) = G_SEXT [[T2]]:_(s10)
1118 ASSERT_TRUE(CheckMachineFunction(*MF
, CheckStr
));
1121 TEST_F(GISelMITest
, NarrowSEXTINREG2
) {
1125 // Declare your legalization info, these aren't actually relevant to the test.
1126 DefineLegalizerInfo(
1127 A
, { getActionDefinitionsBuilder(G_SEXT_INREG
).legalForTypeWithAnyImm({s64
}); });
1129 auto MIB
= B
.buildInstr(
1130 TargetOpcode::G_SEXT_INREG
, {LLT::scalar(32)},
1131 {B
.buildInstr(TargetOpcode::G_TRUNC
, {LLT::scalar(32)}, {Copies
[0]}),
1133 AInfo
Info(MF
->getSubtarget());
1134 DummyGISelObserver Observer
;
1135 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
1136 // Perform Legalization
1137 ASSERT_TRUE(Helper
.narrowScalar(*MIB
, 0, LLT::scalar(8)) ==
1138 LegalizerHelper::LegalizeResult::Legalized
);
1141 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC
1142 CHECK: [[T1:%[0-9]+]]:_(s8), [[T2:%[0-9]+]]:_(s8), [[T3:%[0-9]+]]:_(s8), [[T4:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[T0]]:_(s32)
1143 CHECK: [[CST2:%[0-9]+]]:_(s8) = G_CONSTANT i8 7
1144 CHECK: [[T5:%[0-9]+]]:_(s8) = G_SEXT_INREG [[T2]]:_, 1
1145 CHECK: [[T6:%[0-9]+]]:_(s8) = G_ASHR [[T5]]:_, [[CST2]]:_
1146 CHECK: [[T7:%[0-9]+]]:_(s32) = G_MERGE_VALUES [[T1]]:_(s8), [[T5]]:_(s8), [[T6]]:_(s8), [[T6]]:_(s8)
1150 ASSERT_TRUE(CheckMachineFunction(*MF
, CheckStr
));
1153 TEST_F(GISelMITest
, LowerSEXTINREG
) {
1157 // Declare your legalization info, these aren't actually relevant to the test.
1158 DefineLegalizerInfo(
1159 A
, { getActionDefinitionsBuilder(G_SEXT_INREG
).legalForTypeWithAnyImm({s64
}); });
1161 auto MIB
= B
.buildInstr(
1162 TargetOpcode::G_SEXT_INREG
, {LLT::scalar(32)},
1163 {B
.buildInstr(TargetOpcode::G_TRUNC
, {LLT::scalar(32)}, {Copies
[0]}),
1165 AInfo
Info(MF
->getSubtarget());
1166 DummyGISelObserver Observer
;
1167 LegalizerHelper
Helper(*MF
, Info
, Observer
, B
);
1168 // Perform Legalization
1169 ASSERT_TRUE(Helper
.lower(*MIB
, 0, LLT()) ==
1170 LegalizerHelper::LegalizeResult::Legalized
);
1173 CHECK: [[T1:%[0-9]+]]:_(s32) = G_TRUNC
1174 CHECK: [[CST:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
1175 CHECK: [[T2:%[0-9]+]]:_(s32) = G_SHL [[T1]]:_, [[CST]]:_
1176 CHECK: [[T3:%[0-9]+]]:_(s32) = G_ASHR [[T2]]:_, [[CST]]:_
1180 ASSERT_TRUE(CheckMachineFunction(*MF
, CheckStr
));