[llvm-branch-commits] [llvm] cc87fcf - [AccelTable] Pre-compute entry pool offsets for DW_IDX_parent. NFC (#188915)
Cullen Rhodes via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Mar 30 08:11:06 PDT 2026
Author: Fangrui Song
Date: 2026-03-30T15:10:58Z
New Revision: cc87fcfeef54a313df15c7435da906c5ee775996
URL: https://github.com/llvm/llvm-project/commit/cc87fcfeef54a313df15c7435da906c5ee775996
DIFF: https://github.com/llvm/llvm-project/commit/cc87fcfeef54a313df15c7435da906c5ee775996.diff
LOG: [AccelTable] Pre-compute entry pool offsets for DW_IDX_parent. NFC (#188915)
After PR #150846 changed MCFragment to use fixed 16KB blocks, large
sections like .debug_names produce thousands of fragments. The
DW_IDX_parent emission called emitLabelDifference(ParentSymbol,
EntryPool, 4) per entry, which fell through to
attemptToFoldSymbolOffsetDifference's O(n) fragment walk when symbols
were in different fragments. This caused O(entries * fragments)
quadratic behavior, regressing dsymutil on large binaries like clang.
Fix by pre-computing byte offsets from EntryPool for each entry in a
first pass, then emitting emitInt32(offset) directly for DW_IDX_parent
instead of symbol differences. This also eliminates per-entry MCSymbol
allocation that was only needed for parent references.
Fix #188376
(cherry picked from commit 0f63c0a3a5fa5ed41c1a53ef8520f88c280c5c78)
Added:
Modified:
llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
index 1ea30d8ab3c2b..27868ca4ad791 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/DIE.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include <cstddef>
@@ -225,8 +226,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
void emitAbbrevs() const;
void emitEntry(
const DWARF5AccelTableData &Entry,
- const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
- DenseSet<MCSymbol *> &EmittedAccelEntrySymbols);
+ const DenseMap<OffsetAndUnitID, uint64_t> &DIEOffsetToAccelEntryOffset);
+ uint64_t getEntrySize(const DWARF5AccelTableData &Entry) const;
void emitData();
public:
@@ -523,8 +524,7 @@ void Dwarf5AccelTableWriter::emitAbbrevs() const {
void Dwarf5AccelTableWriter::emitEntry(
const DWARF5AccelTableData &Entry,
- const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
- DenseSet<MCSymbol *> &EmittedAccelEntrySymbols) {
+ const DenseMap<OffsetAndUnitID, uint64_t> &DIEOffsetToAccelEntryOffset) {
unsigned AbbrevIndex = Entry.getAbbrevNumber() - 1;
assert(AbbrevIndex < AbbreviationsVector.size() &&
"Entry abbrev index is outside of abbreviations vector range.");
@@ -533,16 +533,6 @@ void Dwarf5AccelTableWriter::emitEntry(
getIndexForEntry(Entry);
std::optional<OffsetAndUnitID> MaybeParentOffset =
Entry.getParentDieOffsetAndUnitID();
- auto EntrySymbolIt =
- DIEOffsetToAccelEntryLabel.find(Entry.getDieOffsetAndUnitID());
- assert(EntrySymbolIt != DIEOffsetToAccelEntryLabel.end());
- MCSymbol *EntrySymbol = EntrySymbolIt->getSecond();
-
- // Emit the label for this Entry, so that IDX_parents may refer to it.
- // Note: a DIE may have multiple accelerator Entries; this check avoids
- // creating/emitting multiple labels for the same DIE.
- if (EmittedAccelEntrySymbols.insert(EntrySymbol).second)
- Asm->OutStreamer->emitLabel(EntrySymbol);
Asm->emitULEB128(Entry.getAbbrevNumber(), "Abbreviation code");
@@ -563,9 +553,9 @@ void Dwarf5AccelTableWriter::emitEntry(
case dwarf::DW_IDX_parent: {
if (AttrEnc.Form == dwarf::Form::DW_FORM_flag_present)
break;
- auto ParentSymbolIt = DIEOffsetToAccelEntryLabel.find(*MaybeParentOffset);
- assert(ParentSymbolIt != DIEOffsetToAccelEntryLabel.end());
- Asm->emitLabelDifference(ParentSymbolIt->getSecond(), EntryPool, 4);
+ auto It = DIEOffsetToAccelEntryOffset.find(*MaybeParentOffset);
+ assert(It != DIEOffsetToAccelEntryOffset.end());
+ Asm->emitInt32(It->second);
break;
}
default:
@@ -574,20 +564,57 @@ void Dwarf5AccelTableWriter::emitEntry(
}
}
-void Dwarf5AccelTableWriter::emitData() {
- DenseMap<OffsetAndUnitID, MCSymbol *> DIEOffsetToAccelEntryLabel;
+uint64_t
+Dwarf5AccelTableWriter::getEntrySize(const DWARF5AccelTableData &Entry) const {
+ unsigned AbbrevIndex = Entry.getAbbrevNumber() - 1;
+ assert(AbbrevIndex < AbbreviationsVector.size());
+ DebugNamesAbbrev *Abbrev = AbbreviationsVector[AbbrevIndex];
+ uint64_t Size = getULEB128Size(Entry.getAbbrevNumber());
+ std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
+ getIndexForEntry(Entry);
+ for (const auto &AttrEnc : Abbrev->getAttributes()) {
+ switch (AttrEnc.Index) {
+ case dwarf::DW_IDX_compile_unit:
+ case dwarf::DW_IDX_type_unit:
+ Size += DIEInteger(EntryRet->Index)
+ .sizeOf(Asm->getDwarfFormParams(), AttrEnc.Form);
+ break;
+ case dwarf::DW_IDX_die_offset:
+ Size += 4;
+ break;
+ case dwarf::DW_IDX_parent:
+ if (AttrEnc.Form != dwarf::Form::DW_FORM_flag_present)
+ Size += 4;
+ break;
+ default:
+ llvm_unreachable("Unexpected index attribute!");
+ }
+ }
+ return Size;
+}
- for (OffsetAndUnitID Offset : IndexedOffsets)
- DIEOffsetToAccelEntryLabel.insert({Offset, Asm->createTempSymbol("")});
+void Dwarf5AccelTableWriter::emitData() {
+ // Pre-compute entry pool offsets for DW_IDX_parent references.
+ DenseMap<OffsetAndUnitID, uint64_t> DIEOffsetToAccelEntryOffset;
+ uint64_t Offset = 0;
+ for (auto &Bucket : Contents.getBuckets()) {
+ for (auto *Hash : Bucket) {
+ for (const auto *Value : Hash->getValues<DWARF5AccelTableData *>()) {
+ DIEOffsetToAccelEntryOffset.try_emplace(Value->getDieOffsetAndUnitID(),
+ Offset);
+ Offset += getEntrySize(*Value);
+ }
+ Offset += 1; // End of list
+ }
+ }
Asm->OutStreamer->emitLabel(EntryPool);
- DenseSet<MCSymbol *> EmittedAccelEntrySymbols;
for (auto &Bucket : Contents.getBuckets()) {
for (auto *Hash : Bucket) {
// Remember to emit the label for our offset.
Asm->OutStreamer->emitLabel(Hash->Sym);
for (const auto *Value : Hash->getValues<DWARF5AccelTableData *>())
- emitEntry(*Value, DIEOffsetToAccelEntryLabel, EmittedAccelEntrySymbols);
+ emitEntry(*Value, DIEOffsetToAccelEntryOffset);
Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
Asm->emitInt8(0);
}
More information about the llvm-branch-commits
mailing list