1 //===------------- llvm/unittest/CodeGen/InstrRefLDVTest.cpp --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/CodeGen/MIRParser/MIRParser.h" 10 #include "llvm/CodeGen/MachineModuleInfo.h" 11 #include "llvm/CodeGen/TargetLowering.h" 12 #include "llvm/CodeGen/TargetSubtargetInfo.h" 13 #include "llvm/IR/DIBuilder.h" 14 #include "llvm/IR/DebugInfoMetadata.h" 15 #include "llvm/IR/IRBuilder.h" 16 #include "llvm/MC/TargetRegistry.h" 17 #include "llvm/Support/MemoryBuffer.h" 18 #include "llvm/Support/TargetSelect.h" 19 #include "llvm/Target/TargetMachine.h" 20 #include "llvm/Target/TargetOptions.h" 21 22 #include "../lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h" 23 24 #include "gtest/gtest.h" 25 26 using namespace llvm; 27 using namespace LiveDebugValues; 28 29 // Include helper functions to ease the manipulation of MachineFunctions 30 #include "MFCommon.inc" 31 32 class InstrRefLDVTest : public testing::Test { 33 public: 34 friend class InstrRefBasedLDV; 35 using MLocTransferMap = InstrRefBasedLDV::MLocTransferMap; 36 37 LLVMContext Ctx; 38 std::unique_ptr<Module> Mod; 39 std::unique_ptr<TargetMachine> Machine; 40 std::unique_ptr<MachineFunction> MF; 41 std::unique_ptr<MachineDominatorTree> DomTree; 42 std::unique_ptr<MachineModuleInfo> MMI; 43 DICompileUnit *OurCU; 44 DIFile *OurFile; 45 DISubprogram *OurFunc; 46 DILexicalBlock *OurBlock, *AnotherBlock; 47 DISubprogram *ToInlineFunc; 48 DILexicalBlock *ToInlineBlock; 49 DILocalVariable *FuncVariable; 50 DIBasicType *LongInt; 51 DIExpression *EmptyExpr; 52 53 DebugLoc OutermostLoc, InBlockLoc, NotNestedBlockLoc, InlinedLoc; 54 55 MachineBasicBlock *MBB0, *MBB1, *MBB2, *MBB3, *MBB4; 56 57 std::unique_ptr<InstrRefBasedLDV> LDV; 58 std::unique_ptr<MLocTracker> MTracker; 59 std::unique_ptr<VLocTracker> VTracker; 60 61 SmallString<256> MIRStr; 62 63 InstrRefLDVTest() : Ctx(), Mod(std::make_unique<Module>("beehives", Ctx)) {} 64 65 void SetUp() { 66 // Boilerplate that creates a MachineFunction and associated blocks. 67 68 Mod->setDataLayout("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-" 69 "n8:16:32:64-S128"); 70 Triple TargetTriple("x86_64--"); 71 std::string Error; 72 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error); 73 if (!T) 74 GTEST_SKIP(); 75 76 TargetOptions Options; 77 Machine = std::unique_ptr<TargetMachine>( 78 T->createTargetMachine(Triple::normalize("x86_64--"), "", "", Options, 79 None, None, CodeGenOpt::Aggressive)); 80 81 auto Type = FunctionType::get(Type::getVoidTy(Ctx), false); 82 auto F = 83 Function::Create(Type, GlobalValue::ExternalLinkage, "Test", &*Mod); 84 85 unsigned FunctionNum = 42; 86 MMI = std::make_unique<MachineModuleInfo>((LLVMTargetMachine *)&*Machine); 87 const TargetSubtargetInfo &STI = *Machine->getSubtargetImpl(*F); 88 89 MF = std::make_unique<MachineFunction>(*F, (LLVMTargetMachine &)*Machine, 90 STI, FunctionNum, *MMI); 91 92 // Create metadata: CU, subprogram, some blocks and an inline function 93 // scope. 94 DIBuilder DIB(*Mod); 95 OurFile = DIB.createFile("xyzzy.c", "/cave"); 96 OurCU = 97 DIB.createCompileUnit(dwarf::DW_LANG_C99, OurFile, "nou", false, "", 0); 98 auto OurSubT = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); 99 OurFunc = 100 DIB.createFunction(OurCU, "bees", "", OurFile, 1, OurSubT, 1, 101 DINode::FlagZero, DISubprogram::SPFlagDefinition); 102 F->setSubprogram(OurFunc); 103 OurBlock = DIB.createLexicalBlock(OurFunc, OurFile, 2, 3); 104 AnotherBlock = DIB.createLexicalBlock(OurFunc, OurFile, 2, 6); 105 ToInlineFunc = 106 DIB.createFunction(OurFile, "shoes", "", OurFile, 10, OurSubT, 10, 107 DINode::FlagZero, DISubprogram::SPFlagDefinition); 108 109 // Make some nested scopes. 110 OutermostLoc = DILocation::get(Ctx, 3, 1, OurFunc); 111 InBlockLoc = DILocation::get(Ctx, 4, 1, OurBlock); 112 InlinedLoc = DILocation::get(Ctx, 10, 1, ToInlineFunc, InBlockLoc.get()); 113 114 // Make a scope that isn't nested within the others. 115 NotNestedBlockLoc = DILocation::get(Ctx, 4, 1, AnotherBlock); 116 117 LongInt = DIB.createBasicType("long", 64, llvm::dwarf::DW_ATE_unsigned); 118 FuncVariable = DIB.createAutoVariable(OurFunc, "lala", OurFile, 1, LongInt); 119 EmptyExpr = DIExpression::get(Ctx, {}); 120 121 DIB.finalize(); 122 } 123 124 Register getRegByName(const char *WantedName) { 125 auto *TRI = MF->getRegInfo().getTargetRegisterInfo(); 126 // Slow, but works. 127 for (unsigned int I = 1; I < TRI->getNumRegs(); ++I) { 128 const char *Name = TRI->getName(I); 129 if (strcmp(WantedName, Name) == 0) 130 return I; 131 } 132 133 // If this ever fails, something is very wrong with this unit test. 134 llvm_unreachable("Can't find register by name"); 135 } 136 137 InstrRefBasedLDV *setupLDVObj(MachineFunction *MF) { 138 // Create a new LDV object, and plug some relevant object ptrs into it. 139 LDV = std::make_unique<InstrRefBasedLDV>(); 140 const TargetSubtargetInfo &STI = MF->getSubtarget(); 141 LDV->TII = STI.getInstrInfo(); 142 LDV->TRI = STI.getRegisterInfo(); 143 LDV->TFI = STI.getFrameLowering(); 144 LDV->MFI = &MF->getFrameInfo(); 145 146 DomTree = std::make_unique<MachineDominatorTree>(*MF); 147 LDV->DomTree = &*DomTree; 148 149 // Future work: unit tests for mtracker / vtracker / ttracker. 150 151 // Setup things like the artifical block map, and BlockNo <=> RPO Order 152 // mappings. 153 LDV->initialSetup(*MF); 154 LDV->LS.initialize(*MF); 155 addMTracker(MF); 156 return &*LDV; 157 } 158 159 void addMTracker(MachineFunction *MF) { 160 ASSERT_TRUE(LDV); 161 // Add a machine-location-tracking object to LDV. Don't initialize any 162 // register locations within it though. 163 const TargetSubtargetInfo &STI = MF->getSubtarget(); 164 MTracker = std::make_unique<MLocTracker>( 165 *MF, *LDV->TII, *LDV->TRI, *STI.getTargetLowering()); 166 LDV->MTracker = &*MTracker; 167 } 168 169 void addVTracker() { 170 ASSERT_TRUE(LDV); 171 VTracker = std::make_unique<VLocTracker>(); 172 LDV->VTracker = &*VTracker; 173 } 174 175 // Some routines for bouncing into LDV, 176 void buildMLocValueMap(ValueIDNum **MInLocs, ValueIDNum **MOutLocs, 177 SmallVectorImpl<MLocTransferMap> &MLocTransfer) { 178 LDV->buildMLocValueMap(*MF, MInLocs, MOutLocs, MLocTransfer); 179 } 180 181 Optional<ValueIDNum> 182 pickVPHILoc(const MachineBasicBlock &MBB, const DebugVariable &Var, 183 const InstrRefBasedLDV::LiveIdxT &LiveOuts, ValueIDNum **MOutLocs, 184 const SmallVectorImpl<const MachineBasicBlock *> &BlockOrders) { 185 return LDV->pickVPHILoc(MBB, Var, LiveOuts, MOutLocs, BlockOrders); 186 } 187 188 bool vlocJoin(MachineBasicBlock &MBB, InstrRefBasedLDV::LiveIdxT &VLOCOutLocs, 189 SmallPtrSet<const MachineBasicBlock *, 8> &InScopeBlocks, 190 SmallPtrSet<const MachineBasicBlock *, 8> &BlocksToExplore, 191 DbgValue &InLoc) { 192 return LDV->vlocJoin(MBB, VLOCOutLocs, InScopeBlocks, BlocksToExplore, 193 InLoc); 194 } 195 196 void buildVLocValueMap(const DILocation *DILoc, 197 const SmallSet<DebugVariable, 4> &VarsWeCareAbout, 198 SmallPtrSetImpl<MachineBasicBlock *> &AssignBlocks, 199 InstrRefBasedLDV::LiveInsT &Output, ValueIDNum **MOutLocs, 200 ValueIDNum **MInLocs, 201 SmallVectorImpl<VLocTracker> &AllTheVLocs) { 202 LDV->buildVLocValueMap(DILoc, VarsWeCareAbout, AssignBlocks, Output, 203 MOutLocs, MInLocs, AllTheVLocs); 204 } 205 206 void initValueArray(ValueIDNum **Nums, unsigned Blks, unsigned Locs) { 207 for (unsigned int I = 0; I < Blks; ++I) 208 for (unsigned int J = 0; J < Locs; ++J) 209 Nums[I][J] = ValueIDNum::EmptyValue; 210 } 211 212 void setupSingleBlock() { 213 // Add an entry block with nothing but 'ret void' in it. 214 Function &F = const_cast<llvm::Function &>(MF->getFunction()); 215 auto *BB0 = BasicBlock::Create(Ctx, "entry", &F); 216 IRBuilder<> IRB(BB0); 217 IRB.CreateRetVoid(); 218 MBB0 = MF->CreateMachineBasicBlock(BB0); 219 MF->insert(MF->end(), MBB0); 220 MF->RenumberBlocks(); 221 222 setupLDVObj(&*MF); 223 } 224 225 void setupDiamondBlocks() { 226 // entry 227 // / \ 228 // br1 br2 229 // \ / 230 // ret 231 llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction()); 232 auto *BB0 = BasicBlock::Create(Ctx, "a", &F); 233 auto *BB1 = BasicBlock::Create(Ctx, "b", &F); 234 auto *BB2 = BasicBlock::Create(Ctx, "c", &F); 235 auto *BB3 = BasicBlock::Create(Ctx, "d", &F); 236 IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2), IRB3(BB3); 237 IRB0.CreateBr(BB1); 238 IRB1.CreateBr(BB2); 239 IRB2.CreateBr(BB3); 240 IRB3.CreateRetVoid(); 241 MBB0 = MF->CreateMachineBasicBlock(BB0); 242 MF->insert(MF->end(), MBB0); 243 MBB1 = MF->CreateMachineBasicBlock(BB1); 244 MF->insert(MF->end(), MBB1); 245 MBB2 = MF->CreateMachineBasicBlock(BB2); 246 MF->insert(MF->end(), MBB2); 247 MBB3 = MF->CreateMachineBasicBlock(BB3); 248 MF->insert(MF->end(), MBB3); 249 MBB0->addSuccessor(MBB1); 250 MBB0->addSuccessor(MBB2); 251 MBB1->addSuccessor(MBB3); 252 MBB2->addSuccessor(MBB3); 253 MF->RenumberBlocks(); 254 255 setupLDVObj(&*MF); 256 } 257 258 void setupSimpleLoop() { 259 // entry 260 // | 261 // |/-----\ 262 // loopblk | 263 // |\-----/ 264 // | 265 // ret 266 llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction()); 267 auto *BB0 = BasicBlock::Create(Ctx, "entry", &F); 268 auto *BB1 = BasicBlock::Create(Ctx, "loop", &F); 269 auto *BB2 = BasicBlock::Create(Ctx, "ret", &F); 270 IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2); 271 IRB0.CreateBr(BB1); 272 IRB1.CreateBr(BB2); 273 IRB2.CreateRetVoid(); 274 MBB0 = MF->CreateMachineBasicBlock(BB0); 275 MF->insert(MF->end(), MBB0); 276 MBB1 = MF->CreateMachineBasicBlock(BB1); 277 MF->insert(MF->end(), MBB1); 278 MBB2 = MF->CreateMachineBasicBlock(BB2); 279 MF->insert(MF->end(), MBB2); 280 MBB0->addSuccessor(MBB1); 281 MBB1->addSuccessor(MBB2); 282 MBB1->addSuccessor(MBB1); 283 MF->RenumberBlocks(); 284 285 setupLDVObj(&*MF); 286 } 287 288 void setupNestedLoops() { 289 // entry 290 // | 291 // loop1 292 // ^\ 293 // | \ /-\ 294 // | loop2 | 295 // | / \-/ 296 // ^ / 297 // join 298 // | 299 // ret 300 llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction()); 301 auto *BB0 = BasicBlock::Create(Ctx, "entry", &F); 302 auto *BB1 = BasicBlock::Create(Ctx, "loop1", &F); 303 auto *BB2 = BasicBlock::Create(Ctx, "loop2", &F); 304 auto *BB3 = BasicBlock::Create(Ctx, "join", &F); 305 auto *BB4 = BasicBlock::Create(Ctx, "ret", &F); 306 IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2), IRB3(BB3), IRB4(BB4); 307 IRB0.CreateBr(BB1); 308 IRB1.CreateBr(BB2); 309 IRB2.CreateBr(BB3); 310 IRB3.CreateBr(BB4); 311 IRB4.CreateRetVoid(); 312 MBB0 = MF->CreateMachineBasicBlock(BB0); 313 MF->insert(MF->end(), MBB0); 314 MBB1 = MF->CreateMachineBasicBlock(BB1); 315 MF->insert(MF->end(), MBB1); 316 MBB2 = MF->CreateMachineBasicBlock(BB2); 317 MF->insert(MF->end(), MBB2); 318 MBB3 = MF->CreateMachineBasicBlock(BB3); 319 MF->insert(MF->end(), MBB3); 320 MBB4 = MF->CreateMachineBasicBlock(BB4); 321 MF->insert(MF->end(), MBB4); 322 MBB0->addSuccessor(MBB1); 323 MBB1->addSuccessor(MBB2); 324 MBB2->addSuccessor(MBB2); 325 MBB2->addSuccessor(MBB3); 326 MBB3->addSuccessor(MBB1); 327 MBB3->addSuccessor(MBB4); 328 MF->RenumberBlocks(); 329 330 setupLDVObj(&*MF); 331 } 332 333 void setupNoDominatingLoop() { 334 // entry 335 // / \ 336 // / \ 337 // / \ 338 // head1 head2 339 // ^ \ / ^ 340 // ^ \ / ^ 341 // \-joinblk -/ 342 // | 343 // ret 344 llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction()); 345 auto *BB0 = BasicBlock::Create(Ctx, "entry", &F); 346 auto *BB1 = BasicBlock::Create(Ctx, "head1", &F); 347 auto *BB2 = BasicBlock::Create(Ctx, "head2", &F); 348 auto *BB3 = BasicBlock::Create(Ctx, "joinblk", &F); 349 auto *BB4 = BasicBlock::Create(Ctx, "ret", &F); 350 IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2), IRB3(BB3), IRB4(BB4); 351 IRB0.CreateBr(BB1); 352 IRB1.CreateBr(BB2); 353 IRB2.CreateBr(BB3); 354 IRB3.CreateBr(BB4); 355 IRB4.CreateRetVoid(); 356 MBB0 = MF->CreateMachineBasicBlock(BB0); 357 MF->insert(MF->end(), MBB0); 358 MBB1 = MF->CreateMachineBasicBlock(BB1); 359 MF->insert(MF->end(), MBB1); 360 MBB2 = MF->CreateMachineBasicBlock(BB2); 361 MF->insert(MF->end(), MBB2); 362 MBB3 = MF->CreateMachineBasicBlock(BB3); 363 MF->insert(MF->end(), MBB3); 364 MBB4 = MF->CreateMachineBasicBlock(BB4); 365 MF->insert(MF->end(), MBB4); 366 MBB0->addSuccessor(MBB1); 367 MBB0->addSuccessor(MBB2); 368 MBB1->addSuccessor(MBB3); 369 MBB2->addSuccessor(MBB3); 370 MBB3->addSuccessor(MBB1); 371 MBB3->addSuccessor(MBB2); 372 MBB3->addSuccessor(MBB4); 373 MF->RenumberBlocks(); 374 375 setupLDVObj(&*MF); 376 } 377 378 void setupBadlyNestedLoops() { 379 // entry 380 // | 381 // loop1 -o 382 // | ^ 383 // | ^ 384 // loop2 -o 385 // | ^ 386 // | ^ 387 // loop3 -o 388 // | 389 // ret 390 // 391 // NB: the loop blocks self-loop, which is a bit too fiddly to draw on 392 // accurately. 393 llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction()); 394 auto *BB0 = BasicBlock::Create(Ctx, "entry", &F); 395 auto *BB1 = BasicBlock::Create(Ctx, "loop1", &F); 396 auto *BB2 = BasicBlock::Create(Ctx, "loop2", &F); 397 auto *BB3 = BasicBlock::Create(Ctx, "loop3", &F); 398 auto *BB4 = BasicBlock::Create(Ctx, "ret", &F); 399 IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2), IRB3(BB3), IRB4(BB4); 400 IRB0.CreateBr(BB1); 401 IRB1.CreateBr(BB2); 402 IRB2.CreateBr(BB3); 403 IRB3.CreateBr(BB4); 404 IRB4.CreateRetVoid(); 405 MBB0 = MF->CreateMachineBasicBlock(BB0); 406 MF->insert(MF->end(), MBB0); 407 MBB1 = MF->CreateMachineBasicBlock(BB1); 408 MF->insert(MF->end(), MBB1); 409 MBB2 = MF->CreateMachineBasicBlock(BB2); 410 MF->insert(MF->end(), MBB2); 411 MBB3 = MF->CreateMachineBasicBlock(BB3); 412 MF->insert(MF->end(), MBB3); 413 MBB4 = MF->CreateMachineBasicBlock(BB4); 414 MF->insert(MF->end(), MBB4); 415 MBB0->addSuccessor(MBB1); 416 MBB1->addSuccessor(MBB1); 417 MBB1->addSuccessor(MBB2); 418 MBB2->addSuccessor(MBB1); 419 MBB2->addSuccessor(MBB2); 420 MBB2->addSuccessor(MBB3); 421 MBB3->addSuccessor(MBB2); 422 MBB3->addSuccessor(MBB3); 423 MBB3->addSuccessor(MBB4); 424 MF->RenumberBlocks(); 425 426 setupLDVObj(&*MF); 427 } 428 429 MachineFunction *readMIRBlock(const char *Input) { 430 MIRStr.clear(); 431 StringRef S = Twine(Twine(R"MIR( 432 --- | 433 target triple = "x86_64-unknown-linux-gnu" 434 define void @test() { ret void } 435 ... 436 --- 437 name: test 438 tracksRegLiveness: true 439 stack: 440 - { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, 441 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 442 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 443 body: | 444 bb.0: 445 liveins: $rdi, $rsi 446 )MIR") + Twine(Input) + Twine("...\n")) 447 .toNullTerminatedStringRef(MIRStr); 448 ; 449 450 // Clear the "test" function from MMI if it's still present. 451 if (Function *Fn = Mod->getFunction("test")) 452 MMI->deleteMachineFunctionFor(*Fn); 453 454 auto MemBuf = MemoryBuffer::getMemBuffer(S, "<input>"); 455 auto MIRParse = createMIRParser(std::move(MemBuf), Ctx); 456 Mod = MIRParse->parseIRModule(); 457 assert(Mod); 458 Mod->setDataLayout("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-" 459 "n8:16:32:64-S128"); 460 461 bool Result = MIRParse->parseMachineFunctions(*Mod, *MMI); 462 assert(!Result && "Failed to parse unit test machine function?"); 463 (void)Result; 464 465 Function *Fn = Mod->getFunction("test"); 466 assert(Fn && "Failed to parse a unit test module string?"); 467 Fn->setSubprogram(OurFunc); 468 return MMI->getMachineFunction(*Fn); 469 } 470 471 void 472 produceMLocTransferFunction(MachineFunction &MF, 473 SmallVectorImpl<MLocTransferMap> &MLocTransfer, 474 unsigned MaxNumBlocks) { 475 LDV->produceMLocTransferFunction(MF, MLocTransfer, MaxNumBlocks); 476 } 477 }; 478 479 TEST_F(InstrRefLDVTest, MTransferDefs) { 480 MachineFunction *MF = readMIRBlock( 481 " $rax = MOV64ri 0\n" 482 " RETQ $rax\n"); 483 setupLDVObj(MF); 484 485 // We should start with only SP tracked. 486 EXPECT_TRUE(MTracker->getNumLocs() == 1); 487 488 SmallVector<MLocTransferMap, 1> TransferMap; 489 TransferMap.resize(1); 490 produceMLocTransferFunction(*MF, TransferMap, 1); 491 492 // Code contains only one register write: that should assign to each of the 493 // aliasing registers. Test that all of them get locations, and have a 494 // corresponding def at the first instr in the function. 495 const char *RegNames[] = {"RAX", "HAX", "EAX", "AX", "AH", "AL"}; 496 EXPECT_TRUE(MTracker->getNumLocs() == 7); 497 for (const char *RegName : RegNames) { 498 Register R = getRegByName(RegName); 499 ASSERT_TRUE(MTracker->isRegisterTracked(R)); 500 LocIdx L = MTracker->getRegMLoc(R); 501 ValueIDNum V = MTracker->readReg(R); 502 // Value of this register should be: block zero, instruction 1, and the 503 // location it's defined in is itself. 504 ValueIDNum ToCmp(0, 1, L); 505 EXPECT_EQ(V, ToCmp); 506 } 507 508 // Do the same again, but with an aliasing write. This should write to all 509 // the same registers again, except $ah and $hax (the upper 8 bits of $ax 510 // and 32 bits of $rax resp.). 511 MF = readMIRBlock( 512 " $rax = MOV64ri 0\n" 513 " $al = MOV8ri 0\n" 514 " RETQ $rax\n"); 515 setupLDVObj(MF); 516 TransferMap.clear(); 517 TransferMap.resize(1); 518 produceMLocTransferFunction(*MF, TransferMap, 1); 519 520 auto TestRegSetSite = [&](const char *Name, unsigned InstrNum) { 521 Register R = getRegByName(Name); 522 ASSERT_TRUE(MTracker->isRegisterTracked(R)); 523 LocIdx L = MTracker->getRegMLoc(R); 524 ValueIDNum V = MTracker->readMLoc(L); 525 ValueIDNum ToCmp(0, InstrNum, L); 526 EXPECT_EQ(V, ToCmp); 527 }; 528 529 TestRegSetSite("AL", 2); 530 TestRegSetSite("AH", 1); 531 TestRegSetSite("AX", 2); 532 TestRegSetSite("EAX", 2); 533 TestRegSetSite("HAX", 1); 534 TestRegSetSite("RAX", 2); 535 536 // This call should: 537 // * Def rax via the implicit-def, 538 // * Clobber rsi/rdi and all their subregs, via the register mask 539 // * Same for rcx, despite it not being a use in the instr, it's in the mask 540 // * NOT clobber $rsp / $esp $ sp, LiveDebugValues deliberately ignores 541 // these. 542 // * NOT clobber $rbx, because it's non-volatile 543 // * Not track every other register in the machine, only those needed. 544 MF = readMIRBlock( 545 " $rax = MOV64ri 0\n" // instr 1 546 " $rbx = MOV64ri 0\n" // instr 2 547 " $rcx = MOV64ri 0\n" // instr 3 548 " $rdi = MOV64ri 0\n" // instr 4 549 " $rsi = MOV64ri 0\n" // instr 5 550 " CALL64r $rax, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax, implicit-def $esp, implicit-def $sp\n\n\n\n" // instr 6 551 " RETQ $rax\n"); // instr 7 552 setupLDVObj(MF); 553 TransferMap.clear(); 554 TransferMap.resize(1); 555 produceMLocTransferFunction(*MF, TransferMap, 1); 556 557 const char *RegsSetInCall[] = {"AL", "AH", "AX", "EAX", "HAX", "RAX", 558 "DIL", "DIH", "DI", "EDI", "HDI", "RDI", 559 "SIL", "SIH", "SI", "ESI", "HSI", "RSI", 560 "CL", "CH", "CX", "ECX", "HCX", "RCX"}; 561 for (const char *RegSetInCall : RegsSetInCall) 562 TestRegSetSite(RegSetInCall, 6); 563 564 const char *RegsLeftAlone[] = {"BL", "BH", "BX", "EBX", "HBX", "RBX"}; 565 for (const char *RegLeftAlone : RegsLeftAlone) 566 TestRegSetSite(RegLeftAlone, 2); 567 568 // Stack pointer should be the live-in to the function, instruction zero. 569 TestRegSetSite("RSP", 0); 570 // These stack regs should not be tracked either. Nor the (fake) subregs. 571 EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("ESP"))); 572 EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("SP"))); 573 EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("SPL"))); 574 EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("SPH"))); 575 EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("HSP"))); 576 577 // Should only be tracking: 6 x {A, B, C, DI, SI} registers = 30, 578 // Plus RSP, SSP = 32. 579 EXPECT_EQ(32u, MTracker->getNumLocs()); 580 581 582 // When we DBG_PHI something, we should track all its subregs. 583 MF = readMIRBlock( 584 " DBG_PHI $rdi, 0\n" 585 " RETQ\n"); 586 setupLDVObj(MF); 587 TransferMap.clear(); 588 TransferMap.resize(1); 589 produceMLocTransferFunction(*MF, TransferMap, 1); 590 591 // All DI regs and RSP tracked. 592 EXPECT_EQ(7u, MTracker->getNumLocs()); 593 594 // All the DI registers should have block live-in values, i.e. the argument 595 // to the function. 596 const char *DIRegs[] = {"DIL", "DIH", "DI", "EDI", "HDI", "RDI"}; 597 for (const char *DIReg : DIRegs) 598 TestRegSetSite(DIReg, 0); 599 } 600 601 TEST_F(InstrRefLDVTest, MTransferMeta) { 602 // Meta instructions should not have any effect on register values. 603 SmallVector<MLocTransferMap, 1> TransferMap; 604 MachineFunction *MF = readMIRBlock( 605 " $rax = MOV64ri 0\n" 606 " $rax = IMPLICIT_DEF\n" 607 " $rax = KILL killed $rax\n" 608 " RETQ $rax\n"); 609 setupLDVObj(MF); 610 TransferMap.clear(); 611 TransferMap.resize(1); 612 produceMLocTransferFunction(*MF, TransferMap, 1); 613 614 LocIdx RaxLoc = MTracker->getRegMLoc(getRegByName("RAX")); 615 ValueIDNum V = MTracker->readMLoc(RaxLoc); 616 // Def of rax should be from instruction 1, i.e., unmodified. 617 ValueIDNum Cmp(0, 1, RaxLoc); 618 EXPECT_EQ(Cmp, V); 619 } 620 621 TEST_F(InstrRefLDVTest, MTransferCopies) { 622 SmallVector<MLocTransferMap, 1> TransferMap; 623 // This memory spill should be recognised, and a spill slot created. 624 MachineFunction *MF = readMIRBlock( 625 " $rax = MOV64ri 0\n" 626 " MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n" 627 " RETQ $rax\n"); 628 setupLDVObj(MF); 629 TransferMap.clear(); 630 TransferMap.resize(1); 631 produceMLocTransferFunction(*MF, TransferMap, 1); 632 633 // Check that the spill location contains the value defined in rax by 634 // instruction 1. The MIR header says -16 offset, but it's stored as -8; 635 // it's not completely clear why, but here we only care about correctly 636 // identifying the slot, not that all the surrounding data is correct. 637 SpillLoc L = {getRegByName("RSP"), StackOffset::getFixed(-8)}; 638 Optional<ValueIDNum> V = MTracker->readSpill(L); 639 ASSERT_TRUE(V); 640 Register RAX = getRegByName("RAX"); 641 LocIdx RaxLoc = MTracker->getRegMLoc(RAX); 642 ValueIDNum Cmp(0, 1, RaxLoc); 643 EXPECT_EQ(*V, Cmp); 644 645 // A spill and restore should be recognised. 646 MF = readMIRBlock( 647 " $rax = MOV64ri 0\n" 648 " MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n" 649 " $rbx = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)\n" 650 " RETQ\n"); 651 setupLDVObj(MF); 652 TransferMap.clear(); 653 TransferMap.resize(1); 654 produceMLocTransferFunction(*MF, TransferMap, 1); 655 656 // Test that rbx contains rax from instruction 1. 657 RAX = getRegByName("RAX"); 658 RaxLoc = MTracker->getRegMLoc(RAX); 659 Register RBX = getRegByName("RBX"); 660 LocIdx RbxLoc = MTracker->getRegMLoc(RBX); 661 Cmp = ValueIDNum(0, 1, RaxLoc); 662 ValueIDNum RbxVal = MTracker->readMLoc(RbxLoc); 663 EXPECT_EQ(RbxVal, Cmp); 664 665 // FIXME: future work, make sure all the subregisters are transferred too. 666 667 // Copies and x86 movs should be recognised and honoured. In addition, all 668 // of the subregisters should be copied across too. 669 MF = readMIRBlock( 670 " $rax = MOV64ri 0\n" 671 " $rcx = COPY $rax\n" 672 " $rbx = MOV64rr $rcx\n" 673 " RETQ\n"); 674 setupLDVObj(MF); 675 TransferMap.clear(); 676 TransferMap.resize(1); 677 produceMLocTransferFunction(*MF, TransferMap, 1); 678 679 const char *ARegs[] = {"AL", "AH", "AX", "EAX", "HAX", "RAX"}; 680 const char *BRegs[] = {"BL", "BH", "BX", "EBX", "HBX", "RBX"}; 681 const char *CRegs[] = {"CL", "CH", "CX", "ECX", "HCX", "RCX"}; 682 auto CheckReg = [&](unsigned int I) { 683 LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I])); 684 LocIdx B = MTracker->getRegMLoc(getRegByName(BRegs[I])); 685 LocIdx C = MTracker->getRegMLoc(getRegByName(CRegs[I])); 686 ValueIDNum ARefVal(0, 1, A); 687 ValueIDNum AVal = MTracker->readMLoc(A); 688 ValueIDNum BVal = MTracker->readMLoc(B); 689 ValueIDNum CVal = MTracker->readMLoc(C); 690 EXPECT_EQ(ARefVal, AVal); 691 EXPECT_EQ(ARefVal, BVal); 692 EXPECT_EQ(ARefVal, CVal); 693 }; 694 695 for (unsigned int I = 0; I < 6; ++I) 696 CheckReg(I); 697 698 // When we copy to a subregister, the super-register should be def'd too: it's 699 // value will have changed. 700 MF = readMIRBlock( 701 " $rax = MOV64ri 0\n" 702 " $ecx = COPY $eax\n" 703 " RETQ\n"); 704 setupLDVObj(MF); 705 TransferMap.clear(); 706 TransferMap.resize(1); 707 produceMLocTransferFunction(*MF, TransferMap, 1); 708 709 // First four regs [al, ah, ax, eax] should be copied to *cx. 710 for (unsigned int I = 0; I < 4; ++I) { 711 LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I])); 712 LocIdx C = MTracker->getRegMLoc(getRegByName(CRegs[I])); 713 ValueIDNum ARefVal(0, 1, A); 714 ValueIDNum AVal = MTracker->readMLoc(A); 715 ValueIDNum CVal = MTracker->readMLoc(C); 716 EXPECT_EQ(ARefVal, AVal); 717 EXPECT_EQ(ARefVal, CVal); 718 } 719 720 // But rcx should contain a value defined by the COPY. 721 LocIdx RcxLoc = MTracker->getRegMLoc(getRegByName("RCX")); 722 ValueIDNum RcxVal = MTracker->readMLoc(RcxLoc); 723 ValueIDNum RcxDefVal(0, 2, RcxLoc); // instr 2 -> the copy 724 EXPECT_EQ(RcxVal, RcxDefVal); 725 } 726 727 TEST_F(InstrRefLDVTest, MLocSingleBlock) { 728 // Test some very simple properties about interpreting the transfer function. 729 setupSingleBlock(); 730 731 // We should start with a single location, the stack pointer. 732 ASSERT_TRUE(MTracker->getNumLocs() == 1); 733 LocIdx RspLoc(0); 734 735 // Set up live-in and live-out tables for this function: two locations (we 736 // add one later) in a single block. 737 ValueIDNum InLocs[2], OutLocs[2]; 738 ValueIDNum *InLocsPtr[1] = {&InLocs[0]}; 739 ValueIDNum *OutLocsPtr[1] = {&OutLocs[0]}; 740 741 // Transfer function: nothing. 742 SmallVector<MLocTransferMap, 1> TransferFunc = {{}}; 743 744 // Try and build value maps... 745 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 746 747 // The result should be that RSP is marked as a live-in-PHI -- this represents 748 // an argument. And as there's no transfer function, the block live-out should 749 // be the same. 750 EXPECT_EQ(InLocs[0], ValueIDNum(0, 0, RspLoc)); 751 EXPECT_EQ(OutLocs[0], ValueIDNum(0, 0, RspLoc)); 752 753 // Try again, this time initialising the in-locs to be defined by an 754 // instruction. The entry block should always be re-assigned to be the 755 // arguments. 756 initValueArray(InLocsPtr, 1, 2); 757 initValueArray(OutLocsPtr, 1, 2); 758 InLocs[0] = ValueIDNum(0, 1, RspLoc); 759 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 760 EXPECT_EQ(InLocs[0], ValueIDNum(0, 0, RspLoc)); 761 EXPECT_EQ(OutLocs[0], ValueIDNum(0, 0, RspLoc)); 762 763 // Now insert something into the transfer function to assign to the single 764 // machine location. 765 TransferFunc[0].insert({RspLoc, ValueIDNum(0, 1, RspLoc)}); 766 initValueArray(InLocsPtr, 1, 2); 767 initValueArray(OutLocsPtr, 1, 2); 768 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 769 EXPECT_EQ(InLocs[0], ValueIDNum(0, 0, RspLoc)); 770 EXPECT_EQ(OutLocs[0], ValueIDNum(0, 1, RspLoc)); 771 TransferFunc[0].clear(); 772 773 // Add a new register to be tracked, and insert it into the transfer function 774 // as a copy. The output of $rax should be the live-in value of $rsp. 775 Register RAX = getRegByName("RAX"); 776 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 777 TransferFunc[0].insert({RspLoc, ValueIDNum(0, 1, RspLoc)}); 778 TransferFunc[0].insert({RaxLoc, ValueIDNum(0, 0, RspLoc)}); 779 initValueArray(InLocsPtr, 1, 2); 780 initValueArray(OutLocsPtr, 1, 2); 781 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 782 EXPECT_EQ(InLocs[0], ValueIDNum(0, 0, RspLoc)); 783 EXPECT_EQ(InLocs[1], ValueIDNum(0, 0, RaxLoc)); 784 EXPECT_EQ(OutLocs[0], ValueIDNum(0, 1, RspLoc)); 785 EXPECT_EQ(OutLocs[1], ValueIDNum(0, 0, RspLoc)); // Rax contains RspLoc. 786 TransferFunc[0].clear(); 787 } 788 789 TEST_F(InstrRefLDVTest, MLocDiamondBlocks) { 790 // Test that information flows from the entry block to two successors. 791 // entry 792 // / \ 793 // br1 br2 794 // \ / 795 // ret 796 setupDiamondBlocks(); 797 798 ASSERT_TRUE(MTracker->getNumLocs() == 1); 799 LocIdx RspLoc(0); 800 Register RAX = getRegByName("RAX"); 801 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 802 803 ValueIDNum InLocs[4][2], OutLocs[4][2]; 804 ValueIDNum *InLocsPtr[4] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3]}; 805 ValueIDNum *OutLocsPtr[4] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3]}; 806 807 // Transfer function: start with nothing. 808 SmallVector<MLocTransferMap, 1> TransferFunc; 809 TransferFunc.resize(4); 810 811 // Name some values. 812 unsigned EntryBlk = 0, BrBlk1 = 1, BrBlk2 = 2, RetBlk = 3; 813 814 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 815 ValueIDNum RspDefInBlk0(EntryBlk, 1, RspLoc); 816 ValueIDNum RspDefInBlk1(BrBlk1, 1, RspLoc); 817 ValueIDNum RspDefInBlk2(BrBlk2, 1, RspLoc); 818 ValueIDNum RspPHIInBlk3(RetBlk, 0, RspLoc); 819 ValueIDNum RaxLiveInBlk1(BrBlk1, 0, RaxLoc); 820 ValueIDNum RaxLiveInBlk2(BrBlk2, 0, RaxLoc); 821 822 // With no transfer function, the live-in values to the entry block should 823 // propagate to all live-outs and the live-ins to the two successor blocks. 824 // IN ADDITION: this checks that the exit block doesn't get a PHI put in it. 825 initValueArray(InLocsPtr, 4, 2); 826 initValueArray(OutLocsPtr, 4, 2); 827 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 828 EXPECT_EQ(InLocs[0][0], LiveInRsp); 829 EXPECT_EQ(InLocs[1][0], LiveInRsp); 830 EXPECT_EQ(InLocs[2][0], LiveInRsp); 831 EXPECT_EQ(InLocs[3][0], LiveInRsp); 832 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 833 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 834 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 835 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 836 // (Skipped writing out locations for $rax). 837 838 // Check that a def of $rsp in the entry block will likewise reach all the 839 // successors. 840 TransferFunc[0].insert({RspLoc, RspDefInBlk0}); 841 initValueArray(InLocsPtr, 4, 2); 842 initValueArray(OutLocsPtr, 4, 2); 843 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 844 EXPECT_EQ(InLocs[0][0], LiveInRsp); 845 EXPECT_EQ(InLocs[1][0], RspDefInBlk0); 846 EXPECT_EQ(InLocs[2][0], RspDefInBlk0); 847 EXPECT_EQ(InLocs[3][0], RspDefInBlk0); 848 EXPECT_EQ(OutLocs[0][0], RspDefInBlk0); 849 EXPECT_EQ(OutLocs[1][0], RspDefInBlk0); 850 EXPECT_EQ(OutLocs[2][0], RspDefInBlk0); 851 EXPECT_EQ(OutLocs[3][0], RspDefInBlk0); 852 TransferFunc[0].clear(); 853 854 // Def in one branch of the diamond means that we need a PHI in the ret block 855 TransferFunc[0].insert({RspLoc, RspDefInBlk0}); 856 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 857 initValueArray(InLocsPtr, 4, 2); 858 initValueArray(OutLocsPtr, 4, 2); 859 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 860 // This value map: like above, where RspDefInBlk0 is propagated through one 861 // branch of the diamond, but is def'ed in the live-outs of the other. The 862 // ret / merging block should have a PHI in its live-ins. 863 EXPECT_EQ(InLocs[0][0], LiveInRsp); 864 EXPECT_EQ(InLocs[1][0], RspDefInBlk0); 865 EXPECT_EQ(InLocs[2][0], RspDefInBlk0); 866 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 867 EXPECT_EQ(OutLocs[0][0], RspDefInBlk0); 868 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 869 EXPECT_EQ(OutLocs[2][0], RspDefInBlk0); 870 EXPECT_EQ(OutLocs[3][0], RspPHIInBlk3); 871 TransferFunc[0].clear(); 872 TransferFunc[1].clear(); 873 874 // If we have differeing defs in either side of the diamond, we should 875 // continue to produce a PHI, 876 TransferFunc[0].insert({RspLoc, RspDefInBlk0}); 877 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 878 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 879 initValueArray(InLocsPtr, 4, 2); 880 initValueArray(OutLocsPtr, 4, 2); 881 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 882 EXPECT_EQ(InLocs[0][0], LiveInRsp); 883 EXPECT_EQ(InLocs[1][0], RspDefInBlk0); 884 EXPECT_EQ(InLocs[2][0], RspDefInBlk0); 885 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 886 EXPECT_EQ(OutLocs[0][0], RspDefInBlk0); 887 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 888 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 889 EXPECT_EQ(OutLocs[3][0], RspPHIInBlk3); 890 TransferFunc[0].clear(); 891 TransferFunc[1].clear(); 892 TransferFunc[2].clear(); 893 894 // If we have defs of the same value on either side of the branch, a PHI will 895 // initially be created, however value propagation should then eliminate it. 896 // Encode this by copying the live-in value to $rax, and copying it to $rsp 897 // from $rax in each branch of the diamond. We don't allow the definition of 898 // arbitary values in transfer functions. 899 TransferFunc[0].insert({RspLoc, RspDefInBlk0}); 900 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 901 TransferFunc[1].insert({RspLoc, RaxLiveInBlk1}); 902 TransferFunc[2].insert({RspLoc, RaxLiveInBlk2}); 903 initValueArray(InLocsPtr, 4, 2); 904 initValueArray(OutLocsPtr, 4, 2); 905 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 906 EXPECT_EQ(InLocs[0][0], LiveInRsp); 907 EXPECT_EQ(InLocs[1][0], RspDefInBlk0); 908 EXPECT_EQ(InLocs[2][0], RspDefInBlk0); 909 EXPECT_EQ(InLocs[3][0], LiveInRsp); 910 EXPECT_EQ(OutLocs[0][0], RspDefInBlk0); 911 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 912 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 913 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 914 TransferFunc[0].clear(); 915 TransferFunc[1].clear(); 916 TransferFunc[2].clear(); 917 } 918 919 TEST_F(InstrRefLDVTest, MLocSimpleLoop) { 920 // entry 921 // | 922 // |/-----\ 923 // loopblk | 924 // |\-----/ 925 // | 926 // ret 927 setupSimpleLoop(); 928 929 ASSERT_TRUE(MTracker->getNumLocs() == 1); 930 LocIdx RspLoc(0); 931 Register RAX = getRegByName("RAX"); 932 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 933 934 ValueIDNum InLocs[3][2], OutLocs[3][2]; 935 ValueIDNum *InLocsPtr[3] = {InLocs[0], InLocs[1], InLocs[2]}; 936 ValueIDNum *OutLocsPtr[3] = {OutLocs[0], OutLocs[1], OutLocs[2]}; 937 938 SmallVector<MLocTransferMap, 1> TransferFunc; 939 TransferFunc.resize(3); 940 941 // Name some values. 942 unsigned EntryBlk = 0, LoopBlk = 1, RetBlk = 2; 943 944 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 945 ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc); 946 ValueIDNum RspDefInBlk1(LoopBlk, 1, RspLoc); 947 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 948 ValueIDNum RaxPHIInBlk1(LoopBlk, 0, RaxLoc); 949 ValueIDNum RaxPHIInBlk2(RetBlk, 0, RaxLoc); 950 951 // Begin test with all locations being live-through. 952 initValueArray(InLocsPtr, 3, 2); 953 initValueArray(OutLocsPtr, 3, 2); 954 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 955 EXPECT_EQ(InLocs[0][0], LiveInRsp); 956 EXPECT_EQ(InLocs[1][0], LiveInRsp); 957 EXPECT_EQ(InLocs[2][0], LiveInRsp); 958 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 959 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 960 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 961 962 // Add a def of $rsp to the loop block: it should be in the live-outs, but 963 // should cause a PHI to be placed in the live-ins. Test the transfer function 964 // by copying that PHI into $rax in the loop, then back to $rsp in the ret 965 // block. 966 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 967 TransferFunc[1].insert({RaxLoc, RspPHIInBlk1}); 968 TransferFunc[2].insert({RspLoc, RaxPHIInBlk2}); 969 initValueArray(InLocsPtr, 3, 2); 970 initValueArray(OutLocsPtr, 3, 2); 971 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 972 EXPECT_EQ(InLocs[0][0], LiveInRsp); 973 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 974 EXPECT_EQ(InLocs[2][0], RspDefInBlk1); 975 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 976 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 977 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk1); 978 // Check rax as well, 979 EXPECT_EQ(InLocs[0][1], LiveInRax); 980 EXPECT_EQ(InLocs[1][1], RaxPHIInBlk1); 981 EXPECT_EQ(InLocs[2][1], RspPHIInBlk1); 982 EXPECT_EQ(OutLocs[0][1], LiveInRax); 983 EXPECT_EQ(OutLocs[1][1], RspPHIInBlk1); 984 EXPECT_EQ(OutLocs[2][1], RspPHIInBlk1); 985 TransferFunc[1].clear(); 986 TransferFunc[2].clear(); 987 988 // As with the diamond case, a PHI will be created if there's a (implicit) 989 // def in the entry block and loop block; but should be value propagated away 990 // if it copies in the same value. Copy live-in $rsp to $rax, then copy it 991 // into $rsp in the loop. Encoded as copying the live-in $rax value in block 1 992 // to $rsp. 993 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 994 TransferFunc[1].insert({RspLoc, RaxPHIInBlk1}); 995 initValueArray(InLocsPtr, 3, 2); 996 initValueArray(OutLocsPtr, 3, 2); 997 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 998 EXPECT_EQ(InLocs[0][0], LiveInRsp); 999 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1000 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1001 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1002 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1003 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1004 // Check $rax's values. 1005 EXPECT_EQ(InLocs[0][1], LiveInRax); 1006 EXPECT_EQ(InLocs[1][1], LiveInRsp); 1007 EXPECT_EQ(InLocs[2][1], LiveInRsp); 1008 EXPECT_EQ(OutLocs[0][1], LiveInRsp); 1009 EXPECT_EQ(OutLocs[1][1], LiveInRsp); 1010 EXPECT_EQ(OutLocs[2][1], LiveInRsp); 1011 TransferFunc[0].clear(); 1012 TransferFunc[1].clear(); 1013 } 1014 1015 TEST_F(InstrRefLDVTest, MLocNestedLoop) { 1016 // entry 1017 // | 1018 // loop1 1019 // ^\ 1020 // | \ /-\ 1021 // | loop2 | 1022 // | / \-/ 1023 // ^ / 1024 // join 1025 // | 1026 // ret 1027 setupNestedLoops(); 1028 1029 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1030 LocIdx RspLoc(0); 1031 Register RAX = getRegByName("RAX"); 1032 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1033 1034 ValueIDNum InLocs[5][2], OutLocs[5][2]; 1035 ValueIDNum *InLocsPtr[5] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3], 1036 InLocs[4]}; 1037 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], 1038 OutLocs[4]}; 1039 1040 SmallVector<MLocTransferMap, 1> TransferFunc; 1041 TransferFunc.resize(5); 1042 1043 unsigned EntryBlk = 0, Loop1Blk = 1, Loop2Blk = 2, JoinBlk = 3; 1044 1045 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1046 ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc); 1047 ValueIDNum RspDefInBlk1(Loop1Blk, 1, RspLoc); 1048 ValueIDNum RspPHIInBlk2(Loop2Blk, 0, RspLoc); 1049 ValueIDNum RspDefInBlk2(Loop2Blk, 1, RspLoc); 1050 ValueIDNum RspDefInBlk3(JoinBlk, 1, RspLoc); 1051 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1052 ValueIDNum RaxPHIInBlk1(Loop1Blk, 0, RaxLoc); 1053 ValueIDNum RaxPHIInBlk2(Loop2Blk, 0, RaxLoc); 1054 1055 // Like the other tests: first ensure that if there's nothing in the transfer 1056 // function, then everything is live-through (check $rsp). 1057 initValueArray(InLocsPtr, 5, 2); 1058 initValueArray(OutLocsPtr, 5, 2); 1059 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1060 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1061 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1062 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1063 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1064 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1065 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1066 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1067 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1068 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1069 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1070 1071 // A def in the inner loop means we should get PHIs at the heads of both 1072 // loops. Live-outs of the last three blocks will be the def, as it dominates 1073 // those. 1074 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 1075 initValueArray(InLocsPtr, 5, 2); 1076 initValueArray(OutLocsPtr, 5, 2); 1077 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1078 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1079 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1080 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1081 EXPECT_EQ(InLocs[3][0], RspDefInBlk2); 1082 EXPECT_EQ(InLocs[4][0], RspDefInBlk2); 1083 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1084 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1085 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 1086 EXPECT_EQ(OutLocs[3][0], RspDefInBlk2); 1087 EXPECT_EQ(OutLocs[4][0], RspDefInBlk2); 1088 TransferFunc[2].clear(); 1089 1090 // Adding a def to the outer loop header shouldn't affect this much -- the 1091 // live-out of block 1 changes. 1092 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1093 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 1094 initValueArray(InLocsPtr, 5, 2); 1095 initValueArray(OutLocsPtr, 5, 2); 1096 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1097 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1098 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1099 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1100 EXPECT_EQ(InLocs[3][0], RspDefInBlk2); 1101 EXPECT_EQ(InLocs[4][0], RspDefInBlk2); 1102 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1103 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1104 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 1105 EXPECT_EQ(OutLocs[3][0], RspDefInBlk2); 1106 EXPECT_EQ(OutLocs[4][0], RspDefInBlk2); 1107 TransferFunc[1].clear(); 1108 TransferFunc[2].clear(); 1109 1110 // Likewise, putting a def in the outer loop tail shouldn't affect where 1111 // the PHIs go, and should propagate into the ret block. 1112 1113 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1114 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 1115 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1116 initValueArray(InLocsPtr, 5, 2); 1117 initValueArray(OutLocsPtr, 5, 2); 1118 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1119 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1120 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1121 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1122 EXPECT_EQ(InLocs[3][0], RspDefInBlk2); 1123 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1124 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1125 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1126 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 1127 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1128 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1129 TransferFunc[1].clear(); 1130 TransferFunc[2].clear(); 1131 TransferFunc[3].clear(); 1132 1133 // However: if we don't def in the inner-loop, then we just have defs in the 1134 // head and tail of the outer loop. The inner loop should be live-through. 1135 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1136 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1137 initValueArray(InLocsPtr, 5, 2); 1138 initValueArray(OutLocsPtr, 5, 2); 1139 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1140 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1141 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1142 EXPECT_EQ(InLocs[2][0], RspDefInBlk1); 1143 EXPECT_EQ(InLocs[3][0], RspDefInBlk1); 1144 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1145 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1146 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1147 EXPECT_EQ(OutLocs[2][0], RspDefInBlk1); 1148 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1149 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1150 TransferFunc[1].clear(); 1151 TransferFunc[3].clear(); 1152 1153 // Check that this still works if we copy RspDefInBlk1 to $rax and then 1154 // copy it back into $rsp in the inner loop. 1155 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1156 TransferFunc[1].insert({RaxLoc, RspDefInBlk1}); 1157 TransferFunc[2].insert({RspLoc, RaxPHIInBlk2}); 1158 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1159 initValueArray(InLocsPtr, 5, 2); 1160 initValueArray(OutLocsPtr, 5, 2); 1161 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1162 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1163 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1164 EXPECT_EQ(InLocs[2][0], RspDefInBlk1); 1165 EXPECT_EQ(InLocs[3][0], RspDefInBlk1); 1166 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1167 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1168 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1169 EXPECT_EQ(OutLocs[2][0], RspDefInBlk1); 1170 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1171 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1172 // Look at raxes value in the relevant blocks, 1173 EXPECT_EQ(InLocs[2][1], RspDefInBlk1); 1174 EXPECT_EQ(OutLocs[1][1], RspDefInBlk1); 1175 TransferFunc[1].clear(); 1176 TransferFunc[2].clear(); 1177 TransferFunc[3].clear(); 1178 1179 // If we have a single def in the tail of the outer loop, that should produce 1180 // a PHI at the loop head, and be live-through the inner loop. 1181 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1182 initValueArray(InLocsPtr, 5, 2); 1183 initValueArray(OutLocsPtr, 5, 2); 1184 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1185 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1186 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1187 EXPECT_EQ(InLocs[2][0], RspPHIInBlk1); 1188 EXPECT_EQ(InLocs[3][0], RspPHIInBlk1); 1189 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1190 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1191 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1192 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk1); 1193 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1194 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1195 TransferFunc[3].clear(); 1196 1197 // And if we copy from $rsp to $rax in block 2, it should resolve to the PHI 1198 // in block 1, and we should keep that value in rax until the ret block. 1199 // There'll be a PHI in block 1 and 2, because we're putting a def in the 1200 // inner loop. 1201 TransferFunc[2].insert({RaxLoc, RspPHIInBlk2}); 1202 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1203 initValueArray(InLocsPtr, 5, 2); 1204 initValueArray(OutLocsPtr, 5, 2); 1205 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1206 // Examining the values of rax, 1207 EXPECT_EQ(InLocs[0][1], LiveInRax); 1208 EXPECT_EQ(InLocs[1][1], RaxPHIInBlk1); 1209 EXPECT_EQ(InLocs[2][1], RaxPHIInBlk2); 1210 EXPECT_EQ(InLocs[3][1], RspPHIInBlk1); 1211 EXPECT_EQ(InLocs[4][1], RspPHIInBlk1); 1212 EXPECT_EQ(OutLocs[0][1], LiveInRax); 1213 EXPECT_EQ(OutLocs[1][1], RaxPHIInBlk1); 1214 EXPECT_EQ(OutLocs[2][1], RspPHIInBlk1); 1215 EXPECT_EQ(OutLocs[3][1], RspPHIInBlk1); 1216 EXPECT_EQ(OutLocs[4][1], RspPHIInBlk1); 1217 TransferFunc[2].clear(); 1218 TransferFunc[3].clear(); 1219 } 1220 1221 TEST_F(InstrRefLDVTest, MLocNoDominatingLoop) { 1222 // entry 1223 // / \ 1224 // / \ 1225 // / \ 1226 // head1 head2 1227 // ^ \ / ^ 1228 // ^ \ / ^ 1229 // \-joinblk -/ 1230 // | 1231 // ret 1232 setupNoDominatingLoop(); 1233 1234 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1235 LocIdx RspLoc(0); 1236 Register RAX = getRegByName("RAX"); 1237 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1238 1239 ValueIDNum InLocs[5][2], OutLocs[5][2]; 1240 ValueIDNum *InLocsPtr[5] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3], 1241 InLocs[4]}; 1242 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], 1243 OutLocs[4]}; 1244 1245 SmallVector<MLocTransferMap, 1> TransferFunc; 1246 TransferFunc.resize(5); 1247 1248 unsigned EntryBlk = 0, Head1Blk = 1, Head2Blk = 2, JoinBlk = 3; 1249 1250 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1251 ValueIDNum RspPHIInBlk1(Head1Blk, 0, RspLoc); 1252 ValueIDNum RspDefInBlk1(Head1Blk, 1, RspLoc); 1253 ValueIDNum RspPHIInBlk2(Head2Blk, 0, RspLoc); 1254 ValueIDNum RspDefInBlk2(Head2Blk, 1, RspLoc); 1255 ValueIDNum RspPHIInBlk3(JoinBlk, 0, RspLoc); 1256 ValueIDNum RspDefInBlk3(JoinBlk, 1, RspLoc); 1257 ValueIDNum RaxPHIInBlk1(Head1Blk, 0, RaxLoc); 1258 ValueIDNum RaxPHIInBlk2(Head2Blk, 0, RaxLoc); 1259 1260 // As ever, test that everything is live-through if there are no defs. 1261 initValueArray(InLocsPtr, 5, 2); 1262 initValueArray(OutLocsPtr, 5, 2); 1263 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1264 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1265 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1266 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1267 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1268 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1269 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1270 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1271 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1272 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1273 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1274 1275 // Putting a def in the 'join' block will cause us to have two distinct 1276 // PHIs in each loop head, then on entry to the join block. 1277 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1278 initValueArray(InLocsPtr, 5, 2); 1279 initValueArray(OutLocsPtr, 5, 2); 1280 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1281 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1282 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1283 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1284 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1285 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1286 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1287 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1288 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk2); 1289 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1290 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1291 TransferFunc[3].clear(); 1292 1293 // We should get the same behaviour if we put the def in either of the 1294 // loop heads -- it should force the other head to be a PHI. 1295 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1296 initValueArray(InLocsPtr, 5, 2); 1297 initValueArray(OutLocsPtr, 5, 2); 1298 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1299 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1300 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1301 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1302 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1303 EXPECT_EQ(InLocs[4][0], RspPHIInBlk3); 1304 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1305 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1306 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk2); 1307 EXPECT_EQ(OutLocs[3][0], RspPHIInBlk3); 1308 EXPECT_EQ(OutLocs[4][0], RspPHIInBlk3); 1309 TransferFunc[1].clear(); 1310 1311 // Check symmetry, 1312 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 1313 initValueArray(InLocsPtr, 5, 2); 1314 initValueArray(OutLocsPtr, 5, 2); 1315 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1316 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1317 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1318 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1319 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1320 EXPECT_EQ(InLocs[4][0], RspPHIInBlk3); 1321 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1322 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1323 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 1324 EXPECT_EQ(OutLocs[3][0], RspPHIInBlk3); 1325 EXPECT_EQ(OutLocs[4][0], RspPHIInBlk3); 1326 TransferFunc[2].clear(); 1327 1328 // Test some scenarios where there _shouldn't_ be any PHIs created at heads. 1329 // These are those PHIs are created, but value propagation eliminates them. 1330 // For example, lets copy rsp-livein to $rsp inside each loop head, so that 1331 // there's no need for a PHI in the join block. Put a def of $rsp in block 3 1332 // to force PHIs elsewhere. 1333 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 1334 TransferFunc[1].insert({RspLoc, RaxPHIInBlk1}); 1335 TransferFunc[2].insert({RspLoc, RaxPHIInBlk2}); 1336 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1337 initValueArray(InLocsPtr, 5, 2); 1338 initValueArray(OutLocsPtr, 5, 2); 1339 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1340 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1341 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1342 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1343 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1344 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1345 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1346 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1347 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1348 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1349 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1350 TransferFunc[0].clear(); 1351 TransferFunc[1].clear(); 1352 TransferFunc[2].clear(); 1353 TransferFunc[3].clear(); 1354 1355 // In fact, if we eliminate the def in block 3, none of those PHIs are 1356 // necessary, as we're just repeatedly copying LiveInRsp into $rsp. They 1357 // should all be value propagated out. 1358 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 1359 TransferFunc[1].insert({RspLoc, RaxPHIInBlk1}); 1360 TransferFunc[2].insert({RspLoc, RaxPHIInBlk2}); 1361 initValueArray(InLocsPtr, 5, 2); 1362 initValueArray(OutLocsPtr, 5, 2); 1363 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1364 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1365 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1366 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1367 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1368 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1369 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1370 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1371 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1372 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1373 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1374 TransferFunc[0].clear(); 1375 TransferFunc[1].clear(); 1376 TransferFunc[2].clear(); 1377 } 1378 1379 TEST_F(InstrRefLDVTest, MLocBadlyNestedLoops) { 1380 // entry 1381 // | 1382 // loop1 -o 1383 // | ^ 1384 // | ^ 1385 // loop2 -o 1386 // | ^ 1387 // | ^ 1388 // loop3 -o 1389 // | 1390 // ret 1391 setupBadlyNestedLoops(); 1392 1393 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1394 LocIdx RspLoc(0); 1395 Register RAX = getRegByName("RAX"); 1396 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1397 1398 ValueIDNum InLocs[5][2], OutLocs[5][2]; 1399 ValueIDNum *InLocsPtr[5] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3], 1400 InLocs[4]}; 1401 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], 1402 OutLocs[4]}; 1403 1404 SmallVector<MLocTransferMap, 1> TransferFunc; 1405 TransferFunc.resize(5); 1406 1407 unsigned EntryBlk = 0, Loop1Blk = 1, Loop2Blk = 2, Loop3Blk = 3; 1408 1409 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1410 ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc); 1411 ValueIDNum RspDefInBlk1(Loop1Blk, 1, RspLoc); 1412 ValueIDNum RspPHIInBlk2(Loop2Blk, 0, RspLoc); 1413 ValueIDNum RspPHIInBlk3(Loop3Blk, 0, RspLoc); 1414 ValueIDNum RspDefInBlk3(Loop3Blk, 1, RspLoc); 1415 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1416 ValueIDNum RaxPHIInBlk3(Loop3Blk, 0, RaxLoc); 1417 1418 // As ever, test that everything is live-through if there are no defs. 1419 initValueArray(InLocsPtr, 5, 2); 1420 initValueArray(OutLocsPtr, 5, 2); 1421 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1422 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1423 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1424 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1425 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1426 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1427 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1428 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1429 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1430 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1431 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1432 1433 // A def in loop3 should cause PHIs in every loop block: they're all 1434 // reachable from each other. 1435 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1436 initValueArray(InLocsPtr, 5, 2); 1437 initValueArray(OutLocsPtr, 5, 2); 1438 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1439 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1440 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1441 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1442 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1443 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1444 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1445 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1446 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk2); 1447 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1448 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1449 TransferFunc[3].clear(); 1450 1451 // A def in loop1 should cause a PHI in loop1, but not the other blocks. 1452 // loop2 and loop3 are dominated by the def in loop1, so they should have 1453 // that value live-through. 1454 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1455 initValueArray(InLocsPtr, 5, 2); 1456 initValueArray(OutLocsPtr, 5, 2); 1457 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1458 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1459 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1460 EXPECT_EQ(InLocs[2][0], RspDefInBlk1); 1461 EXPECT_EQ(InLocs[3][0], RspDefInBlk1); 1462 EXPECT_EQ(InLocs[4][0], RspDefInBlk1); 1463 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1464 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1465 EXPECT_EQ(OutLocs[2][0], RspDefInBlk1); 1466 EXPECT_EQ(OutLocs[3][0], RspDefInBlk1); 1467 EXPECT_EQ(OutLocs[4][0], RspDefInBlk1); 1468 TransferFunc[1].clear(); 1469 1470 // As with earlier tricks: copy $rsp to $rax in the entry block, then $rax 1471 // to $rsp in block 3. The only def of $rsp is simply copying the same value 1472 // back into itself, and the value of $rsp is LiveInRsp all the way through. 1473 // PHIs should be created, then value-propagated away... however this 1474 // doesn't work in practice. 1475 // Consider the entry to loop3: we can determine that there's an incoming 1476 // PHI value from loop2, and LiveInRsp from the self-loop. This would still 1477 // justify having a PHI on entry to loop3. The only way to completely 1478 // value-propagate these PHIs away would be to speculatively explore what 1479 // PHIs could be eliminated and what that would lead to; which is 1480 // combinatorially complex. 1481 // Happily: 1482 // a) In this scenario, we always have a tracked location for LiveInRsp 1483 // anyway, so there's no loss in availability, 1484 // b) Only DBG_PHIs of a register would be vunlerable to this scenario, and 1485 // even then only if a true PHI became a DBG_PHI and was then optimised 1486 // through branch folding to no longer be at a CFG join, 1487 // c) The register allocator can spot this kind of redundant COPY easily, 1488 // and eliminate it. 1489 // 1490 // This unit test left in as a reference for the limitations of this 1491 // approach. PHIs will be left in $rsp on entry to each block. 1492 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 1493 TransferFunc[3].insert({RspLoc, RaxPHIInBlk3}); 1494 initValueArray(InLocsPtr, 5, 2); 1495 initValueArray(OutLocsPtr, 5, 2); 1496 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1497 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1498 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1499 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1500 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1501 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1502 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1503 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1504 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk2); 1505 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1506 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1507 // Check $rax's value. It should have $rsps value from the entry block 1508 // onwards. 1509 EXPECT_EQ(InLocs[0][1], LiveInRax); 1510 EXPECT_EQ(InLocs[1][1], LiveInRsp); 1511 EXPECT_EQ(InLocs[2][1], LiveInRsp); 1512 EXPECT_EQ(InLocs[3][1], LiveInRsp); 1513 EXPECT_EQ(InLocs[4][1], LiveInRsp); 1514 EXPECT_EQ(OutLocs[0][1], LiveInRsp); 1515 EXPECT_EQ(OutLocs[1][1], LiveInRsp); 1516 EXPECT_EQ(OutLocs[2][1], LiveInRsp); 1517 EXPECT_EQ(OutLocs[3][1], LiveInRsp); 1518 EXPECT_EQ(OutLocs[4][1], LiveInRsp); 1519 } 1520 1521 TEST_F(InstrRefLDVTest, pickVPHILocDiamond) { 1522 // entry 1523 // / \ 1524 // br1 br2 1525 // \ / 1526 // ret 1527 setupDiamondBlocks(); 1528 1529 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1530 LocIdx RspLoc(0); 1531 Register RAX = getRegByName("RAX"); 1532 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1533 1534 ValueIDNum OutLocs[4][2]; 1535 ValueIDNum *OutLocsPtr[4] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3]}; 1536 1537 initValueArray(OutLocsPtr, 4, 2); 1538 1539 unsigned EntryBlk = 0, Br2Blk = 2, RetBlk = 3; 1540 1541 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1542 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1543 ValueIDNum RspPHIInBlk2(Br2Blk, 0, RspLoc); 1544 ValueIDNum RspPHIInBlk3(RetBlk, 0, RspLoc); 1545 1546 DebugVariable Var(FuncVariable, None, nullptr); 1547 DbgValueProperties EmptyProps(EmptyExpr, false); 1548 SmallVector<DbgValue, 32> VLiveOuts; 1549 VLiveOuts.resize(4, DbgValue(EmptyProps, DbgValue::Undef)); 1550 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 1551 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 1552 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 1553 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 1554 VLiveOutIdx[MBB3] = &VLiveOuts[3]; 1555 1556 SmallVector<const MachineBasicBlock *, 2> Preds; 1557 for (const auto *Pred : MBB3->predecessors()) 1558 Preds.push_back(Pred); 1559 1560 // Specify the live-outs around the joining block. 1561 OutLocs[1][0] = LiveInRsp; 1562 OutLocs[2][0] = LiveInRax; 1563 1564 Optional<ValueIDNum> Result; 1565 1566 // Simple case: join two distinct values on entry to the block. 1567 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1568 VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 1569 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1570 // Should have picked a PHI in $rsp in block 3. 1571 EXPECT_TRUE(Result); 1572 if (Result) { 1573 EXPECT_EQ(*Result, RspPHIInBlk3); 1574 } 1575 1576 // If the incoming values are swapped between blocks, we should not 1577 // successfully join. The CFG merge would select the right values, but in 1578 // the wrong conditions. 1579 std::swap(VLiveOuts[1], VLiveOuts[2]); 1580 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1581 EXPECT_FALSE(Result); 1582 1583 // Swap back, 1584 std::swap(VLiveOuts[1], VLiveOuts[2]); 1585 // Setting one of these to being a constant should prohibit merging. 1586 VLiveOuts[1].Kind = DbgValue::Const; 1587 VLiveOuts[1].MO = MachineOperand::CreateImm(0); 1588 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1589 EXPECT_FALSE(Result); 1590 1591 // Seeing both to being a constant -> still prohibit, it shouldn't become 1592 // a value in the register file anywhere. 1593 VLiveOuts[2] = VLiveOuts[1]; 1594 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1595 EXPECT_FALSE(Result); 1596 1597 // NoVals shouldn't join with anything else. 1598 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1599 VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::NoVal); 1600 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1601 EXPECT_FALSE(Result); 1602 1603 // We might merge in another VPHI in such a join. Present pickVPHILoc with 1604 // such a scenario: first, where one incoming edge has a VPHI with no known 1605 // value. This represents an edge where there was a PHI value that can't be 1606 // found in the register file -- we can't subsequently find a PHI here. 1607 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1608 VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); 1609 EXPECT_EQ(VLiveOuts[2].ID, ValueIDNum::EmptyValue); 1610 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1611 EXPECT_FALSE(Result); 1612 1613 // However, if we know the value of the incoming VPHI, we can search for its 1614 // location. Use a PHI machine-value for doing this, as VPHIs should always 1615 // have PHI values, or they should have been eliminated. 1616 OutLocs[2][0] = RspPHIInBlk2; 1617 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1618 VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); 1619 VLiveOuts[2].ID = RspPHIInBlk2; // Set location where PHI happens. 1620 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1621 EXPECT_TRUE(Result); 1622 if (Result) { 1623 EXPECT_EQ(*Result, RspPHIInBlk3); 1624 } 1625 1626 // If that value isn't available from that block, don't join. 1627 OutLocs[2][0] = LiveInRsp; 1628 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1629 EXPECT_FALSE(Result); 1630 1631 // Check that we don't pick values when the properties disagree, for example 1632 // different indirectness or DIExpression. 1633 DIExpression *NewExpr = 1634 DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); 1635 DbgValueProperties PropsWithExpr(NewExpr, false); 1636 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1637 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithExpr, DbgValue::Def); 1638 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1639 EXPECT_FALSE(Result); 1640 1641 DbgValueProperties PropsWithIndirect(EmptyExpr, true); 1642 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1643 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def); 1644 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1645 EXPECT_FALSE(Result); 1646 } 1647 1648 TEST_F(InstrRefLDVTest, pickVPHILocLoops) { 1649 setupSimpleLoop(); 1650 // entry 1651 // | 1652 // |/-----\ 1653 // loopblk | 1654 // |\-----/ 1655 // | 1656 // ret 1657 1658 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1659 LocIdx RspLoc(0); 1660 Register RAX = getRegByName("RAX"); 1661 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1662 1663 ValueIDNum OutLocs[3][2]; 1664 ValueIDNum *OutLocsPtr[4] = {OutLocs[0], OutLocs[1], OutLocs[2]}; 1665 1666 initValueArray(OutLocsPtr, 3, 2); 1667 1668 unsigned EntryBlk = 0, LoopBlk = 1; 1669 1670 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1671 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1672 ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc); 1673 ValueIDNum RaxPHIInBlk1(LoopBlk, 0, RaxLoc); 1674 1675 DebugVariable Var(FuncVariable, None, nullptr); 1676 DbgValueProperties EmptyProps(EmptyExpr, false); 1677 SmallVector<DbgValue, 32> VLiveOuts; 1678 VLiveOuts.resize(3, DbgValue(EmptyProps, DbgValue::Undef)); 1679 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 1680 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 1681 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 1682 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 1683 1684 SmallVector<const MachineBasicBlock *, 2> Preds; 1685 for (const auto *Pred : MBB1->predecessors()) 1686 Preds.push_back(Pred); 1687 1688 // Specify the live-outs around the joining block. 1689 OutLocs[0][0] = LiveInRsp; 1690 OutLocs[1][0] = LiveInRax; 1691 1692 Optional<ValueIDNum> Result; 1693 1694 // See that we can merge as normal on a backedge. 1695 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1696 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 1697 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1698 // Should have picked a PHI in $rsp in block 1. 1699 EXPECT_TRUE(Result); 1700 if (Result) { 1701 EXPECT_EQ(*Result, RspPHIInBlk1); 1702 } 1703 1704 // And that, if the desired values aren't available, we don't merge. 1705 OutLocs[1][0] = LiveInRsp; 1706 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1707 EXPECT_FALSE(Result); 1708 1709 // Test the backedge behaviour: PHIs that feed back into themselves can 1710 // carry this variables value. Feed in LiveInRsp in both $rsp and $rax 1711 // from the entry block, but only put an appropriate backedge PHI in $rax. 1712 // Only the $rax location can form the correct PHI. 1713 OutLocs[0][0] = LiveInRsp; 1714 OutLocs[0][1] = LiveInRsp; 1715 OutLocs[1][0] = RaxPHIInBlk1; 1716 OutLocs[1][1] = RaxPHIInBlk1; 1717 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1718 // Crucially, a VPHI originating in this block: 1719 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 1720 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1721 EXPECT_TRUE(Result); 1722 if (Result) { 1723 EXPECT_EQ(*Result, RaxPHIInBlk1); 1724 } 1725 1726 // Merging should not be permitted if there's a usable PHI on the backedge, 1727 // but it's in the wrong place. (Overwrite $rax). 1728 OutLocs[1][1] = LiveInRax; 1729 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1730 EXPECT_FALSE(Result); 1731 1732 // Additionally, if the VPHI coming back on the loop backedge isn't from 1733 // this block (block 1), we can't merge it. 1734 OutLocs[1][1] = RaxPHIInBlk1; 1735 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1736 VLiveOuts[1] = DbgValue(0, EmptyProps, DbgValue::VPHI); 1737 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1738 EXPECT_FALSE(Result); 1739 } 1740 1741 TEST_F(InstrRefLDVTest, pickVPHILocBadlyNestedLoops) { 1742 // Run some tests similar to pickVPHILocLoops, with more than one backedge, 1743 // and check that we merge correctly over many candidate locations. 1744 setupBadlyNestedLoops(); 1745 // entry 1746 // | 1747 // loop1 -o 1748 // | ^ 1749 // | ^ 1750 // loop2 -o 1751 // | ^ 1752 // | ^ 1753 // loop3 -o 1754 // | 1755 // ret 1756 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1757 LocIdx RspLoc(0); 1758 Register RAX = getRegByName("RAX"); 1759 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1760 Register RBX = getRegByName("RBX"); 1761 LocIdx RbxLoc = MTracker->lookupOrTrackRegister(RBX); 1762 1763 ValueIDNum OutLocs[5][3]; 1764 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], OutLocs[4]}; 1765 1766 initValueArray(OutLocsPtr, 5, 3); 1767 1768 unsigned EntryBlk = 0, Loop1Blk = 1; 1769 1770 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1771 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1772 ValueIDNum LiveInRbx(EntryBlk, 0, RbxLoc); 1773 ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc); 1774 ValueIDNum RaxPHIInBlk1(Loop1Blk, 0, RaxLoc); 1775 ValueIDNum RbxPHIInBlk1(Loop1Blk, 0, RbxLoc); 1776 1777 DebugVariable Var(FuncVariable, None, nullptr); 1778 DbgValueProperties EmptyProps(EmptyExpr, false); 1779 SmallVector<DbgValue, 32> VLiveOuts; 1780 VLiveOuts.resize(5, DbgValue(EmptyProps, DbgValue::Undef)); 1781 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 1782 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 1783 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 1784 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 1785 VLiveOutIdx[MBB3] = &VLiveOuts[3]; 1786 VLiveOutIdx[MBB4] = &VLiveOuts[4]; 1787 1788 // We're going to focus on block 1. 1789 SmallVector<const MachineBasicBlock *, 2> Preds; 1790 for (const auto *Pred : MBB1->predecessors()) 1791 Preds.push_back(Pred); 1792 1793 // Specify the live-outs around the joining block. Incoming edges from the 1794 // entry block, self, and loop2. 1795 OutLocs[0][0] = LiveInRsp; 1796 OutLocs[1][0] = LiveInRax; 1797 OutLocs[2][0] = LiveInRbx; 1798 1799 Optional<ValueIDNum> Result; 1800 1801 // See that we can merge as normal on a backedge. 1802 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1803 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 1804 VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def); 1805 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1806 // Should have picked a PHI in $rsp in block 1. 1807 EXPECT_TRUE(Result); 1808 if (Result) { 1809 EXPECT_EQ(*Result, RspPHIInBlk1); 1810 } 1811 1812 // Check too that permuting the live-out locations prevents merging 1813 OutLocs[0][0] = LiveInRax; 1814 OutLocs[1][0] = LiveInRbx; 1815 OutLocs[2][0] = LiveInRsp; 1816 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1817 EXPECT_FALSE(Result); 1818 1819 OutLocs[0][0] = LiveInRsp; 1820 OutLocs[1][0] = LiveInRax; 1821 OutLocs[2][0] = LiveInRbx; 1822 1823 // Feeding a PHI back on one backedge shouldn't merge (block 1 self backedge 1824 // wants LiveInRax). 1825 OutLocs[1][0] = RspPHIInBlk1; 1826 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1827 EXPECT_FALSE(Result); 1828 1829 // If the variables value on that edge is a VPHI feeding into itself, that's 1830 // fine. 1831 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1832 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 1833 VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def); 1834 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1835 EXPECT_TRUE(Result); 1836 if (Result) { 1837 EXPECT_EQ(*Result, RspPHIInBlk1); 1838 } 1839 1840 // Likewise: the other backedge being a VPHI from block 1 should be accepted. 1841 OutLocs[2][0] = RspPHIInBlk1; 1842 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1843 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 1844 VLiveOuts[2] = DbgValue(1, EmptyProps, DbgValue::VPHI); 1845 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1846 EXPECT_TRUE(Result); 1847 if (Result) { 1848 EXPECT_EQ(*Result, RspPHIInBlk1); 1849 } 1850 1851 // Here's where it becomes tricky: we should not merge if there are two 1852 // _distinct_ backedge PHIs. We can't have a PHI that happens in both rsp 1853 // and rax for example. We can only pick one location as the live-in. 1854 OutLocs[2][0] = RaxPHIInBlk1; 1855 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1856 EXPECT_FALSE(Result); 1857 1858 // The above test sources correct machine-PHI-value from two places. Now 1859 // try with one machine-PHI-value, but placed in two different locations 1860 // on the backedge. Again, we can't merge a location here, there's no 1861 // location that works on all paths. 1862 OutLocs[0][0] = LiveInRsp; 1863 OutLocs[1][0] = RspPHIInBlk1; 1864 OutLocs[2][0] = LiveInRsp; 1865 OutLocs[2][1] = RspPHIInBlk1; 1866 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1867 EXPECT_FALSE(Result); 1868 1869 // Scatter various PHI values across the available locations. Only rbx (loc 2) 1870 // has the right value in both backedges -- that's the loc that should be 1871 // picked. 1872 OutLocs[0][2] = LiveInRsp; 1873 OutLocs[1][0] = RspPHIInBlk1; 1874 OutLocs[1][1] = RaxPHIInBlk1; 1875 OutLocs[1][2] = RbxPHIInBlk1; 1876 OutLocs[2][0] = LiveInRsp; 1877 OutLocs[2][1] = RspPHIInBlk1; 1878 OutLocs[2][2] = RbxPHIInBlk1; 1879 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1880 EXPECT_TRUE(Result); 1881 if (Result) { 1882 EXPECT_EQ(*Result, RbxPHIInBlk1); 1883 } 1884 } 1885 1886 TEST_F(InstrRefLDVTest, vlocJoinDiamond) { 1887 // entry 1888 // / \ 1889 // br1 br2 1890 // \ / 1891 // ret 1892 setupDiamondBlocks(); 1893 1894 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1895 LocIdx RspLoc(0); 1896 Register RAX = getRegByName("RAX"); 1897 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1898 1899 unsigned EntryBlk = 0, Br2Blk = 2, RetBlk = 3; 1900 1901 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1902 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1903 ValueIDNum RspPHIInBlkBr2Blk(Br2Blk, 0, RspLoc); 1904 ValueIDNum RspPHIInBlkRetBlk(RetBlk, 0, RspLoc); 1905 1906 DebugVariable Var(FuncVariable, None, nullptr); 1907 DbgValueProperties EmptyProps(EmptyExpr, false); 1908 SmallVector<DbgValue, 32> VLiveOuts; 1909 VLiveOuts.resize(4, DbgValue(EmptyProps, DbgValue::Undef)); 1910 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 1911 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 1912 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 1913 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 1914 VLiveOutIdx[MBB3] = &VLiveOuts[3]; 1915 1916 SmallPtrSet<const MachineBasicBlock *, 8> AllBlocks; 1917 AllBlocks.insert(MBB0); 1918 AllBlocks.insert(MBB1); 1919 AllBlocks.insert(MBB2); 1920 AllBlocks.insert(MBB3); 1921 1922 SmallVector<const MachineBasicBlock *, 2> Preds; 1923 for (const auto *Pred : MBB3->predecessors()) 1924 Preds.push_back(Pred); 1925 1926 SmallSet<DebugVariable, 4> AllVars; 1927 AllVars.insert(Var); 1928 1929 // vlocJoin is here to propagate incoming values, and eliminate PHIs. Start 1930 // off by propagating a value into the merging block, number 3. 1931 DbgValue JoinedLoc = DbgValue(3, EmptyProps, DbgValue::NoVal); 1932 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1933 VLiveOuts[2] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1934 bool Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 1935 EXPECT_TRUE(Result); // Output locs should have changed. 1936 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 1937 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 1938 1939 // And if we did it a second time, leaving the live-ins as it was, then 1940 // we should report no change. 1941 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 1942 EXPECT_FALSE(Result); 1943 1944 // If the live-in variable values are different, but there's no PHI placed 1945 // in this block, then just pick a location. It should be the first (in RPO) 1946 // predecessor to avoid being a backedge. 1947 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1948 VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 1949 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::NoVal); 1950 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 1951 EXPECT_TRUE(Result); 1952 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 1953 // RPO is blocks 0 2 1 3, so LiveInRax is picked as the first predecessor 1954 // of this join. 1955 EXPECT_EQ(JoinedLoc.ID, LiveInRax); 1956 1957 // No tests for whether vlocJoin will pass-through a variable with differing 1958 // expressions / properties. Those can only come about due to assignments; and 1959 // for any assignment at all, a PHI should have been placed at the dominance 1960 // frontier. We rely on the IDF calculator being accurate (which is OK, 1961 // because so does the rest of LLVM). 1962 1963 // Try placing a PHI. With differing input values (LiveInRsp, LiveInRax), 1964 // this PHI should not be eliminated. 1965 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); 1966 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 1967 // Expect no change. 1968 EXPECT_FALSE(Result); 1969 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 1970 // This should not have been assigned a fixed value. 1971 EXPECT_EQ(JoinedLoc.ID, ValueIDNum::EmptyValue); 1972 EXPECT_EQ(JoinedLoc.BlockNo, 3); 1973 1974 // Try a simple PHI elimination. Put a PHI in block 3, but LiveInRsp on both 1975 // incoming edges. Re-load in and out-locs with unrelated values; they're 1976 // irrelevant. 1977 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1978 VLiveOuts[2] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1979 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); 1980 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 1981 EXPECT_TRUE(Result); 1982 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 1983 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 1984 1985 // If the "current" live-in is a VPHI, but not a VPHI generated in the current 1986 // block, then it's the remains of an earlier value propagation. We should 1987 // value propagate through this merge. Even if the current incoming values 1988 // disagree, because we've previously determined any VPHI here is redundant. 1989 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1990 VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 1991 JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI); 1992 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 1993 EXPECT_TRUE(Result); 1994 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 1995 EXPECT_EQ(JoinedLoc.ID, LiveInRax); // from block 2 1996 1997 // The above test, but test that we will install one value-propagated VPHI 1998 // over another. 1999 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2000 VLiveOuts[2] = DbgValue(0, EmptyProps, DbgValue::VPHI); 2001 JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI); 2002 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2003 EXPECT_TRUE(Result); 2004 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2005 EXPECT_EQ(JoinedLoc.BlockNo, 0); 2006 2007 // We shouldn't eliminate PHIs when properties disagree. 2008 DbgValueProperties PropsWithIndirect(EmptyExpr, true); 2009 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2010 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def); 2011 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); 2012 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2013 EXPECT_FALSE(Result); 2014 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2015 EXPECT_EQ(JoinedLoc.BlockNo, 3); 2016 2017 // Even if properties disagree, we should still value-propagate if there's no 2018 // PHI to be eliminated. The disagreeing values should work themselves out, 2019 // seeing how we've determined no PHI is necessary. 2020 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2021 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def); 2022 JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI); 2023 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2024 EXPECT_TRUE(Result); 2025 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2026 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2027 // Also check properties come from block 2, the first RPO predecessor to block 2028 // three. 2029 EXPECT_EQ(JoinedLoc.Properties, PropsWithIndirect); 2030 2031 // Again, disagreeing properties, this time the expr, should cause a PHI to 2032 // not be eliminated. 2033 DIExpression *NewExpr = 2034 DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); 2035 DbgValueProperties PropsWithExpr(NewExpr, false); 2036 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2037 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithExpr, DbgValue::Def); 2038 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); 2039 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2040 EXPECT_FALSE(Result); 2041 } 2042 2043 TEST_F(InstrRefLDVTest, vlocJoinLoops) { 2044 setupSimpleLoop(); 2045 // entry 2046 // | 2047 // |/-----\ 2048 // loopblk | 2049 // |\-----/ 2050 // | 2051 // ret 2052 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2053 LocIdx RspLoc(0); 2054 Register RAX = getRegByName("RAX"); 2055 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2056 2057 unsigned EntryBlk = 0, LoopBlk = 1; 2058 2059 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 2060 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 2061 ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc); 2062 2063 DebugVariable Var(FuncVariable, None, nullptr); 2064 DbgValueProperties EmptyProps(EmptyExpr, false); 2065 SmallVector<DbgValue, 32> VLiveOuts; 2066 VLiveOuts.resize(3, DbgValue(EmptyProps, DbgValue::Undef)); 2067 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 2068 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 2069 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 2070 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 2071 2072 SmallPtrSet<const MachineBasicBlock *, 8> AllBlocks; 2073 AllBlocks.insert(MBB0); 2074 AllBlocks.insert(MBB1); 2075 AllBlocks.insert(MBB2); 2076 2077 SmallVector<const MachineBasicBlock *, 2> Preds; 2078 for (const auto *Pred : MBB1->predecessors()) 2079 Preds.push_back(Pred); 2080 2081 SmallSet<DebugVariable, 4> AllVars; 2082 AllVars.insert(Var); 2083 2084 // Test some back-edge-specific behaviours of vloc join. Mostly: the fact that 2085 // VPHIs that arrive on backedges can be eliminated, despite having different 2086 // values to the predecessor. 2087 2088 // First: when there's no VPHI placed already, propagate the live-in value of 2089 // the first RPO predecessor. 2090 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2091 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2092 DbgValue JoinedLoc = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2093 bool Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2094 EXPECT_TRUE(Result); 2095 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2096 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2097 2098 // If there is a VPHI: don't elimiante it if there are disagreeing values. 2099 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2100 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2101 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2102 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2103 EXPECT_FALSE(Result); 2104 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2105 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2106 2107 // If we feed this VPHI back into itself though, we can eliminate it. 2108 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2109 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2110 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2111 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2112 EXPECT_TRUE(Result); 2113 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2114 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2115 2116 // Don't eliminate backedge VPHIs if the predecessors have different 2117 // properties. 2118 DIExpression *NewExpr = 2119 DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); 2120 DbgValueProperties PropsWithExpr(NewExpr, false); 2121 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2122 VLiveOuts[1] = DbgValue(1, PropsWithExpr, DbgValue::VPHI); 2123 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2124 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2125 EXPECT_FALSE(Result); 2126 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2127 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2128 2129 // Backedges with VPHIs, but from the wrong block, shouldn't be eliminated. 2130 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2131 VLiveOuts[1] = DbgValue(0, EmptyProps, DbgValue::VPHI); 2132 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2133 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2134 EXPECT_FALSE(Result); 2135 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2136 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2137 } 2138 2139 TEST_F(InstrRefLDVTest, vlocJoinBadlyNestedLoops) { 2140 // Test PHI elimination in the presence of multiple backedges. 2141 setupBadlyNestedLoops(); 2142 // entry 2143 // | 2144 // loop1 -o 2145 // | ^ 2146 // | ^ 2147 // loop2 -o 2148 // | ^ 2149 // | ^ 2150 // loop3 -o 2151 // | 2152 // ret 2153 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2154 LocIdx RspLoc(0); 2155 Register RAX = getRegByName("RAX"); 2156 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2157 Register RBX = getRegByName("RBX"); 2158 LocIdx RbxLoc = MTracker->lookupOrTrackRegister(RBX); 2159 2160 unsigned EntryBlk = 0; 2161 2162 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 2163 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 2164 ValueIDNum LiveInRbx(EntryBlk, 0, RbxLoc); 2165 2166 DebugVariable Var(FuncVariable, None, nullptr); 2167 DbgValueProperties EmptyProps(EmptyExpr, false); 2168 SmallVector<DbgValue, 32> VLiveOuts; 2169 VLiveOuts.resize(5, DbgValue(EmptyProps, DbgValue::Undef)); 2170 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 2171 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 2172 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 2173 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 2174 VLiveOutIdx[MBB3] = &VLiveOuts[3]; 2175 VLiveOutIdx[MBB4] = &VLiveOuts[4]; 2176 2177 SmallPtrSet<const MachineBasicBlock *, 8> AllBlocks; 2178 AllBlocks.insert(MBB0); 2179 AllBlocks.insert(MBB1); 2180 AllBlocks.insert(MBB2); 2181 AllBlocks.insert(MBB3); 2182 AllBlocks.insert(MBB4); 2183 2184 // We're going to focus on block 1. 2185 SmallVector<const MachineBasicBlock *, 3> Preds; 2186 for (const auto *Pred : MBB1->predecessors()) 2187 Preds.push_back(Pred); 2188 2189 SmallSet<DebugVariable, 4> AllVars; 2190 AllVars.insert(Var); 2191 2192 // Test a normal VPHI isn't eliminated. 2193 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2194 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2195 VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def); 2196 DbgValue JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2197 bool Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2198 EXPECT_FALSE(Result); 2199 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2200 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2201 2202 // Common VPHIs on backedges should merge. 2203 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2204 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2205 VLiveOuts[2] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2206 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2207 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2208 EXPECT_TRUE(Result); 2209 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2210 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2211 2212 // They shouldn't merge if one of their properties is different. 2213 DbgValueProperties PropsWithIndirect(EmptyExpr, true); 2214 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2215 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2216 VLiveOuts[2] = DbgValue(1, PropsWithIndirect, DbgValue::VPHI); 2217 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2218 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2219 EXPECT_FALSE(Result); 2220 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2221 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2222 2223 // VPHIs from different blocks should not merge. 2224 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2225 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2226 VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); 2227 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2228 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2229 EXPECT_FALSE(Result); 2230 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2231 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2232 } 2233 2234 // Above are tests for picking VPHI locations, and eliminating VPHIs. No 2235 // unit-tests are written for evaluating the transfer function as that's 2236 // pretty straight forwards, or applying VPHI-location-picking to live-ins. 2237 // Instead, pre-set some machine locations and apply buildVLocValueMap to the 2238 // existing CFG patterns. 2239 TEST_F(InstrRefLDVTest, VLocSingleBlock) { 2240 setupSingleBlock(); 2241 2242 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2243 LocIdx RspLoc(0); 2244 2245 ValueIDNum InLocs[2], OutLocs[2]; 2246 ValueIDNum *InLocsPtr[1] = {&InLocs[0]}; 2247 ValueIDNum *OutLocsPtr[1] = {&OutLocs[0]}; 2248 2249 ValueIDNum LiveInRsp = ValueIDNum(0, 0, RspLoc); 2250 InLocs[0] = OutLocs[0] = LiveInRsp; 2251 2252 DebugVariable Var(FuncVariable, None, nullptr); 2253 DbgValueProperties EmptyProps(EmptyExpr, false); 2254 2255 SmallSet<DebugVariable, 4> AllVars; 2256 AllVars.insert(Var); 2257 2258 // Mild hack: rather than constructing machine instructions in each block 2259 // and creating lexical scopes across them, instead just tell 2260 // buildVLocValueMap that there's an assignment in every block. That makes 2261 // every block in scope. 2262 SmallPtrSet<MachineBasicBlock *, 4> AssignBlocks; 2263 AssignBlocks.insert(MBB0); 2264 2265 SmallVector<VLocTracker, 1> VLocs; 2266 VLocs.resize(1); 2267 2268 InstrRefBasedLDV::LiveInsT Output; 2269 2270 // Test that, with no assignments at all, no mappings are created for the 2271 // variable in this function. 2272 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2273 OutLocsPtr, InLocsPtr, VLocs); 2274 EXPECT_EQ(Output.size(), 0ul); 2275 2276 // If we put an assignment in the transfer function, that should... well, 2277 // do nothing, because we don't store the live-outs. 2278 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2279 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2280 OutLocsPtr, InLocsPtr, VLocs); 2281 EXPECT_EQ(Output.size(), 0ul); 2282 2283 // There is pretty much nothing else of interest to test with a single block. 2284 // It's not relevant to the SSA-construction parts of variable values. 2285 } 2286 2287 TEST_F(InstrRefLDVTest, VLocDiamondBlocks) { 2288 setupDiamondBlocks(); 2289 // entry 2290 // / \ 2291 // br1 br2 2292 // \ / 2293 // ret 2294 2295 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2296 LocIdx RspLoc(0); 2297 Register RAX = getRegByName("RAX"); 2298 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2299 2300 unsigned EntryBlk = 0, RetBlk = 3; 2301 2302 ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc); 2303 ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc); 2304 ValueIDNum RspPHIInBlk3 = ValueIDNum(RetBlk, 0, RspLoc); 2305 2306 ValueIDNum InLocs[4][2], OutLocs[4][2]; 2307 ValueIDNum *InLocsPtr[4] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3]}; 2308 ValueIDNum *OutLocsPtr[4] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3]}; 2309 2310 initValueArray(InLocsPtr, 4, 2); 2311 initValueArray(OutLocsPtr, 4, 2); 2312 2313 DebugVariable Var(FuncVariable, None, nullptr); 2314 DbgValueProperties EmptyProps(EmptyExpr, false); 2315 2316 SmallSet<DebugVariable, 4> AllVars; 2317 AllVars.insert(Var); 2318 2319 // Mild hack: rather than constructing machine instructions in each block 2320 // and creating lexical scopes across them, instead just tell 2321 // buildVLocValueMap that there's an assignment in every block. That makes 2322 // every block in scope. 2323 SmallPtrSet<MachineBasicBlock *, 4> AssignBlocks; 2324 AssignBlocks.insert(MBB0); 2325 AssignBlocks.insert(MBB1); 2326 AssignBlocks.insert(MBB2); 2327 AssignBlocks.insert(MBB3); 2328 2329 SmallVector<VLocTracker, 1> VLocs; 2330 VLocs.resize(4); 2331 2332 InstrRefBasedLDV::LiveInsT Output; 2333 2334 // Start off with LiveInRsp in every location. 2335 for (unsigned int I = 0; I < 4; ++I) { 2336 InLocs[I][0] = InLocs[I][1] = LiveInRsp; 2337 OutLocs[I][0] = OutLocs[I][1] = LiveInRsp; 2338 } 2339 2340 auto ClearOutputs = [&]() { 2341 for (auto &Elem : Output) 2342 Elem.clear(); 2343 }; 2344 Output.resize(4); 2345 2346 // No assignments -> no values. 2347 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2348 OutLocsPtr, InLocsPtr, VLocs); 2349 EXPECT_EQ(Output[0].size(), 0ul); 2350 EXPECT_EQ(Output[1].size(), 0ul); 2351 EXPECT_EQ(Output[2].size(), 0ul); 2352 EXPECT_EQ(Output[3].size(), 0ul); 2353 2354 // An assignment in the end block should also not affect other blocks; or 2355 // produce any live-ins. 2356 VLocs[3].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2357 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2358 OutLocsPtr, InLocsPtr, VLocs); 2359 EXPECT_EQ(Output[0].size(), 0ul); 2360 EXPECT_EQ(Output[1].size(), 0ul); 2361 EXPECT_EQ(Output[2].size(), 0ul); 2362 EXPECT_EQ(Output[3].size(), 0ul); 2363 ClearOutputs(); 2364 2365 // Assignments in either of the side-of-diamond blocks should also not be 2366 // propagated anywhere. 2367 VLocs[3].Vars.clear(); 2368 VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2369 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2370 OutLocsPtr, InLocsPtr, VLocs); 2371 EXPECT_EQ(Output[0].size(), 0ul); 2372 EXPECT_EQ(Output[1].size(), 0ul); 2373 EXPECT_EQ(Output[2].size(), 0ul); 2374 EXPECT_EQ(Output[3].size(), 0ul); 2375 VLocs[2].Vars.clear(); 2376 ClearOutputs(); 2377 2378 VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2379 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2380 OutLocsPtr, InLocsPtr, VLocs); 2381 EXPECT_EQ(Output[0].size(), 0ul); 2382 EXPECT_EQ(Output[1].size(), 0ul); 2383 EXPECT_EQ(Output[2].size(), 0ul); 2384 EXPECT_EQ(Output[3].size(), 0ul); 2385 VLocs[1].Vars.clear(); 2386 ClearOutputs(); 2387 2388 // However: putting an assignment in the first block should propagate variable 2389 // values through to all other blocks, as it dominates. 2390 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2391 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2392 OutLocsPtr, InLocsPtr, VLocs); 2393 EXPECT_EQ(Output[0].size(), 0ul); 2394 ASSERT_EQ(Output[1].size(), 1ul); 2395 ASSERT_EQ(Output[2].size(), 1ul); 2396 ASSERT_EQ(Output[3].size(), 1ul); 2397 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2398 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2399 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2400 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2401 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2402 EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); 2403 ClearOutputs(); 2404 VLocs[0].Vars.clear(); 2405 2406 // Additionally, even if that value isn't available in the register file, it 2407 // should still be propagated, as buildVLocValueMap shouldn't care about 2408 // what's in the registers (except for PHIs). 2409 // values through to all other blocks, as it dominates. 2410 VLocs[0].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2411 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2412 OutLocsPtr, InLocsPtr, VLocs); 2413 EXPECT_EQ(Output[0].size(), 0ul); 2414 ASSERT_EQ(Output[1].size(), 1ul); 2415 ASSERT_EQ(Output[2].size(), 1ul); 2416 ASSERT_EQ(Output[3].size(), 1ul); 2417 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2418 EXPECT_EQ(Output[1][0].second.ID, LiveInRax); 2419 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2420 EXPECT_EQ(Output[2][0].second.ID, LiveInRax); 2421 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2422 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 2423 ClearOutputs(); 2424 VLocs[0].Vars.clear(); 2425 2426 // We should get a live-in to the merging block, if there are two assigns of 2427 // the same value in either side of the diamond. 2428 VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2429 VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2430 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2431 OutLocsPtr, InLocsPtr, VLocs); 2432 EXPECT_EQ(Output[0].size(), 0ul); 2433 EXPECT_EQ(Output[1].size(), 0ul); 2434 EXPECT_EQ(Output[2].size(), 0ul); 2435 ASSERT_EQ(Output[3].size(), 1ul); 2436 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2437 EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); 2438 ClearOutputs(); 2439 VLocs[1].Vars.clear(); 2440 VLocs[2].Vars.clear(); 2441 2442 // If we assign a value in the entry block, then 'undef' on a branch, we 2443 // shouldn't have a live-in in the merge block. 2444 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2445 VLocs[1].Vars.insert({Var, DbgValue(EmptyProps, DbgValue::Undef)}); 2446 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2447 OutLocsPtr, InLocsPtr, VLocs); 2448 EXPECT_EQ(Output[0].size(), 0ul); 2449 ASSERT_EQ(Output[1].size(), 1ul); 2450 ASSERT_EQ(Output[2].size(), 1ul); 2451 EXPECT_EQ(Output[3].size(), 0ul); 2452 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2453 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2454 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2455 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2456 ClearOutputs(); 2457 VLocs[0].Vars.clear(); 2458 VLocs[1].Vars.clear(); 2459 2460 // Having different values joining into the merge block should mean we have 2461 // no live-in in that block. Block ones LiveInRax value doesn't appear as a 2462 // live-in anywhere, it's block internal. 2463 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2464 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2465 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2466 OutLocsPtr, InLocsPtr, VLocs); 2467 EXPECT_EQ(Output[0].size(), 0ul); 2468 ASSERT_EQ(Output[1].size(), 1ul); 2469 ASSERT_EQ(Output[2].size(), 1ul); 2470 EXPECT_EQ(Output[3].size(), 0ul); 2471 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2472 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2473 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2474 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2475 ClearOutputs(); 2476 VLocs[0].Vars.clear(); 2477 VLocs[1].Vars.clear(); 2478 2479 // But on the other hand, if there's a location in the register file where 2480 // those two values can be joined, do so. 2481 OutLocs[1][0] = LiveInRax; 2482 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2483 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2484 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2485 OutLocsPtr, InLocsPtr, VLocs); 2486 EXPECT_EQ(Output[0].size(), 0ul); 2487 ASSERT_EQ(Output[1].size(), 1ul); 2488 ASSERT_EQ(Output[2].size(), 1ul); 2489 ASSERT_EQ(Output[3].size(), 1ul); 2490 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2491 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2492 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2493 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2494 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2495 EXPECT_EQ(Output[3][0].second.ID, RspPHIInBlk3); 2496 ClearOutputs(); 2497 VLocs[0].Vars.clear(); 2498 VLocs[1].Vars.clear(); 2499 } 2500 2501 TEST_F(InstrRefLDVTest, VLocSimpleLoop) { 2502 setupSimpleLoop(); 2503 // entry 2504 // | 2505 // |/-----\ 2506 // loopblk | 2507 // |\-----/ 2508 // | 2509 // ret 2510 2511 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2512 LocIdx RspLoc(0); 2513 Register RAX = getRegByName("RAX"); 2514 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2515 2516 unsigned EntryBlk = 0, LoopBlk = 1; 2517 2518 ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc); 2519 ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc); 2520 ValueIDNum RspPHIInBlk1 = ValueIDNum(LoopBlk, 0, RspLoc); 2521 ValueIDNum RspDefInBlk1 = ValueIDNum(LoopBlk, 1, RspLoc); 2522 ValueIDNum RaxPHIInBlk1 = ValueIDNum(LoopBlk, 0, RaxLoc); 2523 2524 ValueIDNum InLocs[3][2], OutLocs[3][2]; 2525 ValueIDNum *InLocsPtr[3] = {InLocs[0], InLocs[1], InLocs[2]}; 2526 ValueIDNum *OutLocsPtr[3] = {OutLocs[0], OutLocs[1], OutLocs[2]}; 2527 2528 initValueArray(InLocsPtr, 3, 2); 2529 initValueArray(OutLocsPtr, 3, 2); 2530 2531 DebugVariable Var(FuncVariable, None, nullptr); 2532 DbgValueProperties EmptyProps(EmptyExpr, false); 2533 2534 SmallSet<DebugVariable, 4> AllVars; 2535 AllVars.insert(Var); 2536 2537 SmallPtrSet<MachineBasicBlock *, 4> AssignBlocks; 2538 AssignBlocks.insert(MBB0); 2539 AssignBlocks.insert(MBB1); 2540 AssignBlocks.insert(MBB2); 2541 2542 SmallVector<VLocTracker, 3> VLocs; 2543 VLocs.resize(3); 2544 2545 InstrRefBasedLDV::LiveInsT Output; 2546 2547 // Start off with LiveInRsp in every location. 2548 for (unsigned int I = 0; I < 3; ++I) { 2549 InLocs[I][0] = InLocs[I][1] = LiveInRsp; 2550 OutLocs[I][0] = OutLocs[I][1] = LiveInRsp; 2551 } 2552 2553 auto ClearOutputs = [&]() { 2554 for (auto &Elem : Output) 2555 Elem.clear(); 2556 }; 2557 Output.resize(3); 2558 2559 // Easy starter: a dominating assign should propagate to all blocks. 2560 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2561 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2562 OutLocsPtr, InLocsPtr, VLocs); 2563 EXPECT_EQ(Output[0].size(), 0ul); 2564 ASSERT_EQ(Output[1].size(), 1ul); 2565 ASSERT_EQ(Output[2].size(), 1ul); 2566 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2567 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2568 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2569 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2570 ClearOutputs(); 2571 VLocs[0].Vars.clear(); 2572 VLocs[1].Vars.clear(); 2573 2574 // Put an undef assignment in the loop. Should get no live-in value. 2575 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2576 VLocs[1].Vars.insert({Var, DbgValue(EmptyProps, DbgValue::Undef)}); 2577 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2578 OutLocsPtr, InLocsPtr, VLocs); 2579 EXPECT_EQ(Output[0].size(), 0ul); 2580 EXPECT_EQ(Output[1].size(), 0ul); 2581 EXPECT_EQ(Output[2].size(), 0ul); 2582 ClearOutputs(); 2583 VLocs[0].Vars.clear(); 2584 VLocs[1].Vars.clear(); 2585 2586 // Assignment of the same value should naturally join. 2587 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2588 VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2589 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2590 OutLocsPtr, InLocsPtr, VLocs); 2591 EXPECT_EQ(Output[0].size(), 0ul); 2592 ASSERT_EQ(Output[1].size(), 1ul); 2593 ASSERT_EQ(Output[2].size(), 1ul); 2594 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2595 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2596 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2597 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2598 ClearOutputs(); 2599 VLocs[0].Vars.clear(); 2600 VLocs[1].Vars.clear(); 2601 2602 // Assignment of different values shouldn't join with no machine PHI vals. 2603 // Will be live-in to exit block as it's dominated. 2604 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2605 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2606 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2607 OutLocsPtr, InLocsPtr, VLocs); 2608 EXPECT_EQ(Output[0].size(), 0ul); 2609 EXPECT_EQ(Output[1].size(), 0ul); 2610 ASSERT_EQ(Output[2].size(), 1ul); 2611 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2612 EXPECT_EQ(Output[2][0].second.ID, LiveInRax); 2613 ClearOutputs(); 2614 VLocs[0].Vars.clear(); 2615 VLocs[1].Vars.clear(); 2616 2617 // Install a completely unrelated PHI value, that we should not join on. Try 2618 // with unrelated assign in loop block again. 2619 InLocs[1][0] = RspPHIInBlk1; 2620 OutLocs[1][0] = RspDefInBlk1; 2621 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2622 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2623 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2624 OutLocsPtr, InLocsPtr, VLocs); 2625 EXPECT_EQ(Output[0].size(), 0ul); 2626 EXPECT_EQ(Output[1].size(), 0ul); 2627 ASSERT_EQ(Output[2].size(), 1ul); 2628 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2629 EXPECT_EQ(Output[2][0].second.ID, LiveInRax); 2630 ClearOutputs(); 2631 VLocs[0].Vars.clear(); 2632 VLocs[1].Vars.clear(); 2633 2634 // Now, if we assign RspDefInBlk1 in the loop block, we should be able to 2635 // find the appropriate PHI. 2636 InLocs[1][0] = RspPHIInBlk1; 2637 OutLocs[1][0] = RspDefInBlk1; 2638 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2639 VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)}); 2640 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2641 OutLocsPtr, InLocsPtr, VLocs); 2642 EXPECT_EQ(Output[0].size(), 0ul); 2643 ASSERT_EQ(Output[1].size(), 1ul); 2644 ASSERT_EQ(Output[2].size(), 1ul); 2645 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2646 EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); 2647 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2648 EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1); 2649 ClearOutputs(); 2650 VLocs[0].Vars.clear(); 2651 VLocs[1].Vars.clear(); 2652 2653 // If the PHI happens in a different location, the live-in should happen 2654 // there. 2655 InLocs[1][0] = LiveInRsp; 2656 OutLocs[1][0] = LiveInRsp; 2657 InLocs[1][1] = RaxPHIInBlk1; 2658 OutLocs[1][1] = RspDefInBlk1; 2659 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2660 VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)}); 2661 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2662 OutLocsPtr, InLocsPtr, VLocs); 2663 EXPECT_EQ(Output[0].size(), 0ul); 2664 ASSERT_EQ(Output[1].size(), 1ul); 2665 ASSERT_EQ(Output[2].size(), 1ul); 2666 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2667 EXPECT_EQ(Output[1][0].second.ID, RaxPHIInBlk1); 2668 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2669 EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1); 2670 ClearOutputs(); 2671 VLocs[0].Vars.clear(); 2672 VLocs[1].Vars.clear(); 2673 2674 // The PHI happening in both places should be handled too. Exactly where 2675 // isn't important, but if the location picked changes, this test will let 2676 // you know. 2677 InLocs[1][0] = RaxPHIInBlk1; 2678 OutLocs[1][0] = RspDefInBlk1; 2679 InLocs[1][1] = RaxPHIInBlk1; 2680 OutLocs[1][1] = RspDefInBlk1; 2681 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2682 VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)}); 2683 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2684 OutLocsPtr, InLocsPtr, VLocs); 2685 EXPECT_EQ(Output[0].size(), 0ul); 2686 ASSERT_EQ(Output[1].size(), 1ul); 2687 ASSERT_EQ(Output[2].size(), 1ul); 2688 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2689 // Today, the first register is picked. 2690 EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); 2691 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2692 EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1); 2693 ClearOutputs(); 2694 VLocs[0].Vars.clear(); 2695 VLocs[1].Vars.clear(); 2696 2697 // If the loop block looked a bit like this: 2698 // %0 = PHI %1, %2 2699 // [...] 2700 // DBG_VALUE %0 2701 // Then with instr-ref it becomes: 2702 // DBG_PHI %0 2703 // [...] 2704 // DBG_INSTR_REF 2705 // And we would be feeding a machine PHI-value back around the loop. However: 2706 // this does not mean we can eliminate the variable value PHI and use the 2707 // variable value from the entry block: they are distinct values that must be 2708 // joined at some location by the control flow. 2709 // [This test input would never occur naturally, the machine-PHI would be 2710 // eliminated] 2711 InLocs[1][0] = RspPHIInBlk1; 2712 OutLocs[1][0] = RspPHIInBlk1; 2713 InLocs[1][1] = LiveInRax; 2714 OutLocs[1][1] = LiveInRax; 2715 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2716 VLocs[1].Vars.insert({Var, DbgValue(RspPHIInBlk1, EmptyProps, DbgValue::Def)}); 2717 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2718 OutLocsPtr, InLocsPtr, VLocs); 2719 EXPECT_EQ(Output[0].size(), 0ul); 2720 ASSERT_EQ(Output[1].size(), 1ul); 2721 ASSERT_EQ(Output[2].size(), 1ul); 2722 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2723 EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); 2724 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2725 EXPECT_EQ(Output[2][0].second.ID, RspPHIInBlk1); 2726 ClearOutputs(); 2727 VLocs[0].Vars.clear(); 2728 VLocs[1].Vars.clear(); 2729 2730 // Test that we can eliminate PHIs. A PHI will be placed at the loop head 2731 // because there's a def in in. 2732 InLocs[1][0] = LiveInRsp; 2733 OutLocs[1][0] = LiveInRsp; 2734 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2735 VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2736 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2737 OutLocsPtr, InLocsPtr, VLocs); 2738 EXPECT_EQ(Output[0].size(), 0ul); 2739 ASSERT_EQ(Output[1].size(), 1ul); 2740 ASSERT_EQ(Output[2].size(), 1ul); 2741 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2742 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2743 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2744 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2745 ClearOutputs(); 2746 VLocs[0].Vars.clear(); 2747 VLocs[1].Vars.clear(); 2748 } 2749 2750 // test phi elimination with the nested situation 2751 TEST_F(InstrRefLDVTest, VLocNestedLoop) { 2752 // entry 2753 // | 2754 // loop1 2755 // ^\ 2756 // | \ /-\ 2757 // | loop2 | 2758 // | / \-/ 2759 // ^ / 2760 // join 2761 // | 2762 // ret 2763 setupNestedLoops(); 2764 2765 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2766 LocIdx RspLoc(0); 2767 Register RAX = getRegByName("RAX"); 2768 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2769 2770 unsigned EntryBlk = 0, Loop1Blk = 1, Loop2Blk = 2; 2771 2772 ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc); 2773 ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc); 2774 ValueIDNum RspPHIInBlk1 = ValueIDNum(Loop1Blk, 0, RspLoc); 2775 ValueIDNum RspPHIInBlk2 = ValueIDNum(Loop2Blk, 0, RspLoc); 2776 ValueIDNum RspDefInBlk2 = ValueIDNum(Loop2Blk, 1, RspLoc); 2777 2778 ValueIDNum InLocs[5][2], OutLocs[5][2]; 2779 ValueIDNum *InLocsPtr[5] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3], InLocs[4]}; 2780 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], OutLocs[4]}; 2781 2782 initValueArray(InLocsPtr, 5, 2); 2783 initValueArray(OutLocsPtr, 5, 2); 2784 2785 DebugVariable Var(FuncVariable, None, nullptr); 2786 DbgValueProperties EmptyProps(EmptyExpr, false); 2787 2788 SmallSet<DebugVariable, 4> AllVars; 2789 AllVars.insert(Var); 2790 2791 SmallPtrSet<MachineBasicBlock *, 5> AssignBlocks; 2792 AssignBlocks.insert(MBB0); 2793 AssignBlocks.insert(MBB1); 2794 AssignBlocks.insert(MBB2); 2795 AssignBlocks.insert(MBB3); 2796 AssignBlocks.insert(MBB4); 2797 2798 SmallVector<VLocTracker, 5> VLocs; 2799 VLocs.resize(5); 2800 2801 InstrRefBasedLDV::LiveInsT Output; 2802 2803 // Start off with LiveInRsp in every location. 2804 for (unsigned int I = 0; I < 5; ++I) { 2805 InLocs[I][0] = InLocs[I][1] = LiveInRsp; 2806 OutLocs[I][0] = OutLocs[I][1] = LiveInRsp; 2807 } 2808 2809 auto ClearOutputs = [&]() { 2810 for (auto &Elem : Output) 2811 Elem.clear(); 2812 }; 2813 Output.resize(5); 2814 2815 // A dominating assign should propagate to all blocks. 2816 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2817 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2818 OutLocsPtr, InLocsPtr, VLocs); 2819 EXPECT_EQ(Output[0].size(), 0ul); 2820 ASSERT_EQ(Output[1].size(), 1ul); 2821 ASSERT_EQ(Output[2].size(), 1ul); 2822 ASSERT_EQ(Output[3].size(), 1ul); 2823 ASSERT_EQ(Output[4].size(), 1ul); 2824 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2825 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2826 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2827 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2828 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2829 EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); 2830 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 2831 EXPECT_EQ(Output[4][0].second.ID, LiveInRsp); 2832 ClearOutputs(); 2833 VLocs[0].Vars.clear(); 2834 2835 // Test that an assign in the inner loop causes unresolved PHIs at the heads 2836 // of both loops, and no output location. Dominated blocks do get values. 2837 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2838 VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2839 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2840 OutLocsPtr, InLocsPtr, VLocs); 2841 EXPECT_EQ(Output[0].size(), 0ul); 2842 EXPECT_EQ(Output[1].size(), 0ul); 2843 EXPECT_EQ(Output[2].size(), 0ul); 2844 ASSERT_EQ(Output[3].size(), 1ul); 2845 ASSERT_EQ(Output[4].size(), 1ul); 2846 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2847 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 2848 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 2849 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 2850 ClearOutputs(); 2851 VLocs[0].Vars.clear(); 2852 VLocs[2].Vars.clear(); 2853 2854 // Same test, but with no assignment in block 0. We should still get values 2855 // in dominated blocks. 2856 VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2857 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2858 OutLocsPtr, InLocsPtr, VLocs); 2859 EXPECT_EQ(Output[0].size(), 0ul); 2860 EXPECT_EQ(Output[1].size(), 0ul); 2861 EXPECT_EQ(Output[2].size(), 0ul); 2862 ASSERT_EQ(Output[3].size(), 1ul); 2863 ASSERT_EQ(Output[4].size(), 1ul); 2864 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2865 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 2866 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 2867 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 2868 ClearOutputs(); 2869 VLocs[2].Vars.clear(); 2870 2871 // Similarly, assignments in the outer loop gives location to dominated 2872 // blocks, but no PHI locations are found at the outer loop head. 2873 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2874 VLocs[3].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2875 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2876 OutLocsPtr, InLocsPtr, VLocs); 2877 EXPECT_EQ(Output[0].size(), 0ul); 2878 EXPECT_EQ(Output[1].size(), 0ul); 2879 EXPECT_EQ(Output[2].size(), 0ul); 2880 EXPECT_EQ(Output[3].size(), 0ul); 2881 ASSERT_EQ(Output[4].size(), 1ul); 2882 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 2883 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 2884 ClearOutputs(); 2885 VLocs[0].Vars.clear(); 2886 VLocs[3].Vars.clear(); 2887 2888 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2889 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2890 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2891 OutLocsPtr, InLocsPtr, VLocs); 2892 EXPECT_EQ(Output[0].size(), 0ul); 2893 EXPECT_EQ(Output[1].size(), 0ul); 2894 ASSERT_EQ(Output[2].size(), 1ul); 2895 ASSERT_EQ(Output[3].size(), 1ul); 2896 ASSERT_EQ(Output[4].size(), 1ul); 2897 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2898 EXPECT_EQ(Output[2][0].second.ID, LiveInRax); 2899 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2900 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 2901 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 2902 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 2903 ClearOutputs(); 2904 VLocs[0].Vars.clear(); 2905 VLocs[1].Vars.clear(); 2906 2907 // With an assignment of the same value in the inner loop, we should work out 2908 // that all PHIs can be eliminated and the same value is live-through the 2909 // whole function. 2910 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2911 VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2912 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2913 OutLocsPtr, InLocsPtr, VLocs); 2914 EXPECT_EQ(Output[0].size(), 0ul); 2915 EXPECT_EQ(Output[1].size(), 1ul); 2916 EXPECT_EQ(Output[2].size(), 1ul); 2917 ASSERT_EQ(Output[3].size(), 1ul); 2918 ASSERT_EQ(Output[4].size(), 1ul); 2919 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2920 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2921 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2922 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2923 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2924 EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); 2925 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 2926 EXPECT_EQ(Output[4][0].second.ID, LiveInRsp); 2927 ClearOutputs(); 2928 VLocs[0].Vars.clear(); 2929 VLocs[2].Vars.clear(); 2930 2931 // If we have an assignment in the inner loop, and a PHI for it at the inner 2932 // loop head, we could find a live-in location for the inner loop. But because 2933 // the outer loop has no PHI, we can't find a variable value for outer loop 2934 // head, so can't have a live-in value for the inner loop head. 2935 InLocs[2][0] = RspPHIInBlk2; 2936 OutLocs[2][0] = LiveInRax; 2937 // NB: all other machine locations are LiveInRsp, disallowing a PHI in block 2938 // one. Even though RspPHIInBlk2 isn't available later in the function, we 2939 // should still produce a live-in value. The fact it's unavailable is a 2940 // different concern. 2941 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2942 VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2943 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2944 OutLocsPtr, InLocsPtr, VLocs); 2945 EXPECT_EQ(Output[0].size(), 0ul); 2946 EXPECT_EQ(Output[1].size(), 0ul); 2947 EXPECT_EQ(Output[2].size(), 0ul); 2948 ASSERT_EQ(Output[3].size(), 1ul); 2949 ASSERT_EQ(Output[4].size(), 1ul); 2950 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2951 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 2952 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 2953 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 2954 ClearOutputs(); 2955 VLocs[0].Vars.clear(); 2956 VLocs[2].Vars.clear(); 2957 2958 // Have an assignment in inner loop that can have a PHI resolved; and add a 2959 // machine value PHI to the outer loop head, so that we can find a location 2960 // all the way through the function. 2961 InLocs[1][0] = RspPHIInBlk1; 2962 OutLocs[1][0] = RspPHIInBlk1; 2963 InLocs[2][0] = RspPHIInBlk2; 2964 OutLocs[2][0] = RspDefInBlk2; 2965 InLocs[3][0] = RspDefInBlk2; 2966 OutLocs[3][0] = RspDefInBlk2; 2967 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2968 VLocs[2].Vars.insert({Var, DbgValue(RspDefInBlk2, EmptyProps, DbgValue::Def)}); 2969 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2970 OutLocsPtr, InLocsPtr, VLocs); 2971 EXPECT_EQ(Output[0].size(), 0ul); 2972 ASSERT_EQ(Output[1].size(), 1ul); 2973 ASSERT_EQ(Output[2].size(), 1ul); 2974 ASSERT_EQ(Output[3].size(), 1ul); 2975 ASSERT_EQ(Output[4].size(), 1ul); 2976 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2977 EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); 2978 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2979 EXPECT_EQ(Output[2][0].second.ID, RspPHIInBlk2); 2980 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2981 EXPECT_EQ(Output[3][0].second.ID, RspDefInBlk2); 2982 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 2983 EXPECT_EQ(Output[4][0].second.ID, RspDefInBlk2); 2984 ClearOutputs(); 2985 VLocs[0].Vars.clear(); 2986 VLocs[2].Vars.clear(); 2987 } 2988 2989