[llvm] [DebugInfo] Add DWARFUnit::clearDWO() (PR #214899)

Rafael Auler via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 14 14:53:00 PDT 2026


https://github.com/rafaelauler updated https://github.com/llvm/llvm-project/pull/214899

>From 56085f9db55022a7eace22a3c1ebf7e1f877f39d Mon Sep 17 00:00:00 2001
From: Rafael Auler <rafaelauler at fb.com>
Date: Thu, 30 Jul 2026 18:45:01 -0700
Subject: [PATCH 1/3] [DebugInfo] Add DWARFUnit::clearDWO()

Add DWARFUnit::clearDWO() so a skeleton unit can drop the DWO context
it owns without being destroyed itself. Also add DWARFUnit::hasDWO()
to answer if that skeleton CU is currently caching a DWO context, so
users can easily look it up.

For example, BOLT opened a DWARFContext for every .dwo during
readDebugInfo and kept them all alive until teardown. On large
split-DWARF targets that is tens of GiB held
resident. clearDWO()/hasDWO() expose to users DWARFUnit's caching
capacity, allowing them to spontaneously drop the cache/look it
up/re-load it for memory management.
---
 llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index bc5a0eb7c044f..593d0efc81568 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -461,6 +461,16 @@ class LLVM_ABI DWARFUnit {
                : getUnitDIE(ExtractUnitDIEOnly);
   }
 
+  /// Return the split unit this skeleton unit currently owns, or null if its
+  /// DWO context is not open.
+  DWARFUnit *getDWO() const { return DWO.get(); }
+
+  /// Release the DWO context owned by this skeleton unit, freeing the memory
+  /// held by its DWARFContext and parsed unit vector. This is safe to call once
+  /// the split-unit debug info has been fully processed; a subsequent
+  /// parseDWO() will transparently re-open it on demand.
+  void clearDWO() { DWO.reset(); }
+
   const char *getCompilationDir();
   std::optional<uint64_t> getDWOId() {
     extractDIEsIfNeeded(/*CUDieOnly*/ true);

>From 24a22b03366fd39acee9797c0d1d3c93c09076ea Mon Sep 17 00:00:00 2001
From: Rafael Auler <rafaelauler at fb.com>
Date: Wed, 12 Aug 2026 17:24:01 -0700
Subject: [PATCH 2/3] Add use case for clearDWO in llvm-dwarfdump

---
 llvm/lib/DebugInfo/DWARF/DWARFContext.cpp    | 22 +++++++++++++++-----
 llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp |  9 ++++++++
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 70ce257a5804a..570620575cd0e 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -1021,8 +1021,12 @@ void DWARFContext::dump(
 
   auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) {
     OS << '\n' << Name << " contents:\n";
-    if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo])
-      for (const auto &U : Units) {
+    std::optional<uint64_t> DumpOffset = DumpOffsets[DIDT_ID_DebugInfo];
+    for (const auto &U : Units) {
+      // For dumping of DWOs, remember if unit is already holding its context in
+      // memory
+      const bool HadDWO = U->getDWO();
+      if (DumpOffset) {
         U->getDIEForOffset(*DumpOffset)
             .dump(OS, 0, DumpOpts.noImplicitRecursion());
         DWARFDie CUDie = U->getUnitDIE(false);
@@ -1032,10 +1036,18 @@ void DWARFContext::dump(
               ->getDIEForOffset(*DumpOffset)
               .dump(OS, 0, DumpOpts.noImplicitRecursion());
         }
-      }
-    else
-      for (const auto &U : Units)
+      } else {
         U->dump(OS, DumpOpts);
+      }
+      // If our dump caused a new context for the non-skeleton unit in a DWO to
+      // be freshly opened, release it now. We won't re-use it. This avoids
+      // holding a lot of unnecessary anon memory while streaming through
+      // multiple DWOs (OTOH DWP is shared ctx, so better not to drop it
+      // otherwise it will be immediately reopened by the next non-skeleton CU).
+      const DWARFUnit *DWO = U->getDWO();
+      if (!HadDWO && DWO && !DWO->getContext().isDWP())
+        U->clearDWO();
+    }
   };
   if ((DumpType & DIDT_DebugInfo)) {
     if (Explicit || getNumCompileUnits())
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 4d7fc7e3108bf..41f9b1dc88284 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -492,11 +492,20 @@ static void filterByName(
     filterDieNames(CU.get());
     if (DumpNonSkeleton) {
       // If we have split DWARF, then recurse down into the .dwo files as well.
+      // Matching DIEs are printed as they are found and nothing here outlives
+      // them, so the split unit can be released instead of keeping every .dwo
+      // context resident until the end of the search.
+      const bool HadDWO = CU->getDWO();
       DWARFDie CUDie = CU->getUnitDIE(false);
       DWARFDie CUNonSkeletonDie = CU->getNonSkeletonUnitDIE(false);
       // If we have a DWO file, we need to search it as well
       if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie)
         filterDieNames(CUNonSkeletonDie.getDwarfUnit());
+      const DWARFUnit *DWO = CU->getDWO();
+      // Don't release a DWP context -- it is the same for every non-skeleton CU
+      // and we benefit from keeping it resident to avoid the re-parse.
+      if (!HadDWO && DWO && !DWO->getContext().isDWP())
+        CU->clearDWO();
     }
   }
 }

>From 0f54f2ecb3d0685bbaad3b463b6bbfb3e86c1349 Mon Sep 17 00:00:00 2001
From: Rafael Auler <rafaelauler at fb.com>
Date: Fri, 14 Aug 2026 14:52:24 -0700
Subject: [PATCH 3/3] Drop const in local

---
 llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 570620575cd0e..3cbfb0959e5f1 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -1025,7 +1025,7 @@ void DWARFContext::dump(
     for (const auto &U : Units) {
       // For dumping of DWOs, remember if unit is already holding its context in
       // memory
-      const bool HadDWO = U->getDWO();
+      bool HadDWO = U->getDWO();
       if (DumpOffset) {
         U->getDIEForOffset(*DumpOffset)
             .dump(OS, 0, DumpOpts.noImplicitRecursion());



More information about the llvm-commits mailing list