1 #include "llvm/ADT/STLExtras.h"
2 #include "llvm/CodeGen/LiveIntervals.h"
3 #include "llvm/CodeGen/MIRParser/MIRParser.h"
4 #include "llvm/CodeGen/MachineFunction.h"
5 #include "llvm/CodeGen/MachineModuleInfo.h"
6 #include "llvm/CodeGen/TargetRegisterInfo.h"
7 #include "llvm/IR/LegacyPassManager.h"
8 #include "llvm/InitializePasses.h"
9 #include "llvm/Support/MemoryBuffer.h"
10 #include "llvm/Support/SourceMgr.h"
11 #include "llvm/Support/TargetRegistry.h"
12 #include "llvm/Support/TargetSelect.h"
13 #include "llvm/Target/TargetMachine.h"
14 #include "llvm/Target/TargetOptions.h"
15 #include "gtest/gtest.h"
16 
17 using namespace llvm;
18 
19 namespace llvm {
20   void initializeTestPassPass(PassRegistry &);
21 }
22 
23 namespace {
24 
initLLVM()25 void initLLVM() {
26   InitializeAllTargets();
27   InitializeAllTargetMCs();
28   InitializeAllAsmPrinters();
29   InitializeAllAsmParsers();
30 
31   PassRegistry *Registry = PassRegistry::getPassRegistry();
32   initializeCore(*Registry);
33   initializeCodeGen(*Registry);
34 }
35 
36 /// Create a TargetMachine. As we lack a dedicated always available target for
37 /// unittests, we go for "AMDGPU" to be able to test normal and subregister
38 /// liveranges.
createTargetMachine()39 std::unique_ptr<LLVMTargetMachine> createTargetMachine() {
40   Triple TargetTriple("amdgcn--");
41   std::string Error;
42   const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
43   if (!T)
44     return nullptr;
45 
46   TargetOptions Options;
47   return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine*>(
48       T->createTargetMachine("AMDGPU", "gfx900", "", Options, None, None,
49                              CodeGenOpt::Aggressive)));
50 }
51 
parseMIR(LLVMContext & Context,legacy::PassManagerBase & PM,std::unique_ptr<MIRParser> & MIR,const LLVMTargetMachine & TM,StringRef MIRCode,const char * FuncName)52 std::unique_ptr<Module> parseMIR(LLVMContext &Context,
53     legacy::PassManagerBase &PM, std::unique_ptr<MIRParser> &MIR,
54     const LLVMTargetMachine &TM, StringRef MIRCode, const char *FuncName) {
55   SMDiagnostic Diagnostic;
56   std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
57   MIR = createMIRParser(std::move(MBuffer), Context);
58   if (!MIR)
59     return nullptr;
60 
61   std::unique_ptr<Module> M = MIR->parseIRModule();
62   if (!M)
63     return nullptr;
64 
65   M->setDataLayout(TM.createDataLayout());
66 
67   MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(&TM);
68   if (MIR->parseMachineFunctions(*M, MMIWP->getMMI()))
69     return nullptr;
70   PM.add(MMIWP);
71 
72   return M;
73 }
74 
75 typedef std::function<void(MachineFunction&,LiveIntervals&)> LiveIntervalTest;
76 
77 struct TestPass : public MachineFunctionPass {
78   static char ID;
TestPass__anon81d60cd40111::TestPass79   TestPass() : MachineFunctionPass(ID) {
80     // We should never call this but always use PM.add(new TestPass(...))
81     abort();
82   }
TestPass__anon81d60cd40111::TestPass83   TestPass(LiveIntervalTest T) : MachineFunctionPass(ID), T(T) {
84     initializeTestPassPass(*PassRegistry::getPassRegistry());
85   }
86 
runOnMachineFunction__anon81d60cd40111::TestPass87   bool runOnMachineFunction(MachineFunction &MF) override {
88     LiveIntervals &LIS = getAnalysis<LiveIntervals>();
89     T(MF, LIS);
90     EXPECT_TRUE(MF.verify(this));
91     return true;
92   }
93 
getAnalysisUsage__anon81d60cd40111::TestPass94   void getAnalysisUsage(AnalysisUsage &AU) const override {
95     AU.setPreservesAll();
96     AU.addRequired<LiveIntervals>();
97     AU.addPreserved<LiveIntervals>();
98     MachineFunctionPass::getAnalysisUsage(AU);
99   }
100 private:
101   LiveIntervalTest T;
102 };
103 
getMI(MachineFunction & MF,unsigned At,unsigned BlockNum)104 static MachineInstr &getMI(MachineFunction &MF, unsigned At,
105                            unsigned BlockNum) {
106   MachineBasicBlock &MBB = *MF.getBlockNumbered(BlockNum);
107 
108   unsigned I = 0;
109   for (MachineInstr &MI : MBB) {
110     if (I == At)
111       return MI;
112     ++I;
113   }
114   llvm_unreachable("Instruction not found");
115 }
116 
117 /**
118  * Move instruction number \p From in front of instruction number \p To and
119  * update affected liveness intervals with LiveIntervalAnalysis::handleMove().
120  */
testHandleMove(MachineFunction & MF,LiveIntervals & LIS,unsigned From,unsigned To,unsigned BlockNum=0)121 static void testHandleMove(MachineFunction &MF, LiveIntervals &LIS,
122                            unsigned From, unsigned To, unsigned BlockNum = 0) {
123   MachineInstr &FromInstr = getMI(MF, From, BlockNum);
124   MachineInstr &ToInstr = getMI(MF, To, BlockNum);
125 
126   MachineBasicBlock &MBB = *FromInstr.getParent();
127   MBB.splice(ToInstr.getIterator(), &MBB, FromInstr.getIterator());
128   LIS.handleMove(FromInstr, true);
129 }
130 
131 /**
132  * Move instructions numbered \p From inclusive through instruction number
133  * \p To into a newly formed bundle and update affected liveness intervals
134  * with LiveIntervalAnalysis::handleMoveIntoNewBundle().
135  */
testHandleMoveIntoNewBundle(MachineFunction & MF,LiveIntervals & LIS,unsigned From,unsigned To,unsigned BlockNum=0)136 static void testHandleMoveIntoNewBundle(MachineFunction &MF, LiveIntervals &LIS,
137                                         unsigned From, unsigned To,
138                                         unsigned BlockNum = 0) {
139   MachineInstr &FromInstr = getMI(MF, From, BlockNum);
140   MachineInstr &ToInstr = getMI(MF, To, BlockNum);
141   MachineBasicBlock &MBB = *FromInstr.getParent();
142   MachineBasicBlock::instr_iterator I = FromInstr.getIterator();
143 
144   // Build bundle
145   finalizeBundle(MBB, I, std::next(ToInstr.getIterator()));
146 
147   // Update LiveIntervals
148   MachineBasicBlock::instr_iterator BundleStart = std::prev(I);
149   LIS.handleMoveIntoNewBundle(*BundleStart, true);
150 }
151 
152 /**
153  * Split block numbered \p BlockNum at instruction \p SplitAt using
154  * MachineBasicBlock::splitAt updating liveness intervals.
155  */
testSplitAt(MachineFunction & MF,LiveIntervals & LIS,unsigned SplitAt,unsigned BlockNum)156 static void testSplitAt(MachineFunction &MF, LiveIntervals &LIS,
157                         unsigned SplitAt, unsigned BlockNum) {
158   MachineInstr &SplitInstr = getMI(MF, SplitAt, BlockNum);
159   MachineBasicBlock &MBB = *SplitInstr.getParent();
160 
161   // Split block and update live intervals
162   MBB.splitAt(SplitInstr, false, &LIS);
163 }
164 
liveIntervalTest(StringRef MIRFunc,LiveIntervalTest T)165 static void liveIntervalTest(StringRef MIRFunc, LiveIntervalTest T) {
166   LLVMContext Context;
167   std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
168   // This test is designed for the X86 backend; stop if it is not available.
169   if (!TM)
170     return;
171 
172   legacy::PassManager PM;
173 
174   SmallString<160> S;
175   StringRef MIRString = (Twine(R"MIR(
176 ---
177 ...
178 name: func
179 registers:
180   - { id: 0, class: sreg_64 }
181 body: |
182   bb.0:
183 )MIR") + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
184   std::unique_ptr<MIRParser> MIR;
185   std::unique_ptr<Module> M = parseMIR(Context, PM, MIR, *TM, MIRString,
186                                        "func");
187   ASSERT_TRUE(M);
188 
189   PM.add(new TestPass(T));
190 
191   PM.run(*M);
192 }
193 
194 } // End of anonymous namespace.
195 
196 char TestPass::ID = 0;
197 INITIALIZE_PASS(TestPass, "testpass", "testpass", false, false)
198 
TEST(LiveIntervalTest,MoveUpDef)199 TEST(LiveIntervalTest, MoveUpDef) {
200   // Value defined.
201   liveIntervalTest(R"MIR(
202     S_NOP 0
203     S_NOP 0
204     early-clobber %0 = IMPLICIT_DEF
205     S_NOP 0, implicit %0
206 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
207     testHandleMove(MF, LIS, 2, 1);
208   });
209 }
210 
TEST(LiveIntervalTest,MoveUpRedef)211 TEST(LiveIntervalTest, MoveUpRedef) {
212   liveIntervalTest(R"MIR(
213     %0 = IMPLICIT_DEF
214     S_NOP 0
215     %0 = IMPLICIT_DEF implicit %0(tied-def 0)
216     S_NOP 0, implicit %0
217 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
218     testHandleMove(MF, LIS, 2, 1);
219   });
220 }
221 
TEST(LiveIntervalTest,MoveUpEarlyDef)222 TEST(LiveIntervalTest, MoveUpEarlyDef) {
223   liveIntervalTest(R"MIR(
224     S_NOP 0
225     S_NOP 0
226     early-clobber %0 = IMPLICIT_DEF
227     S_NOP 0, implicit %0
228 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
229     testHandleMove(MF, LIS, 2, 1);
230   });
231 }
232 
TEST(LiveIntervalTest,MoveUpEarlyRedef)233 TEST(LiveIntervalTest, MoveUpEarlyRedef) {
234   liveIntervalTest(R"MIR(
235     %0 = IMPLICIT_DEF
236     S_NOP 0
237     early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)
238     S_NOP 0, implicit %0
239 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
240     testHandleMove(MF, LIS, 2, 1);
241   });
242 }
243 
TEST(LiveIntervalTest,MoveUpKill)244 TEST(LiveIntervalTest, MoveUpKill) {
245   liveIntervalTest(R"MIR(
246     %0 = IMPLICIT_DEF
247     S_NOP 0
248     S_NOP 0, implicit %0
249 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
250     testHandleMove(MF, LIS, 2, 1);
251   });
252 }
253 
TEST(LiveIntervalTest,MoveUpKillFollowing)254 TEST(LiveIntervalTest, MoveUpKillFollowing) {
255   liveIntervalTest(R"MIR(
256     %0 = IMPLICIT_DEF
257     S_NOP 0
258     S_NOP 0, implicit %0
259     S_NOP 0, implicit %0
260 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
261     testHandleMove(MF, LIS, 2, 1);
262   });
263 }
264 
265 // TODO: Construct a situation where we have intervals following a hole
266 // while still having connected components.
267 
TEST(LiveIntervalTest,MoveDownDef)268 TEST(LiveIntervalTest, MoveDownDef) {
269   // Value defined.
270   liveIntervalTest(R"MIR(
271     S_NOP 0
272     early-clobber %0 = IMPLICIT_DEF
273     S_NOP 0
274     S_NOP 0, implicit %0
275 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
276     testHandleMove(MF, LIS, 1, 2);
277   });
278 }
279 
TEST(LiveIntervalTest,MoveDownRedef)280 TEST(LiveIntervalTest, MoveDownRedef) {
281   liveIntervalTest(R"MIR(
282     %0 = IMPLICIT_DEF
283     %0 = IMPLICIT_DEF implicit %0(tied-def 0)
284     S_NOP 0
285     S_NOP 0, implicit %0
286 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
287     testHandleMove(MF, LIS, 1, 2);
288   });
289 }
290 
TEST(LiveIntervalTest,MoveDownEarlyDef)291 TEST(LiveIntervalTest, MoveDownEarlyDef) {
292   liveIntervalTest(R"MIR(
293     S_NOP 0
294     early-clobber %0 = IMPLICIT_DEF
295     S_NOP 0
296     S_NOP 0, implicit %0
297 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
298     testHandleMove(MF, LIS, 1, 2);
299   });
300 }
301 
TEST(LiveIntervalTest,MoveDownEarlyRedef)302 TEST(LiveIntervalTest, MoveDownEarlyRedef) {
303   liveIntervalTest(R"MIR(
304     %0 = IMPLICIT_DEF
305     early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)
306     S_NOP 0
307     S_NOP 0, implicit %0
308 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
309     testHandleMove(MF, LIS, 1, 2);
310   });
311 }
312 
TEST(LiveIntervalTest,MoveDownKill)313 TEST(LiveIntervalTest, MoveDownKill) {
314   liveIntervalTest(R"MIR(
315     %0 = IMPLICIT_DEF
316     S_NOP 0, implicit %0
317     S_NOP 0
318 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
319     testHandleMove(MF, LIS, 1, 2);
320   });
321 }
322 
TEST(LiveIntervalTest,MoveDownKillFollowing)323 TEST(LiveIntervalTest, MoveDownKillFollowing) {
324   liveIntervalTest(R"MIR(
325     %0 = IMPLICIT_DEF
326     S_NOP 0
327     S_NOP 0, implicit %0
328     S_NOP 0, implicit %0
329 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
330     testHandleMove(MF, LIS, 1, 2);
331   });
332 }
333 
TEST(LiveIntervalTest,MoveUndefUse)334 TEST(LiveIntervalTest, MoveUndefUse) {
335   liveIntervalTest(R"MIR(
336     %0 = IMPLICIT_DEF
337     S_NOP 0, implicit undef %0
338     S_NOP 0, implicit %0
339     S_NOP 0
340 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
341     testHandleMove(MF, LIS, 1, 3);
342   });
343 }
344 
TEST(LiveIntervalTest,MoveUpValNos)345 TEST(LiveIntervalTest, MoveUpValNos) {
346   // handleMoveUp() had a bug where it would reuse the value number of the
347   // destination segment, even though we have no guarantee that this valno
348   // wasn't used in other segments.
349   liveIntervalTest(R"MIR(
350     successors: %bb.1, %bb.2
351     %0 = IMPLICIT_DEF
352     S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
353     S_BRANCH %bb.1
354   bb.2:
355     S_NOP 0, implicit %0
356   bb.1:
357     successors: %bb.2
358     %0 = IMPLICIT_DEF implicit %0(tied-def 0)
359     %0 = IMPLICIT_DEF implicit %0(tied-def 0)
360     %0 = IMPLICIT_DEF implicit %0(tied-def 0)
361     S_BRANCH %bb.2
362 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
363     testHandleMove(MF, LIS, 2, 0, 2);
364   });
365 }
366 
TEST(LiveIntervalTest,MoveOverUndefUse0)367 TEST(LiveIntervalTest, MoveOverUndefUse0) {
368   // findLastUseBefore() used by handleMoveUp() must ignore undef operands.
369   liveIntervalTest(R"MIR(
370     %0 = IMPLICIT_DEF
371     S_NOP 0
372     S_NOP 0, implicit undef %0
373     %0 = IMPLICIT_DEF implicit %0(tied-def 0)
374 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
375     testHandleMove(MF, LIS, 3, 1);
376   });
377 }
378 
TEST(LiveIntervalTest,MoveOverUndefUse1)379 TEST(LiveIntervalTest, MoveOverUndefUse1) {
380   // findLastUseBefore() used by handleMoveUp() must ignore undef operands.
381   liveIntervalTest(R"MIR(
382     $sgpr0 = IMPLICIT_DEF
383     S_NOP 0
384     S_NOP 0, implicit undef $sgpr0
385     $sgpr0 = IMPLICIT_DEF implicit $sgpr0(tied-def 0)
386 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
387     testHandleMove(MF, LIS, 3, 1);
388   });
389 }
390 
TEST(LiveIntervalTest,SubRegMoveDown)391 TEST(LiveIntervalTest, SubRegMoveDown) {
392   // Subregister ranges can have holes inside a basic block. Check for a
393   // movement of the form 32->150 in a liverange [16, 32) [100,200).
394   liveIntervalTest(R"MIR(
395     successors: %bb.1, %bb.2
396     %0 = IMPLICIT_DEF
397     S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
398     S_BRANCH %bb.1
399   bb.2:
400     successors: %bb.1
401     S_NOP 0, implicit %0.sub0
402     S_NOP 0, implicit %0.sub1
403     S_NOP 0
404     undef %0.sub0 = IMPLICIT_DEF
405     %0.sub1 = IMPLICIT_DEF
406   bb.1:
407     S_NOP 0, implicit %0
408 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
409     // Scheduler behaviour: Clear def,read-undef flag and move.
410     MachineInstr &MI = getMI(MF, 3, /*BlockNum=*/1);
411     MI.getOperand(0).setIsUndef(false);
412     testHandleMove(MF, LIS, 1, 4, /*BlockNum=*/1);
413   });
414 }
415 
TEST(LiveIntervalTest,SubRegMoveUp)416 TEST(LiveIntervalTest, SubRegMoveUp) {
417   // handleMoveUp had a bug not updating valno of segment incoming to bb.2
418   // after swapping subreg definitions.
419   liveIntervalTest(R"MIR(
420     successors: %bb.1, %bb.2
421     undef %0.sub0 = IMPLICIT_DEF
422     %0.sub1 = IMPLICIT_DEF
423     S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
424     S_BRANCH %bb.1
425   bb.1:
426     S_NOP 0, implicit %0.sub1
427   bb.2:
428     S_NOP 0, implicit %0.sub1
429 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
430     testHandleMove(MF, LIS, 1, 0);
431   });
432 }
433 
TEST(LiveIntervalTest,DeadSubRegMoveUp)434 TEST(LiveIntervalTest, DeadSubRegMoveUp) {
435   // handleMoveUp had a bug where moving a dead subreg def into the middle of
436   // an earlier segment resulted in an invalid live range.
437   liveIntervalTest(R"MIR(
438     undef %125.sub0:vreg_128 = V_MOV_B32_e32 0, implicit $exec
439     %125.sub1:vreg_128 = COPY %125.sub0
440     %125.sub2:vreg_128 = COPY %125.sub0
441     undef %51.sub0:vreg_128 = V_MOV_B32_e32 898625526, implicit $exec
442     %51.sub1:vreg_128 = COPY %51.sub0
443     %51.sub2:vreg_128 = COPY %51.sub0
444     %52:vgpr_32 = V_MOV_B32_e32 986714345, implicit $exec
445     %54:vgpr_32 = V_MOV_B32_e32 1742342378, implicit $exec
446     %57:vgpr_32 = V_MOV_B32_e32 3168768712, implicit $exec
447     %59:vgpr_32 = V_MOV_B32_e32 1039972644, implicit $exec
448     %60:vgpr_32 = nofpexcept V_MAD_F32_e64 0, %52, 0, undef %61:vgpr_32, 0, %59, 0, 0, implicit $mode, implicit $exec
449     %63:vgpr_32 = nofpexcept V_ADD_F32_e32 %51.sub3, undef %64:vgpr_32, implicit $mode, implicit $exec
450     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
451     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
452     %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
453     dead undef %125.sub3:vreg_128 = nofpexcept V_MAC_F32_e32 %63, undef %76:vgpr_32, %125.sub3, implicit $mode, implicit $exec
454 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
455     testHandleMove(MF, LIS, 15, 12);
456   });
457 }
458 
TEST(LiveIntervalTest,EarlyClobberSubRegMoveUp)459 TEST(LiveIntervalTest, EarlyClobberSubRegMoveUp) {
460   // handleMoveUp had a bug where moving an early-clobber subreg def into the
461   // middle of an earlier segment resulted in an invalid live range.
462   liveIntervalTest(R"MIR(
463     %4:sreg_32 = IMPLICIT_DEF
464     %6:sreg_32 = IMPLICIT_DEF
465     undef early-clobber %9.sub0:sreg_64 = STRICT_WWM %4:sreg_32, implicit $exec
466     %5:sreg_32 = S_FLBIT_I32_B32 %9.sub0:sreg_64
467     early-clobber %9.sub1:sreg_64 = STRICT_WWM %6:sreg_32, implicit $exec
468     %7:sreg_32 = S_FLBIT_I32_B32 %9.sub1:sreg_64
469 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
470     testHandleMove(MF, LIS, 4, 3);
471   });
472 }
473 
TEST(LiveIntervalTest,TestMoveSubRegDefAcrossUseDef)474 TEST(LiveIntervalTest, TestMoveSubRegDefAcrossUseDef) {
475   liveIntervalTest(R"MIR(
476     %1:vreg_64 = IMPLICIT_DEF
477 
478   bb.1:
479     %2:vgpr_32 = V_MOV_B32_e32 2, implicit $exec
480     %3:vgpr_32 = V_ADD_U32_e32 %2, %1.sub0, implicit $exec
481     undef %1.sub0:vreg_64 = V_ADD_U32_e32 %2, %2, implicit $exec
482     %1.sub1:vreg_64 = COPY %2
483     S_NOP 0, implicit %1.sub1
484     S_BRANCH %bb.1
485 
486 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
487      MachineInstr &UndefSubregDef = getMI(MF, 2, 1);
488      // The scheduler clears undef from subregister defs before moving
489      UndefSubregDef.getOperand(0).setIsUndef(false);
490      testHandleMove(MF, LIS, 3, 1, 1);
491   });
492 }
493 
TEST(LiveIntervalTest,TestMoveSubRegDefAcrossUseDefMulti)494 TEST(LiveIntervalTest, TestMoveSubRegDefAcrossUseDefMulti) {
495   liveIntervalTest(R"MIR(
496     %1:vreg_96 = IMPLICIT_DEF
497 
498   bb.1:
499     %2:vgpr_32 = V_MOV_B32_e32 2, implicit $exec
500     %3:vgpr_32 = V_ADD_U32_e32 %2, %1.sub0, implicit $exec
501     undef %1.sub0:vreg_96 = V_ADD_U32_e32 %2, %2, implicit $exec
502     %1.sub1:vreg_96 = COPY %2
503     %1.sub2:vreg_96 = COPY %2
504     S_NOP 0, implicit %1.sub1, implicit %1.sub2
505     S_BRANCH %bb.1
506 
507 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
508      MachineInstr &UndefSubregDef = getMI(MF, 2, 1);
509      // The scheduler clears undef from subregister defs before moving
510      UndefSubregDef.getOperand(0).setIsUndef(false);
511      testHandleMove(MF, LIS, 4, 1, 1);
512   });
513 }
514 
TEST(LiveIntervalTest,TestMoveSubRegUseAcrossMainRangeHole)515 TEST(LiveIntervalTest, TestMoveSubRegUseAcrossMainRangeHole) {
516   liveIntervalTest(R"MIR(
517     %1:sgpr_128 = IMPLICIT_DEF
518   bb.1:
519     %2:sgpr_32 = COPY %1.sub2
520     %3:sgpr_32 = COPY %1.sub1
521     %1.sub2 = COPY %2
522     undef %1.sub0 = IMPLICIT_DEF
523     %1.sub2 = IMPLICIT_DEF
524     S_CBRANCH_SCC1 %bb.1, implicit undef $scc
525     S_BRANCH %bb.2
526   bb.2:
527 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
528     MachineInstr &MI = getMI(MF, 3, /*BlockNum=*/1);
529     MI.getOperand(0).setIsUndef(false);
530     testHandleMove(MF, LIS, 4, 3, 1);
531     testHandleMove(MF, LIS, 1, 4, 1);
532   });
533 }
534 
TEST(LiveIntervalTest,BundleUse)535 TEST(LiveIntervalTest, BundleUse) {
536   liveIntervalTest(R"MIR(
537     %0 = IMPLICIT_DEF
538     S_NOP 0
539     S_NOP 0, implicit %0
540     S_NOP 0
541 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
542     testHandleMoveIntoNewBundle(MF, LIS, 1, 2);
543   });
544 }
545 
TEST(LiveIntervalTest,BundleDef)546 TEST(LiveIntervalTest, BundleDef) {
547   liveIntervalTest(R"MIR(
548     %0 = IMPLICIT_DEF
549     S_NOP 0
550     S_NOP 0, implicit %0
551     S_NOP 0
552 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
553     testHandleMoveIntoNewBundle(MF, LIS, 0, 1);
554   });
555 }
556 
TEST(LiveIntervalTest,BundleRedef)557 TEST(LiveIntervalTest, BundleRedef) {
558   liveIntervalTest(R"MIR(
559     %0 = IMPLICIT_DEF
560     S_NOP 0
561     %0 = IMPLICIT_DEF implicit %0(tied-def 0)
562     S_NOP 0, implicit %0
563 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
564     testHandleMoveIntoNewBundle(MF, LIS, 1, 2);
565   });
566 }
567 
TEST(LiveIntervalTest,BundleInternalUse)568 TEST(LiveIntervalTest, BundleInternalUse) {
569   liveIntervalTest(R"MIR(
570     %0 = IMPLICIT_DEF
571     S_NOP 0
572     S_NOP 0, implicit %0
573     S_NOP 0
574 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
575     testHandleMoveIntoNewBundle(MF, LIS, 0, 2);
576   });
577 }
578 
TEST(LiveIntervalTest,BundleUndefUse)579 TEST(LiveIntervalTest, BundleUndefUse) {
580   liveIntervalTest(R"MIR(
581     %0 = IMPLICIT_DEF
582     S_NOP 0
583     S_NOP 0, implicit undef %0
584     S_NOP 0
585 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
586     testHandleMoveIntoNewBundle(MF, LIS, 1, 2);
587   });
588 }
589 
TEST(LiveIntervalTest,BundleSubRegUse)590 TEST(LiveIntervalTest, BundleSubRegUse) {
591   liveIntervalTest(R"MIR(
592     successors: %bb.1, %bb.2
593     undef %0.sub0 = IMPLICIT_DEF
594     %0.sub1 = IMPLICIT_DEF
595     S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
596     S_BRANCH %bb.1
597   bb.1:
598     S_NOP 0
599     S_NOP 0, implicit %0.sub1
600   bb.2:
601     S_NOP 0, implicit %0.sub1
602 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
603     testHandleMoveIntoNewBundle(MF, LIS, 0, 1, 1);
604   });
605 }
606 
TEST(LiveIntervalTest,BundleSubRegDef)607 TEST(LiveIntervalTest, BundleSubRegDef) {
608   liveIntervalTest(R"MIR(
609     successors: %bb.1, %bb.2
610     undef %0.sub0 = IMPLICIT_DEF
611     %0.sub1 = IMPLICIT_DEF
612     S_CBRANCH_VCCNZ %bb.2, implicit undef $vcc
613     S_BRANCH %bb.1
614   bb.1:
615     S_NOP 0
616     S_NOP 0, implicit %0.sub1
617   bb.2:
618     S_NOP 0, implicit %0.sub1
619 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
620     testHandleMoveIntoNewBundle(MF, LIS, 0, 1, 0);
621   });
622 }
623 
TEST(LiveIntervalTest,SplitAtOneInstruction)624 TEST(LiveIntervalTest, SplitAtOneInstruction) {
625   liveIntervalTest(R"MIR(
626     successors: %bb.1
627     %0 = IMPLICIT_DEF
628     S_BRANCH %bb.1
629   bb.1:
630     S_NOP 0
631 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
632     testSplitAt(MF, LIS, 1, 0);
633   });
634 }
635 
TEST(LiveIntervalTest,SplitAtMultiInstruction)636 TEST(LiveIntervalTest, SplitAtMultiInstruction) {
637   liveIntervalTest(R"MIR(
638     successors: %bb.1
639     %0 = IMPLICIT_DEF
640     S_NOP 0
641     S_NOP 0
642     S_NOP 0
643     S_NOP 0
644     S_BRANCH %bb.1
645   bb.1:
646     S_NOP 0
647 )MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
648     testSplitAt(MF, LIS, 0, 0);
649   });
650 }
651 
main(int argc,char ** argv)652 int main(int argc, char **argv) {
653   ::testing::InitGoogleTest(&argc, argv);
654   initLLVM();
655   return RUN_ALL_TESTS();
656 }
657