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