|
17 | 17 | #include "gtest/gtest.h" |
18 | 18 | using namespace llvm; |
19 | 19 |
|
| 20 | +extern cl::opt<bool> UseNewDbgInfoFormat; |
| 21 | + |
20 | 22 | namespace { |
21 | 23 |
|
22 | 24 | TEST(ValueTest, UsedInBasicBlock) { |
@@ -314,4 +316,78 @@ TEST(ValueTest, replaceUsesOutsideBlock) { |
314 | 316 | ASSERT_TRUE(ExitDbg->getValue(0) == cast<Value>(B)); |
315 | 317 | ASSERT_TRUE(Ret->getOperand(0) == cast<Value>(B)); |
316 | 318 | } |
| 319 | + |
| 320 | +TEST(ValueTest, replaceUsesOutsideBlockDPValue) { |
| 321 | + // Check that Value::replaceUsesOutsideBlock(New, BB) replaces uses outside |
| 322 | + // BB, including DPValues. |
| 323 | + const auto *IR = R"( |
| 324 | + define i32 @f() !dbg !6 { |
| 325 | + entry: |
| 326 | + %a = add i32 0, 1, !dbg !15 |
| 327 | + %b = add i32 0, 2, !dbg !15 |
| 328 | + %c = add i32 %a, 2, !dbg !15 |
| 329 | + call void @llvm.dbg.value(metadata i32 %a, metadata !9, metadata !DIExpression()), !dbg !15 |
| 330 | + br label %exit, !dbg !15 |
| 331 | +
|
| 332 | + exit: |
| 333 | + call void @llvm.dbg.value(metadata i32 %a, metadata !11, metadata !DIExpression()), !dbg !16 |
| 334 | + ret i32 %a, !dbg !16 |
| 335 | + } |
| 336 | +
|
| 337 | + declare void @llvm.dbg.value(metadata, metadata, metadata) |
| 338 | +
|
| 339 | + !llvm.dbg.cu = !{!0} |
| 340 | + !llvm.module.flags = !{!5} |
| 341 | +
|
| 342 | + !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) |
| 343 | + !1 = !DIFile(filename: "test.ll", directory: "/") |
| 344 | + !2 = !{} |
| 345 | + !5 = !{i32 2, !"Debug Info Version", i32 3} |
| 346 | + !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) |
| 347 | + !7 = !DISubroutineType(types: !2) |
| 348 | + !8 = !{!9, !11} |
| 349 | + !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10) |
| 350 | + !10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_signed) |
| 351 | + !11 = !DILocalVariable(name: "2", scope: !6, file: !1, line: 2, type: !12) |
| 352 | + !12 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_signed) |
| 353 | + !15 = !DILocation(line: 1, column: 1, scope: !6) |
| 354 | + !16 = !DILocation(line: 5, column: 1, scope: !6) |
| 355 | + )"; |
| 356 | + LLVMContext Ctx; |
| 357 | + SMDiagnostic Err; |
| 358 | + std::unique_ptr<Module> M = parseAssemblyString(IR, Err, Ctx); |
| 359 | + if (!M) |
| 360 | + Err.print("ValueTest", errs()); |
| 361 | + |
| 362 | + bool OldDbgValueMode = UseNewDbgInfoFormat; |
| 363 | + UseNewDbgInfoFormat = true; |
| 364 | + M->convertToNewDbgValues(); |
| 365 | + |
| 366 | + auto GetNext = [](auto *I) { return &*++I->getIterator(); }; |
| 367 | + |
| 368 | + Function *F = M->getFunction("f"); |
| 369 | + // Entry. |
| 370 | + BasicBlock *Entry = &F->front(); |
| 371 | + Instruction *A = &Entry->front(); |
| 372 | + Instruction *B = GetNext(A); |
| 373 | + Instruction *C = GetNext(B); |
| 374 | + Instruction *Branch = GetNext(C); |
| 375 | + // Exit. |
| 376 | + BasicBlock *Exit = GetNext(Entry); |
| 377 | + Instruction *Ret = &Exit->front(); |
| 378 | + |
| 379 | + EXPECT_TRUE(Branch->hasDbgValues()); |
| 380 | + EXPECT_TRUE(Ret->hasDbgValues()); |
| 381 | + |
| 382 | + DPValue *DPV1 = &*Branch->getDbgValueRange().begin(); |
| 383 | + DPValue *DPV2 = &*Ret->getDbgValueRange().begin(); |
| 384 | + |
| 385 | + A->replaceUsesOutsideBlock(B, Entry); |
| 386 | + // These users are in Entry so shouldn't be changed. |
| 387 | + EXPECT_TRUE(DPV1->getVariableLocationOp(0) == cast<Value>(A)); |
| 388 | + // These users are outside Entry so should be changed. |
| 389 | + EXPECT_TRUE(DPV2->getVariableLocationOp(0) == cast<Value>(B)); |
| 390 | + UseNewDbgInfoFormat = OldDbgValueMode; |
| 391 | +} |
| 392 | + |
317 | 393 | } // end anonymous namespace |
0 commit comments