[HLSL] Implement RWBuffer::operator[] via __builtin_hlsl_resource_getpointer (#117017)
[llvm-project.git] / llvm / unittests / MI / LiveIntervalTest.cpp
blobcd3307598de52186bffee8879688ad9d4cf22724
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/IR/Module.h"
11 #include "llvm/InitializePasses.h"
12 #include "llvm/MC/TargetRegistry.h"
13 #include "llvm/Support/MemoryBuffer.h"
14 #include "llvm/Support/SourceMgr.h"
15 #include "llvm/Support/TargetSelect.h"
16 #include "llvm/Target/TargetMachine.h"
17 #include "llvm/Target/TargetOptions.h"
18 #include "gtest/gtest.h"
20 #include "../lib/CodeGen/RegisterCoalescer.h"
22 using namespace llvm;
24 namespace llvm {
25 void initializeTestPassPass(PassRegistry &);
28 namespace {
30 void initLLVM() {
31 InitializeAllTargets();
32 InitializeAllTargetMCs();
33 InitializeAllAsmPrinters();
34 InitializeAllAsmParsers();
36 PassRegistry *Registry = PassRegistry::getPassRegistry();
37 initializeCore(*Registry);
38 initializeCodeGen(*Registry);
41 /// Create a TargetMachine. As we lack a dedicated always available target for
42 /// unittests, we go for "AMDGPU" to be able to test normal and subregister
43 /// liveranges.
44 std::unique_ptr<TargetMachine> createTargetMachine() {
45 Triple TargetTriple("amdgcn--");
46 std::string Error;
47 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
48 if (!T)
49 return nullptr;
51 TargetOptions Options;
52 return std::unique_ptr<TargetMachine>(
53 T->createTargetMachine("AMDGPU", "gfx900", "", Options, std::nullopt,
54 std::nullopt, CodeGenOptLevel::Aggressive));
57 std::unique_ptr<Module> parseMIR(LLVMContext &Context,
58 legacy::PassManagerBase &PM,
59 std::unique_ptr<MIRParser> &MIR,
60 const TargetMachine &TM, StringRef MIRCode) {
61 SMDiagnostic Diagnostic;
62 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
63 MIR = createMIRParser(std::move(MBuffer), Context);
64 if (!MIR)
65 return nullptr;
67 std::unique_ptr<Module> M = MIR->parseIRModule();
68 if (!M)
69 return nullptr;
71 M->setDataLayout(TM.createDataLayout());
73 MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(&TM);
74 if (MIR->parseMachineFunctions(*M, MMIWP->getMMI()))
75 return nullptr;
76 PM.add(MMIWP);
78 return M;
81 struct TestPass : public MachineFunctionPass {
82 static char ID;
83 TestPass() : MachineFunctionPass(ID) {}
86 template <typename AnalysisType>
87 struct TestPassT : public TestPass {
89 typedef std::function<void(MachineFunction&,AnalysisType&)> TestFx;
91 TestPassT() {
92 // We should never call this but always use PM.add(new TestPass(...))
93 abort();
95 TestPassT(TestFx T, bool ShouldPass)
96 : T(T), ShouldPass(ShouldPass) {
97 initializeTestPassPass(*PassRegistry::getPassRegistry());
100 bool runOnMachineFunction(MachineFunction &MF) override {
101 AnalysisType &A = getAnalysis<AnalysisType>();
102 T(MF, A);
103 EXPECT_EQ(MF.verify(this, /* Banner=*/nullptr,
104 /*OS=*/nullptr,
105 /* AbortOnError=*/false),
106 ShouldPass);
107 return true;
110 void getAnalysisUsage(AnalysisUsage &AU) const override {
111 AU.setPreservesAll();
112 AU.addRequired<AnalysisType>();
113 AU.addPreserved<AnalysisType>();
114 MachineFunctionPass::getAnalysisUsage(AU);
116 private:
117 TestFx T;
118 bool ShouldPass;
121 static MachineInstr &getMI(MachineFunction &MF, unsigned At,
122 unsigned BlockNum) {
123 MachineBasicBlock &MBB = *MF.getBlockNumbered(BlockNum);
125 unsigned I = 0;
126 for (MachineInstr &MI : MBB) {
127 if (I == At)
128 return MI;
129 ++I;
131 llvm_unreachable("Instruction not found");
135 * Move instruction number \p From in front of instruction number \p To and
136 * update affected liveness intervals with LiveIntervalAnalysis::handleMove().
138 static void testHandleMove(MachineFunction &MF, LiveIntervals &LIS,
139 unsigned From, unsigned To, unsigned BlockNum = 0) {
140 MachineInstr &FromInstr = getMI(MF, From, BlockNum);
141 MachineInstr &ToInstr = getMI(MF, To, BlockNum);
143 MachineBasicBlock &MBB = *FromInstr.getParent();
144 MBB.splice(ToInstr.getIterator(), &MBB, FromInstr.getIterator());
145 LIS.handleMove(FromInstr, true);
149 * Move instructions numbered \p From inclusive through instruction number
150 * \p To into a newly formed bundle and update affected liveness intervals
151 * with LiveIntervalAnalysis::handleMoveIntoNewBundle().
153 static void testHandleMoveIntoNewBundle(MachineFunction &MF, LiveIntervals &LIS,
154 unsigned From, unsigned To,
155 unsigned BlockNum = 0) {
156 MachineInstr &FromInstr = getMI(MF, From, BlockNum);
157 MachineInstr &ToInstr = getMI(MF, To, BlockNum);
158 MachineBasicBlock &MBB = *FromInstr.getParent();
159 MachineBasicBlock::instr_iterator I = FromInstr.getIterator();
161 // Build bundle
162 finalizeBundle(MBB, I, std::next(ToInstr.getIterator()));
163 MF.getProperties().reset(MachineFunctionProperties::Property::IsSSA);
165 // Update LiveIntervals
166 MachineBasicBlock::instr_iterator BundleStart = std::prev(I);
167 LIS.handleMoveIntoNewBundle(*BundleStart, true);
171 * Split block numbered \p BlockNum at instruction \p SplitAt using
172 * MachineBasicBlock::splitAt updating liveness intervals.
174 static void testSplitAt(MachineFunction &MF, LiveIntervals &LIS,
175 unsigned SplitAt, unsigned BlockNum) {
176 MachineInstr &SplitInstr = getMI(MF, SplitAt, BlockNum);
177 MachineBasicBlock &MBB = *SplitInstr.getParent();
179 // Split block and update live intervals
180 MBB.splitAt(SplitInstr, false, &LIS);
184 * Helper function to test for interference between a hard register and a
185 * virtual register live ranges.
187 static bool checkRegUnitInterference(LiveIntervals &LIS,
188 const TargetRegisterInfo &TRI,
189 const LiveInterval &VirtReg,
190 MCRegister PhysReg) {
191 if (VirtReg.empty())
192 return false;
193 CoalescerPair CP(VirtReg.reg(), PhysReg, TRI);
195 for (MCRegUnit Unit : TRI.regunits(PhysReg)) {
196 const LiveRange &UnitRange = LIS.getRegUnit(Unit);
197 if (VirtReg.overlaps(UnitRange, CP, *LIS.getSlotIndexes()))
198 return true;
200 return false;
203 template <typename AnalysisType>
204 static void doTest(StringRef MIRFunc,
205 typename TestPassT<AnalysisType>::TestFx T,
206 bool ShouldPass = true) {
207 LLVMContext Context;
208 std::unique_ptr<TargetMachine> TM = createTargetMachine();
209 // This test is designed for the X86 backend; stop if it is not available.
210 if (!TM)
211 return;
213 legacy::PassManager PM;
214 std::unique_ptr<MIRParser> MIR;
215 std::unique_ptr<Module> M = parseMIR(Context, PM, MIR, *TM, MIRFunc);
216 ASSERT_TRUE(M);
218 PM.add(new TestPassT<AnalysisType>(T, ShouldPass));
220 PM.run(*M);
223 static void liveIntervalTest(StringRef MIRFunc,
224 TestPassT<LiveIntervalsWrapperPass>::TestFx T,
225 bool ShouldPass = true) {
226 SmallString<160> S;
227 StringRef MIRString = (Twine(R"MIR(
230 name: func
231 registers:
232 - { id: 0, class: sreg_64 }
233 body: |
234 bb.0:
235 )MIR") + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
237 doTest<LiveIntervalsWrapperPass>(MIRString, T, ShouldPass);
240 static void liveVariablesTest(StringRef MIRFunc,
241 TestPassT<LiveVariablesWrapperPass>::TestFx T,
242 bool ShouldPass = true) {
243 SmallString<160> S;
244 StringRef MIRString = (Twine(R"MIR(
247 name: func
248 tracksRegLiveness: true
249 registers:
250 - { id: 0, class: sreg_64 }
251 body: |
252 bb.0:
253 )MIR") + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
254 doTest<LiveVariablesWrapperPass>(MIRString, T, ShouldPass);
257 } // End of anonymous namespace.
259 char TestPass::ID = 0;
260 INITIALIZE_PASS(TestPass, "testpass", "testpass", false, false)
262 TEST(LiveIntervalTest, MoveUpDef) {
263 // Value defined.
264 liveIntervalTest(
265 R"MIR(
266 S_NOP 0
267 S_NOP 0
268 early-clobber %0 = IMPLICIT_DEF
269 S_NOP 0, implicit %0
270 )MIR",
271 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
272 testHandleMove(MF, LISWrapper.getLIS(), 2, 1);
276 TEST(LiveIntervalTest, MoveUpRedef) {
277 liveIntervalTest(R"MIR(
278 %0 = IMPLICIT_DEF
279 S_NOP 0
280 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
281 S_NOP 0, implicit %0
282 )MIR",
283 [](MachineFunction &MF, LiveIntervalsWrapperPass &LIS) {
284 testHandleMove(MF, LIS.getLIS(), 2, 1);
288 TEST(LiveIntervalTest, MoveUpEarlyDef) {
289 liveIntervalTest(
290 R"MIR(
291 S_NOP 0
292 S_NOP 0
293 early-clobber %0 = IMPLICIT_DEF
294 S_NOP 0, implicit %0
295 )MIR",
296 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
297 testHandleMove(MF, LISWrapper.getLIS(), 2, 1);
301 TEST(LiveIntervalTest, MoveUpEarlyRedef) {
302 liveIntervalTest(
303 R"MIR(
304 %0 = IMPLICIT_DEF
305 S_NOP 0
306 early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)
307 S_NOP 0, implicit %0
308 )MIR",
309 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
310 testHandleMove(MF, LISWrapper.getLIS(), 2, 1);
314 TEST(LiveIntervalTest, MoveUpKill) {
315 liveIntervalTest(
316 R"MIR(
317 %0 = IMPLICIT_DEF
318 S_NOP 0
319 S_NOP 0, implicit %0
320 )MIR",
321 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
322 testHandleMove(MF, LISWrapper.getLIS(), 2, 1);
326 TEST(LiveIntervalTest, MoveUpKillFollowing) {
327 liveIntervalTest(
328 R"MIR(
329 %0 = IMPLICIT_DEF
330 S_NOP 0
331 S_NOP 0, implicit %0
332 S_NOP 0, implicit %0
333 )MIR",
334 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
335 testHandleMove(MF, LISWrapper.getLIS(), 2, 1);
339 // TODO: Construct a situation where we have intervals following a hole
340 // while still having connected components.
342 TEST(LiveIntervalTest, MoveDownDef) {
343 // Value defined.
344 liveIntervalTest(
345 R"MIR(
346 S_NOP 0
347 early-clobber %0 = IMPLICIT_DEF
348 S_NOP 0
349 S_NOP 0, implicit %0
350 )MIR",
351 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
352 testHandleMove(MF, LISWrapper.getLIS(), 1, 2);
356 TEST(LiveIntervalTest, MoveDownRedef) {
357 liveIntervalTest(
358 R"MIR(
359 %0 = IMPLICIT_DEF
360 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
361 S_NOP 0
362 S_NOP 0, implicit %0
363 )MIR",
364 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
365 testHandleMove(MF, LISWrapper.getLIS(), 1, 2);
369 TEST(LiveIntervalTest, MoveDownEarlyDef) {
370 liveIntervalTest(
371 R"MIR(
372 S_NOP 0
373 early-clobber %0 = IMPLICIT_DEF
374 S_NOP 0
375 S_NOP 0, implicit %0
376 )MIR",
377 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
378 testHandleMove(MF, LISWrapper.getLIS(), 1, 2);
382 TEST(LiveIntervalTest, MoveDownEarlyRedef) {
383 liveIntervalTest(
384 R"MIR(
385 %0 = IMPLICIT_DEF
386 early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)
387 S_NOP 0
388 S_NOP 0, implicit %0
389 )MIR",
390 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
391 testHandleMove(MF, LISWrapper.getLIS(), 1, 2);
395 TEST(LiveIntervalTest, MoveDownKill) {
396 liveIntervalTest(
397 R"MIR(
398 %0 = IMPLICIT_DEF
399 S_NOP 0, implicit %0
400 S_NOP 0
401 )MIR",
402 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
403 testHandleMove(MF, LISWrapper.getLIS(), 1, 2);
407 TEST(LiveIntervalTest, MoveDownKillFollowing) {
408 liveIntervalTest(
409 R"MIR(
410 %0 = IMPLICIT_DEF
411 S_NOP 0
412 S_NOP 0, implicit %0
413 S_NOP 0, implicit %0
414 )MIR",
415 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
416 testHandleMove(MF, LISWrapper.getLIS(), 1, 2);
420 TEST(LiveIntervalTest, MoveUndefUse) {
421 liveIntervalTest(
422 R"MIR(
423 %0 = IMPLICIT_DEF
424 S_NOP 0, implicit undef %0
425 S_NOP 0, implicit %0
426 S_NOP 0
427 )MIR",
428 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
429 testHandleMove(MF, LISWrapper.getLIS(), 1, 3);
433 TEST(LiveIntervalTest, MoveUpValNos) {
434 // handleMoveUp() had a bug where it would reuse the value number of the
435 // destination segment, even though we have no guarantee that this valno
436 // wasn't used in other segments.
437 liveIntervalTest(
438 R"MIR(
439 successors: %bb.1, %bb.2
440 %0 = IMPLICIT_DEF
441 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
442 S_BRANCH %bb.1
443 bb.2:
444 S_NOP 0, implicit %0
445 bb.1:
446 successors: %bb.2
447 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
448 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
449 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
450 S_BRANCH %bb.2
451 )MIR",
452 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
453 testHandleMove(MF, LISWrapper.getLIS(), 2, 0, 2);
457 TEST(LiveIntervalTest, MoveOverUndefUse0) {
458 // findLastUseBefore() used by handleMoveUp() must ignore undef operands.
459 liveIntervalTest(
460 R"MIR(
461 %0 = IMPLICIT_DEF
462 S_NOP 0
463 S_NOP 0, implicit undef %0
464 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
465 )MIR",
466 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
467 testHandleMove(MF, LISWrapper.getLIS(), 3, 1);
471 TEST(LiveIntervalTest, MoveOverUndefUse1) {
472 // findLastUseBefore() used by handleMoveUp() must ignore undef operands.
473 liveIntervalTest(
474 R"MIR(
475 $sgpr0 = IMPLICIT_DEF
476 S_NOP 0
477 S_NOP 0, implicit undef $sgpr0
478 $sgpr0 = IMPLICIT_DEF implicit $sgpr0(tied-def 0)
479 )MIR",
480 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
481 testHandleMove(MF, LISWrapper.getLIS(), 3, 1);
485 TEST(LiveIntervalTest, SubRegMoveDown) {
486 // Subregister ranges can have holes inside a basic block. Check for a
487 // movement of the form 32->150 in a liverange [16, 32) [100,200).
488 liveIntervalTest(
489 R"MIR(
490 successors: %bb.1, %bb.2
491 %0 = IMPLICIT_DEF
492 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
493 S_BRANCH %bb.1
494 bb.2:
495 successors: %bb.1
496 S_NOP 0, implicit %0.sub0
497 S_NOP 0, implicit %0.sub1
498 S_NOP 0
499 undef %0.sub0 = IMPLICIT_DEF
500 %0.sub1 = IMPLICIT_DEF
501 bb.1:
502 S_NOP 0, implicit %0
503 )MIR",
504 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
505 // Scheduler behaviour: Clear def,read-undef flag and move.
506 MachineInstr &MI = getMI(MF, 3, /*BlockNum=*/1);
507 MI.getOperand(0).setIsUndef(false);
508 testHandleMove(MF, LISWrapper.getLIS(), 1, 4, /*BlockNum=*/1);
512 TEST(LiveIntervalTest, SubRegMoveUp) {
513 // handleMoveUp had a bug not updating valno of segment incoming to bb.2
514 // after swapping subreg definitions.
515 liveIntervalTest(
516 R"MIR(
517 successors: %bb.1, %bb.2
518 undef %0.sub0 = IMPLICIT_DEF
519 %0.sub1 = IMPLICIT_DEF
520 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
521 S_BRANCH %bb.1
522 bb.1:
523 S_NOP 0, implicit %0.sub1
524 bb.2:
525 S_NOP 0, implicit %0.sub1
526 )MIR",
527 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
528 testHandleMove(MF, LISWrapper.getLIS(), 1, 0);
532 TEST(LiveIntervalTest, DeadSubRegMoveUp) {
533 // handleMoveUp had a bug where moving a dead subreg def into the middle of
534 // an earlier segment resulted in an invalid live range.
535 liveIntervalTest(
536 R"MIR(
537 undef %125.sub0:vreg_128 = V_MOV_B32_e32 0, implicit $exec
538 %125.sub1:vreg_128 = COPY %125.sub0
539 %125.sub2:vreg_128 = COPY %125.sub0
540 undef %51.sub0:vreg_128 = V_MOV_B32_e32 898625526, implicit $exec
541 %51.sub1:vreg_128 = COPY %51.sub0
542 %51.sub2:vreg_128 = COPY %51.sub0
543 %52:vgpr_32 = V_MOV_B32_e32 986714345, implicit $exec
544 %54:vgpr_32 = V_MOV_B32_e32 1742342378, implicit $exec
545 %57:vgpr_32 = V_MOV_B32_e32 3168768712, implicit $exec
546 %59:vgpr_32 = V_MOV_B32_e32 1039972644, implicit $exec
547 %60:vgpr_32 = nofpexcept V_MAD_F32_e64 0, %52, 0, undef %61:vgpr_32, 0, %59, 0, 0, implicit $mode, implicit $exec
548 %63:vgpr_32 = nofpexcept V_ADD_F32_e32 %51.sub3, undef %64:vgpr_32, implicit $mode, implicit $exec
549 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
550 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
551 %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
552 dead undef %125.sub3:vreg_128 = nofpexcept V_MAC_F32_e32 %63, undef %76:vgpr_32, %125.sub3, implicit $mode, implicit $exec
553 )MIR",
554 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
555 testHandleMove(MF, LISWrapper.getLIS(), 15, 12);
559 TEST(LiveIntervalTest, EarlyClobberSubRegMoveUp) {
560 // handleMoveUp had a bug where moving an early-clobber subreg def into the
561 // middle of an earlier segment resulted in an invalid live range.
562 liveIntervalTest(
563 R"MIR(
564 %4:sreg_32 = IMPLICIT_DEF
565 %6:sreg_32 = IMPLICIT_DEF
566 undef early-clobber %9.sub0:sreg_64 = STRICT_WWM %4:sreg_32, implicit $exec
567 %5:sreg_32 = S_FLBIT_I32_B32 %9.sub0:sreg_64
568 early-clobber %9.sub1:sreg_64 = STRICT_WWM %6:sreg_32, implicit $exec
569 %7:sreg_32 = S_FLBIT_I32_B32 %9.sub1:sreg_64
570 )MIR",
571 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
572 testHandleMove(MF, LISWrapper.getLIS(), 4, 3);
576 TEST(LiveIntervalTest, TestMoveSubRegDefAcrossUseDef) {
577 liveIntervalTest(
578 R"MIR(
579 %1:vreg_64 = IMPLICIT_DEF
581 bb.1:
582 %2:vgpr_32 = V_MOV_B32_e32 2, implicit $exec
583 %3:vgpr_32 = V_ADD_U32_e32 %2, %1.sub0, implicit $exec
584 undef %1.sub0:vreg_64 = V_ADD_U32_e32 %2, %2, implicit $exec
585 %1.sub1:vreg_64 = COPY %2
586 S_NOP 0, implicit %1.sub1
587 S_BRANCH %bb.1
589 )MIR",
590 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
591 MachineInstr &UndefSubregDef = getMI(MF, 2, 1);
592 // The scheduler clears undef from subregister defs before moving
593 UndefSubregDef.getOperand(0).setIsUndef(false);
594 testHandleMove(MF, LISWrapper.getLIS(), 3, 1, 1);
598 TEST(LiveIntervalTest, TestMoveSubRegDefAcrossUseDefMulti) {
599 liveIntervalTest(
600 R"MIR(
601 %1:vreg_96 = IMPLICIT_DEF
603 bb.1:
604 %2:vgpr_32 = V_MOV_B32_e32 2, implicit $exec
605 %3:vgpr_32 = V_ADD_U32_e32 %2, %1.sub0, implicit $exec
606 undef %1.sub0:vreg_96 = V_ADD_U32_e32 %2, %2, implicit $exec
607 %1.sub1:vreg_96 = COPY %2
608 %1.sub2:vreg_96 = COPY %2
609 S_NOP 0, implicit %1.sub1, implicit %1.sub2
610 S_BRANCH %bb.1
612 )MIR",
613 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
614 MachineInstr &UndefSubregDef = getMI(MF, 2, 1);
615 // The scheduler clears undef from subregister defs before moving
616 UndefSubregDef.getOperand(0).setIsUndef(false);
617 testHandleMove(MF, LISWrapper.getLIS(), 4, 1, 1);
621 TEST(LiveIntervalTest, TestMoveSubRegUseAcrossMainRangeHole) {
622 liveIntervalTest(
623 R"MIR(
624 %1:sgpr_128 = IMPLICIT_DEF
625 bb.1:
626 %2:sgpr_32 = COPY %1.sub2
627 %3:sgpr_32 = COPY %1.sub1
628 %1.sub2 = COPY %2
629 undef %1.sub0 = IMPLICIT_DEF
630 %1.sub2 = IMPLICIT_DEF
631 S_CBRANCH_SCC1 %bb.1, implicit undef $scc
632 S_BRANCH %bb.2
633 bb.2:
634 )MIR",
635 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
636 MachineInstr &MI = getMI(MF, 3, /*BlockNum=*/1);
637 MI.getOperand(0).setIsUndef(false);
638 testHandleMove(MF, LISWrapper.getLIS(), 4, 3, 1);
639 testHandleMove(MF, LISWrapper.getLIS(), 1, 4, 1);
643 TEST(LiveIntervalTest, TestMoveSubRegsOfOneReg) {
644 liveIntervalTest(
645 R"MIR(
646 INLINEASM &"", 0, 1835018, def undef %4.sub0:vreg_64, 1835018, def undef %4.sub1:vreg_64
647 %1:vreg_64 = COPY %4
648 undef %2.sub0:vreg_64 = V_MOV_B32_e32 0, implicit $exec
649 %2.sub1:vreg_64 = COPY %2.sub0
650 %3:vreg_64 = COPY %2
651 )MIR",
652 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
653 testHandleMove(MF, LISWrapper.getLIS(), 1, 4);
654 testHandleMove(MF, LISWrapper.getLIS(), 0, 3);
658 TEST(LiveIntervalTest, BundleUse) {
659 liveIntervalTest(
660 R"MIR(
661 %0 = IMPLICIT_DEF
662 S_NOP 0
663 S_NOP 0, implicit %0
664 S_NOP 0
665 )MIR",
666 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
667 testHandleMoveIntoNewBundle(MF, LISWrapper.getLIS(), 1, 2);
671 TEST(LiveIntervalTest, BundleDef) {
672 liveIntervalTest(
673 R"MIR(
674 %0 = IMPLICIT_DEF
675 S_NOP 0
676 S_NOP 0, implicit %0
677 S_NOP 0
678 )MIR",
679 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
680 testHandleMoveIntoNewBundle(MF, LISWrapper.getLIS(), 0, 1);
684 TEST(LiveIntervalTest, BundleRedef) {
685 liveIntervalTest(
686 R"MIR(
687 %0 = IMPLICIT_DEF
688 S_NOP 0
689 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
690 S_NOP 0, implicit %0
691 )MIR",
692 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
693 testHandleMoveIntoNewBundle(MF, LISWrapper.getLIS(), 1, 2);
697 TEST(LiveIntervalTest, BundleInternalUse) {
698 liveIntervalTest(
699 R"MIR(
700 %0 = IMPLICIT_DEF
701 S_NOP 0
702 S_NOP 0, implicit %0
703 S_NOP 0
704 )MIR",
705 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
706 testHandleMoveIntoNewBundle(MF, LISWrapper.getLIS(), 0, 2);
710 TEST(LiveIntervalTest, BundleUndefUse) {
711 liveIntervalTest(
712 R"MIR(
713 %0 = IMPLICIT_DEF
714 S_NOP 0
715 S_NOP 0, implicit undef %0
716 S_NOP 0
717 )MIR",
718 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
719 testHandleMoveIntoNewBundle(MF, LISWrapper.getLIS(), 1, 2);
723 TEST(LiveIntervalTest, BundleSubRegUse) {
724 liveIntervalTest(
725 R"MIR(
726 successors: %bb.1, %bb.2
727 undef %0.sub0 = IMPLICIT_DEF
728 %0.sub1 = IMPLICIT_DEF
729 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
730 S_BRANCH %bb.1
731 bb.1:
732 S_NOP 0
733 S_NOP 0, implicit %0.sub1
734 bb.2:
735 S_NOP 0, implicit %0.sub1
736 )MIR",
737 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
738 testHandleMoveIntoNewBundle(MF, LISWrapper.getLIS(), 0, 1, 1);
742 TEST(LiveIntervalTest, BundleSubRegDef) {
743 liveIntervalTest(
744 R"MIR(
745 successors: %bb.1, %bb.2
746 undef %0.sub0 = IMPLICIT_DEF
747 %0.sub1 = IMPLICIT_DEF
748 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
749 S_BRANCH %bb.1
750 bb.1:
751 S_NOP 0
752 S_NOP 0, implicit %0.sub1
753 bb.2:
754 S_NOP 0, implicit %0.sub1
755 )MIR",
756 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
757 testHandleMoveIntoNewBundle(MF, LISWrapper.getLIS(), 0, 1, 0);
761 TEST(LiveIntervalTest, SplitAtOneInstruction) {
762 liveIntervalTest(
763 R"MIR(
764 successors: %bb.1
765 %0 = IMPLICIT_DEF
766 S_BRANCH %bb.1
767 bb.1:
768 S_NOP 0
769 )MIR",
770 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
771 testSplitAt(MF, LISWrapper.getLIS(), 1, 0);
775 TEST(LiveIntervalTest, SplitAtMultiInstruction) {
776 liveIntervalTest(
777 R"MIR(
778 successors: %bb.1
779 %0 = IMPLICIT_DEF
780 S_NOP 0
781 S_NOP 0
782 S_NOP 0
783 S_NOP 0
784 S_BRANCH %bb.1
785 bb.1:
786 S_NOP 0
787 )MIR",
788 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
789 testSplitAt(MF, LISWrapper.getLIS(), 0, 0);
793 TEST(LiveIntervalTest, RepairIntervals) {
794 liveIntervalTest(
795 R"MIR(
796 %1:sgpr_32 = IMPLICIT_DEF
797 dead %2:sgpr_32 = COPY undef %3.sub0:sgpr_128
798 undef %4.sub2:sgpr_128 = COPY %1:sgpr_32
799 %5:sgpr_32 = COPY %4.sub2:sgpr_128
800 )MIR",
801 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
802 auto &LIS = LISWrapper.getLIS();
803 MachineInstr &Instr1 = getMI(MF, 1, 0);
804 MachineInstr &Instr2 = getMI(MF, 2, 0);
805 MachineInstr &Instr3 = getMI(MF, 3, 0);
806 LIS.RemoveMachineInstrFromMaps(Instr2);
807 MachineBasicBlock *MBB = Instr1.getParent();
808 SmallVector<Register> OrigRegs{
809 Instr1.getOperand(0).getReg(),
810 Instr2.getOperand(0).getReg(),
811 Instr2.getOperand(1).getReg(),
813 LIS.repairIntervalsInRange(MBB, Instr2, Instr3, OrigRegs);
817 TEST(LiveIntervalTest, AdjacentIntervals) {
818 liveIntervalTest(
819 R"MIR(
820 successors: %bb.1, %bb.2
822 $vgpr1 = IMPLICIT_DEF
823 S_NOP 0, implicit $vgpr1
824 %1:vgpr_32 = IMPLICIT_DEF
825 %2:vgpr_32 = IMPLICIT_DEF
826 S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
827 S_BRANCH %bb.1
828 bb.1:
829 $vgpr0, dead renamable $vcc = V_ADD_CO_U32_e64 %1, %2, 0, implicit $exec
830 S_NOP 0, implicit $vgpr0
831 S_BRANCH %bb.3
832 bb.2:
833 $vgpr0 = IMPLICIT_DEF
834 $vgpr1, dead renamable $vcc = V_ADD_CO_U32_e64 %1, %2, 0, implicit $exec
835 S_NOP 0, implicit $vgpr0, implicit $vgpr1
836 S_BRANCH %bb.3
837 bb.3:
838 )MIR",
839 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
840 auto &LIS = LISWrapper.getLIS();
841 const auto &R1 =
842 LIS.getInterval(getMI(MF, 2, 0).getOperand(0).getReg());
843 const auto &R2 =
844 LIS.getInterval(getMI(MF, 3, 0).getOperand(0).getReg());
845 MCRegister V1 = getMI(MF, 1, 2).getOperand(0).getReg().asMCReg();
847 ASSERT_FALSE(checkRegUnitInterference(
848 LIS, *MF.getSubtarget().getRegisterInfo(), R1, V1));
849 ASSERT_FALSE(checkRegUnitInterference(
850 LIS, *MF.getSubtarget().getRegisterInfo(), R2, V1));
854 TEST(LiveIntervalTest, LiveThroughSegments) {
855 liveIntervalTest(
856 R"MIR(
857 %0 = IMPLICIT_DEF
858 S_BRANCH %bb.2
859 bb.1:
860 S_NOP 0, implicit %0
861 S_ENDPGM 0
862 bb.2:
863 S_BRANCH %bb.1
864 )MIR",
865 [](MachineFunction &MF, LiveIntervalsWrapperPass &LISWrapper) {
866 auto &LIS = LISWrapper.getLIS();
867 MachineInstr &ImpDef = getMI(MF, 0, 0);
868 MachineInstr &Nop = getMI(MF, 0, 1);
869 LiveInterval &LI = LIS.getInterval(ImpDef.getOperand(0).getReg());
870 SlotIndex OrigIdx = LIS.getInstructionIndex(ImpDef).getRegSlot();
871 LiveInterval::iterator FirstSeg = LI.FindSegmentContaining(OrigIdx);
873 // %0 is live through bb.2. Move its def into bb.1 and update LIS but do
874 // not remove the segment for bb.2. This should cause machine
875 // verification to fail.
876 LIS.RemoveMachineInstrFromMaps(ImpDef);
877 ImpDef.moveBefore(&Nop);
878 LIS.InsertMachineInstrInMaps(ImpDef);
880 SlotIndex NewIdx = LIS.getInstructionIndex(ImpDef).getRegSlot();
881 FirstSeg->start = NewIdx;
882 FirstSeg->valno->def = NewIdx;
884 false);
887 TEST(LiveVariablesTest, recomputeForSingleDefVirtReg_handle_undef1) {
888 liveVariablesTest(
889 R"MIR(
890 %0 = IMPLICIT_DEF
891 S_NOP 0, implicit %0
892 S_NOP 0, implicit undef %0
893 )MIR",
894 [](MachineFunction &MF, LiveVariablesWrapperPass &LVWrapper) {
895 auto &LV = LVWrapper.getLV();
896 auto &FirstNop = getMI(MF, 1, 0);
897 auto &SecondNop = getMI(MF, 2, 0);
898 EXPECT_TRUE(FirstNop.getOperand(1).isKill());
899 EXPECT_FALSE(SecondNop.getOperand(1).isKill());
901 Register R = Register::index2VirtReg(0);
902 LV.recomputeForSingleDefVirtReg(R);
904 EXPECT_TRUE(FirstNop.getOperand(1).isKill());
905 EXPECT_FALSE(SecondNop.getOperand(1).isKill());
909 TEST(LiveVariablesTest, recomputeForSingleDefVirtReg_handle_undef2) {
910 liveVariablesTest(
911 R"MIR(
912 %0 = IMPLICIT_DEF
913 S_NOP 0, implicit %0
914 S_NOP 0, implicit undef %0, implicit %0
915 )MIR",
916 [](MachineFunction &MF, LiveVariablesWrapperPass &LVWrapper) {
917 auto &LV = LVWrapper.getLV();
918 auto &FirstNop = getMI(MF, 1, 0);
919 auto &SecondNop = getMI(MF, 2, 0);
920 EXPECT_FALSE(FirstNop.getOperand(1).isKill());
921 EXPECT_FALSE(SecondNop.getOperand(1).isKill());
922 EXPECT_TRUE(SecondNop.getOperand(2).isKill());
924 Register R = Register::index2VirtReg(0);
925 LV.recomputeForSingleDefVirtReg(R);
927 EXPECT_FALSE(FirstNop.getOperand(1).isKill());
928 EXPECT_FALSE(SecondNop.getOperand(1).isKill());
929 EXPECT_TRUE(SecondNop.getOperand(2).isKill());
933 int main(int argc, char **argv) {
934 ::testing::InitGoogleTest(&argc, argv);
935 initLLVM();
936 return RUN_ALL_TESTS();