diff --git a/llvm/lib/Transforms/IPO/StripSymbols.cpp b/llvm/lib/Transforms/IPO/StripSymbols.cpp --- a/llvm/lib/Transforms/IPO/StripSymbols.cpp +++ b/llvm/lib/Transforms/IPO/StripSymbols.cpp @@ -176,44 +176,6 @@ return true; } -/// Collects compilation units referenced by functions or lexical scopes. -/// Accepts any DIScope and uses recursive bottom-up approach to reach either -/// DISubprogram or DILexicalBlockBase. -static void -collectCUsWithScope(const DIScope *Scope, std::set &LiveCUs, - SmallPtrSet &VisitedScopes) { - if (!Scope) - return; - - auto InS = VisitedScopes.insert(Scope); - if (!InS.second) - return; - - if (const auto *SP = dyn_cast(Scope)) { - if (SP->getUnit()) - LiveCUs.insert(SP->getUnit()); - return; - } - if (const auto *LB = dyn_cast(Scope)) { - const DISubprogram *SP = LB->getSubprogram(); - if (SP && SP->getUnit()) - LiveCUs.insert(SP->getUnit()); - return; - } - - collectCUsWithScope(Scope->getScope(), LiveCUs, VisitedScopes); -} - -static void -collectCUsForInlinedFuncs(const DILocation *Loc, - std::set &LiveCUs, - SmallPtrSet &VisitedScopes) { - if (!Loc || !Loc->getInlinedAt()) - return; - collectCUsWithScope(Loc->getScope(), LiveCUs, VisitedScopes); - collectCUsForInlinedFuncs(Loc->getInlinedAt(), LiveCUs, VisitedScopes); -} - static bool stripDeadDebugInfoImpl(Module &M) { bool Changed = false; @@ -241,19 +203,15 @@ } std::set LiveCUs; - SmallPtrSet VisitedScopes; - // Any CU is live if is referenced from a subprogram metadata that is attached - // to a function defined or inlined in the module. - for (const Function &Fn : M.functions()) { - collectCUsWithScope(Fn.getSubprogram(), LiveCUs, VisitedScopes); - for (const_inst_iterator I = inst_begin(&Fn), E = inst_end(&Fn); I != E; - ++I) { - if (!I->getDebugLoc()) - continue; - const DILocation *DILoc = I->getDebugLoc().get(); - collectCUsForInlinedFuncs(DILoc, LiveCUs, VisitedScopes); - } + DebugInfoFinder LiveCUFinder; + for (const Function &F : M.functions()) { + if (auto *SP = cast_or_null(F.getSubprogram())) + LiveCUFinder.processSubprogram(SP); + for (const Instruction &I : instructions(F)) + LiveCUFinder.processInstruction(M, I); } + auto FoundCUs = LiveCUFinder.compile_units(); + LiveCUs.insert(FoundCUs.begin(), FoundCUs.end()); bool HasDeadCUs = false; for (DICompileUnit *DIC : F.compile_units()) { diff --git a/llvm/test/Transforms/StripSymbols/find-live-cu.ll b/llvm/test/Transforms/StripSymbols/find-live-cu.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/StripSymbols/find-live-cu.ll @@ -0,0 +1,37 @@ +; This test checks that strip-dead-debug-info pass doesn't delete debug compile +; units if they are used by @llvm.dbg.* intrinsics + +; RUN: opt -passes='strip-dead-debug-info,verify' %s -S | FileCheck %s + +; CHECK: !llvm.dbg.cu = !{!{{[0-9]+}}, !{{[0-9]+}}} +; CHECK-COUNT-2: !DICompileUnit + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +define void @func() { + %a = alloca i64 + call void @llvm.dbg.value(metadata ptr %a, metadata !7, metadata !DIExpression()), !dbg !9 + ret void +} + +!llvm.dbg.cu = !{!0, !1} +!llvm.module.flags = !{!10} + + +; We have two different compile units to able to check different paths of +; finding compile units (intrinsic argument and attached location to instruction) +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !11) +!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !11) + +!2 = distinct !DISubprogram(name: "func", unit: !0) +!3 = distinct !DICompositeType(tag: DW_TAG_class_type, scope: !2) +!4 = !DIDerivedType(tag: DW_TAG_member, scope: !3, baseType: !5) +!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6) +!6 = !DIBasicType(tag: DW_TAG_base_type) +!7 = !DILocalVariable(name: "a", type: !5, scope: !8) +!8 = distinct !DISubprogram(name: "func", unit: !1) +!9 = !DILocation(scope: !8) + +!10 = !{i32 2, !"Debug Info Version", i32 3} + +!11 = !DIFile(filename: "a", directory: "")