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 SpillLocationNo SpillNo = MTracker->getOrTrackSpillLoc(L); 639 unsigned SpillLocID = MTracker->getLocID(SpillNo, {64, 0}); 640 LocIdx SpillLoc = MTracker->getSpillMLoc(SpillLocID); 641 ValueIDNum V = MTracker->readMLoc(SpillLoc); 642 Register RAX = getRegByName("RAX"); 643 LocIdx RaxLoc = MTracker->getRegMLoc(RAX); 644 ValueIDNum Cmp(0, 1, RaxLoc); 645 EXPECT_EQ(V, Cmp); 646 647 // A spill and restore should be recognised. 648 MF = readMIRBlock( 649 " $rax = MOV64ri 0\n" 650 " MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n" 651 " $rbx = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)\n" 652 " RETQ\n"); 653 setupLDVObj(MF); 654 TransferMap.clear(); 655 TransferMap.resize(1); 656 produceMLocTransferFunction(*MF, TransferMap, 1); 657 658 // Test that rbx contains rax from instruction 1. 659 RAX = getRegByName("RAX"); 660 RaxLoc = MTracker->getRegMLoc(RAX); 661 Register RBX = getRegByName("RBX"); 662 LocIdx RbxLoc = MTracker->getRegMLoc(RBX); 663 Cmp = ValueIDNum(0, 1, RaxLoc); 664 ValueIDNum RbxVal = MTracker->readMLoc(RbxLoc); 665 EXPECT_EQ(RbxVal, Cmp); 666 667 // Testing that all the subregisters are transferred happens in 668 // MTransferSubregSpills. 669 670 // Copies and x86 movs should be recognised and honoured. In addition, all 671 // of the subregisters should be copied across too. 672 MF = readMIRBlock( 673 " $rax = MOV64ri 0\n" 674 " $rcx = COPY $rax\n" 675 " $rbx = MOV64rr $rcx\n" 676 " RETQ\n"); 677 setupLDVObj(MF); 678 TransferMap.clear(); 679 TransferMap.resize(1); 680 produceMLocTransferFunction(*MF, TransferMap, 1); 681 682 const char *ARegs[] = {"AL", "AH", "AX", "EAX", "HAX", "RAX"}; 683 const char *BRegs[] = {"BL", "BH", "BX", "EBX", "HBX", "RBX"}; 684 const char *CRegs[] = {"CL", "CH", "CX", "ECX", "HCX", "RCX"}; 685 auto CheckReg = [&](unsigned int I) { 686 LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I])); 687 LocIdx B = MTracker->getRegMLoc(getRegByName(BRegs[I])); 688 LocIdx C = MTracker->getRegMLoc(getRegByName(CRegs[I])); 689 ValueIDNum ARefVal(0, 1, A); 690 ValueIDNum AVal = MTracker->readMLoc(A); 691 ValueIDNum BVal = MTracker->readMLoc(B); 692 ValueIDNum CVal = MTracker->readMLoc(C); 693 EXPECT_EQ(ARefVal, AVal); 694 EXPECT_EQ(ARefVal, BVal); 695 EXPECT_EQ(ARefVal, CVal); 696 }; 697 698 for (unsigned int I = 0; I < 6; ++I) 699 CheckReg(I); 700 701 // When we copy to a subregister, the super-register should be def'd too: it's 702 // value will have changed. 703 MF = readMIRBlock( 704 " $rax = MOV64ri 0\n" 705 " $ecx = COPY $eax\n" 706 " RETQ\n"); 707 setupLDVObj(MF); 708 TransferMap.clear(); 709 TransferMap.resize(1); 710 produceMLocTransferFunction(*MF, TransferMap, 1); 711 712 // First four regs [al, ah, ax, eax] should be copied to *cx. 713 for (unsigned int I = 0; I < 4; ++I) { 714 LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I])); 715 LocIdx C = MTracker->getRegMLoc(getRegByName(CRegs[I])); 716 ValueIDNum ARefVal(0, 1, A); 717 ValueIDNum AVal = MTracker->readMLoc(A); 718 ValueIDNum CVal = MTracker->readMLoc(C); 719 EXPECT_EQ(ARefVal, AVal); 720 EXPECT_EQ(ARefVal, CVal); 721 } 722 723 // But rcx should contain a value defined by the COPY. 724 LocIdx RcxLoc = MTracker->getRegMLoc(getRegByName("RCX")); 725 ValueIDNum RcxVal = MTracker->readMLoc(RcxLoc); 726 ValueIDNum RcxDefVal(0, 2, RcxLoc); // instr 2 -> the copy 727 EXPECT_EQ(RcxVal, RcxDefVal); 728 } 729 730 TEST_F(InstrRefLDVTest, MTransferSubregSpills) { 731 SmallVector<MLocTransferMap, 1> TransferMap; 732 MachineFunction *MF = readMIRBlock( 733 " $rax = MOV64ri 0\n" 734 " MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n" 735 " $rbx = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)\n" 736 " RETQ\n"); 737 setupLDVObj(MF); 738 TransferMap.clear(); 739 TransferMap.resize(1); 740 produceMLocTransferFunction(*MF, TransferMap, 1); 741 742 // Check that all the subregs of rax and rbx contain the same values. One 743 // should completely transfer to the other. 744 const char *ARegs[] = {"AL", "AH", "AX", "EAX", "HAX", "RAX"}; 745 const char *BRegs[] = {"BL", "BH", "BX", "EBX", "HBX", "RBX"}; 746 for (unsigned int I = 0; I < 6; ++I) { 747 LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I])); 748 LocIdx B = MTracker->getRegMLoc(getRegByName(BRegs[I])); 749 EXPECT_EQ(MTracker->readMLoc(A), MTracker->readMLoc(B)); 750 } 751 752 // Explicitly check what's in the different subreg slots, on the stack. 753 // Pair up subreg idx fields with the corresponding subregister in $rax. 754 MLocTracker::StackSlotPos SubRegIdxes[] = {{8, 0}, {8, 8}, {16, 0}, {32, 0}, {64, 0}}; 755 const char *SubRegNames[] = {"AL", "AH", "AX", "EAX", "RAX"}; 756 for (unsigned int I = 0; I < 5; ++I) { 757 // Value number where it's defined, 758 LocIdx RegLoc = MTracker->getRegMLoc(getRegByName(SubRegNames[I])); 759 ValueIDNum DefNum(0, 1, RegLoc); 760 // Read the corresponding subreg field from the stack. 761 SpillLoc L = {getRegByName("RSP"), StackOffset::getFixed(-8)}; 762 SpillLocationNo SpillNo = MTracker->getOrTrackSpillLoc(L); 763 unsigned SpillID = MTracker->getLocID(SpillNo, SubRegIdxes[I]); 764 LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID); 765 ValueIDNum SpillValue = MTracker->readMLoc(SpillLoc); 766 EXPECT_EQ(DefNum, SpillValue); 767 } 768 769 // If we have exactly the same code, but we write $eax to the stack slot after 770 // $rax, then we should still have exactly the same output in the lower five 771 // subregisters. Storing $eax to the start of the slot will overwrite with the 772 // same values. $rax, as an aliasing register, should be reset to something 773 // else by that write. 774 // In theory, we could try and recognise that we're writing the _same_ values 775 // to the stack again, and so $rax doesn't need to be reset to something else. 776 // It seems vanishingly unlikely that LLVM would generate such code though, 777 // so the benefits would be small. 778 MF = readMIRBlock( 779 " $rax = MOV64ri 0\n" 780 " MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n" 781 " MOV32mr $rsp, 1, $noreg, 16, $noreg, $eax :: (store 4 into %stack.0)\n" 782 " $rbx = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)\n" 783 " RETQ\n"); 784 setupLDVObj(MF); 785 TransferMap.clear(); 786 TransferMap.resize(1); 787 produceMLocTransferFunction(*MF, TransferMap, 1); 788 789 // Check lower five registers up to and include $eax == $ebx, 790 for (unsigned int I = 0; I < 5; ++I) { 791 LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I])); 792 LocIdx B = MTracker->getRegMLoc(getRegByName(BRegs[I])); 793 EXPECT_EQ(MTracker->readMLoc(A), MTracker->readMLoc(B)); 794 } 795 796 // $rbx should contain something else; today it's a def at the spill point 797 // of the 4 byte value. 798 SpillLoc L = {getRegByName("RSP"), StackOffset::getFixed(-8)}; 799 SpillLocationNo SpillNo = MTracker->getOrTrackSpillLoc(L); 800 unsigned SpillID = MTracker->getLocID(SpillNo, {64, 0}); 801 LocIdx Spill64Loc = MTracker->getSpillMLoc(SpillID); 802 ValueIDNum DefAtSpill64(0, 3, Spill64Loc); 803 LocIdx RbxLoc = MTracker->getRegMLoc(getRegByName("RBX")); 804 EXPECT_EQ(MTracker->readMLoc(RbxLoc), DefAtSpill64); 805 806 // Same again, test that the lower four subreg slots on the stack are the 807 // value defined by $rax in instruction 1. 808 for (unsigned int I = 0; I < 4; ++I) { 809 // Value number where it's defined, 810 LocIdx RegLoc = MTracker->getRegMLoc(getRegByName(SubRegNames[I])); 811 ValueIDNum DefNum(0, 1, RegLoc); 812 // Read the corresponding subreg field from the stack. 813 SpillNo = MTracker->getOrTrackSpillLoc(L); 814 SpillID = MTracker->getLocID(SpillNo, SubRegIdxes[I]); 815 LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID); 816 ValueIDNum SpillValue = MTracker->readMLoc(SpillLoc); 817 EXPECT_EQ(DefNum, SpillValue); 818 } 819 820 // Stack slot for $rax should be a different value, today it's EmptyValue. 821 ValueIDNum SpillValue = MTracker->readMLoc(Spill64Loc); 822 EXPECT_EQ(SpillValue, DefAtSpill64); 823 824 // If we write something to the stack, then over-write with some register 825 // from a completely different hierarchy, none of the "old" values should be 826 // readable. 827 // NB: slight hack, store 16 in to a 8 byte stack slot. 828 MF = readMIRBlock( 829 " $rax = MOV64ri 0\n" 830 " MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n" 831 " $xmm0 = IMPLICIT_DEF\n" 832 " MOVUPDmr $rsp, 1, $noreg, 16, $noreg, killed $xmm0 :: (store (s128) into %stack.0)\n" 833 " $rbx = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)\n" 834 " RETQ\n"); 835 setupLDVObj(MF); 836 TransferMap.clear(); 837 TransferMap.resize(1); 838 produceMLocTransferFunction(*MF, TransferMap, 1); 839 840 for (unsigned int I = 0; I < 5; ++I) { 841 // Read subreg fields from the stack. 842 SpillLocationNo SpillNo = MTracker->getOrTrackSpillLoc(L); 843 unsigned SpillID = MTracker->getLocID(SpillNo, SubRegIdxes[I]); 844 LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID); 845 ValueIDNum SpillValue = MTracker->readMLoc(SpillLoc); 846 847 // Value should be defined by the spill-to-xmm0 instr, get value of a def 848 // at the point of the spill. 849 ValueIDNum SpillDef(0, 4, SpillLoc); 850 EXPECT_EQ(SpillValue, SpillDef); 851 } 852 853 // Read xmm0's position and ensure it has a value. Should be the live-in 854 // value to the block, as IMPLICIT_DEF isn't a real def. 855 SpillNo = MTracker->getOrTrackSpillLoc(L); 856 SpillID = MTracker->getLocID(SpillNo, {128, 0}); 857 LocIdx Spill128Loc = MTracker->getSpillMLoc(SpillID); 858 SpillValue = MTracker->readMLoc(Spill128Loc); 859 Register XMM0 = getRegByName("XMM0"); 860 LocIdx Xmm0Loc = MTracker->getRegMLoc(XMM0); 861 EXPECT_EQ(ValueIDNum(0, 0, Xmm0Loc), SpillValue); 862 863 // What happens if we spill ah to the stack, then load al? It should find 864 // the same value. 865 MF = readMIRBlock( 866 " $rax = MOV64ri 0\n" 867 " MOV8mr $rsp, 1, $noreg, 16, $noreg, $ah :: (store 1 into %stack.0)\n" 868 " $al = MOV8rm $rsp, 1, $noreg, 0, $noreg :: (load 1 from %stack.0)\n" 869 " RETQ\n"); 870 setupLDVObj(MF); 871 TransferMap.clear(); 872 TransferMap.resize(1); 873 produceMLocTransferFunction(*MF, TransferMap, 1); 874 875 Register AL = getRegByName("AL"); 876 Register AH = getRegByName("AH"); 877 LocIdx AlLoc = MTracker->getRegMLoc(AL); 878 LocIdx AhLoc = MTracker->getRegMLoc(AH); 879 ValueIDNum AHDef(0, 1, AhLoc); 880 ValueIDNum ALValue = MTracker->readMLoc(AlLoc); 881 EXPECT_EQ(ALValue, AHDef); 882 } 883 884 TEST_F(InstrRefLDVTest, MLocSingleBlock) { 885 // Test some very simple properties about interpreting the transfer function. 886 setupSingleBlock(); 887 888 // We should start with a single location, the stack pointer. 889 ASSERT_TRUE(MTracker->getNumLocs() == 1); 890 LocIdx RspLoc(0); 891 892 // Set up live-in and live-out tables for this function: two locations (we 893 // add one later) in a single block. 894 ValueIDNum InLocs[2], OutLocs[2]; 895 ValueIDNum *InLocsPtr[1] = {&InLocs[0]}; 896 ValueIDNum *OutLocsPtr[1] = {&OutLocs[0]}; 897 898 // Transfer function: nothing. 899 SmallVector<MLocTransferMap, 1> TransferFunc = {{}}; 900 901 // Try and build value maps... 902 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 903 904 // The result should be that RSP is marked as a live-in-PHI -- this represents 905 // an argument. And as there's no transfer function, the block live-out should 906 // be the same. 907 EXPECT_EQ(InLocs[0], ValueIDNum(0, 0, RspLoc)); 908 EXPECT_EQ(OutLocs[0], ValueIDNum(0, 0, RspLoc)); 909 910 // Try again, this time initialising the in-locs to be defined by an 911 // instruction. The entry block should always be re-assigned to be the 912 // arguments. 913 initValueArray(InLocsPtr, 1, 2); 914 initValueArray(OutLocsPtr, 1, 2); 915 InLocs[0] = ValueIDNum(0, 1, RspLoc); 916 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 917 EXPECT_EQ(InLocs[0], ValueIDNum(0, 0, RspLoc)); 918 EXPECT_EQ(OutLocs[0], ValueIDNum(0, 0, RspLoc)); 919 920 // Now insert something into the transfer function to assign to the single 921 // machine location. 922 TransferFunc[0].insert({RspLoc, ValueIDNum(0, 1, RspLoc)}); 923 initValueArray(InLocsPtr, 1, 2); 924 initValueArray(OutLocsPtr, 1, 2); 925 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 926 EXPECT_EQ(InLocs[0], ValueIDNum(0, 0, RspLoc)); 927 EXPECT_EQ(OutLocs[0], ValueIDNum(0, 1, RspLoc)); 928 TransferFunc[0].clear(); 929 930 // Add a new register to be tracked, and insert it into the transfer function 931 // as a copy. The output of $rax should be the live-in value of $rsp. 932 Register RAX = getRegByName("RAX"); 933 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 934 TransferFunc[0].insert({RspLoc, ValueIDNum(0, 1, RspLoc)}); 935 TransferFunc[0].insert({RaxLoc, ValueIDNum(0, 0, RspLoc)}); 936 initValueArray(InLocsPtr, 1, 2); 937 initValueArray(OutLocsPtr, 1, 2); 938 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 939 EXPECT_EQ(InLocs[0], ValueIDNum(0, 0, RspLoc)); 940 EXPECT_EQ(InLocs[1], ValueIDNum(0, 0, RaxLoc)); 941 EXPECT_EQ(OutLocs[0], ValueIDNum(0, 1, RspLoc)); 942 EXPECT_EQ(OutLocs[1], ValueIDNum(0, 0, RspLoc)); // Rax contains RspLoc. 943 TransferFunc[0].clear(); 944 } 945 946 TEST_F(InstrRefLDVTest, MLocDiamondBlocks) { 947 // Test that information flows from the entry block to two successors. 948 // entry 949 // / \ 950 // br1 br2 951 // \ / 952 // ret 953 setupDiamondBlocks(); 954 955 ASSERT_TRUE(MTracker->getNumLocs() == 1); 956 LocIdx RspLoc(0); 957 Register RAX = getRegByName("RAX"); 958 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 959 960 ValueIDNum InLocs[4][2], OutLocs[4][2]; 961 ValueIDNum *InLocsPtr[4] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3]}; 962 ValueIDNum *OutLocsPtr[4] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3]}; 963 964 // Transfer function: start with nothing. 965 SmallVector<MLocTransferMap, 1> TransferFunc; 966 TransferFunc.resize(4); 967 968 // Name some values. 969 unsigned EntryBlk = 0, BrBlk1 = 1, BrBlk2 = 2, RetBlk = 3; 970 971 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 972 ValueIDNum RspDefInBlk0(EntryBlk, 1, RspLoc); 973 ValueIDNum RspDefInBlk1(BrBlk1, 1, RspLoc); 974 ValueIDNum RspDefInBlk2(BrBlk2, 1, RspLoc); 975 ValueIDNum RspPHIInBlk3(RetBlk, 0, RspLoc); 976 ValueIDNum RaxLiveInBlk1(BrBlk1, 0, RaxLoc); 977 ValueIDNum RaxLiveInBlk2(BrBlk2, 0, RaxLoc); 978 979 // With no transfer function, the live-in values to the entry block should 980 // propagate to all live-outs and the live-ins to the two successor blocks. 981 // IN ADDITION: this checks that the exit block doesn't get a PHI put in it. 982 initValueArray(InLocsPtr, 4, 2); 983 initValueArray(OutLocsPtr, 4, 2); 984 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 985 EXPECT_EQ(InLocs[0][0], LiveInRsp); 986 EXPECT_EQ(InLocs[1][0], LiveInRsp); 987 EXPECT_EQ(InLocs[2][0], LiveInRsp); 988 EXPECT_EQ(InLocs[3][0], LiveInRsp); 989 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 990 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 991 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 992 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 993 // (Skipped writing out locations for $rax). 994 995 // Check that a def of $rsp in the entry block will likewise reach all the 996 // successors. 997 TransferFunc[0].insert({RspLoc, RspDefInBlk0}); 998 initValueArray(InLocsPtr, 4, 2); 999 initValueArray(OutLocsPtr, 4, 2); 1000 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1001 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1002 EXPECT_EQ(InLocs[1][0], RspDefInBlk0); 1003 EXPECT_EQ(InLocs[2][0], RspDefInBlk0); 1004 EXPECT_EQ(InLocs[3][0], RspDefInBlk0); 1005 EXPECT_EQ(OutLocs[0][0], RspDefInBlk0); 1006 EXPECT_EQ(OutLocs[1][0], RspDefInBlk0); 1007 EXPECT_EQ(OutLocs[2][0], RspDefInBlk0); 1008 EXPECT_EQ(OutLocs[3][0], RspDefInBlk0); 1009 TransferFunc[0].clear(); 1010 1011 // Def in one branch of the diamond means that we need a PHI in the ret block 1012 TransferFunc[0].insert({RspLoc, RspDefInBlk0}); 1013 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1014 initValueArray(InLocsPtr, 4, 2); 1015 initValueArray(OutLocsPtr, 4, 2); 1016 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1017 // This value map: like above, where RspDefInBlk0 is propagated through one 1018 // branch of the diamond, but is def'ed in the live-outs of the other. The 1019 // ret / merging block should have a PHI in its live-ins. 1020 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1021 EXPECT_EQ(InLocs[1][0], RspDefInBlk0); 1022 EXPECT_EQ(InLocs[2][0], RspDefInBlk0); 1023 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1024 EXPECT_EQ(OutLocs[0][0], RspDefInBlk0); 1025 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1026 EXPECT_EQ(OutLocs[2][0], RspDefInBlk0); 1027 EXPECT_EQ(OutLocs[3][0], RspPHIInBlk3); 1028 TransferFunc[0].clear(); 1029 TransferFunc[1].clear(); 1030 1031 // If we have differeing defs in either side of the diamond, we should 1032 // continue to produce a PHI, 1033 TransferFunc[0].insert({RspLoc, RspDefInBlk0}); 1034 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1035 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 1036 initValueArray(InLocsPtr, 4, 2); 1037 initValueArray(OutLocsPtr, 4, 2); 1038 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1039 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1040 EXPECT_EQ(InLocs[1][0], RspDefInBlk0); 1041 EXPECT_EQ(InLocs[2][0], RspDefInBlk0); 1042 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1043 EXPECT_EQ(OutLocs[0][0], RspDefInBlk0); 1044 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1045 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 1046 EXPECT_EQ(OutLocs[3][0], RspPHIInBlk3); 1047 TransferFunc[0].clear(); 1048 TransferFunc[1].clear(); 1049 TransferFunc[2].clear(); 1050 1051 // If we have defs of the same value on either side of the branch, a PHI will 1052 // initially be created, however value propagation should then eliminate it. 1053 // Encode this by copying the live-in value to $rax, and copying it to $rsp 1054 // from $rax in each branch of the diamond. We don't allow the definition of 1055 // arbitary values in transfer functions. 1056 TransferFunc[0].insert({RspLoc, RspDefInBlk0}); 1057 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 1058 TransferFunc[1].insert({RspLoc, RaxLiveInBlk1}); 1059 TransferFunc[2].insert({RspLoc, RaxLiveInBlk2}); 1060 initValueArray(InLocsPtr, 4, 2); 1061 initValueArray(OutLocsPtr, 4, 2); 1062 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1063 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1064 EXPECT_EQ(InLocs[1][0], RspDefInBlk0); 1065 EXPECT_EQ(InLocs[2][0], RspDefInBlk0); 1066 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1067 EXPECT_EQ(OutLocs[0][0], RspDefInBlk0); 1068 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1069 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1070 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1071 TransferFunc[0].clear(); 1072 TransferFunc[1].clear(); 1073 TransferFunc[2].clear(); 1074 } 1075 1076 TEST_F(InstrRefLDVTest, MLocSimpleLoop) { 1077 // entry 1078 // | 1079 // |/-----\ 1080 // loopblk | 1081 // |\-----/ 1082 // | 1083 // ret 1084 setupSimpleLoop(); 1085 1086 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1087 LocIdx RspLoc(0); 1088 Register RAX = getRegByName("RAX"); 1089 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1090 1091 ValueIDNum InLocs[3][2], OutLocs[3][2]; 1092 ValueIDNum *InLocsPtr[3] = {InLocs[0], InLocs[1], InLocs[2]}; 1093 ValueIDNum *OutLocsPtr[3] = {OutLocs[0], OutLocs[1], OutLocs[2]}; 1094 1095 SmallVector<MLocTransferMap, 1> TransferFunc; 1096 TransferFunc.resize(3); 1097 1098 // Name some values. 1099 unsigned EntryBlk = 0, LoopBlk = 1, RetBlk = 2; 1100 1101 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1102 ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc); 1103 ValueIDNum RspDefInBlk1(LoopBlk, 1, RspLoc); 1104 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1105 ValueIDNum RaxPHIInBlk1(LoopBlk, 0, RaxLoc); 1106 ValueIDNum RaxPHIInBlk2(RetBlk, 0, RaxLoc); 1107 1108 // Begin test with all locations being live-through. 1109 initValueArray(InLocsPtr, 3, 2); 1110 initValueArray(OutLocsPtr, 3, 2); 1111 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1112 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1113 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1114 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1115 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1116 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1117 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1118 1119 // Add a def of $rsp to the loop block: it should be in the live-outs, but 1120 // should cause a PHI to be placed in the live-ins. Test the transfer function 1121 // by copying that PHI into $rax in the loop, then back to $rsp in the ret 1122 // block. 1123 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1124 TransferFunc[1].insert({RaxLoc, RspPHIInBlk1}); 1125 TransferFunc[2].insert({RspLoc, RaxPHIInBlk2}); 1126 initValueArray(InLocsPtr, 3, 2); 1127 initValueArray(OutLocsPtr, 3, 2); 1128 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1129 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1130 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1131 EXPECT_EQ(InLocs[2][0], RspDefInBlk1); 1132 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1133 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1134 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk1); 1135 // Check rax as well, 1136 EXPECT_EQ(InLocs[0][1], LiveInRax); 1137 EXPECT_EQ(InLocs[1][1], RaxPHIInBlk1); 1138 EXPECT_EQ(InLocs[2][1], RspPHIInBlk1); 1139 EXPECT_EQ(OutLocs[0][1], LiveInRax); 1140 EXPECT_EQ(OutLocs[1][1], RspPHIInBlk1); 1141 EXPECT_EQ(OutLocs[2][1], RspPHIInBlk1); 1142 TransferFunc[1].clear(); 1143 TransferFunc[2].clear(); 1144 1145 // As with the diamond case, a PHI will be created if there's a (implicit) 1146 // def in the entry block and loop block; but should be value propagated away 1147 // if it copies in the same value. Copy live-in $rsp to $rax, then copy it 1148 // into $rsp in the loop. Encoded as copying the live-in $rax value in block 1 1149 // to $rsp. 1150 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 1151 TransferFunc[1].insert({RspLoc, RaxPHIInBlk1}); 1152 initValueArray(InLocsPtr, 3, 2); 1153 initValueArray(OutLocsPtr, 3, 2); 1154 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1155 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1156 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1157 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1158 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1159 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1160 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1161 // Check $rax's values. 1162 EXPECT_EQ(InLocs[0][1], LiveInRax); 1163 EXPECT_EQ(InLocs[1][1], LiveInRsp); 1164 EXPECT_EQ(InLocs[2][1], LiveInRsp); 1165 EXPECT_EQ(OutLocs[0][1], LiveInRsp); 1166 EXPECT_EQ(OutLocs[1][1], LiveInRsp); 1167 EXPECT_EQ(OutLocs[2][1], LiveInRsp); 1168 TransferFunc[0].clear(); 1169 TransferFunc[1].clear(); 1170 } 1171 1172 TEST_F(InstrRefLDVTest, MLocNestedLoop) { 1173 // entry 1174 // | 1175 // loop1 1176 // ^\ 1177 // | \ /-\ 1178 // | loop2 | 1179 // | / \-/ 1180 // ^ / 1181 // join 1182 // | 1183 // ret 1184 setupNestedLoops(); 1185 1186 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1187 LocIdx RspLoc(0); 1188 Register RAX = getRegByName("RAX"); 1189 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1190 1191 ValueIDNum InLocs[5][2], OutLocs[5][2]; 1192 ValueIDNum *InLocsPtr[5] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3], 1193 InLocs[4]}; 1194 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], 1195 OutLocs[4]}; 1196 1197 SmallVector<MLocTransferMap, 1> TransferFunc; 1198 TransferFunc.resize(5); 1199 1200 unsigned EntryBlk = 0, Loop1Blk = 1, Loop2Blk = 2, JoinBlk = 3; 1201 1202 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1203 ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc); 1204 ValueIDNum RspDefInBlk1(Loop1Blk, 1, RspLoc); 1205 ValueIDNum RspPHIInBlk2(Loop2Blk, 0, RspLoc); 1206 ValueIDNum RspDefInBlk2(Loop2Blk, 1, RspLoc); 1207 ValueIDNum RspDefInBlk3(JoinBlk, 1, RspLoc); 1208 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1209 ValueIDNum RaxPHIInBlk1(Loop1Blk, 0, RaxLoc); 1210 ValueIDNum RaxPHIInBlk2(Loop2Blk, 0, RaxLoc); 1211 1212 // Like the other tests: first ensure that if there's nothing in the transfer 1213 // function, then everything is live-through (check $rsp). 1214 initValueArray(InLocsPtr, 5, 2); 1215 initValueArray(OutLocsPtr, 5, 2); 1216 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1217 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1218 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1219 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1220 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1221 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1222 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1223 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1224 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1225 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1226 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1227 1228 // A def in the inner loop means we should get PHIs at the heads of both 1229 // loops. Live-outs of the last three blocks will be the def, as it dominates 1230 // those. 1231 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 1232 initValueArray(InLocsPtr, 5, 2); 1233 initValueArray(OutLocsPtr, 5, 2); 1234 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1235 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1236 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1237 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1238 EXPECT_EQ(InLocs[3][0], RspDefInBlk2); 1239 EXPECT_EQ(InLocs[4][0], RspDefInBlk2); 1240 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1241 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1242 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 1243 EXPECT_EQ(OutLocs[3][0], RspDefInBlk2); 1244 EXPECT_EQ(OutLocs[4][0], RspDefInBlk2); 1245 TransferFunc[2].clear(); 1246 1247 // Adding a def to the outer loop header shouldn't affect this much -- the 1248 // live-out of block 1 changes. 1249 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1250 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 1251 initValueArray(InLocsPtr, 5, 2); 1252 initValueArray(OutLocsPtr, 5, 2); 1253 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1254 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1255 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1256 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1257 EXPECT_EQ(InLocs[3][0], RspDefInBlk2); 1258 EXPECT_EQ(InLocs[4][0], RspDefInBlk2); 1259 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1260 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1261 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 1262 EXPECT_EQ(OutLocs[3][0], RspDefInBlk2); 1263 EXPECT_EQ(OutLocs[4][0], RspDefInBlk2); 1264 TransferFunc[1].clear(); 1265 TransferFunc[2].clear(); 1266 1267 // Likewise, putting a def in the outer loop tail shouldn't affect where 1268 // the PHIs go, and should propagate into the ret block. 1269 1270 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1271 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 1272 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1273 initValueArray(InLocsPtr, 5, 2); 1274 initValueArray(OutLocsPtr, 5, 2); 1275 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1276 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1277 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1278 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1279 EXPECT_EQ(InLocs[3][0], RspDefInBlk2); 1280 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1281 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1282 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1283 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 1284 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1285 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1286 TransferFunc[1].clear(); 1287 TransferFunc[2].clear(); 1288 TransferFunc[3].clear(); 1289 1290 // However: if we don't def in the inner-loop, then we just have defs in the 1291 // head and tail of the outer loop. The inner loop should be live-through. 1292 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1293 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1294 initValueArray(InLocsPtr, 5, 2); 1295 initValueArray(OutLocsPtr, 5, 2); 1296 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1297 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1298 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1299 EXPECT_EQ(InLocs[2][0], RspDefInBlk1); 1300 EXPECT_EQ(InLocs[3][0], RspDefInBlk1); 1301 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1302 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1303 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1304 EXPECT_EQ(OutLocs[2][0], RspDefInBlk1); 1305 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1306 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1307 TransferFunc[1].clear(); 1308 TransferFunc[3].clear(); 1309 1310 // Check that this still works if we copy RspDefInBlk1 to $rax and then 1311 // copy it back into $rsp in the inner loop. 1312 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1313 TransferFunc[1].insert({RaxLoc, RspDefInBlk1}); 1314 TransferFunc[2].insert({RspLoc, RaxPHIInBlk2}); 1315 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1316 initValueArray(InLocsPtr, 5, 2); 1317 initValueArray(OutLocsPtr, 5, 2); 1318 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1319 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1320 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1321 EXPECT_EQ(InLocs[2][0], RspDefInBlk1); 1322 EXPECT_EQ(InLocs[3][0], RspDefInBlk1); 1323 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1324 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1325 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1326 EXPECT_EQ(OutLocs[2][0], RspDefInBlk1); 1327 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1328 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1329 // Look at raxes value in the relevant blocks, 1330 EXPECT_EQ(InLocs[2][1], RspDefInBlk1); 1331 EXPECT_EQ(OutLocs[1][1], RspDefInBlk1); 1332 TransferFunc[1].clear(); 1333 TransferFunc[2].clear(); 1334 TransferFunc[3].clear(); 1335 1336 // If we have a single def in the tail of the outer loop, that should produce 1337 // a PHI at the loop head, and be live-through the inner loop. 1338 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1339 initValueArray(InLocsPtr, 5, 2); 1340 initValueArray(OutLocsPtr, 5, 2); 1341 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1342 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1343 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1344 EXPECT_EQ(InLocs[2][0], RspPHIInBlk1); 1345 EXPECT_EQ(InLocs[3][0], RspPHIInBlk1); 1346 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1347 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1348 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1349 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk1); 1350 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1351 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1352 TransferFunc[3].clear(); 1353 1354 // And if we copy from $rsp to $rax in block 2, it should resolve to the PHI 1355 // in block 1, and we should keep that value in rax until the ret block. 1356 // There'll be a PHI in block 1 and 2, because we're putting a def in the 1357 // inner loop. 1358 TransferFunc[2].insert({RaxLoc, RspPHIInBlk2}); 1359 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1360 initValueArray(InLocsPtr, 5, 2); 1361 initValueArray(OutLocsPtr, 5, 2); 1362 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1363 // Examining the values of rax, 1364 EXPECT_EQ(InLocs[0][1], LiveInRax); 1365 EXPECT_EQ(InLocs[1][1], RaxPHIInBlk1); 1366 EXPECT_EQ(InLocs[2][1], RaxPHIInBlk2); 1367 EXPECT_EQ(InLocs[3][1], RspPHIInBlk1); 1368 EXPECT_EQ(InLocs[4][1], RspPHIInBlk1); 1369 EXPECT_EQ(OutLocs[0][1], LiveInRax); 1370 EXPECT_EQ(OutLocs[1][1], RaxPHIInBlk1); 1371 EXPECT_EQ(OutLocs[2][1], RspPHIInBlk1); 1372 EXPECT_EQ(OutLocs[3][1], RspPHIInBlk1); 1373 EXPECT_EQ(OutLocs[4][1], RspPHIInBlk1); 1374 TransferFunc[2].clear(); 1375 TransferFunc[3].clear(); 1376 } 1377 1378 TEST_F(InstrRefLDVTest, MLocNoDominatingLoop) { 1379 // entry 1380 // / \ 1381 // / \ 1382 // / \ 1383 // head1 head2 1384 // ^ \ / ^ 1385 // ^ \ / ^ 1386 // \-joinblk -/ 1387 // | 1388 // ret 1389 setupNoDominatingLoop(); 1390 1391 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1392 LocIdx RspLoc(0); 1393 Register RAX = getRegByName("RAX"); 1394 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1395 1396 ValueIDNum InLocs[5][2], OutLocs[5][2]; 1397 ValueIDNum *InLocsPtr[5] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3], 1398 InLocs[4]}; 1399 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], 1400 OutLocs[4]}; 1401 1402 SmallVector<MLocTransferMap, 1> TransferFunc; 1403 TransferFunc.resize(5); 1404 1405 unsigned EntryBlk = 0, Head1Blk = 1, Head2Blk = 2, JoinBlk = 3; 1406 1407 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1408 ValueIDNum RspPHIInBlk1(Head1Blk, 0, RspLoc); 1409 ValueIDNum RspDefInBlk1(Head1Blk, 1, RspLoc); 1410 ValueIDNum RspPHIInBlk2(Head2Blk, 0, RspLoc); 1411 ValueIDNum RspDefInBlk2(Head2Blk, 1, RspLoc); 1412 ValueIDNum RspPHIInBlk3(JoinBlk, 0, RspLoc); 1413 ValueIDNum RspDefInBlk3(JoinBlk, 1, RspLoc); 1414 ValueIDNum RaxPHIInBlk1(Head1Blk, 0, RaxLoc); 1415 ValueIDNum RaxPHIInBlk2(Head2Blk, 0, RaxLoc); 1416 1417 // As ever, test that everything is live-through if there are no defs. 1418 initValueArray(InLocsPtr, 5, 2); 1419 initValueArray(OutLocsPtr, 5, 2); 1420 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1421 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1422 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1423 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1424 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1425 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1426 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1427 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1428 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1429 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1430 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1431 1432 // Putting a def in the 'join' block will cause us to have two distinct 1433 // PHIs in each loop head, then on entry to the join block. 1434 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1435 initValueArray(InLocsPtr, 5, 2); 1436 initValueArray(OutLocsPtr, 5, 2); 1437 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1438 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1439 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1440 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1441 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1442 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1443 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1444 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1445 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk2); 1446 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1447 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1448 TransferFunc[3].clear(); 1449 1450 // We should get the same behaviour if we put the def in either of the 1451 // loop heads -- it should force the other head to be a PHI. 1452 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1453 initValueArray(InLocsPtr, 5, 2); 1454 initValueArray(OutLocsPtr, 5, 2); 1455 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1456 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1457 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1458 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1459 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1460 EXPECT_EQ(InLocs[4][0], RspPHIInBlk3); 1461 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1462 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1463 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk2); 1464 EXPECT_EQ(OutLocs[3][0], RspPHIInBlk3); 1465 EXPECT_EQ(OutLocs[4][0], RspPHIInBlk3); 1466 TransferFunc[1].clear(); 1467 1468 // Check symmetry, 1469 TransferFunc[2].insert({RspLoc, RspDefInBlk2}); 1470 initValueArray(InLocsPtr, 5, 2); 1471 initValueArray(OutLocsPtr, 5, 2); 1472 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1473 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1474 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1475 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1476 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1477 EXPECT_EQ(InLocs[4][0], RspPHIInBlk3); 1478 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1479 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1480 EXPECT_EQ(OutLocs[2][0], RspDefInBlk2); 1481 EXPECT_EQ(OutLocs[3][0], RspPHIInBlk3); 1482 EXPECT_EQ(OutLocs[4][0], RspPHIInBlk3); 1483 TransferFunc[2].clear(); 1484 1485 // Test some scenarios where there _shouldn't_ be any PHIs created at heads. 1486 // These are those PHIs are created, but value propagation eliminates them. 1487 // For example, lets copy rsp-livein to $rsp inside each loop head, so that 1488 // there's no need for a PHI in the join block. Put a def of $rsp in block 3 1489 // to force PHIs elsewhere. 1490 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 1491 TransferFunc[1].insert({RspLoc, RaxPHIInBlk1}); 1492 TransferFunc[2].insert({RspLoc, RaxPHIInBlk2}); 1493 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 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], LiveInRsp); 1501 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1502 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1503 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1504 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1505 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1506 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1507 TransferFunc[0].clear(); 1508 TransferFunc[1].clear(); 1509 TransferFunc[2].clear(); 1510 TransferFunc[3].clear(); 1511 1512 // In fact, if we eliminate the def in block 3, none of those PHIs are 1513 // necessary, as we're just repeatedly copying LiveInRsp into $rsp. They 1514 // should all be value propagated out. 1515 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 1516 TransferFunc[1].insert({RspLoc, RaxPHIInBlk1}); 1517 TransferFunc[2].insert({RspLoc, RaxPHIInBlk2}); 1518 initValueArray(InLocsPtr, 5, 2); 1519 initValueArray(OutLocsPtr, 5, 2); 1520 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1521 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1522 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1523 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1524 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1525 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1526 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1527 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1528 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1529 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1530 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1531 TransferFunc[0].clear(); 1532 TransferFunc[1].clear(); 1533 TransferFunc[2].clear(); 1534 } 1535 1536 TEST_F(InstrRefLDVTest, MLocBadlyNestedLoops) { 1537 // entry 1538 // | 1539 // loop1 -o 1540 // | ^ 1541 // | ^ 1542 // loop2 -o 1543 // | ^ 1544 // | ^ 1545 // loop3 -o 1546 // | 1547 // ret 1548 setupBadlyNestedLoops(); 1549 1550 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1551 LocIdx RspLoc(0); 1552 Register RAX = getRegByName("RAX"); 1553 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1554 1555 ValueIDNum InLocs[5][2], OutLocs[5][2]; 1556 ValueIDNum *InLocsPtr[5] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3], 1557 InLocs[4]}; 1558 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], 1559 OutLocs[4]}; 1560 1561 SmallVector<MLocTransferMap, 1> TransferFunc; 1562 TransferFunc.resize(5); 1563 1564 unsigned EntryBlk = 0, Loop1Blk = 1, Loop2Blk = 2, Loop3Blk = 3; 1565 1566 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1567 ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc); 1568 ValueIDNum RspDefInBlk1(Loop1Blk, 1, RspLoc); 1569 ValueIDNum RspPHIInBlk2(Loop2Blk, 0, RspLoc); 1570 ValueIDNum RspPHIInBlk3(Loop3Blk, 0, RspLoc); 1571 ValueIDNum RspDefInBlk3(Loop3Blk, 1, RspLoc); 1572 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1573 ValueIDNum RaxPHIInBlk3(Loop3Blk, 0, RaxLoc); 1574 1575 // As ever, test that everything is live-through if there are no defs. 1576 initValueArray(InLocsPtr, 5, 2); 1577 initValueArray(OutLocsPtr, 5, 2); 1578 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1579 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1580 EXPECT_EQ(InLocs[1][0], LiveInRsp); 1581 EXPECT_EQ(InLocs[2][0], LiveInRsp); 1582 EXPECT_EQ(InLocs[3][0], LiveInRsp); 1583 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1584 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1585 EXPECT_EQ(OutLocs[1][0], LiveInRsp); 1586 EXPECT_EQ(OutLocs[2][0], LiveInRsp); 1587 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1588 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1589 1590 // A def in loop3 should cause PHIs in every loop block: they're all 1591 // reachable from each other. 1592 TransferFunc[3].insert({RspLoc, RspDefInBlk3}); 1593 initValueArray(InLocsPtr, 5, 2); 1594 initValueArray(OutLocsPtr, 5, 2); 1595 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1596 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1597 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1598 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1599 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1600 EXPECT_EQ(InLocs[4][0], RspDefInBlk3); 1601 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1602 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1603 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk2); 1604 EXPECT_EQ(OutLocs[3][0], RspDefInBlk3); 1605 EXPECT_EQ(OutLocs[4][0], RspDefInBlk3); 1606 TransferFunc[3].clear(); 1607 1608 // A def in loop1 should cause a PHI in loop1, but not the other blocks. 1609 // loop2 and loop3 are dominated by the def in loop1, so they should have 1610 // that value live-through. 1611 TransferFunc[1].insert({RspLoc, RspDefInBlk1}); 1612 initValueArray(InLocsPtr, 5, 2); 1613 initValueArray(OutLocsPtr, 5, 2); 1614 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1615 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1616 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1617 EXPECT_EQ(InLocs[2][0], RspDefInBlk1); 1618 EXPECT_EQ(InLocs[3][0], RspDefInBlk1); 1619 EXPECT_EQ(InLocs[4][0], RspDefInBlk1); 1620 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1621 EXPECT_EQ(OutLocs[1][0], RspDefInBlk1); 1622 EXPECT_EQ(OutLocs[2][0], RspDefInBlk1); 1623 EXPECT_EQ(OutLocs[3][0], RspDefInBlk1); 1624 EXPECT_EQ(OutLocs[4][0], RspDefInBlk1); 1625 TransferFunc[1].clear(); 1626 1627 // As with earlier tricks: copy $rsp to $rax in the entry block, then $rax 1628 // to $rsp in block 3. The only def of $rsp is simply copying the same value 1629 // back into itself, and the value of $rsp is LiveInRsp all the way through. 1630 // PHIs should be created, then value-propagated away... however this 1631 // doesn't work in practice. 1632 // Consider the entry to loop3: we can determine that there's an incoming 1633 // PHI value from loop2, and LiveInRsp from the self-loop. This would still 1634 // justify having a PHI on entry to loop3. The only way to completely 1635 // value-propagate these PHIs away would be to speculatively explore what 1636 // PHIs could be eliminated and what that would lead to; which is 1637 // combinatorially complex. 1638 // Happily: 1639 // a) In this scenario, we always have a tracked location for LiveInRsp 1640 // anyway, so there's no loss in availability, 1641 // b) Only DBG_PHIs of a register would be vunlerable to this scenario, and 1642 // even then only if a true PHI became a DBG_PHI and was then optimised 1643 // through branch folding to no longer be at a CFG join, 1644 // c) The register allocator can spot this kind of redundant COPY easily, 1645 // and eliminate it. 1646 // 1647 // This unit test left in as a reference for the limitations of this 1648 // approach. PHIs will be left in $rsp on entry to each block. 1649 TransferFunc[0].insert({RaxLoc, LiveInRsp}); 1650 TransferFunc[3].insert({RspLoc, RaxPHIInBlk3}); 1651 initValueArray(InLocsPtr, 5, 2); 1652 initValueArray(OutLocsPtr, 5, 2); 1653 buildMLocValueMap(InLocsPtr, OutLocsPtr, TransferFunc); 1654 EXPECT_EQ(InLocs[0][0], LiveInRsp); 1655 EXPECT_EQ(InLocs[1][0], RspPHIInBlk1); 1656 EXPECT_EQ(InLocs[2][0], RspPHIInBlk2); 1657 EXPECT_EQ(InLocs[3][0], RspPHIInBlk3); 1658 EXPECT_EQ(InLocs[4][0], LiveInRsp); 1659 EXPECT_EQ(OutLocs[0][0], LiveInRsp); 1660 EXPECT_EQ(OutLocs[1][0], RspPHIInBlk1); 1661 EXPECT_EQ(OutLocs[2][0], RspPHIInBlk2); 1662 EXPECT_EQ(OutLocs[3][0], LiveInRsp); 1663 EXPECT_EQ(OutLocs[4][0], LiveInRsp); 1664 // Check $rax's value. It should have $rsps value from the entry block 1665 // onwards. 1666 EXPECT_EQ(InLocs[0][1], LiveInRax); 1667 EXPECT_EQ(InLocs[1][1], LiveInRsp); 1668 EXPECT_EQ(InLocs[2][1], LiveInRsp); 1669 EXPECT_EQ(InLocs[3][1], LiveInRsp); 1670 EXPECT_EQ(InLocs[4][1], LiveInRsp); 1671 EXPECT_EQ(OutLocs[0][1], LiveInRsp); 1672 EXPECT_EQ(OutLocs[1][1], LiveInRsp); 1673 EXPECT_EQ(OutLocs[2][1], LiveInRsp); 1674 EXPECT_EQ(OutLocs[3][1], LiveInRsp); 1675 EXPECT_EQ(OutLocs[4][1], LiveInRsp); 1676 } 1677 1678 TEST_F(InstrRefLDVTest, pickVPHILocDiamond) { 1679 // entry 1680 // / \ 1681 // br1 br2 1682 // \ / 1683 // ret 1684 setupDiamondBlocks(); 1685 1686 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1687 LocIdx RspLoc(0); 1688 Register RAX = getRegByName("RAX"); 1689 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1690 1691 ValueIDNum OutLocs[4][2]; 1692 ValueIDNum *OutLocsPtr[4] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3]}; 1693 1694 initValueArray(OutLocsPtr, 4, 2); 1695 1696 unsigned EntryBlk = 0, Br2Blk = 2, RetBlk = 3; 1697 1698 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1699 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1700 ValueIDNum RspPHIInBlk2(Br2Blk, 0, RspLoc); 1701 ValueIDNum RspPHIInBlk3(RetBlk, 0, RspLoc); 1702 1703 DebugVariable Var(FuncVariable, None, nullptr); 1704 DbgValueProperties EmptyProps(EmptyExpr, false); 1705 SmallVector<DbgValue, 32> VLiveOuts; 1706 VLiveOuts.resize(4, DbgValue(EmptyProps, DbgValue::Undef)); 1707 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 1708 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 1709 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 1710 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 1711 VLiveOutIdx[MBB3] = &VLiveOuts[3]; 1712 1713 SmallVector<const MachineBasicBlock *, 2> Preds; 1714 for (const auto *Pred : MBB3->predecessors()) 1715 Preds.push_back(Pred); 1716 1717 // Specify the live-outs around the joining block. 1718 OutLocs[1][0] = LiveInRsp; 1719 OutLocs[2][0] = LiveInRax; 1720 1721 Optional<ValueIDNum> Result; 1722 1723 // Simple case: join two distinct values on entry to the block. 1724 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1725 VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 1726 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1727 // Should have picked a PHI in $rsp in block 3. 1728 EXPECT_TRUE(Result); 1729 if (Result) { 1730 EXPECT_EQ(*Result, RspPHIInBlk3); 1731 } 1732 1733 // If the incoming values are swapped between blocks, we should not 1734 // successfully join. The CFG merge would select the right values, but in 1735 // the wrong conditions. 1736 std::swap(VLiveOuts[1], VLiveOuts[2]); 1737 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1738 EXPECT_FALSE(Result); 1739 1740 // Swap back, 1741 std::swap(VLiveOuts[1], VLiveOuts[2]); 1742 // Setting one of these to being a constant should prohibit merging. 1743 VLiveOuts[1].Kind = DbgValue::Const; 1744 VLiveOuts[1].MO = MachineOperand::CreateImm(0); 1745 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1746 EXPECT_FALSE(Result); 1747 1748 // Seeing both to being a constant -> still prohibit, it shouldn't become 1749 // a value in the register file anywhere. 1750 VLiveOuts[2] = VLiveOuts[1]; 1751 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1752 EXPECT_FALSE(Result); 1753 1754 // NoVals shouldn't join with anything else. 1755 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1756 VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::NoVal); 1757 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1758 EXPECT_FALSE(Result); 1759 1760 // We might merge in another VPHI in such a join. Present pickVPHILoc with 1761 // such a scenario: first, where one incoming edge has a VPHI with no known 1762 // value. This represents an edge where there was a PHI value that can't be 1763 // found in the register file -- we can't subsequently find a PHI here. 1764 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1765 VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); 1766 EXPECT_EQ(VLiveOuts[2].ID, ValueIDNum::EmptyValue); 1767 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1768 EXPECT_FALSE(Result); 1769 1770 // However, if we know the value of the incoming VPHI, we can search for its 1771 // location. Use a PHI machine-value for doing this, as VPHIs should always 1772 // have PHI values, or they should have been eliminated. 1773 OutLocs[2][0] = RspPHIInBlk2; 1774 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1775 VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); 1776 VLiveOuts[2].ID = RspPHIInBlk2; // Set location where PHI happens. 1777 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1778 EXPECT_TRUE(Result); 1779 if (Result) { 1780 EXPECT_EQ(*Result, RspPHIInBlk3); 1781 } 1782 1783 // If that value isn't available from that block, don't join. 1784 OutLocs[2][0] = LiveInRsp; 1785 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1786 EXPECT_FALSE(Result); 1787 1788 // Check that we don't pick values when the properties disagree, for example 1789 // different indirectness or DIExpression. 1790 DIExpression *NewExpr = 1791 DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); 1792 DbgValueProperties PropsWithExpr(NewExpr, false); 1793 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1794 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithExpr, DbgValue::Def); 1795 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1796 EXPECT_FALSE(Result); 1797 1798 DbgValueProperties PropsWithIndirect(EmptyExpr, true); 1799 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1800 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def); 1801 Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, OutLocsPtr, Preds); 1802 EXPECT_FALSE(Result); 1803 } 1804 1805 TEST_F(InstrRefLDVTest, pickVPHILocLoops) { 1806 setupSimpleLoop(); 1807 // entry 1808 // | 1809 // |/-----\ 1810 // loopblk | 1811 // |\-----/ 1812 // | 1813 // ret 1814 1815 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1816 LocIdx RspLoc(0); 1817 Register RAX = getRegByName("RAX"); 1818 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1819 1820 ValueIDNum OutLocs[3][2]; 1821 ValueIDNum *OutLocsPtr[4] = {OutLocs[0], OutLocs[1], OutLocs[2]}; 1822 1823 initValueArray(OutLocsPtr, 3, 2); 1824 1825 unsigned EntryBlk = 0, LoopBlk = 1; 1826 1827 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1828 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1829 ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc); 1830 ValueIDNum RaxPHIInBlk1(LoopBlk, 0, RaxLoc); 1831 1832 DebugVariable Var(FuncVariable, None, nullptr); 1833 DbgValueProperties EmptyProps(EmptyExpr, false); 1834 SmallVector<DbgValue, 32> VLiveOuts; 1835 VLiveOuts.resize(3, DbgValue(EmptyProps, DbgValue::Undef)); 1836 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 1837 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 1838 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 1839 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 1840 1841 SmallVector<const MachineBasicBlock *, 2> Preds; 1842 for (const auto *Pred : MBB1->predecessors()) 1843 Preds.push_back(Pred); 1844 1845 // Specify the live-outs around the joining block. 1846 OutLocs[0][0] = LiveInRsp; 1847 OutLocs[1][0] = LiveInRax; 1848 1849 Optional<ValueIDNum> Result; 1850 1851 // See that we can merge as normal on a backedge. 1852 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1853 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 1854 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1855 // Should have picked a PHI in $rsp in block 1. 1856 EXPECT_TRUE(Result); 1857 if (Result) { 1858 EXPECT_EQ(*Result, RspPHIInBlk1); 1859 } 1860 1861 // And that, if the desired values aren't available, we don't merge. 1862 OutLocs[1][0] = LiveInRsp; 1863 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1864 EXPECT_FALSE(Result); 1865 1866 // Test the backedge behaviour: PHIs that feed back into themselves can 1867 // carry this variables value. Feed in LiveInRsp in both $rsp and $rax 1868 // from the entry block, but only put an appropriate backedge PHI in $rax. 1869 // Only the $rax location can form the correct PHI. 1870 OutLocs[0][0] = LiveInRsp; 1871 OutLocs[0][1] = LiveInRsp; 1872 OutLocs[1][0] = RaxPHIInBlk1; 1873 OutLocs[1][1] = RaxPHIInBlk1; 1874 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1875 // Crucially, a VPHI originating in this block: 1876 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 1877 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1878 EXPECT_TRUE(Result); 1879 if (Result) { 1880 EXPECT_EQ(*Result, RaxPHIInBlk1); 1881 } 1882 1883 // Merging should not be permitted if there's a usable PHI on the backedge, 1884 // but it's in the wrong place. (Overwrite $rax). 1885 OutLocs[1][1] = LiveInRax; 1886 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1887 EXPECT_FALSE(Result); 1888 1889 // Additionally, if the VPHI coming back on the loop backedge isn't from 1890 // this block (block 1), we can't merge it. 1891 OutLocs[1][1] = RaxPHIInBlk1; 1892 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1893 VLiveOuts[1] = DbgValue(0, EmptyProps, DbgValue::VPHI); 1894 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1895 EXPECT_FALSE(Result); 1896 } 1897 1898 TEST_F(InstrRefLDVTest, pickVPHILocBadlyNestedLoops) { 1899 // Run some tests similar to pickVPHILocLoops, with more than one backedge, 1900 // and check that we merge correctly over many candidate locations. 1901 setupBadlyNestedLoops(); 1902 // entry 1903 // | 1904 // loop1 -o 1905 // | ^ 1906 // | ^ 1907 // loop2 -o 1908 // | ^ 1909 // | ^ 1910 // loop3 -o 1911 // | 1912 // ret 1913 ASSERT_TRUE(MTracker->getNumLocs() == 1); 1914 LocIdx RspLoc(0); 1915 Register RAX = getRegByName("RAX"); 1916 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 1917 Register RBX = getRegByName("RBX"); 1918 LocIdx RbxLoc = MTracker->lookupOrTrackRegister(RBX); 1919 1920 ValueIDNum OutLocs[5][3]; 1921 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], OutLocs[4]}; 1922 1923 initValueArray(OutLocsPtr, 5, 3); 1924 1925 unsigned EntryBlk = 0, Loop1Blk = 1; 1926 1927 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 1928 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 1929 ValueIDNum LiveInRbx(EntryBlk, 0, RbxLoc); 1930 ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc); 1931 ValueIDNum RaxPHIInBlk1(Loop1Blk, 0, RaxLoc); 1932 ValueIDNum RbxPHIInBlk1(Loop1Blk, 0, RbxLoc); 1933 1934 DebugVariable Var(FuncVariable, None, nullptr); 1935 DbgValueProperties EmptyProps(EmptyExpr, false); 1936 SmallVector<DbgValue, 32> VLiveOuts; 1937 VLiveOuts.resize(5, DbgValue(EmptyProps, DbgValue::Undef)); 1938 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 1939 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 1940 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 1941 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 1942 VLiveOutIdx[MBB3] = &VLiveOuts[3]; 1943 VLiveOutIdx[MBB4] = &VLiveOuts[4]; 1944 1945 // We're going to focus on block 1. 1946 SmallVector<const MachineBasicBlock *, 2> Preds; 1947 for (const auto *Pred : MBB1->predecessors()) 1948 Preds.push_back(Pred); 1949 1950 // Specify the live-outs around the joining block. Incoming edges from the 1951 // entry block, self, and loop2. 1952 OutLocs[0][0] = LiveInRsp; 1953 OutLocs[1][0] = LiveInRax; 1954 OutLocs[2][0] = LiveInRbx; 1955 1956 Optional<ValueIDNum> Result; 1957 1958 // See that we can merge as normal on a backedge. 1959 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1960 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 1961 VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def); 1962 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1963 // Should have picked a PHI in $rsp in block 1. 1964 EXPECT_TRUE(Result); 1965 if (Result) { 1966 EXPECT_EQ(*Result, RspPHIInBlk1); 1967 } 1968 1969 // Check too that permuting the live-out locations prevents merging 1970 OutLocs[0][0] = LiveInRax; 1971 OutLocs[1][0] = LiveInRbx; 1972 OutLocs[2][0] = LiveInRsp; 1973 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1974 EXPECT_FALSE(Result); 1975 1976 OutLocs[0][0] = LiveInRsp; 1977 OutLocs[1][0] = LiveInRax; 1978 OutLocs[2][0] = LiveInRbx; 1979 1980 // Feeding a PHI back on one backedge shouldn't merge (block 1 self backedge 1981 // wants LiveInRax). 1982 OutLocs[1][0] = RspPHIInBlk1; 1983 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1984 EXPECT_FALSE(Result); 1985 1986 // If the variables value on that edge is a VPHI feeding into itself, that's 1987 // fine. 1988 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 1989 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 1990 VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def); 1991 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 1992 EXPECT_TRUE(Result); 1993 if (Result) { 1994 EXPECT_EQ(*Result, RspPHIInBlk1); 1995 } 1996 1997 // Likewise: the other backedge being a VPHI from block 1 should be accepted. 1998 OutLocs[2][0] = RspPHIInBlk1; 1999 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2000 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2001 VLiveOuts[2] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2002 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 2003 EXPECT_TRUE(Result); 2004 if (Result) { 2005 EXPECT_EQ(*Result, RspPHIInBlk1); 2006 } 2007 2008 // Here's where it becomes tricky: we should not merge if there are two 2009 // _distinct_ backedge PHIs. We can't have a PHI that happens in both rsp 2010 // and rax for example. We can only pick one location as the live-in. 2011 OutLocs[2][0] = RaxPHIInBlk1; 2012 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 2013 EXPECT_FALSE(Result); 2014 2015 // The above test sources correct machine-PHI-value from two places. Now 2016 // try with one machine-PHI-value, but placed in two different locations 2017 // on the backedge. Again, we can't merge a location here, there's no 2018 // location that works on all paths. 2019 OutLocs[0][0] = LiveInRsp; 2020 OutLocs[1][0] = RspPHIInBlk1; 2021 OutLocs[2][0] = LiveInRsp; 2022 OutLocs[2][1] = RspPHIInBlk1; 2023 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 2024 EXPECT_FALSE(Result); 2025 2026 // Scatter various PHI values across the available locations. Only rbx (loc 2) 2027 // has the right value in both backedges -- that's the loc that should be 2028 // picked. 2029 OutLocs[0][2] = LiveInRsp; 2030 OutLocs[1][0] = RspPHIInBlk1; 2031 OutLocs[1][1] = RaxPHIInBlk1; 2032 OutLocs[1][2] = RbxPHIInBlk1; 2033 OutLocs[2][0] = LiveInRsp; 2034 OutLocs[2][1] = RspPHIInBlk1; 2035 OutLocs[2][2] = RbxPHIInBlk1; 2036 Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, OutLocsPtr, Preds); 2037 EXPECT_TRUE(Result); 2038 if (Result) { 2039 EXPECT_EQ(*Result, RbxPHIInBlk1); 2040 } 2041 } 2042 2043 TEST_F(InstrRefLDVTest, vlocJoinDiamond) { 2044 // entry 2045 // / \ 2046 // br1 br2 2047 // \ / 2048 // ret 2049 setupDiamondBlocks(); 2050 2051 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2052 LocIdx RspLoc(0); 2053 Register RAX = getRegByName("RAX"); 2054 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2055 2056 unsigned EntryBlk = 0, Br2Blk = 2, RetBlk = 3; 2057 2058 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 2059 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 2060 ValueIDNum RspPHIInBlkBr2Blk(Br2Blk, 0, RspLoc); 2061 ValueIDNum RspPHIInBlkRetBlk(RetBlk, 0, RspLoc); 2062 2063 DebugVariable Var(FuncVariable, None, nullptr); 2064 DbgValueProperties EmptyProps(EmptyExpr, false); 2065 SmallVector<DbgValue, 32> VLiveOuts; 2066 VLiveOuts.resize(4, DbgValue(EmptyProps, DbgValue::Undef)); 2067 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 2068 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 2069 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 2070 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 2071 VLiveOutIdx[MBB3] = &VLiveOuts[3]; 2072 2073 SmallPtrSet<const MachineBasicBlock *, 8> AllBlocks; 2074 AllBlocks.insert(MBB0); 2075 AllBlocks.insert(MBB1); 2076 AllBlocks.insert(MBB2); 2077 AllBlocks.insert(MBB3); 2078 2079 SmallVector<const MachineBasicBlock *, 2> Preds; 2080 for (const auto *Pred : MBB3->predecessors()) 2081 Preds.push_back(Pred); 2082 2083 SmallSet<DebugVariable, 4> AllVars; 2084 AllVars.insert(Var); 2085 2086 // vlocJoin is here to propagate incoming values, and eliminate PHIs. Start 2087 // off by propagating a value into the merging block, number 3. 2088 DbgValue JoinedLoc = DbgValue(3, EmptyProps, DbgValue::NoVal); 2089 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2090 VLiveOuts[2] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2091 bool Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2092 EXPECT_TRUE(Result); // Output locs should have changed. 2093 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2094 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2095 2096 // And if we did it a second time, leaving the live-ins as it was, then 2097 // we should report no change. 2098 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2099 EXPECT_FALSE(Result); 2100 2101 // If the live-in variable values are different, but there's no PHI placed 2102 // in this block, then just pick a location. It should be the first (in RPO) 2103 // predecessor to avoid being a backedge. 2104 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2105 VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2106 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::NoVal); 2107 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2108 EXPECT_TRUE(Result); 2109 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2110 // RPO is blocks 0 2 1 3, so LiveInRax is picked as the first predecessor 2111 // of this join. 2112 EXPECT_EQ(JoinedLoc.ID, LiveInRax); 2113 2114 // No tests for whether vlocJoin will pass-through a variable with differing 2115 // expressions / properties. Those can only come about due to assignments; and 2116 // for any assignment at all, a PHI should have been placed at the dominance 2117 // frontier. We rely on the IDF calculator being accurate (which is OK, 2118 // because so does the rest of LLVM). 2119 2120 // Try placing a PHI. With differing input values (LiveInRsp, LiveInRax), 2121 // this PHI should not be eliminated. 2122 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); 2123 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2124 // Expect no change. 2125 EXPECT_FALSE(Result); 2126 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2127 // This should not have been assigned a fixed value. 2128 EXPECT_EQ(JoinedLoc.ID, ValueIDNum::EmptyValue); 2129 EXPECT_EQ(JoinedLoc.BlockNo, 3); 2130 2131 // Try a simple PHI elimination. Put a PHI in block 3, but LiveInRsp on both 2132 // incoming edges. Re-load in and out-locs with unrelated values; they're 2133 // irrelevant. 2134 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2135 VLiveOuts[2] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2136 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); 2137 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2138 EXPECT_TRUE(Result); 2139 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2140 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2141 2142 // If the "current" live-in is a VPHI, but not a VPHI generated in the current 2143 // block, then it's the remains of an earlier value propagation. We should 2144 // value propagate through this merge. Even if the current incoming values 2145 // disagree, because we've previously determined any VPHI here is redundant. 2146 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2147 VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2148 JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI); 2149 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2150 EXPECT_TRUE(Result); 2151 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2152 EXPECT_EQ(JoinedLoc.ID, LiveInRax); // from block 2 2153 2154 // The above test, but test that we will install one value-propagated VPHI 2155 // over another. 2156 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2157 VLiveOuts[2] = DbgValue(0, EmptyProps, DbgValue::VPHI); 2158 JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI); 2159 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2160 EXPECT_TRUE(Result); 2161 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2162 EXPECT_EQ(JoinedLoc.BlockNo, 0); 2163 2164 // We shouldn't eliminate PHIs when properties disagree. 2165 DbgValueProperties PropsWithIndirect(EmptyExpr, true); 2166 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2167 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def); 2168 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); 2169 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2170 EXPECT_FALSE(Result); 2171 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2172 EXPECT_EQ(JoinedLoc.BlockNo, 3); 2173 2174 // Even if properties disagree, we should still value-propagate if there's no 2175 // PHI to be eliminated. The disagreeing values should work themselves out, 2176 // seeing how we've determined no PHI is necessary. 2177 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2178 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def); 2179 JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI); 2180 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2181 EXPECT_TRUE(Result); 2182 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2183 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2184 // Also check properties come from block 2, the first RPO predecessor to block 2185 // three. 2186 EXPECT_EQ(JoinedLoc.Properties, PropsWithIndirect); 2187 2188 // Again, disagreeing properties, this time the expr, should cause a PHI to 2189 // not be eliminated. 2190 DIExpression *NewExpr = 2191 DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); 2192 DbgValueProperties PropsWithExpr(NewExpr, false); 2193 VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2194 VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithExpr, DbgValue::Def); 2195 JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI); 2196 Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2197 EXPECT_FALSE(Result); 2198 } 2199 2200 TEST_F(InstrRefLDVTest, vlocJoinLoops) { 2201 setupSimpleLoop(); 2202 // entry 2203 // | 2204 // |/-----\ 2205 // loopblk | 2206 // |\-----/ 2207 // | 2208 // ret 2209 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2210 LocIdx RspLoc(0); 2211 Register RAX = getRegByName("RAX"); 2212 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2213 2214 unsigned EntryBlk = 0, LoopBlk = 1; 2215 2216 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 2217 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 2218 ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc); 2219 2220 DebugVariable Var(FuncVariable, None, nullptr); 2221 DbgValueProperties EmptyProps(EmptyExpr, false); 2222 SmallVector<DbgValue, 32> VLiveOuts; 2223 VLiveOuts.resize(3, DbgValue(EmptyProps, DbgValue::Undef)); 2224 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 2225 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 2226 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 2227 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 2228 2229 SmallPtrSet<const MachineBasicBlock *, 8> AllBlocks; 2230 AllBlocks.insert(MBB0); 2231 AllBlocks.insert(MBB1); 2232 AllBlocks.insert(MBB2); 2233 2234 SmallVector<const MachineBasicBlock *, 2> Preds; 2235 for (const auto *Pred : MBB1->predecessors()) 2236 Preds.push_back(Pred); 2237 2238 SmallSet<DebugVariable, 4> AllVars; 2239 AllVars.insert(Var); 2240 2241 // Test some back-edge-specific behaviours of vloc join. Mostly: the fact that 2242 // VPHIs that arrive on backedges can be eliminated, despite having different 2243 // values to the predecessor. 2244 2245 // First: when there's no VPHI placed already, propagate the live-in value of 2246 // the first RPO predecessor. 2247 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2248 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2249 DbgValue JoinedLoc = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2250 bool Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2251 EXPECT_TRUE(Result); 2252 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2253 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2254 2255 // If there is a VPHI: don't elimiante it if there are disagreeing values. 2256 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2257 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2258 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2259 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2260 EXPECT_FALSE(Result); 2261 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2262 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2263 2264 // If we feed this VPHI back into itself though, we can eliminate it. 2265 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2266 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2267 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2268 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2269 EXPECT_TRUE(Result); 2270 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2271 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2272 2273 // Don't eliminate backedge VPHIs if the predecessors have different 2274 // properties. 2275 DIExpression *NewExpr = 2276 DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); 2277 DbgValueProperties PropsWithExpr(NewExpr, false); 2278 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2279 VLiveOuts[1] = DbgValue(1, PropsWithExpr, DbgValue::VPHI); 2280 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2281 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2282 EXPECT_FALSE(Result); 2283 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2284 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2285 2286 // Backedges with VPHIs, but from the wrong block, shouldn't be eliminated. 2287 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2288 VLiveOuts[1] = DbgValue(0, EmptyProps, DbgValue::VPHI); 2289 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2290 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2291 EXPECT_FALSE(Result); 2292 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2293 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2294 } 2295 2296 TEST_F(InstrRefLDVTest, vlocJoinBadlyNestedLoops) { 2297 // Test PHI elimination in the presence of multiple backedges. 2298 setupBadlyNestedLoops(); 2299 // entry 2300 // | 2301 // loop1 -o 2302 // | ^ 2303 // | ^ 2304 // loop2 -o 2305 // | ^ 2306 // | ^ 2307 // loop3 -o 2308 // | 2309 // ret 2310 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2311 LocIdx RspLoc(0); 2312 Register RAX = getRegByName("RAX"); 2313 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2314 Register RBX = getRegByName("RBX"); 2315 LocIdx RbxLoc = MTracker->lookupOrTrackRegister(RBX); 2316 2317 unsigned EntryBlk = 0; 2318 2319 ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc); 2320 ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); 2321 ValueIDNum LiveInRbx(EntryBlk, 0, RbxLoc); 2322 2323 DebugVariable Var(FuncVariable, None, nullptr); 2324 DbgValueProperties EmptyProps(EmptyExpr, false); 2325 SmallVector<DbgValue, 32> VLiveOuts; 2326 VLiveOuts.resize(5, DbgValue(EmptyProps, DbgValue::Undef)); 2327 InstrRefBasedLDV::LiveIdxT VLiveOutIdx; 2328 VLiveOutIdx[MBB0] = &VLiveOuts[0]; 2329 VLiveOutIdx[MBB1] = &VLiveOuts[1]; 2330 VLiveOutIdx[MBB2] = &VLiveOuts[2]; 2331 VLiveOutIdx[MBB3] = &VLiveOuts[3]; 2332 VLiveOutIdx[MBB4] = &VLiveOuts[4]; 2333 2334 SmallPtrSet<const MachineBasicBlock *, 8> AllBlocks; 2335 AllBlocks.insert(MBB0); 2336 AllBlocks.insert(MBB1); 2337 AllBlocks.insert(MBB2); 2338 AllBlocks.insert(MBB3); 2339 AllBlocks.insert(MBB4); 2340 2341 // We're going to focus on block 1. 2342 SmallVector<const MachineBasicBlock *, 3> Preds; 2343 for (const auto *Pred : MBB1->predecessors()) 2344 Preds.push_back(Pred); 2345 2346 SmallSet<DebugVariable, 4> AllVars; 2347 AllVars.insert(Var); 2348 2349 // Test a normal VPHI isn't eliminated. 2350 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2351 VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def); 2352 VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def); 2353 DbgValue JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2354 bool Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2355 EXPECT_FALSE(Result); 2356 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2357 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2358 2359 // Common VPHIs on backedges should merge. 2360 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2361 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2362 VLiveOuts[2] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2363 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2364 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2365 EXPECT_TRUE(Result); 2366 EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def); 2367 EXPECT_EQ(JoinedLoc.ID, LiveInRsp); 2368 2369 // They shouldn't merge if one of their properties is different. 2370 DbgValueProperties PropsWithIndirect(EmptyExpr, true); 2371 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2372 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2373 VLiveOuts[2] = DbgValue(1, PropsWithIndirect, DbgValue::VPHI); 2374 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2375 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2376 EXPECT_FALSE(Result); 2377 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2378 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2379 2380 // VPHIs from different blocks should not merge. 2381 VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def); 2382 VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); 2383 VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); 2384 JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI); 2385 Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, AllBlocks, JoinedLoc); 2386 EXPECT_FALSE(Result); 2387 EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI); 2388 EXPECT_EQ(JoinedLoc.BlockNo, 1); 2389 } 2390 2391 // Above are tests for picking VPHI locations, and eliminating VPHIs. No 2392 // unit-tests are written for evaluating the transfer function as that's 2393 // pretty straight forwards, or applying VPHI-location-picking to live-ins. 2394 // Instead, pre-set some machine locations and apply buildVLocValueMap to the 2395 // existing CFG patterns. 2396 TEST_F(InstrRefLDVTest, VLocSingleBlock) { 2397 setupSingleBlock(); 2398 2399 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2400 LocIdx RspLoc(0); 2401 2402 ValueIDNum InLocs[2], OutLocs[2]; 2403 ValueIDNum *InLocsPtr[1] = {&InLocs[0]}; 2404 ValueIDNum *OutLocsPtr[1] = {&OutLocs[0]}; 2405 2406 ValueIDNum LiveInRsp = ValueIDNum(0, 0, RspLoc); 2407 InLocs[0] = OutLocs[0] = LiveInRsp; 2408 2409 DebugVariable Var(FuncVariable, None, nullptr); 2410 DbgValueProperties EmptyProps(EmptyExpr, false); 2411 2412 SmallSet<DebugVariable, 4> AllVars; 2413 AllVars.insert(Var); 2414 2415 // Mild hack: rather than constructing machine instructions in each block 2416 // and creating lexical scopes across them, instead just tell 2417 // buildVLocValueMap that there's an assignment in every block. That makes 2418 // every block in scope. 2419 SmallPtrSet<MachineBasicBlock *, 4> AssignBlocks; 2420 AssignBlocks.insert(MBB0); 2421 2422 SmallVector<VLocTracker, 1> VLocs; 2423 VLocs.resize(1); 2424 2425 InstrRefBasedLDV::LiveInsT Output; 2426 2427 // Test that, with no assignments at all, no mappings are created for the 2428 // variable in this function. 2429 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2430 OutLocsPtr, InLocsPtr, VLocs); 2431 EXPECT_EQ(Output.size(), 0ul); 2432 2433 // If we put an assignment in the transfer function, that should... well, 2434 // do nothing, because we don't store the live-outs. 2435 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2436 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2437 OutLocsPtr, InLocsPtr, VLocs); 2438 EXPECT_EQ(Output.size(), 0ul); 2439 2440 // There is pretty much nothing else of interest to test with a single block. 2441 // It's not relevant to the SSA-construction parts of variable values. 2442 } 2443 2444 TEST_F(InstrRefLDVTest, VLocDiamondBlocks) { 2445 setupDiamondBlocks(); 2446 // entry 2447 // / \ 2448 // br1 br2 2449 // \ / 2450 // ret 2451 2452 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2453 LocIdx RspLoc(0); 2454 Register RAX = getRegByName("RAX"); 2455 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2456 2457 unsigned EntryBlk = 0, RetBlk = 3; 2458 2459 ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc); 2460 ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc); 2461 ValueIDNum RspPHIInBlk3 = ValueIDNum(RetBlk, 0, RspLoc); 2462 2463 ValueIDNum InLocs[4][2], OutLocs[4][2]; 2464 ValueIDNum *InLocsPtr[4] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3]}; 2465 ValueIDNum *OutLocsPtr[4] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3]}; 2466 2467 initValueArray(InLocsPtr, 4, 2); 2468 initValueArray(OutLocsPtr, 4, 2); 2469 2470 DebugVariable Var(FuncVariable, None, nullptr); 2471 DbgValueProperties EmptyProps(EmptyExpr, false); 2472 2473 SmallSet<DebugVariable, 4> AllVars; 2474 AllVars.insert(Var); 2475 2476 // Mild hack: rather than constructing machine instructions in each block 2477 // and creating lexical scopes across them, instead just tell 2478 // buildVLocValueMap that there's an assignment in every block. That makes 2479 // every block in scope. 2480 SmallPtrSet<MachineBasicBlock *, 4> AssignBlocks; 2481 AssignBlocks.insert(MBB0); 2482 AssignBlocks.insert(MBB1); 2483 AssignBlocks.insert(MBB2); 2484 AssignBlocks.insert(MBB3); 2485 2486 SmallVector<VLocTracker, 1> VLocs; 2487 VLocs.resize(4); 2488 2489 InstrRefBasedLDV::LiveInsT Output; 2490 2491 // Start off with LiveInRsp in every location. 2492 for (unsigned int I = 0; I < 4; ++I) { 2493 InLocs[I][0] = InLocs[I][1] = LiveInRsp; 2494 OutLocs[I][0] = OutLocs[I][1] = LiveInRsp; 2495 } 2496 2497 auto ClearOutputs = [&]() { 2498 for (auto &Elem : Output) 2499 Elem.clear(); 2500 }; 2501 Output.resize(4); 2502 2503 // No assignments -> no values. 2504 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2505 OutLocsPtr, InLocsPtr, VLocs); 2506 EXPECT_EQ(Output[0].size(), 0ul); 2507 EXPECT_EQ(Output[1].size(), 0ul); 2508 EXPECT_EQ(Output[2].size(), 0ul); 2509 EXPECT_EQ(Output[3].size(), 0ul); 2510 2511 // An assignment in the end block should also not affect other blocks; or 2512 // produce any live-ins. 2513 VLocs[3].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2514 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2515 OutLocsPtr, InLocsPtr, VLocs); 2516 EXPECT_EQ(Output[0].size(), 0ul); 2517 EXPECT_EQ(Output[1].size(), 0ul); 2518 EXPECT_EQ(Output[2].size(), 0ul); 2519 EXPECT_EQ(Output[3].size(), 0ul); 2520 ClearOutputs(); 2521 2522 // Assignments in either of the side-of-diamond blocks should also not be 2523 // propagated anywhere. 2524 VLocs[3].Vars.clear(); 2525 VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2526 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2527 OutLocsPtr, InLocsPtr, VLocs); 2528 EXPECT_EQ(Output[0].size(), 0ul); 2529 EXPECT_EQ(Output[1].size(), 0ul); 2530 EXPECT_EQ(Output[2].size(), 0ul); 2531 EXPECT_EQ(Output[3].size(), 0ul); 2532 VLocs[2].Vars.clear(); 2533 ClearOutputs(); 2534 2535 VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2536 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2537 OutLocsPtr, InLocsPtr, VLocs); 2538 EXPECT_EQ(Output[0].size(), 0ul); 2539 EXPECT_EQ(Output[1].size(), 0ul); 2540 EXPECT_EQ(Output[2].size(), 0ul); 2541 EXPECT_EQ(Output[3].size(), 0ul); 2542 VLocs[1].Vars.clear(); 2543 ClearOutputs(); 2544 2545 // However: putting an assignment in the first block should propagate variable 2546 // values through to all other blocks, as it dominates. 2547 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2548 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2549 OutLocsPtr, InLocsPtr, VLocs); 2550 EXPECT_EQ(Output[0].size(), 0ul); 2551 ASSERT_EQ(Output[1].size(), 1ul); 2552 ASSERT_EQ(Output[2].size(), 1ul); 2553 ASSERT_EQ(Output[3].size(), 1ul); 2554 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2555 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2556 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2557 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2558 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2559 EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); 2560 ClearOutputs(); 2561 VLocs[0].Vars.clear(); 2562 2563 // Additionally, even if that value isn't available in the register file, it 2564 // should still be propagated, as buildVLocValueMap shouldn't care about 2565 // what's in the registers (except for PHIs). 2566 // values through to all other blocks, as it dominates. 2567 VLocs[0].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2568 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2569 OutLocsPtr, InLocsPtr, VLocs); 2570 EXPECT_EQ(Output[0].size(), 0ul); 2571 ASSERT_EQ(Output[1].size(), 1ul); 2572 ASSERT_EQ(Output[2].size(), 1ul); 2573 ASSERT_EQ(Output[3].size(), 1ul); 2574 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2575 EXPECT_EQ(Output[1][0].second.ID, LiveInRax); 2576 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2577 EXPECT_EQ(Output[2][0].second.ID, LiveInRax); 2578 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2579 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 2580 ClearOutputs(); 2581 VLocs[0].Vars.clear(); 2582 2583 // We should get a live-in to the merging block, if there are two assigns of 2584 // the same value in either side of the diamond. 2585 VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2586 VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2587 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2588 OutLocsPtr, InLocsPtr, VLocs); 2589 EXPECT_EQ(Output[0].size(), 0ul); 2590 EXPECT_EQ(Output[1].size(), 0ul); 2591 EXPECT_EQ(Output[2].size(), 0ul); 2592 ASSERT_EQ(Output[3].size(), 1ul); 2593 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2594 EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); 2595 ClearOutputs(); 2596 VLocs[1].Vars.clear(); 2597 VLocs[2].Vars.clear(); 2598 2599 // If we assign a value in the entry block, then 'undef' on a branch, we 2600 // shouldn't have a live-in in the merge block. 2601 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2602 VLocs[1].Vars.insert({Var, DbgValue(EmptyProps, DbgValue::Undef)}); 2603 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2604 OutLocsPtr, InLocsPtr, VLocs); 2605 EXPECT_EQ(Output[0].size(), 0ul); 2606 ASSERT_EQ(Output[1].size(), 1ul); 2607 ASSERT_EQ(Output[2].size(), 1ul); 2608 EXPECT_EQ(Output[3].size(), 0ul); 2609 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2610 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2611 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2612 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2613 ClearOutputs(); 2614 VLocs[0].Vars.clear(); 2615 VLocs[1].Vars.clear(); 2616 2617 // Having different values joining into the merge block should mean we have 2618 // no live-in in that block. Block ones LiveInRax value doesn't appear as a 2619 // live-in anywhere, it's block internal. 2620 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2621 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2622 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2623 OutLocsPtr, InLocsPtr, VLocs); 2624 EXPECT_EQ(Output[0].size(), 0ul); 2625 ASSERT_EQ(Output[1].size(), 1ul); 2626 ASSERT_EQ(Output[2].size(), 1ul); 2627 EXPECT_EQ(Output[3].size(), 0ul); 2628 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2629 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2630 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2631 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2632 ClearOutputs(); 2633 VLocs[0].Vars.clear(); 2634 VLocs[1].Vars.clear(); 2635 2636 // But on the other hand, if there's a location in the register file where 2637 // those two values can be joined, do so. 2638 OutLocs[1][0] = LiveInRax; 2639 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2640 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2641 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2642 OutLocsPtr, InLocsPtr, VLocs); 2643 EXPECT_EQ(Output[0].size(), 0ul); 2644 ASSERT_EQ(Output[1].size(), 1ul); 2645 ASSERT_EQ(Output[2].size(), 1ul); 2646 ASSERT_EQ(Output[3].size(), 1ul); 2647 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2648 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2649 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2650 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2651 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2652 EXPECT_EQ(Output[3][0].second.ID, RspPHIInBlk3); 2653 ClearOutputs(); 2654 VLocs[0].Vars.clear(); 2655 VLocs[1].Vars.clear(); 2656 } 2657 2658 TEST_F(InstrRefLDVTest, VLocSimpleLoop) { 2659 setupSimpleLoop(); 2660 // entry 2661 // | 2662 // |/-----\ 2663 // loopblk | 2664 // |\-----/ 2665 // | 2666 // ret 2667 2668 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2669 LocIdx RspLoc(0); 2670 Register RAX = getRegByName("RAX"); 2671 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2672 2673 unsigned EntryBlk = 0, LoopBlk = 1; 2674 2675 ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc); 2676 ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc); 2677 ValueIDNum RspPHIInBlk1 = ValueIDNum(LoopBlk, 0, RspLoc); 2678 ValueIDNum RspDefInBlk1 = ValueIDNum(LoopBlk, 1, RspLoc); 2679 ValueIDNum RaxPHIInBlk1 = ValueIDNum(LoopBlk, 0, RaxLoc); 2680 2681 ValueIDNum InLocs[3][2], OutLocs[3][2]; 2682 ValueIDNum *InLocsPtr[3] = {InLocs[0], InLocs[1], InLocs[2]}; 2683 ValueIDNum *OutLocsPtr[3] = {OutLocs[0], OutLocs[1], OutLocs[2]}; 2684 2685 initValueArray(InLocsPtr, 3, 2); 2686 initValueArray(OutLocsPtr, 3, 2); 2687 2688 DebugVariable Var(FuncVariable, None, nullptr); 2689 DbgValueProperties EmptyProps(EmptyExpr, false); 2690 2691 SmallSet<DebugVariable, 4> AllVars; 2692 AllVars.insert(Var); 2693 2694 SmallPtrSet<MachineBasicBlock *, 4> AssignBlocks; 2695 AssignBlocks.insert(MBB0); 2696 AssignBlocks.insert(MBB1); 2697 AssignBlocks.insert(MBB2); 2698 2699 SmallVector<VLocTracker, 3> VLocs; 2700 VLocs.resize(3); 2701 2702 InstrRefBasedLDV::LiveInsT Output; 2703 2704 // Start off with LiveInRsp in every location. 2705 for (unsigned int I = 0; I < 3; ++I) { 2706 InLocs[I][0] = InLocs[I][1] = LiveInRsp; 2707 OutLocs[I][0] = OutLocs[I][1] = LiveInRsp; 2708 } 2709 2710 auto ClearOutputs = [&]() { 2711 for (auto &Elem : Output) 2712 Elem.clear(); 2713 }; 2714 Output.resize(3); 2715 2716 // Easy starter: a dominating assign should propagate to all blocks. 2717 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2718 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2719 OutLocsPtr, InLocsPtr, VLocs); 2720 EXPECT_EQ(Output[0].size(), 0ul); 2721 ASSERT_EQ(Output[1].size(), 1ul); 2722 ASSERT_EQ(Output[2].size(), 1ul); 2723 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2724 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2725 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2726 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2727 ClearOutputs(); 2728 VLocs[0].Vars.clear(); 2729 VLocs[1].Vars.clear(); 2730 2731 // Put an undef assignment in the loop. Should get no live-in value. 2732 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2733 VLocs[1].Vars.insert({Var, DbgValue(EmptyProps, DbgValue::Undef)}); 2734 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2735 OutLocsPtr, InLocsPtr, VLocs); 2736 EXPECT_EQ(Output[0].size(), 0ul); 2737 EXPECT_EQ(Output[1].size(), 0ul); 2738 EXPECT_EQ(Output[2].size(), 0ul); 2739 ClearOutputs(); 2740 VLocs[0].Vars.clear(); 2741 VLocs[1].Vars.clear(); 2742 2743 // Assignment of the same value should naturally join. 2744 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2745 VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2746 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2747 OutLocsPtr, InLocsPtr, VLocs); 2748 EXPECT_EQ(Output[0].size(), 0ul); 2749 ASSERT_EQ(Output[1].size(), 1ul); 2750 ASSERT_EQ(Output[2].size(), 1ul); 2751 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2752 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2753 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2754 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2755 ClearOutputs(); 2756 VLocs[0].Vars.clear(); 2757 VLocs[1].Vars.clear(); 2758 2759 // Assignment of different values shouldn't join with no machine PHI vals. 2760 // Will be live-in to exit block as it's dominated. 2761 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2762 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2763 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2764 OutLocsPtr, InLocsPtr, VLocs); 2765 EXPECT_EQ(Output[0].size(), 0ul); 2766 EXPECT_EQ(Output[1].size(), 0ul); 2767 ASSERT_EQ(Output[2].size(), 1ul); 2768 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2769 EXPECT_EQ(Output[2][0].second.ID, LiveInRax); 2770 ClearOutputs(); 2771 VLocs[0].Vars.clear(); 2772 VLocs[1].Vars.clear(); 2773 2774 // Install a completely unrelated PHI value, that we should not join on. Try 2775 // with unrelated assign in loop block again. 2776 InLocs[1][0] = RspPHIInBlk1; 2777 OutLocs[1][0] = RspDefInBlk1; 2778 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2779 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2780 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2781 OutLocsPtr, InLocsPtr, VLocs); 2782 EXPECT_EQ(Output[0].size(), 0ul); 2783 EXPECT_EQ(Output[1].size(), 0ul); 2784 ASSERT_EQ(Output[2].size(), 1ul); 2785 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2786 EXPECT_EQ(Output[2][0].second.ID, LiveInRax); 2787 ClearOutputs(); 2788 VLocs[0].Vars.clear(); 2789 VLocs[1].Vars.clear(); 2790 2791 // Now, if we assign RspDefInBlk1 in the loop block, we should be able to 2792 // find the appropriate PHI. 2793 InLocs[1][0] = RspPHIInBlk1; 2794 OutLocs[1][0] = RspDefInBlk1; 2795 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2796 VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)}); 2797 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2798 OutLocsPtr, InLocsPtr, VLocs); 2799 EXPECT_EQ(Output[0].size(), 0ul); 2800 ASSERT_EQ(Output[1].size(), 1ul); 2801 ASSERT_EQ(Output[2].size(), 1ul); 2802 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2803 EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); 2804 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2805 EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1); 2806 ClearOutputs(); 2807 VLocs[0].Vars.clear(); 2808 VLocs[1].Vars.clear(); 2809 2810 // If the PHI happens in a different location, the live-in should happen 2811 // there. 2812 InLocs[1][0] = LiveInRsp; 2813 OutLocs[1][0] = LiveInRsp; 2814 InLocs[1][1] = RaxPHIInBlk1; 2815 OutLocs[1][1] = RspDefInBlk1; 2816 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2817 VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)}); 2818 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2819 OutLocsPtr, InLocsPtr, VLocs); 2820 EXPECT_EQ(Output[0].size(), 0ul); 2821 ASSERT_EQ(Output[1].size(), 1ul); 2822 ASSERT_EQ(Output[2].size(), 1ul); 2823 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2824 EXPECT_EQ(Output[1][0].second.ID, RaxPHIInBlk1); 2825 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2826 EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1); 2827 ClearOutputs(); 2828 VLocs[0].Vars.clear(); 2829 VLocs[1].Vars.clear(); 2830 2831 // The PHI happening in both places should be handled too. Exactly where 2832 // isn't important, but if the location picked changes, this test will let 2833 // you know. 2834 InLocs[1][0] = RaxPHIInBlk1; 2835 OutLocs[1][0] = RspDefInBlk1; 2836 InLocs[1][1] = RaxPHIInBlk1; 2837 OutLocs[1][1] = RspDefInBlk1; 2838 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2839 VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)}); 2840 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2841 OutLocsPtr, InLocsPtr, VLocs); 2842 EXPECT_EQ(Output[0].size(), 0ul); 2843 ASSERT_EQ(Output[1].size(), 1ul); 2844 ASSERT_EQ(Output[2].size(), 1ul); 2845 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2846 // Today, the first register is picked. 2847 EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); 2848 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2849 EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1); 2850 ClearOutputs(); 2851 VLocs[0].Vars.clear(); 2852 VLocs[1].Vars.clear(); 2853 2854 // If the loop block looked a bit like this: 2855 // %0 = PHI %1, %2 2856 // [...] 2857 // DBG_VALUE %0 2858 // Then with instr-ref it becomes: 2859 // DBG_PHI %0 2860 // [...] 2861 // DBG_INSTR_REF 2862 // And we would be feeding a machine PHI-value back around the loop. However: 2863 // this does not mean we can eliminate the variable value PHI and use the 2864 // variable value from the entry block: they are distinct values that must be 2865 // joined at some location by the control flow. 2866 // [This test input would never occur naturally, the machine-PHI would be 2867 // eliminated] 2868 InLocs[1][0] = RspPHIInBlk1; 2869 OutLocs[1][0] = RspPHIInBlk1; 2870 InLocs[1][1] = LiveInRax; 2871 OutLocs[1][1] = LiveInRax; 2872 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2873 VLocs[1].Vars.insert({Var, DbgValue(RspPHIInBlk1, EmptyProps, DbgValue::Def)}); 2874 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2875 OutLocsPtr, InLocsPtr, VLocs); 2876 EXPECT_EQ(Output[0].size(), 0ul); 2877 ASSERT_EQ(Output[1].size(), 1ul); 2878 ASSERT_EQ(Output[2].size(), 1ul); 2879 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2880 EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); 2881 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2882 EXPECT_EQ(Output[2][0].second.ID, RspPHIInBlk1); 2883 ClearOutputs(); 2884 VLocs[0].Vars.clear(); 2885 VLocs[1].Vars.clear(); 2886 2887 // Test that we can eliminate PHIs. A PHI will be placed at the loop head 2888 // because there's a def in in. 2889 InLocs[1][0] = LiveInRsp; 2890 OutLocs[1][0] = LiveInRsp; 2891 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2892 VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2893 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2894 OutLocsPtr, InLocsPtr, VLocs); 2895 EXPECT_EQ(Output[0].size(), 0ul); 2896 ASSERT_EQ(Output[1].size(), 1ul); 2897 ASSERT_EQ(Output[2].size(), 1ul); 2898 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2899 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2900 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2901 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2902 ClearOutputs(); 2903 VLocs[0].Vars.clear(); 2904 VLocs[1].Vars.clear(); 2905 } 2906 2907 // test phi elimination with the nested situation 2908 TEST_F(InstrRefLDVTest, VLocNestedLoop) { 2909 // entry 2910 // | 2911 // loop1 2912 // ^\ 2913 // | \ /-\ 2914 // | loop2 | 2915 // | / \-/ 2916 // ^ / 2917 // join 2918 // | 2919 // ret 2920 setupNestedLoops(); 2921 2922 ASSERT_TRUE(MTracker->getNumLocs() == 1); 2923 LocIdx RspLoc(0); 2924 Register RAX = getRegByName("RAX"); 2925 LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX); 2926 2927 unsigned EntryBlk = 0, Loop1Blk = 1, Loop2Blk = 2; 2928 2929 ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc); 2930 ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc); 2931 ValueIDNum RspPHIInBlk1 = ValueIDNum(Loop1Blk, 0, RspLoc); 2932 ValueIDNum RspPHIInBlk2 = ValueIDNum(Loop2Blk, 0, RspLoc); 2933 ValueIDNum RspDefInBlk2 = ValueIDNum(Loop2Blk, 1, RspLoc); 2934 2935 ValueIDNum InLocs[5][2], OutLocs[5][2]; 2936 ValueIDNum *InLocsPtr[5] = {InLocs[0], InLocs[1], InLocs[2], InLocs[3], InLocs[4]}; 2937 ValueIDNum *OutLocsPtr[5] = {OutLocs[0], OutLocs[1], OutLocs[2], OutLocs[3], OutLocs[4]}; 2938 2939 initValueArray(InLocsPtr, 5, 2); 2940 initValueArray(OutLocsPtr, 5, 2); 2941 2942 DebugVariable Var(FuncVariable, None, nullptr); 2943 DbgValueProperties EmptyProps(EmptyExpr, false); 2944 2945 SmallSet<DebugVariable, 4> AllVars; 2946 AllVars.insert(Var); 2947 2948 SmallPtrSet<MachineBasicBlock *, 5> AssignBlocks; 2949 AssignBlocks.insert(MBB0); 2950 AssignBlocks.insert(MBB1); 2951 AssignBlocks.insert(MBB2); 2952 AssignBlocks.insert(MBB3); 2953 AssignBlocks.insert(MBB4); 2954 2955 SmallVector<VLocTracker, 5> VLocs; 2956 VLocs.resize(5); 2957 2958 InstrRefBasedLDV::LiveInsT Output; 2959 2960 // Start off with LiveInRsp in every location. 2961 for (unsigned int I = 0; I < 5; ++I) { 2962 InLocs[I][0] = InLocs[I][1] = LiveInRsp; 2963 OutLocs[I][0] = OutLocs[I][1] = LiveInRsp; 2964 } 2965 2966 auto ClearOutputs = [&]() { 2967 for (auto &Elem : Output) 2968 Elem.clear(); 2969 }; 2970 Output.resize(5); 2971 2972 // A dominating assign should propagate to all blocks. 2973 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2974 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2975 OutLocsPtr, InLocsPtr, VLocs); 2976 EXPECT_EQ(Output[0].size(), 0ul); 2977 ASSERT_EQ(Output[1].size(), 1ul); 2978 ASSERT_EQ(Output[2].size(), 1ul); 2979 ASSERT_EQ(Output[3].size(), 1ul); 2980 ASSERT_EQ(Output[4].size(), 1ul); 2981 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 2982 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 2983 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 2984 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 2985 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 2986 EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); 2987 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 2988 EXPECT_EQ(Output[4][0].second.ID, LiveInRsp); 2989 ClearOutputs(); 2990 VLocs[0].Vars.clear(); 2991 2992 // Test that an assign in the inner loop causes unresolved PHIs at the heads 2993 // of both loops, and no output location. Dominated blocks do get values. 2994 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 2995 VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 2996 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 2997 OutLocsPtr, InLocsPtr, VLocs); 2998 EXPECT_EQ(Output[0].size(), 0ul); 2999 EXPECT_EQ(Output[1].size(), 0ul); 3000 EXPECT_EQ(Output[2].size(), 0ul); 3001 ASSERT_EQ(Output[3].size(), 1ul); 3002 ASSERT_EQ(Output[4].size(), 1ul); 3003 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 3004 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 3005 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 3006 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 3007 ClearOutputs(); 3008 VLocs[0].Vars.clear(); 3009 VLocs[2].Vars.clear(); 3010 3011 // Same test, but with no assignment in block 0. We should still get values 3012 // in dominated blocks. 3013 VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 3014 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 3015 OutLocsPtr, InLocsPtr, VLocs); 3016 EXPECT_EQ(Output[0].size(), 0ul); 3017 EXPECT_EQ(Output[1].size(), 0ul); 3018 EXPECT_EQ(Output[2].size(), 0ul); 3019 ASSERT_EQ(Output[3].size(), 1ul); 3020 ASSERT_EQ(Output[4].size(), 1ul); 3021 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 3022 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 3023 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 3024 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 3025 ClearOutputs(); 3026 VLocs[2].Vars.clear(); 3027 3028 // Similarly, assignments in the outer loop gives location to dominated 3029 // blocks, but no PHI locations are found at the outer loop head. 3030 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 3031 VLocs[3].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 3032 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 3033 OutLocsPtr, InLocsPtr, VLocs); 3034 EXPECT_EQ(Output[0].size(), 0ul); 3035 EXPECT_EQ(Output[1].size(), 0ul); 3036 EXPECT_EQ(Output[2].size(), 0ul); 3037 EXPECT_EQ(Output[3].size(), 0ul); 3038 ASSERT_EQ(Output[4].size(), 1ul); 3039 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 3040 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 3041 ClearOutputs(); 3042 VLocs[0].Vars.clear(); 3043 VLocs[3].Vars.clear(); 3044 3045 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 3046 VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 3047 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 3048 OutLocsPtr, InLocsPtr, VLocs); 3049 EXPECT_EQ(Output[0].size(), 0ul); 3050 EXPECT_EQ(Output[1].size(), 0ul); 3051 ASSERT_EQ(Output[2].size(), 1ul); 3052 ASSERT_EQ(Output[3].size(), 1ul); 3053 ASSERT_EQ(Output[4].size(), 1ul); 3054 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 3055 EXPECT_EQ(Output[2][0].second.ID, LiveInRax); 3056 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 3057 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 3058 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 3059 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 3060 ClearOutputs(); 3061 VLocs[0].Vars.clear(); 3062 VLocs[1].Vars.clear(); 3063 3064 // With an assignment of the same value in the inner loop, we should work out 3065 // that all PHIs can be eliminated and the same value is live-through the 3066 // whole function. 3067 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 3068 VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 3069 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 3070 OutLocsPtr, InLocsPtr, VLocs); 3071 EXPECT_EQ(Output[0].size(), 0ul); 3072 EXPECT_EQ(Output[1].size(), 1ul); 3073 EXPECT_EQ(Output[2].size(), 1ul); 3074 ASSERT_EQ(Output[3].size(), 1ul); 3075 ASSERT_EQ(Output[4].size(), 1ul); 3076 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 3077 EXPECT_EQ(Output[1][0].second.ID, LiveInRsp); 3078 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 3079 EXPECT_EQ(Output[2][0].second.ID, LiveInRsp); 3080 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 3081 EXPECT_EQ(Output[3][0].second.ID, LiveInRsp); 3082 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 3083 EXPECT_EQ(Output[4][0].second.ID, LiveInRsp); 3084 ClearOutputs(); 3085 VLocs[0].Vars.clear(); 3086 VLocs[2].Vars.clear(); 3087 3088 // If we have an assignment in the inner loop, and a PHI for it at the inner 3089 // loop head, we could find a live-in location for the inner loop. But because 3090 // the outer loop has no PHI, we can't find a variable value for outer loop 3091 // head, so can't have a live-in value for the inner loop head. 3092 InLocs[2][0] = RspPHIInBlk2; 3093 OutLocs[2][0] = LiveInRax; 3094 // NB: all other machine locations are LiveInRsp, disallowing a PHI in block 3095 // one. Even though RspPHIInBlk2 isn't available later in the function, we 3096 // should still produce a live-in value. The fact it's unavailable is a 3097 // different concern. 3098 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 3099 VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)}); 3100 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 3101 OutLocsPtr, InLocsPtr, VLocs); 3102 EXPECT_EQ(Output[0].size(), 0ul); 3103 EXPECT_EQ(Output[1].size(), 0ul); 3104 EXPECT_EQ(Output[2].size(), 0ul); 3105 ASSERT_EQ(Output[3].size(), 1ul); 3106 ASSERT_EQ(Output[4].size(), 1ul); 3107 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 3108 EXPECT_EQ(Output[3][0].second.ID, LiveInRax); 3109 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 3110 EXPECT_EQ(Output[4][0].second.ID, LiveInRax); 3111 ClearOutputs(); 3112 VLocs[0].Vars.clear(); 3113 VLocs[2].Vars.clear(); 3114 3115 // Have an assignment in inner loop that can have a PHI resolved; and add a 3116 // machine value PHI to the outer loop head, so that we can find a location 3117 // all the way through the function. 3118 InLocs[1][0] = RspPHIInBlk1; 3119 OutLocs[1][0] = RspPHIInBlk1; 3120 InLocs[2][0] = RspPHIInBlk2; 3121 OutLocs[2][0] = RspDefInBlk2; 3122 InLocs[3][0] = RspDefInBlk2; 3123 OutLocs[3][0] = RspDefInBlk2; 3124 VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)}); 3125 VLocs[2].Vars.insert({Var, DbgValue(RspDefInBlk2, EmptyProps, DbgValue::Def)}); 3126 buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, 3127 OutLocsPtr, InLocsPtr, VLocs); 3128 EXPECT_EQ(Output[0].size(), 0ul); 3129 ASSERT_EQ(Output[1].size(), 1ul); 3130 ASSERT_EQ(Output[2].size(), 1ul); 3131 ASSERT_EQ(Output[3].size(), 1ul); 3132 ASSERT_EQ(Output[4].size(), 1ul); 3133 EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); 3134 EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1); 3135 EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); 3136 EXPECT_EQ(Output[2][0].second.ID, RspPHIInBlk2); 3137 EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def); 3138 EXPECT_EQ(Output[3][0].second.ID, RspDefInBlk2); 3139 EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def); 3140 EXPECT_EQ(Output[4][0].second.ID, RspDefInBlk2); 3141 ClearOutputs(); 3142 VLocs[0].Vars.clear(); 3143 VLocs[2].Vars.clear(); 3144 } 3145 3146