[llvm] 2bb5535 - [StripDeadDebugInfo] Drop dead CUs

Alexey Bader via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 11 01:34:14 PDT 2022


Author: Alexey Bader
Date: 2022-09-11T01:31:03-07:00
New Revision: 2bb5535b58edb04358e58495b302c9613b101227

URL: https://github.com/llvm/llvm-project/commit/2bb5535b58edb04358e58495b302c9613b101227
DIFF: https://github.com/llvm/llvm-project/commit/2bb5535b58edb04358e58495b302c9613b101227.diff

LOG: [StripDeadDebugInfo] Drop dead CUs

In situations when a submodule is extracted from big module (i.e. using
CloneModule) a lot of debug info is copied via metadata nodes. Despite of
the fact that part of that info is not linked to any instruction in extracted
IR file, StripDeadDebugInfo pass doesn't drop them.
Strengthen criteria for debug info that should be kept in a module:
- Only those compile units are left that referenced by a subprogram debug info
node that is attached to a function definition in the module or to an instruction
in the module that belongs to an inlined function.

Signed-off-by: Mikhail Lychkov <mikhail.lychkov at intel.com>

Differential Revision: https://reviews.llvm.org/D122163

Added: 
    llvm/test/Transforms/StripSymbols/strip-cu-with-dangling-subprogram.ll

Modified: 
    llvm/lib/Transforms/IPO/StripSymbols.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/StripSymbols.cpp b/llvm/lib/Transforms/IPO/StripSymbols.cpp
index c05829faf7862..159f0b25ecad6 100644
--- a/llvm/lib/Transforms/IPO/StripSymbols.cpp
+++ b/llvm/lib/Transforms/IPO/StripSymbols.cpp
@@ -24,6 +24,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/PassManager.h"
@@ -294,6 +295,44 @@ bool StripDebugDeclare::runOnModule(Module &M) {
   return stripDebugDeclareImpl(M);
 }
 
+/// 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<DICompileUnit *> &LiveCUs,
+                    SmallPtrSet<const DIScope *, 8> &VisitedScopes) {
+  if (!Scope)
+    return;
+
+  auto InS = VisitedScopes.insert(Scope);
+  if (!InS.second)
+    return;
+
+  if (const auto *SP = dyn_cast<DISubprogram>(Scope)) {
+    if (SP->getUnit())
+      LiveCUs.insert(SP->getUnit());
+    return;
+  }
+  if (const auto *LB = dyn_cast<DILexicalBlockBase>(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<DICompileUnit *> &LiveCUs,
+                          SmallPtrSet<const DIScope *, 8> &VisitedScopes) {
+  if (!Loc || !Loc->getInlinedAt())
+    return;
+  collectCUsWithScope(Loc->getScope(), LiveCUs, VisitedScopes);
+  collectCUsForInlinedFuncs(Loc->getInlinedAt(), LiveCUs, VisitedScopes);
+}
+
 static bool stripDeadDebugInfoImpl(Module &M) {
   bool Changed = false;
 
@@ -321,10 +360,18 @@ static bool stripDeadDebugInfoImpl(Module &M) {
   }
 
   std::set<DICompileUnit *> LiveCUs;
-  // Any CU referenced from a subprogram is live.
-  for (DISubprogram *SP : F.subprograms()) {
-    if (SP->getUnit())
-      LiveCUs.insert(SP->getUnit());
+  SmallPtrSet<const DIScope *, 8> 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);
+    }
   }
 
   bool HasDeadCUs = false;

diff  --git a/llvm/test/Transforms/StripSymbols/strip-cu-with-dangling-subprogram.ll b/llvm/test/Transforms/StripSymbols/strip-cu-with-dangling-subprogram.ll
new file mode 100644
index 0000000000000..9b36aa6a6760e
--- /dev/null
+++ b/llvm/test/Transforms/StripSymbols/strip-cu-with-dangling-subprogram.ll
@@ -0,0 +1,43 @@
+; This test checks that strip-dead-debug-info pass deletes debug compile units
+; if functions from those units are absent in that module.
+
+; RUN: opt -passes='strip-dead-debug-info,verify' %s -S | FileCheck %s
+
+; CHECK: !llvm.dbg.cu = !{!{{[0-9]+}}, !{{[0-9]+}}}
+; CHECK-COUNT-2: !DICompileUnit
+
+;target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
+;target triple = "spir64-unknown-unknown"
+
+; Function Attrs: nounwind
+define void @dev_func1() #0 !dbg !13 {
+  ret void, !dbg !14
+}
+
+; Function Attrs: nounwind
+define void @dev_func2() #0 !dbg !15 {
+  ret void, !dbg !16
+}
+
+attributes #0 = { nounwind }
+
+!llvm.dbg.cu = !{!0, !3, !5}
+!llvm.module.flags = !{!12}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, imports: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "dev_func1.cpp", directory: "/home/user/test")
+!2 = !{}
+!3 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !4, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, imports: !2, splitDebugInlining: false, nameTableKind: None)
+!4 = !DIFile(filename: "dev_func2.cpp", directory: "/home/user/test")
+!5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !6, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, imports: !7, splitDebugInlining: false, nameTableKind: None)
+!6 = !DIFile(filename: "dev_func3.cpp", directory: "/home/user/test")
+!7 = !{!8}
+!8 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !6, entity: !9, file: !6, line: 129)
+!9 = distinct !DISubprogram(name: "dev_func3", linkageName: "dev_func3", scope: !6, file: !6, line: 96, type: !10, scopeLine: 96, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !5, retainedNodes: !2)
+!10 = !DISubroutineType(types: !11)
+!11 = !{null}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = distinct !DISubprogram(name: "dev_func1", linkageName: "dev_func1", scope: !1, file: !1, line: 22, type: !10, scopeLine: 22, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!14 = !DILocation(line: 29, column: 5, scope: !13)
+!15 = distinct !DISubprogram(name: "dev_func2", linkageName: "dev_func2", scope: !4, file: !4, line: 22, type: !10, scopeLine: 22, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !3, retainedNodes: !2)
+!16 = !DILocation(line: 29, column: 5, scope: !15)


        


More information about the llvm-commits mailing list