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/MC/TargetRegistry.h" 10 #include "llvm/Support/MemoryBuffer.h" 11 #include "llvm/Support/SourceMgr.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 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. 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 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; 79 TestPass() : MachineFunctionPass(ID) { 80 // We should never call this but always use PM.add(new TestPass(...)) 81 abort(); 82 } 83 TestPass(LiveIntervalTest T) : MachineFunctionPass(ID), T(T) { 84 initializeTestPassPass(*PassRegistry::getPassRegistry()); 85 } 86 87 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 94 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 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 652 int main(int argc, char **argv) { 653 ::testing::InitGoogleTest(&argc, argv); 654 initLLVM(); 655 return RUN_ALL_TESTS(); 656 } 657