1 //===- Local.cpp - Unit tests for Local -----------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/Transforms/Utils/Local.h" 11 #include "llvm/AsmParser/Parser.h" 12 #include "llvm/IR/BasicBlock.h" 13 #include "llvm/IR/DIBuilder.h" 14 #include "llvm/IR/IRBuilder.h" 15 #include "llvm/IR/Instructions.h" 16 #include "llvm/IR/IntrinsicInst.h" 17 #include "llvm/IR/LLVMContext.h" 18 #include "llvm/IR/Verifier.h" 19 #include "llvm/Support/SourceMgr.h" 20 #include "gtest/gtest.h" 21 22 using namespace llvm; 23 24 TEST(Local, RecursivelyDeleteDeadPHINodes) { 25 LLVMContext C; 26 27 IRBuilder<> builder(C); 28 29 // Make blocks 30 BasicBlock *bb0 = BasicBlock::Create(C); 31 BasicBlock *bb1 = BasicBlock::Create(C); 32 33 builder.SetInsertPoint(bb0); 34 PHINode *phi = builder.CreatePHI(Type::getInt32Ty(C), 2); 35 BranchInst *br0 = builder.CreateCondBr(builder.getTrue(), bb0, bb1); 36 37 builder.SetInsertPoint(bb1); 38 BranchInst *br1 = builder.CreateBr(bb0); 39 40 phi->addIncoming(phi, bb0); 41 phi->addIncoming(phi, bb1); 42 43 // The PHI will be removed 44 EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi)); 45 46 // Make sure the blocks only contain the branches 47 EXPECT_EQ(&bb0->front(), br0); 48 EXPECT_EQ(&bb1->front(), br1); 49 50 builder.SetInsertPoint(bb0); 51 phi = builder.CreatePHI(Type::getInt32Ty(C), 0); 52 53 EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi)); 54 55 builder.SetInsertPoint(bb0); 56 phi = builder.CreatePHI(Type::getInt32Ty(C), 0); 57 builder.CreateAdd(phi, phi); 58 59 EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi)); 60 61 bb0->dropAllReferences(); 62 bb1->dropAllReferences(); 63 delete bb0; 64 delete bb1; 65 } 66 67 TEST(Local, RemoveDuplicatePHINodes) { 68 LLVMContext C; 69 IRBuilder<> B(C); 70 71 std::unique_ptr<Function> F( 72 Function::Create(FunctionType::get(B.getVoidTy(), false), 73 GlobalValue::ExternalLinkage, "F")); 74 BasicBlock *Entry(BasicBlock::Create(C, "", F.get())); 75 BasicBlock *BB(BasicBlock::Create(C, "", F.get())); 76 BranchInst::Create(BB, Entry); 77 78 B.SetInsertPoint(BB); 79 80 AssertingVH<PHINode> P1 = B.CreatePHI(Type::getInt32Ty(C), 2); 81 P1->addIncoming(B.getInt32(42), Entry); 82 83 PHINode *P2 = B.CreatePHI(Type::getInt32Ty(C), 2); 84 P2->addIncoming(B.getInt32(42), Entry); 85 86 AssertingVH<PHINode> P3 = B.CreatePHI(Type::getInt32Ty(C), 2); 87 P3->addIncoming(B.getInt32(42), Entry); 88 P3->addIncoming(B.getInt32(23), BB); 89 90 PHINode *P4 = B.CreatePHI(Type::getInt32Ty(C), 2); 91 P4->addIncoming(B.getInt32(42), Entry); 92 P4->addIncoming(B.getInt32(23), BB); 93 94 P1->addIncoming(P3, BB); 95 P2->addIncoming(P4, BB); 96 BranchInst::Create(BB, BB); 97 98 // Verify that we can eliminate PHIs that become duplicates after chaning PHIs 99 // downstream. 100 EXPECT_TRUE(EliminateDuplicatePHINodes(BB)); 101 EXPECT_EQ(3U, BB->size()); 102 } 103 104 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { 105 SMDiagnostic Err; 106 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); 107 if (!Mod) 108 Err.print("UtilsTests", errs()); 109 return Mod; 110 } 111 112 TEST(Local, ReplaceDbgDeclare) { 113 LLVMContext C; 114 115 // Original C source to get debug info for a local variable: 116 // void f() { int x; } 117 std::unique_ptr<Module> M = parseIR(C, 118 R"( 119 define void @f() !dbg !8 { 120 entry: 121 %x = alloca i32, align 4 122 call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata !DIExpression()), !dbg !13 123 call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata !DIExpression()), !dbg !13 124 ret void, !dbg !14 125 } 126 declare void @llvm.dbg.declare(metadata, metadata, metadata) 127 !llvm.dbg.cu = !{!0} 128 !llvm.module.flags = !{!3, !4} 129 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) 130 !1 = !DIFile(filename: "t2.c", directory: "foo") 131 !2 = !{} 132 !3 = !{i32 2, !"Dwarf Version", i32 4} 133 !4 = !{i32 2, !"Debug Info Version", i32 3} 134 !8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2) 135 !9 = !DISubroutineType(types: !10) 136 !10 = !{null} 137 !11 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !12) 138 !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) 139 !13 = !DILocation(line: 2, column: 7, scope: !8) 140 !14 = !DILocation(line: 3, column: 1, scope: !8) 141 )"); 142 auto *GV = M->getNamedValue("f"); 143 ASSERT_TRUE(GV); 144 auto *F = dyn_cast<Function>(GV); 145 ASSERT_TRUE(F); 146 Instruction *Inst = &F->front().front(); 147 auto *AI = dyn_cast<AllocaInst>(Inst); 148 ASSERT_TRUE(AI); 149 Inst = Inst->getNextNode()->getNextNode(); 150 ASSERT_TRUE(Inst); 151 auto *DII = dyn_cast<DbgDeclareInst>(Inst); 152 ASSERT_TRUE(DII); 153 Value *NewBase = Constant::getNullValue(Type::getInt32PtrTy(C)); 154 DIBuilder DIB(*M); 155 replaceDbgDeclare(AI, NewBase, DII, DIB, DIExpression::NoDeref, 0, 156 DIExpression::NoDeref); 157 158 // There should be exactly two dbg.declares. 159 int Declares = 0; 160 for (const Instruction &I : F->front()) 161 if (isa<DbgDeclareInst>(I)) 162 Declares++; 163 EXPECT_EQ(2, Declares); 164 } 165 166 /// Build the dominator tree for the function and run the Test. 167 static void runWithDomTree( 168 Module &M, StringRef FuncName, 169 function_ref<void(Function &F, DominatorTree *DT)> Test) { 170 auto *F = M.getFunction(FuncName); 171 ASSERT_NE(F, nullptr) << "Could not find " << FuncName; 172 // Compute the dominator tree for the function. 173 DominatorTree DT(*F); 174 Test(*F, &DT); 175 } 176 177 TEST(Local, MergeBasicBlockIntoOnlyPred) { 178 LLVMContext C; 179 180 std::unique_ptr<Module> M = parseIR(C, 181 R"( 182 define i32 @f(i8* %str) { 183 entry: 184 br label %bb2.i 185 bb2.i: ; preds = %bb4.i, %entry 186 br i1 false, label %bb4.i, label %base2flt.exit204 187 bb4.i: ; preds = %bb2.i 188 br i1 false, label %base2flt.exit204, label %bb2.i 189 bb10.i196.bb7.i197_crit_edge: ; No predecessors! 190 br label %bb7.i197 191 bb7.i197: ; preds = %bb10.i196.bb7.i197_crit_edge 192 %.reg2mem.0 = phi i32 [ %.reg2mem.0, %bb10.i196.bb7.i197_crit_edge ] 193 br i1 undef, label %base2flt.exit204, label %base2flt.exit204 194 base2flt.exit204: ; preds = %bb7.i197, %bb7.i197, %bb2.i, %bb4.i 195 ret i32 0 196 } 197 )"); 198 runWithDomTree( 199 *M, "f", [&](Function &F, DominatorTree *DT) { 200 for (Function::iterator I = F.begin(), E = F.end(); I != E;) { 201 BasicBlock *BB = &*I++; 202 BasicBlock *SinglePred = BB->getSinglePredecessor(); 203 if (!SinglePred || SinglePred == BB || BB->hasAddressTaken()) continue; 204 BranchInst *Term = dyn_cast<BranchInst>(SinglePred->getTerminator()); 205 if (Term && !Term->isConditional()) 206 MergeBasicBlockIntoOnlyPred(BB, DT); 207 } 208 EXPECT_TRUE(DT->verify()); 209 }); 210 } 211 212 TEST(Local, ConstantFoldTerminator) { 213 LLVMContext C; 214 215 std::unique_ptr<Module> M = parseIR(C, 216 R"( 217 define void @br_same_dest() { 218 entry: 219 br i1 false, label %bb0, label %bb0 220 bb0: 221 ret void 222 } 223 224 define void @br_different_dest() { 225 entry: 226 br i1 true, label %bb0, label %bb1 227 bb0: 228 br label %exit 229 bb1: 230 br label %exit 231 exit: 232 ret void 233 } 234 235 define void @switch_2_different_dest() { 236 entry: 237 switch i32 0, label %default [ i32 0, label %bb0 ] 238 default: 239 ret void 240 bb0: 241 ret void 242 } 243 define void @switch_2_different_dest_default() { 244 entry: 245 switch i32 1, label %default [ i32 0, label %bb0 ] 246 default: 247 ret void 248 bb0: 249 ret void 250 } 251 define void @switch_3_different_dest() { 252 entry: 253 switch i32 0, label %default [ i32 0, label %bb0 254 i32 1, label %bb1 ] 255 default: 256 ret void 257 bb0: 258 ret void 259 bb1: 260 ret void 261 } 262 263 define void @switch_variable_2_default_dest(i32 %arg) { 264 entry: 265 switch i32 %arg, label %default [ i32 0, label %default ] 266 default: 267 ret void 268 } 269 270 define void @switch_constant_2_default_dest() { 271 entry: 272 switch i32 1, label %default [ i32 0, label %default ] 273 default: 274 ret void 275 } 276 277 define void @switch_constant_3_repeated_dest() { 278 entry: 279 switch i32 0, label %default [ i32 0, label %bb0 280 i32 1, label %bb0 ] 281 bb0: 282 ret void 283 default: 284 ret void 285 } 286 287 define void @indirectbr() { 288 entry: 289 indirectbr i8* blockaddress(@indirectbr, %bb0), [label %bb0, label %bb1] 290 bb0: 291 ret void 292 bb1: 293 ret void 294 } 295 296 define void @indirectbr_repeated() { 297 entry: 298 indirectbr i8* blockaddress(@indirectbr_repeated, %bb0), [label %bb0, label %bb0] 299 bb0: 300 ret void 301 } 302 303 define void @indirectbr_unreachable() { 304 entry: 305 indirectbr i8* blockaddress(@indirectbr_unreachable, %bb0), [label %bb1] 306 bb0: 307 ret void 308 bb1: 309 ret void 310 } 311 )"); 312 313 auto CFAllTerminators = [&](Function &F, DominatorTree *DT) { 314 DeferredDominance DDT(*DT); 315 for (Function::iterator I = F.begin(), E = F.end(); I != E;) { 316 BasicBlock *BB = &*I++; 317 ConstantFoldTerminator(BB, true, nullptr, &DDT); 318 } 319 320 EXPECT_TRUE(DDT.flush().verify()); 321 }; 322 323 runWithDomTree(*M, "br_same_dest", CFAllTerminators); 324 runWithDomTree(*M, "br_different_dest", CFAllTerminators); 325 runWithDomTree(*M, "switch_2_different_dest", CFAllTerminators); 326 runWithDomTree(*M, "switch_2_different_dest_default", CFAllTerminators); 327 runWithDomTree(*M, "switch_3_different_dest", CFAllTerminators); 328 runWithDomTree(*M, "switch_variable_2_default_dest", CFAllTerminators); 329 runWithDomTree(*M, "switch_constant_2_default_dest", CFAllTerminators); 330 runWithDomTree(*M, "switch_constant_3_repeated_dest", CFAllTerminators); 331 runWithDomTree(*M, "indirectbr", CFAllTerminators); 332 runWithDomTree(*M, "indirectbr_repeated", CFAllTerminators); 333 runWithDomTree(*M, "indirectbr_unreachable", CFAllTerminators); 334 } 335 336 struct SalvageDebugInfoTest : ::testing::Test { 337 LLVMContext C; 338 std::unique_ptr<Module> M; 339 Function *F = nullptr; 340 341 void SetUp() { 342 M = parseIR(C, 343 R"( 344 define void @f() !dbg !8 { 345 entry: 346 %x = add i32 0, 1 347 %y = add i32 %x, 2 348 call void @llvm.dbg.value(metadata i32 %x, metadata !11, metadata !DIExpression()), !dbg !13 349 call void @llvm.dbg.value(metadata i32 %y, metadata !11, metadata !DIExpression()), !dbg !13 350 ret void, !dbg !14 351 } 352 declare void @llvm.dbg.value(metadata, metadata, metadata) 353 !llvm.dbg.cu = !{!0} 354 !llvm.module.flags = !{!3, !4} 355 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) 356 !1 = !DIFile(filename: "t2.c", directory: "foo") 357 !2 = !{} 358 !3 = !{i32 2, !"Dwarf Version", i32 4} 359 !4 = !{i32 2, !"Debug Info Version", i32 3} 360 !8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2) 361 !9 = !DISubroutineType(types: !10) 362 !10 = !{null} 363 !11 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !12) 364 !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) 365 !13 = !DILocation(line: 2, column: 7, scope: !8) 366 !14 = !DILocation(line: 3, column: 1, scope: !8) 367 )"); 368 369 auto *GV = M->getNamedValue("f"); 370 ASSERT_TRUE(GV); 371 F = dyn_cast<Function>(GV); 372 ASSERT_TRUE(F); 373 } 374 375 bool doesDebugValueDescribeX(const DbgValueInst &DI) { 376 const auto &CI = *cast<ConstantInt>(DI.getValue()); 377 if (CI.isZero()) 378 return DI.getExpression()->getElements().equals( 379 {dwarf::DW_OP_plus_uconst, 1, dwarf::DW_OP_stack_value}); 380 else if (CI.isOneValue()) 381 return DI.getExpression()->getElements().empty(); 382 return false; 383 } 384 385 bool doesDebugValueDescribeY(const DbgValueInst &DI) { 386 const auto &CI = *cast<ConstantInt>(DI.getValue()); 387 if (CI.isZero()) 388 return DI.getExpression()->getElements().equals( 389 {dwarf::DW_OP_plus_uconst, 1, dwarf::DW_OP_plus_uconst, 2, 390 dwarf::DW_OP_stack_value}); 391 else if (CI.isOneValue()) 392 return DI.getExpression()->getElements().equals( 393 {dwarf::DW_OP_plus_uconst, 2, dwarf::DW_OP_stack_value}); 394 return false; 395 } 396 397 void verifyDebugValuesAreSalvaged() { 398 // Check that the debug values for %x and %y are preserved. 399 bool FoundX = false; 400 bool FoundY = false; 401 for (const Instruction &I : F->front()) { 402 auto DI = dyn_cast<DbgValueInst>(&I); 403 if (!DI) { 404 // The function should only contain debug values and a terminator. 405 ASSERT_TRUE(isa<TerminatorInst>(&I)); 406 continue; 407 } 408 EXPECT_EQ(DI->getVariable()->getName(), "x"); 409 FoundX |= doesDebugValueDescribeX(*DI); 410 FoundY |= doesDebugValueDescribeY(*DI); 411 } 412 ASSERT_TRUE(FoundX); 413 ASSERT_TRUE(FoundY); 414 } 415 }; 416 417 TEST_F(SalvageDebugInfoTest, RecursiveInstDeletion) { 418 Instruction *Inst = &F->front().front(); 419 Inst = Inst->getNextNode(); // Get %y = add ... 420 ASSERT_TRUE(Inst); 421 bool Deleted = RecursivelyDeleteTriviallyDeadInstructions(Inst); 422 ASSERT_TRUE(Deleted); 423 verifyDebugValuesAreSalvaged(); 424 } 425 426 TEST_F(SalvageDebugInfoTest, RecursiveBlockSimplification) { 427 BasicBlock *BB = &F->front(); 428 ASSERT_TRUE(BB); 429 bool Deleted = SimplifyInstructionsInBlock(BB); 430 ASSERT_TRUE(Deleted); 431 verifyDebugValuesAreSalvaged(); 432 } 433 434 TEST(Local, ReplaceAllDbgUsesWith) { 435 using namespace llvm::dwarf; 436 437 LLVMContext Ctx; 438 439 // Note: The datalayout simulates Darwin/x86_64. 440 std::unique_ptr<Module> M = parseIR(Ctx, 441 R"( 442 target datalayout = "e-m:o-i63:64-f80:128-n8:16:32:64-S128" 443 444 declare i32 @escape(i32) 445 446 define void @f() !dbg !6 { 447 entry: 448 %a = add i32 0, 1, !dbg !15 449 call void @llvm.dbg.value(metadata i32 %a, metadata !9, metadata !DIExpression()), !dbg !15 450 451 %b = add i64 0, 1, !dbg !16 452 call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression()), !dbg !16 453 call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_lit0, DW_OP_mul)), !dbg !16 454 call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_stack_value)), !dbg !16 455 call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 8)), !dbg !16 456 call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_fragment, 0, 8)), !dbg !16 457 call void @llvm.dbg.value(metadata i64 %b, metadata !11, metadata !DIExpression(DW_OP_lit0, DW_OP_mul, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8)), !dbg !16 458 459 %c = inttoptr i64 0 to i64*, !dbg !17 460 call void @llvm.dbg.declare(metadata i64* %c, metadata !13, metadata !DIExpression()), !dbg !17 461 462 %d = inttoptr i64 0 to i32*, !dbg !18 463 call void @llvm.dbg.addr(metadata i32* %d, metadata !20, metadata !DIExpression()), !dbg !18 464 465 %e = add <2 x i16> zeroinitializer, zeroinitializer 466 call void @llvm.dbg.value(metadata <2 x i16> %e, metadata !14, metadata !DIExpression()), !dbg !18 467 468 %f = call i32 @escape(i32 0) 469 call void @llvm.dbg.value(metadata i32 %f, metadata !9, metadata !DIExpression()), !dbg !15 470 471 %barrier = call i32 @escape(i32 0) 472 473 %g = call i32 @escape(i32 %f) 474 call void @llvm.dbg.value(metadata i32 %g, metadata !9, metadata !DIExpression()), !dbg !15 475 476 ret void, !dbg !19 477 } 478 479 declare void @llvm.dbg.addr(metadata, metadata, metadata) 480 declare void @llvm.dbg.declare(metadata, metadata, metadata) 481 declare void @llvm.dbg.value(metadata, metadata, metadata) 482 483 !llvm.dbg.cu = !{!0} 484 !llvm.module.flags = !{!5} 485 486 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) 487 !1 = !DIFile(filename: "/Users/vsk/Desktop/foo.ll", directory: "/") 488 !2 = !{} 489 !5 = !{i32 2, !"Debug Info Version", i32 3} 490 !6 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8) 491 !7 = !DISubroutineType(types: !2) 492 !8 = !{!9, !11, !13, !14} 493 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10) 494 !10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_signed) 495 !11 = !DILocalVariable(name: "2", scope: !6, file: !1, line: 2, type: !12) 496 !12 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_signed) 497 !13 = !DILocalVariable(name: "3", scope: !6, file: !1, line: 3, type: !12) 498 !14 = !DILocalVariable(name: "4", scope: !6, file: !1, line: 4, type: !10) 499 !15 = !DILocation(line: 1, column: 1, scope: !6) 500 !16 = !DILocation(line: 2, column: 1, scope: !6) 501 !17 = !DILocation(line: 3, column: 1, scope: !6) 502 !18 = !DILocation(line: 4, column: 1, scope: !6) 503 !19 = !DILocation(line: 5, column: 1, scope: !6) 504 !20 = !DILocalVariable(name: "5", scope: !6, file: !1, line: 5, type: !10) 505 )"); 506 507 bool BrokenDebugInfo = true; 508 verifyModule(*M, &errs(), &BrokenDebugInfo); 509 ASSERT_FALSE(BrokenDebugInfo); 510 511 Function &F = *cast<Function>(M->getNamedValue("f")); 512 DominatorTree DT{F}; 513 514 BasicBlock &BB = F.front(); 515 Instruction &A = BB.front(); 516 Instruction &B = *A.getNextNonDebugInstruction(); 517 Instruction &C = *B.getNextNonDebugInstruction(); 518 Instruction &D = *C.getNextNonDebugInstruction(); 519 Instruction &E = *D.getNextNonDebugInstruction(); 520 Instruction &F_ = *E.getNextNonDebugInstruction(); 521 Instruction &Barrier = *F_.getNextNonDebugInstruction(); 522 Instruction &G = *Barrier.getNextNonDebugInstruction(); 523 524 // Simulate i32 <-> i64* conversion. Expect no updates: the datalayout says 525 // pointers are 64 bits, so the conversion would be lossy. 526 EXPECT_FALSE(replaceAllDbgUsesWith(A, C, C, DT)); 527 EXPECT_FALSE(replaceAllDbgUsesWith(C, A, A, DT)); 528 529 // Simulate i32 <-> <2 x i16> conversion. This is unsupported. 530 EXPECT_FALSE(replaceAllDbgUsesWith(E, A, A, DT)); 531 EXPECT_FALSE(replaceAllDbgUsesWith(A, E, E, DT)); 532 533 // Simulate i32* <-> i64* conversion. 534 EXPECT_TRUE(replaceAllDbgUsesWith(D, C, C, DT)); 535 536 SmallVector<DbgInfoIntrinsic *, 2> CDbgVals; 537 findDbgUsers(CDbgVals, &C); 538 EXPECT_EQ(2U, CDbgVals.size()); 539 EXPECT_TRUE(any_of(CDbgVals, [](DbgInfoIntrinsic *DII) { 540 return isa<DbgAddrIntrinsic>(DII); 541 })); 542 EXPECT_TRUE(any_of(CDbgVals, [](DbgInfoIntrinsic *DII) { 543 return isa<DbgDeclareInst>(DII); 544 })); 545 546 EXPECT_TRUE(replaceAllDbgUsesWith(C, D, D, DT)); 547 548 SmallVector<DbgInfoIntrinsic *, 2> DDbgVals; 549 findDbgUsers(DDbgVals, &D); 550 EXPECT_EQ(2U, DDbgVals.size()); 551 EXPECT_TRUE(any_of(DDbgVals, [](DbgInfoIntrinsic *DII) { 552 return isa<DbgAddrIntrinsic>(DII); 553 })); 554 EXPECT_TRUE(any_of(DDbgVals, [](DbgInfoIntrinsic *DII) { 555 return isa<DbgDeclareInst>(DII); 556 })); 557 558 // Introduce a use-before-def. Check that the dbg.value for %a is salvaged. 559 EXPECT_TRUE(replaceAllDbgUsesWith(A, F_, F_, DT)); 560 561 auto *ADbgVal = cast<DbgValueInst>(A.getNextNode()); 562 EXPECT_EQ(ConstantInt::get(A.getType(), 0), ADbgVal->getVariableLocation()); 563 564 // Introduce a use-before-def. Check that the dbg.values for %f are deleted. 565 EXPECT_TRUE(replaceAllDbgUsesWith(F_, G, G, DT)); 566 567 SmallVector<DbgValueInst *, 1> FDbgVals; 568 findDbgValues(FDbgVals, &F); 569 EXPECT_EQ(0U, FDbgVals.size()); 570 571 // Simulate i32 -> i64 conversion to test sign-extension. Here are some 572 // interesting cases to handle: 573 // 1) debug user has empty DIExpression 574 // 2) debug user has non-empty, non-stack-value'd DIExpression 575 // 3) debug user has non-empty, stack-value'd DIExpression 576 // 4-6) like (1-3), but with a fragment 577 EXPECT_TRUE(replaceAllDbgUsesWith(B, A, A, DT)); 578 579 SmallVector<DbgValueInst *, 8> ADbgVals; 580 findDbgValues(ADbgVals, &A); 581 EXPECT_EQ(6U, ADbgVals.size()); 582 583 // Check that %a has a dbg.value with a DIExpression matching \p Ops. 584 auto hasADbgVal = [&](ArrayRef<uint64_t> Ops) { 585 return any_of(ADbgVals, [&](DbgValueInst *DVI) { 586 assert(DVI->getVariable()->getName() == "2"); 587 return DVI->getExpression()->getElements() == Ops; 588 }); 589 }; 590 591 // Case 1: The original expr is empty, so no deref is needed. 592 EXPECT_TRUE(hasADbgVal({DW_OP_dup, DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, 593 DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value})); 594 595 // Case 2: Perform an address calculation with the original expr, deref it, 596 // then sign-extend the result. 597 EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_dup, 598 DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, DW_OP_not, 599 DW_OP_mul, DW_OP_or, DW_OP_stack_value})); 600 601 // Case 3: Insert the sign-extension logic before the DW_OP_stack_value. 602 EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_dup, DW_OP_constu, 31, 603 DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, 604 DW_OP_stack_value})); 605 606 // Cases 4-6: Just like cases 1-3, but preserve the fragment at the end. 607 EXPECT_TRUE(hasADbgVal({DW_OP_dup, DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, 608 DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value, 609 DW_OP_LLVM_fragment, 0, 8})); 610 EXPECT_TRUE( 611 hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_dup, DW_OP_constu, 612 31, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, 613 DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); 614 EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_dup, DW_OP_constu, 31, 615 DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, 616 DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); 617 618 verifyModule(*M, &errs(), &BrokenDebugInfo); 619 ASSERT_FALSE(BrokenDebugInfo); 620 } 621