Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / unittests / MI / LiveIntervalTest.cpp
blob1fd1c78a5e55dfc60f193deef6332c1bf58a684b
1 #include "llvm/ADT/STLExtras.h"
2 #include "llvm/CodeGen/LiveIntervals.h"
3 #include "llvm/CodeGen/LiveVariables.h"
4 #include "llvm/CodeGen/MIRParser/MIRParser.h"
5 #include "llvm/CodeGen/MachineFunction.h"
6 #include "llvm/CodeGen/MachineModuleInfo.h"
7 #include "llvm/CodeGen/TargetRegisterInfo.h"
8 #include "llvm/CodeGen/TargetSubtargetInfo.h"
9 #include "llvm/IR/LegacyPassManager.h"
10 #include "llvm/InitializePasses.h"
11 #include "llvm/MC/TargetRegistry.h"
12 #include "llvm/Support/MemoryBuffer.h"
13 #include "llvm/Support/SourceMgr.h"
14 #include "llvm/Support/TargetSelect.h"
15 #include "llvm/Target/TargetMachine.h"
16 #include "llvm/Target/TargetOptions.h"
17 #include "gtest/gtest.h"
19 #include "../lib/CodeGen/RegisterCoalescer.h"
21 using namespace llvm;
23 namespace llvm {
24 void initializeTestPassPass(PassRegistry &);
27 namespace {
29 void initLLVM() {
30 InitializeAllTargets();
31 InitializeAllTargetMCs();
32 InitializeAllAsmPrinters();
33 InitializeAllAsmParsers();
35 PassRegistry *Registry = PassRegistry::getPassRegistry();
36 initializeCore(*Registry);
37 initializeCodeGen(*Registry);
40 /// Create a TargetMachine. As we lack a dedicated always available target for
41 /// unittests, we go for "AMDGPU" to be able to test normal and subregister
42 /// liveranges.
43 std::unique_ptr<LLVMTargetMachine> createTargetMachine() {
44 Triple TargetTriple("amdgcn--");
45 std::string Error;
46 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
47 if (!T)
48 return nullptr;
50 TargetOptions Options;
51 return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
52 T->createTargetMachine("AMDGPU", "gfx900", "", Options, std::nullopt,
53 std::nullopt, CodeGenOptLevel::Aggressive)));
56 std::unique_ptr<Module> parseMIR(LLVMContext &Context,
57 legacy::PassManagerBase &PM, std::unique_ptr<MIRParser> &MIR,
58 const LLVMTargetMachine &TM, StringRef MIRCode, const char *FuncName) {
59 SMDiagnostic Diagnostic;
60 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
61 MIR = createMIRParser(std::move(MBuffer), Context);
62 if (!MIR)
63 return nullptr;
65 std::unique_ptr<Module> M = MIR->parseIRModule();
66 if (!M)
67 return nullptr;
69 M->setDataLayout(TM.createDataLayout());
71 MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(&TM);
72 if (MIR->parseMachineFunctions(*M, MMIWP->getMMI()))
73 return nullptr;
74 PM.add(MMIWP);
76 return M;
79 struct TestPass : public MachineFunctionPass {
80 static char ID;
81 TestPass() : MachineFunctionPass(ID) {}
84 template <typename AnalysisType>
85 struct TestPassT : public TestPass {
87 typedef std::function<void(MachineFunction&,AnalysisType&)> TestFx;
89 TestPassT() {
90 // We should never call this but always use PM.add(new TestPass(...))
91 abort();
93 TestPassT(TestFx T, bool ShouldPass)
94 : T(T), ShouldPass(ShouldPass) {
95 initializeTestPassPass(*PassRegistry::getPassRegistry());
98 bool runOnMachineFunction(MachineFunction &MF) override {
99 AnalysisType &A = getAnalysis<AnalysisType>();
100 T(MF, A);
101 EXPECT_EQ(MF.verify(this, /* Banner */ nullptr, /* AbortOnError */ false),
102 ShouldPass);
103 return true;
106 void getAnalysisUsage(AnalysisUsage &AU) const override {
107 AU.setPreservesAll();
108 AU.addRequired<AnalysisType>();
109 AU.addPreserved<AnalysisType>();
110 MachineFunctionPass::getAnalysisUsage(AU);
112 private:
113 TestFx T;
114 bool ShouldPass;
117 static MachineInstr &getMI(MachineFunction &MF, unsigned At,
118 unsigned BlockNum) {
119 MachineBasicBlock &MBB = *MF.getBlockNumbered(BlockNum);
121 unsigned I = 0;
122 for (MachineInstr &MI : MBB) {
123 if (I == At)
124 return MI;
125 ++I;
127 llvm_unreachable("Instruction not found");
131 * Move instruction number \p From in front of instruction number \p To and
132 * update affected liveness intervals with LiveIntervalAnalysis::handleMove().
134 static void testHandleMove(MachineFunction &MF, LiveIntervals &LIS,
135 unsigned From, unsigned To, unsigned BlockNum = 0) {
136 MachineInstr &FromInstr = getMI(MF, From, BlockNum);
137 MachineInstr &ToInstr = getMI(MF, To, BlockNum);
139 MachineBasicBlock &MBB = *FromInstr.getParent();
140 MBB.splice(ToInstr.getIterator(), &MBB, FromInstr.getIterator());
141 LIS.handleMove(FromInstr, true);
145 * Move instructions numbered \p From inclusive through instruction number
146 * \p To into a newly formed bundle and update affected liveness intervals
147 * with LiveIntervalAnalysis::handleMoveIntoNewBundle().
149 static void testHandleMoveIntoNewBundle(MachineFunction &MF, LiveIntervals &LIS,
150 unsigned From, unsigned To,
151 unsigned BlockNum = 0) {
152 MachineInstr &FromInstr = getMI(MF, From, BlockNum);
153 MachineInstr &ToInstr = getMI(MF, To, BlockNum);
154 MachineBasicBlock &MBB = *FromInstr.getParent();
155 MachineBasicBlock::instr_iterator I = FromInstr.getIterator();
157 // Build bundle
158 finalizeBundle(MBB, I, std::next(ToInstr.getIterator()));
160 // Update LiveIntervals
161 MachineBasicBlock::instr_iterator BundleStart = std::prev(I);
162 LIS.handleMoveIntoNewBundle(*BundleStart, true);
166 * Split block numbered \p BlockNum at instruction \p SplitAt using
167 * MachineBasicBlock::splitAt updating liveness intervals.
169 static void testSplitAt(MachineFunction &MF, LiveIntervals &LIS,
170 unsigned SplitAt, unsigned BlockNum) {
171 MachineInstr &SplitInstr = getMI(MF, SplitAt, BlockNum);
172 MachineBasicBlock &MBB = *SplitInstr.getParent();
174 // Split block and update live intervals
175 MBB.splitAt(SplitInstr, false, &LIS);
179 * Helper function to test for interference between a hard register and a
180 * virtual register live ranges.
182 static bool checkRegUnitInterference(LiveIntervals &LIS,
183 const TargetRegisterInfo &TRI,
184 const LiveInterval &VirtReg,
185 MCRegister PhysReg) {
186 if (VirtReg.empty())
187 return false;
188 CoalescerPair CP(VirtReg.reg(), PhysReg, TRI);
190 for (MCRegUnit Unit : TRI.regunits(PhysReg)) {
191 const LiveRange &UnitRange = LIS.getRegUnit(Unit);
192 if (VirtReg.overlaps(UnitRange, CP, *LIS.getSlotIndexes()))
193 return true;
195 return false;
198 template <typename AnalysisType>
199 static void doTest(StringRef MIRFunc,
200 typename TestPassT<AnalysisType>::TestFx T,
201 bool ShouldPass = true) {
202 LLVMContext Context;
203 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
204 // This test is designed for the X86 backend; stop if it is not available.
205 if (!TM)
206 return;
208 legacy::PassManager PM;
209 std::unique_ptr<MIRParser> MIR;
210 std::unique_ptr<Module> M = parseMIR(Context, PM, MIR, *TM, MIRFunc, "func");
211 ASSERT_TRUE(M);
213 PM.add(new TestPassT<AnalysisType>(T, ShouldPass));
215 PM.run(*M);
218 static void liveIntervalTest(StringRef MIRFunc,
219 TestPassT<LiveIntervals>::TestFx T,
220 bool ShouldPass = true) {
221 SmallString<160> S;
222 StringRef MIRString = (Twine(R"MIR(
225 name: func
226 registers:
227 - { id: 0, class: sreg_64 }
228 body: |
229 bb.0:
230 )MIR") + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
232 doTest<LiveIntervals>(MIRString, T, ShouldPass);
235 static void liveVariablesTest(StringRef MIRFunc,
236 TestPassT<LiveVariables>::TestFx T,
237 bool ShouldPass = true) {
238 SmallString<160> S;
239 StringRef MIRString = (Twine(R"MIR(
242 name: func
243 tracksRegLiveness: true
244 registers:
245 - { id: 0, class: sreg_64 }
246 body: |
247 bb.0:
248 )MIR") + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
249 doTest<LiveVariables>(MIRString, T, ShouldPass);
252 } // End of anonymous namespace.
254 char TestPass::ID = 0;
255 INITIALIZE_PASS(TestPass, "testpass", "testpass", false, false)
257 TEST(LiveIntervalTest, MoveUpDef) {
258 // Value defined.
259 liveIntervalTest(R"MIR(
260 S_NOP 0
261 S_NOP 0
262 early-clobber %0 = IMPLICIT_DEF
263 S_NOP 0, implicit %0
264 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
265 testHandleMove(MF, LIS, 2, 1);
269 TEST(LiveIntervalTest, MoveUpRedef) {
270 liveIntervalTest(R"MIR(
271 %0 = IMPLICIT_DEF
272 S_NOP 0
273 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
274 S_NOP 0, implicit %0
275 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
276 testHandleMove(MF, LIS, 2, 1);
280 TEST(LiveIntervalTest, MoveUpEarlyDef) {
281 liveIntervalTest(R"MIR(
282 S_NOP 0
283 S_NOP 0
284 early-clobber %0 = IMPLICIT_DEF
285 S_NOP 0, implicit %0
286 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
287 testHandleMove(MF, LIS, 2, 1);
291 TEST(LiveIntervalTest, MoveUpEarlyRedef) {
292 liveIntervalTest(R"MIR(
293 %0 = IMPLICIT_DEF
294 S_NOP 0
295 early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)
296 S_NOP 0, implicit %0
297 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
298 testHandleMove(MF, LIS, 2, 1);
302 TEST(LiveIntervalTest, MoveUpKill) {
303 liveIntervalTest(R"MIR(
304 %0 = IMPLICIT_DEF
305 S_NOP 0
306 S_NOP 0, implicit %0
307 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
308 testHandleMove(MF, LIS, 2, 1);
312 TEST(LiveIntervalTest, MoveUpKillFollowing) {
313 liveIntervalTest(R"MIR(
314 %0 = IMPLICIT_DEF
315 S_NOP 0
316 S_NOP 0, implicit %0
317 S_NOP 0, implicit %0
318 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
319 testHandleMove(MF, LIS, 2, 1);
323 // TODO: Construct a situation where we have intervals following a hole
324 // while still having connected components.
326 TEST(LiveIntervalTest, MoveDownDef) {
327 // Value defined.
328 liveIntervalTest(R"MIR(
329 S_NOP 0
330 early-clobber %0 = IMPLICIT_DEF
331 S_NOP 0
332 S_NOP 0, implicit %0
333 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
334 testHandleMove(MF, LIS, 1, 2);
338 TEST(LiveIntervalTest, MoveDownRedef) {
339 liveIntervalTest(R"MIR(
340 %0 = IMPLICIT_DEF
341 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
342 S_NOP 0
343 S_NOP 0, implicit %0
344 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
345 testHandleMove(MF, LIS, 1, 2);
349 TEST(LiveIntervalTest, MoveDownEarlyDef) {
350 liveIntervalTest(R"MIR(
351 S_NOP 0
352 early-clobber %0 = IMPLICIT_DEF
353 S_NOP 0
354 S_NOP 0, implicit %0
355 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
356 testHandleMove(MF, LIS, 1, 2);
360 TEST(LiveIntervalTest, MoveDownEarlyRedef) {
361 liveIntervalTest(R"MIR(
362 %0 = IMPLICIT_DEF
363 early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)
364 S_NOP 0
365 S_NOP 0, implicit %0
366 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
367 testHandleMove(MF, LIS, 1, 2);
371 TEST(LiveIntervalTest, MoveDownKill) {
372 liveIntervalTest(R"MIR(
373 %0 = IMPLICIT_DEF
374 S_NOP 0, implicit %0
375 S_NOP 0
376 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
377 testHandleMove(MF, LIS, 1, 2);
381 TEST(LiveIntervalTest, MoveDownKillFollowing) {
382 liveIntervalTest(R"MIR(
383 %0 = IMPLICIT_DEF
384 S_NOP 0
385 S_NOP 0, implicit %0
386 S_NOP 0, implicit %0
387 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
388 testHandleMove(MF, LIS, 1, 2);
392 TEST(LiveIntervalTest, MoveUndefUse) {
393 liveIntervalTest(R"MIR(
394 %0 = IMPLICIT_DEF
395 S_NOP 0, implicit undef %0
396 S_NOP 0, implicit %0
397 S_NOP 0
398 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
399 testHandleMove(MF, LIS, 1, 3);
403 TEST(LiveIntervalTest, MoveUpValNos) {
404 // handleMoveUp() had a bug where it would reuse the value number of the
405 // destination segment, even though we have no guarantee that this valno
406 // wasn't used in other segments.
407 liveIntervalTest(R"MIR(
408 successors: %bb.1, %bb.2
409 %0 = IMPLICIT_DEF
410 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
411 S_BRANCH %bb.1
412 bb.2:
413 S_NOP 0, implicit %0
414 bb.1:
415 successors: %bb.2
416 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
417 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
418 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
419 S_BRANCH %bb.2
420 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
421 testHandleMove(MF, LIS, 2, 0, 2);
425 TEST(LiveIntervalTest, MoveOverUndefUse0) {
426 // findLastUseBefore() used by handleMoveUp() must ignore undef operands.
427 liveIntervalTest(R"MIR(
428 %0 = IMPLICIT_DEF
429 S_NOP 0
430 S_NOP 0, implicit undef %0
431 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
432 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
433 testHandleMove(MF, LIS, 3, 1);
437 TEST(LiveIntervalTest, MoveOverUndefUse1) {
438 // findLastUseBefore() used by handleMoveUp() must ignore undef operands.
439 liveIntervalTest(R"MIR(
440 $sgpr0 = IMPLICIT_DEF
441 S_NOP 0
442 S_NOP 0, implicit undef $sgpr0
443 $sgpr0 = IMPLICIT_DEF implicit $sgpr0(tied-def 0)
444 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
445 testHandleMove(MF, LIS, 3, 1);
449 TEST(LiveIntervalTest, SubRegMoveDown) {
450 // Subregister ranges can have holes inside a basic block. Check for a
451 // movement of the form 32->150 in a liverange [16, 32) [100,200).
452 liveIntervalTest(R"MIR(
453 successors: %bb.1, %bb.2
454 %0 = IMPLICIT_DEF
455 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
456 S_BRANCH %bb.1
457 bb.2:
458 successors: %bb.1
459 S_NOP 0, implicit %0.sub0
460 S_NOP 0, implicit %0.sub1
461 S_NOP 0
462 undef %0.sub0 = IMPLICIT_DEF
463 %0.sub1 = IMPLICIT_DEF
464 bb.1:
465 S_NOP 0, implicit %0
466 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
467 // Scheduler behaviour: Clear def,read-undef flag and move.
468 MachineInstr &MI = getMI(MF, 3, /*BlockNum=*/1);
469 MI.getOperand(0).setIsUndef(false);
470 testHandleMove(MF, LIS, 1, 4, /*BlockNum=*/1);
474 TEST(LiveIntervalTest, SubRegMoveUp) {
475 // handleMoveUp had a bug not updating valno of segment incoming to bb.2
476 // after swapping subreg definitions.
477 liveIntervalTest(R"MIR(
478 successors: %bb.1, %bb.2
479 undef %0.sub0 = IMPLICIT_DEF
480 %0.sub1 = IMPLICIT_DEF
481 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
482 S_BRANCH %bb.1
483 bb.1:
484 S_NOP 0, implicit %0.sub1
485 bb.2:
486 S_NOP 0, implicit %0.sub1
487 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
488 testHandleMove(MF, LIS, 1, 0);
492 TEST(LiveIntervalTest, DeadSubRegMoveUp) {
493 // handleMoveUp had a bug where moving a dead subreg def into the middle of
494 // an earlier segment resulted in an invalid live range.
495 liveIntervalTest(R"MIR(
496 undef %125.sub0:vreg_128 = V_MOV_B32_e32 0, implicit $exec
497 %125.sub1:vreg_128 = COPY %125.sub0
498 %125.sub2:vreg_128 = COPY %125.sub0
499 undef %51.sub0:vreg_128 = V_MOV_B32_e32 898625526, implicit $exec
500 %51.sub1:vreg_128 = COPY %51.sub0
501 %51.sub2:vreg_128 = COPY %51.sub0
502 %52:vgpr_32 = V_MOV_B32_e32 986714345, implicit $exec
503 %54:vgpr_32 = V_MOV_B32_e32 1742342378, implicit $exec
504 %57:vgpr_32 = V_MOV_B32_e32 3168768712, implicit $exec
505 %59:vgpr_32 = V_MOV_B32_e32 1039972644, implicit $exec
506 %60:vgpr_32 = nofpexcept V_MAD_F32_e64 0, %52, 0, undef %61:vgpr_32, 0, %59, 0, 0, implicit $mode, implicit $exec
507 %63:vgpr_32 = nofpexcept V_ADD_F32_e32 %51.sub3, undef %64:vgpr_32, implicit $mode, implicit $exec
508 dead %66:vgpr_32 = nofpexcept V_MAD_F32_e64 0, %60, 0, undef %67:vgpr_32, 0, %125.sub2, 0, 0, implicit $mode, implicit $exec
509 undef %124.sub1:vreg_128 = nofpexcept V_MAD_F32_e64 0, %57, 0, undef %70:vgpr_32, 0, %125.sub1, 0, 0, implicit $mode, implicit $exec
510 %124.sub0:vreg_128 = nofpexcept V_MAD_F32_e64 0, %54, 0, undef %73:vgpr_32, 0, %125.sub0, 0, 0, implicit $mode, implicit $exec
511 dead undef %125.sub3:vreg_128 = nofpexcept V_MAC_F32_e32 %63, undef %76:vgpr_32, %125.sub3, implicit $mode, implicit $exec
512 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
513 testHandleMove(MF, LIS, 15, 12);
517 TEST(LiveIntervalTest, EarlyClobberSubRegMoveUp) {
518 // handleMoveUp had a bug where moving an early-clobber subreg def into the
519 // middle of an earlier segment resulted in an invalid live range.
520 liveIntervalTest(R"MIR(
521 %4:sreg_32 = IMPLICIT_DEF
522 %6:sreg_32 = IMPLICIT_DEF
523 undef early-clobber %9.sub0:sreg_64 = STRICT_WWM %4:sreg_32, implicit $exec
524 %5:sreg_32 = S_FLBIT_I32_B32 %9.sub0:sreg_64
525 early-clobber %9.sub1:sreg_64 = STRICT_WWM %6:sreg_32, implicit $exec
526 %7:sreg_32 = S_FLBIT_I32_B32 %9.sub1:sreg_64
527 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
528 testHandleMove(MF, LIS, 4, 3);
532 TEST(LiveIntervalTest, TestMoveSubRegDefAcrossUseDef) {
533 liveIntervalTest(R"MIR(
534 %1:vreg_64 = IMPLICIT_DEF
536 bb.1:
537 %2:vgpr_32 = V_MOV_B32_e32 2, implicit $exec
538 %3:vgpr_32 = V_ADD_U32_e32 %2, %1.sub0, implicit $exec
539 undef %1.sub0:vreg_64 = V_ADD_U32_e32 %2, %2, implicit $exec
540 %1.sub1:vreg_64 = COPY %2
541 S_NOP 0, implicit %1.sub1
542 S_BRANCH %bb.1
544 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
545 MachineInstr &UndefSubregDef = getMI(MF, 2, 1);
546 // The scheduler clears undef from subregister defs before moving
547 UndefSubregDef.getOperand(0).setIsUndef(false);
548 testHandleMove(MF, LIS, 3, 1, 1);
552 TEST(LiveIntervalTest, TestMoveSubRegDefAcrossUseDefMulti) {
553 liveIntervalTest(R"MIR(
554 %1:vreg_96 = IMPLICIT_DEF
556 bb.1:
557 %2:vgpr_32 = V_MOV_B32_e32 2, implicit $exec
558 %3:vgpr_32 = V_ADD_U32_e32 %2, %1.sub0, implicit $exec
559 undef %1.sub0:vreg_96 = V_ADD_U32_e32 %2, %2, implicit $exec
560 %1.sub1:vreg_96 = COPY %2
561 %1.sub2:vreg_96 = COPY %2
562 S_NOP 0, implicit %1.sub1, implicit %1.sub2
563 S_BRANCH %bb.1
565 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
566 MachineInstr &UndefSubregDef = getMI(MF, 2, 1);
567 // The scheduler clears undef from subregister defs before moving
568 UndefSubregDef.getOperand(0).setIsUndef(false);
569 testHandleMove(MF, LIS, 4, 1, 1);
573 TEST(LiveIntervalTest, TestMoveSubRegUseAcrossMainRangeHole) {
574 liveIntervalTest(R"MIR(
575 %1:sgpr_128 = IMPLICIT_DEF
576 bb.1:
577 %2:sgpr_32 = COPY %1.sub2
578 %3:sgpr_32 = COPY %1.sub1
579 %1.sub2 = COPY %2
580 undef %1.sub0 = IMPLICIT_DEF
581 %1.sub2 = IMPLICIT_DEF
582 S_CBRANCH_SCC1 %bb.1, implicit undef $scc
583 S_BRANCH %bb.2
584 bb.2:
585 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
586 MachineInstr &MI = getMI(MF, 3, /*BlockNum=*/1);
587 MI.getOperand(0).setIsUndef(false);
588 testHandleMove(MF, LIS, 4, 3, 1);
589 testHandleMove(MF, LIS, 1, 4, 1);
593 TEST(LiveIntervalTest, TestMoveSubRegsOfOneReg) {
594 liveIntervalTest(R"MIR(
595 INLINEASM &"", 0, 1835018, def undef %4.sub0:vreg_64, 1835018, def undef %4.sub1:vreg_64
596 %1:vreg_64 = COPY %4
597 undef %2.sub0:vreg_64 = V_MOV_B32_e32 0, implicit $exec
598 %2.sub1:vreg_64 = COPY %2.sub0
599 %3:vreg_64 = COPY %2
600 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
601 testHandleMove(MF, LIS, 1, 4);
602 testHandleMove(MF, LIS, 0, 3);
606 TEST(LiveIntervalTest, BundleUse) {
607 liveIntervalTest(R"MIR(
608 %0 = IMPLICIT_DEF
609 S_NOP 0
610 S_NOP 0, implicit %0
611 S_NOP 0
612 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
613 testHandleMoveIntoNewBundle(MF, LIS, 1, 2);
617 TEST(LiveIntervalTest, BundleDef) {
618 liveIntervalTest(R"MIR(
619 %0 = IMPLICIT_DEF
620 S_NOP 0
621 S_NOP 0, implicit %0
622 S_NOP 0
623 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
624 testHandleMoveIntoNewBundle(MF, LIS, 0, 1);
628 TEST(LiveIntervalTest, BundleRedef) {
629 liveIntervalTest(R"MIR(
630 %0 = IMPLICIT_DEF
631 S_NOP 0
632 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
633 S_NOP 0, implicit %0
634 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
635 testHandleMoveIntoNewBundle(MF, LIS, 1, 2);
639 TEST(LiveIntervalTest, BundleInternalUse) {
640 liveIntervalTest(R"MIR(
641 %0 = IMPLICIT_DEF
642 S_NOP 0
643 S_NOP 0, implicit %0
644 S_NOP 0
645 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
646 testHandleMoveIntoNewBundle(MF, LIS, 0, 2);
650 TEST(LiveIntervalTest, BundleUndefUse) {
651 liveIntervalTest(R"MIR(
652 %0 = IMPLICIT_DEF
653 S_NOP 0
654 S_NOP 0, implicit undef %0
655 S_NOP 0
656 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
657 testHandleMoveIntoNewBundle(MF, LIS, 1, 2);
661 TEST(LiveIntervalTest, BundleSubRegUse) {
662 liveIntervalTest(R"MIR(
663 successors: %bb.1, %bb.2
664 undef %0.sub0 = IMPLICIT_DEF
665 %0.sub1 = IMPLICIT_DEF
666 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
667 S_BRANCH %bb.1
668 bb.1:
669 S_NOP 0
670 S_NOP 0, implicit %0.sub1
671 bb.2:
672 S_NOP 0, implicit %0.sub1
673 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
674 testHandleMoveIntoNewBundle(MF, LIS, 0, 1, 1);
678 TEST(LiveIntervalTest, BundleSubRegDef) {
679 liveIntervalTest(R"MIR(
680 successors: %bb.1, %bb.2
681 undef %0.sub0 = IMPLICIT_DEF
682 %0.sub1 = IMPLICIT_DEF
683 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
684 S_BRANCH %bb.1
685 bb.1:
686 S_NOP 0
687 S_NOP 0, implicit %0.sub1
688 bb.2:
689 S_NOP 0, implicit %0.sub1
690 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
691 testHandleMoveIntoNewBundle(MF, LIS, 0, 1, 0);
695 TEST(LiveIntervalTest, SplitAtOneInstruction) {
696 liveIntervalTest(R"MIR(
697 successors: %bb.1
698 %0 = IMPLICIT_DEF
699 S_BRANCH %bb.1
700 bb.1:
701 S_NOP 0
702 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
703 testSplitAt(MF, LIS, 1, 0);
707 TEST(LiveIntervalTest, SplitAtMultiInstruction) {
708 liveIntervalTest(R"MIR(
709 successors: %bb.1
710 %0 = IMPLICIT_DEF
711 S_NOP 0
712 S_NOP 0
713 S_NOP 0
714 S_NOP 0
715 S_BRANCH %bb.1
716 bb.1:
717 S_NOP 0
718 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
719 testSplitAt(MF, LIS, 0, 0);
723 TEST(LiveIntervalTest, RepairIntervals) {
724 liveIntervalTest(R"MIR(
725 %1:sgpr_32 = IMPLICIT_DEF
726 dead %2:sgpr_32 = COPY undef %3.sub0:sgpr_128
727 undef %4.sub2:sgpr_128 = COPY %1:sgpr_32
728 %5:sgpr_32 = COPY %4.sub2:sgpr_128
729 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
730 MachineInstr &Instr1 = getMI(MF, 1, 0);
731 MachineInstr &Instr2 = getMI(MF, 2, 0);
732 MachineInstr &Instr3 = getMI(MF, 3, 0);
733 LIS.RemoveMachineInstrFromMaps(Instr2);
734 MachineBasicBlock *MBB = Instr1.getParent();
735 SmallVector<Register> OrigRegs{
736 Instr1.getOperand(0).getReg(),
737 Instr2.getOperand(0).getReg(),
738 Instr2.getOperand(1).getReg(),
740 LIS.repairIntervalsInRange(MBB, Instr2, Instr3, OrigRegs);
744 TEST(LiveIntervalTest, AdjacentIntervals) {
745 liveIntervalTest(
746 R"MIR(
747 successors: %bb.1, %bb.2
749 $vgpr1 = IMPLICIT_DEF
750 S_NOP 0, implicit $vgpr1
751 %1:vgpr_32 = IMPLICIT_DEF
752 %2:vgpr_32 = IMPLICIT_DEF
753 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
754 S_BRANCH %bb.1
755 bb.1:
756 $vgpr0, dead renamable $vcc = V_ADD_CO_U32_e64 %1, %2, 0, implicit $exec
757 S_NOP 0, implicit $vgpr0
758 S_BRANCH %bb.3
759 bb.2:
760 $vgpr0 = IMPLICIT_DEF
761 $vgpr1, dead renamable $vcc = V_ADD_CO_U32_e64 %1, %2, 0, implicit $exec
762 S_NOP 0, implicit $vgpr0, implicit $vgpr1
763 S_BRANCH %bb.3
764 bb.3:
765 )MIR",
766 [](MachineFunction &MF, LiveIntervals &LIS) {
767 const auto &R1 =
768 LIS.getInterval(getMI(MF, 2, 0).getOperand(0).getReg());
769 const auto &R2 =
770 LIS.getInterval(getMI(MF, 3, 0).getOperand(0).getReg());
771 MCRegister V1 = getMI(MF, 1, 2).getOperand(0).getReg().asMCReg();
773 ASSERT_FALSE(checkRegUnitInterference(
774 LIS, *MF.getSubtarget().getRegisterInfo(), R1, V1));
775 ASSERT_FALSE(checkRegUnitInterference(
776 LIS, *MF.getSubtarget().getRegisterInfo(), R2, V1));
780 TEST(LiveIntervalTest, LiveThroughSegments) {
781 liveIntervalTest(
782 R"MIR(
783 %0 = IMPLICIT_DEF
784 S_BRANCH %bb.2
785 bb.1:
786 S_NOP 0, implicit %0
787 S_ENDPGM 0
788 bb.2:
789 S_BRANCH %bb.1
790 )MIR",
791 [](MachineFunction &MF, LiveIntervals &LIS) {
792 MachineInstr &ImpDef = getMI(MF, 0, 0);
793 MachineInstr &Nop = getMI(MF, 0, 1);
794 LiveInterval &LI = LIS.getInterval(ImpDef.getOperand(0).getReg());
795 SlotIndex OrigIdx = LIS.getInstructionIndex(ImpDef).getRegSlot();
796 LiveInterval::iterator FirstSeg = LI.FindSegmentContaining(OrigIdx);
798 // %0 is live through bb.2. Move its def into bb.1 and update LIS but do
799 // not remove the segment for bb.2. This should cause machine
800 // verification to fail.
801 LIS.RemoveMachineInstrFromMaps(ImpDef);
802 ImpDef.moveBefore(&Nop);
803 LIS.InsertMachineInstrInMaps(ImpDef);
805 SlotIndex NewIdx = LIS.getInstructionIndex(ImpDef).getRegSlot();
806 FirstSeg->start = NewIdx;
807 FirstSeg->valno->def = NewIdx;
809 false);
812 TEST(LiveVariablesTest, recomputeForSingleDefVirtReg_handle_undef1) {
813 liveVariablesTest(R"MIR(
814 %0 = IMPLICIT_DEF
815 S_NOP 0, implicit %0
816 S_NOP 0, implicit undef %0
817 )MIR", [](MachineFunction &MF, LiveVariables &LV) {
818 auto &FirstNop = getMI(MF, 1, 0);
819 auto &SecondNop = getMI(MF, 2, 0);
820 EXPECT_TRUE(FirstNop.getOperand(1).isKill());
821 EXPECT_FALSE(SecondNop.getOperand(1).isKill());
823 Register R = Register::index2VirtReg(0);
824 LV.recomputeForSingleDefVirtReg(R);
826 EXPECT_TRUE(FirstNop.getOperand(1).isKill());
827 EXPECT_FALSE(SecondNop.getOperand(1).isKill());
831 TEST(LiveVariablesTest, recomputeForSingleDefVirtReg_handle_undef2) {
832 liveVariablesTest(R"MIR(
833 %0 = IMPLICIT_DEF
834 S_NOP 0, implicit %0
835 S_NOP 0, implicit undef %0, implicit %0
836 )MIR", [](MachineFunction &MF, LiveVariables &LV) {
837 auto &FirstNop = getMI(MF, 1, 0);
838 auto &SecondNop = getMI(MF, 2, 0);
839 EXPECT_FALSE(FirstNop.getOperand(1).isKill());
840 EXPECT_FALSE(SecondNop.getOperand(1).isKill());
841 EXPECT_TRUE(SecondNop.getOperand(2).isKill());
843 Register R = Register::index2VirtReg(0);
844 LV.recomputeForSingleDefVirtReg(R);
846 EXPECT_FALSE(FirstNop.getOperand(1).isKill());
847 EXPECT_FALSE(SecondNop.getOperand(1).isKill());
848 EXPECT_TRUE(SecondNop.getOperand(2).isKill());
852 int main(int argc, char **argv) {
853 ::testing::InitGoogleTest(&argc, argv);
854 initLLVM();
855 return RUN_ALL_TESTS();