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