Index: lib/Transforms/Scalar/ADCE.cpp =================================================================== --- lib/Transforms/Scalar/ADCE.cpp +++ lib/Transforms/Scalar/ADCE.cpp @@ -470,6 +470,17 @@ // Routines to update the CFG and SSA information before removing dead code. // //===----------------------------------------------------------------------===// + +/// Traverse through the inlinedAt field of \p DL and each subsequent DebugLoc +/// until no more inlinedAt field is found. +static DebugLoc getInlinedAtLeaf(DebugLoc DL) { + while (DebugLoc InlinedAt = DL.getInlinedAt()) { + DL = InlinedAt; + } + + return DL; +} + bool AggressiveDeadCodeElimination::removeDeadInstructions() { // Updates control and dataflow around dead blocks @@ -482,8 +493,9 @@ continue; if (auto *DII = dyn_cast(&I)) { - // Check if the scope of this variable location is alive. - if (AliveScopes.count(DII->getDebugLoc()->getScope())) + // Check if the scope of this variable location is alive. Follow each + // "inlinedAt" if present. + if (AliveScopes.count(getInlinedAtLeaf(DII->getDebugLoc()).getScope())) continue; // If intrinsic is pointing at a live SSA value, there may be an @@ -507,8 +519,9 @@ continue; if (auto *DII = dyn_cast(&I)) { - // Check if the scope of this variable location is alive. - if (AliveScopes.count(DII->getDebugLoc()->getScope())) + // Check if the scope of this variable location is alive. Follow each + // "inlinedAt" if present. + if (AliveScopes.count(getInlinedAtLeaf(DII->getDebugLoc()).getScope())) continue; // Fallthrough and drop the intrinsic. Index: test/Transforms/ADCE/debug-info-intrinsic-inlinedat.ll =================================================================== --- /dev/null +++ test/Transforms/ADCE/debug-info-intrinsic-inlinedat.ll @@ -0,0 +1,42 @@ +; RUN: opt -S -adce %s -o - | FileCheck %s + +; The call to dbg.value is the result of a previously inlined call to function +; f1. Thus !9 uses a scope in f1, and "inlinedAt" is set, pointing to the +; location of the call. + +; This dbg.value can be useful and shouldn't be removed. Make sure it's still there +; after ADCE has run. + +@a = external global i16 +@b = external global i16 + +define void @f2() { + %_tmp = load i16, i16* @a, !dbg !8 + call void @llvm.dbg.value(metadata i16 %_tmp, metadata !5, metadata !6), !dbg !9 + store i16 %_tmp, i16* @b + ret void +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!2, !3} + +!0 = !DIFile(filename: "foo.c", directory: "bar") +!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !0) +!2 = !{i32 2, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = distinct !DISubprogram(name: "f1", unit: !1) +!5 = !DILocalVariable(scope: !4) +!6 = !DIExpression() +!7 = distinct !DISubprogram(name: "f2", unit: !1) +!8 = !DILocation(scope: !7) +!9 = !DILocation(scope: !4, inlinedAt: !10) +!10 = distinct !DILocation(scope: !7) + +; Make sure there is still a dbg.value for %_tmp + +; CHECK: define void @f2 +; CHECK: %_tmp = load +; CHECK: call void @llvm.dbg.value(metadata i16 %_tmp +; CHECK: store i16 %_tmp