summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2018-08-07 09:54:52 +0000
committerPavel Labath <pavel@labath.sk>2018-08-07 09:54:52 +0000
commit2f0881160c2135e1e3230c50645d9728ed51844c (patch)
tree8706f3838d69e574f9d1549e1f0cea1bf6f28b08 /llvm/lib/CodeGen
parent7e189387933796602b65aa8dc04c4b3309e47e47 (diff)
downloadbcm5719-llvm-2f0881160c2135e1e3230c50645d9728ed51844c.tar.gz
bcm5719-llvm-2f0881160c2135e1e3230c50645d9728ed51844c.zip
[DebugInfo] Reduce debug_str_offsets section size
Summary: The accelerator tables use the debug_str section to store their strings. However, they do not support the indirect method of access that is available for the debug_info section (DW_FORM_strx et al.). Currently our code is assuming that all strings can/will be referenced indirectly, and puts all of them into the debug_str_offsets section. This is generally true for regular (unsplit) dwarf, but in the DWO case, most of the strings in the debug_str section will only be used from the accelerator tables. Therefore the contents of the debug_str_offsets section will be largely unused and bloating the main executable. This patch rectifies this by teaching the DwarfStringPool to differentiate between strings accessed directly and indirectly. When a user inserts a string into the pool it has to declare whether that string will be referenced directly or not. If at least one user requsts indirect access, that string will be assigned an index ID and put into debug_str_offsets table. Otherwise, the offset table is skipped. This approach reduces the overall binary size (when compiled with -gdwarf-5 -gsplit-dwarf) in my tests by about 2% (debug_str_offsets is shrunk by 99%). Reviewers: probinson, dblaikie, JDevlieghere Subscribers: aprantl, mgrang, llvm-commits Differential Revision: https://reviews.llvm.org/D49493 llvm-svn: 339122
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp50
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h10
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp7
4 files changed, 56 insertions, 14 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 549bf74a129..388fe8a822f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -2437,8 +2437,7 @@ void DwarfDebug::addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name,
return;
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
- DwarfStringPoolEntryRef Ref =
- Holder.getStringPool().getEntry(*Asm, Name);
+ DwarfStringPoolEntryRef Ref = Holder.getStringPool().getEntry(*Asm, Name);
switch (getAccelTableKind()) {
case AccelTableKind::Apple:
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
index a61fa83cfb0..83c07d1fe45 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
@@ -24,25 +24,39 @@ DwarfStringPool::DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm,
: Pool(A), Prefix(Prefix),
ShouldCreateSymbols(Asm.MAI->doesDwarfUseRelocationsAcrossSections()) {}
-DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
- StringRef Str) {
+StringMapEntry<DwarfStringPool::EntryTy> &
+DwarfStringPool::getEntryImpl(AsmPrinter &Asm, StringRef Str) {
auto I = Pool.insert(std::make_pair(Str, EntryTy()));
+ auto &Entry = I.first->second;
if (I.second) {
- auto &Entry = I.first->second;
- Entry.Index = Pool.size() - 1;
+ Entry.Index = EntryTy::NotIndexed;
Entry.Offset = NumBytes;
Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) : nullptr;
NumBytes += Str.size() + 1;
assert(NumBytes > Entry.Offset && "Unexpected overflow");
}
- return EntryRef(*I.first);
+ return *I.first;
+}
+
+DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
+ StringRef Str) {
+ auto &MapEntry = getEntryImpl(Asm, Str);
+ return EntryRef(MapEntry, false);
+}
+
+DwarfStringPool::EntryRef DwarfStringPool::getIndexedEntry(AsmPrinter &Asm,
+ StringRef Str) {
+ auto &MapEntry = getEntryImpl(Asm, Str);
+ if (!MapEntry.getValue().isIndexed())
+ MapEntry.getValue().Index = NumIndexedStrings++;
+ return EntryRef(MapEntry, true);
}
void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
MCSection *Section,
MCSymbol *StartSym) {
- if (empty())
+ if (getNumIndexedStrings() == 0)
return;
Asm.OutStreamer->SwitchSection(Section);
unsigned EntrySize = 4;
@@ -51,7 +65,7 @@ void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
// table. The header consists of an entry with the contribution's
// size (not including the size of the length field), the DWARF version and
// 2 bytes of padding.
- Asm.emitInt32(size() * EntrySize + 4);
+ Asm.emitInt32(getNumIndexedStrings() * EntrySize + 4);
Asm.emitInt16(Asm.getDwarfVersion());
Asm.emitInt16(0);
// Define the symbol that marks the start of the contribution. It is
@@ -69,12 +83,18 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
// Start the dwarf str section.
Asm.OutStreamer->SwitchSection(StrSection);
- // Get all of the string pool entries and put them in an array by their ID so
- // we can sort them.
- SmallVector<const StringMapEntry<EntryTy> *, 64> Entries(Pool.size());
+ // Get all of the string pool entries and sort them by their offset.
+ SmallVector<const StringMapEntry<EntryTy> *, 64> Entries;
+ Entries.reserve(Pool.size());
for (const auto &E : Pool)
- Entries[E.getValue().Index] = &E;
+ Entries.push_back(&E);
+
+ llvm::sort(
+ Entries.begin(), Entries.end(),
+ [](const StringMapEntry<EntryTy> *A, const StringMapEntry<EntryTy> *B) {
+ return A->getValue().Offset < B->getValue().Offset;
+ });
for (const auto &Entry : Entries) {
assert(ShouldCreateSymbols == static_cast<bool>(Entry->getValue().Symbol) &&
@@ -93,6 +113,14 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
// If we've got an offset section go ahead and emit that now as well.
if (OffsetSection) {
+ // Now only take the indexed entries and put them in an array by their ID so
+ // we can emit them in order.
+ Entries.resize(NumIndexedStrings);
+ for (const auto &Entry : Pool) {
+ if (Entry.getValue().isIndexed())
+ Entries[Entry.getValue().Index] = &Entry;
+ }
+
Asm.OutStreamer->SwitchSection(OffsetSection);
unsigned size = 4; // FIXME: DWARF64 is 8.
for (const auto &Entry : Entries)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h b/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h
index 6e6988ea4ad..f484540d8d3 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h
@@ -30,8 +30,11 @@ class DwarfStringPool {
StringMap<EntryTy, BumpPtrAllocator &> Pool;
StringRef Prefix;
unsigned NumBytes = 0;
+ unsigned NumIndexedStrings = 0;
bool ShouldCreateSymbols;
+ StringMapEntry<EntryTy> &getEntryImpl(AsmPrinter &Asm, StringRef Str);
+
public:
using EntryRef = DwarfStringPoolEntryRef;
@@ -48,8 +51,15 @@ public:
unsigned size() const { return Pool.size(); }
+ unsigned getNumIndexedStrings() const { return NumIndexedStrings; }
+
/// Get a reference to an entry in the string pool.
EntryRef getEntry(AsmPrinter &Asm, StringRef Str);
+
+ /// Same as getEntry, except that you can use EntryRef::getIndex to obtain a
+ /// unique ID of this entry (e.g., for use in indexed forms like
+ /// DW_FORM_strx).
+ EntryRef getIndexedEntry(AsmPrinter &Asm, StringRef Str);
};
} // end namespace llvm
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index df67c5ff176..e38c854bc3d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -243,9 +243,14 @@ void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute,
DIEInlineString(String, DIEValueAllocator));
return;
}
- auto StringPoolEntry = DU->getStringPool().getEntry(*Asm, String);
dwarf::Form IxForm =
isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp;
+
+ auto StringPoolEntry =
+ useSegmentedStringOffsetsTable() || IxForm == dwarf::DW_FORM_GNU_str_index
+ ? DU->getStringPool().getIndexedEntry(*Asm, String)
+ : DU->getStringPool().getEntry(*Asm, String);
+
// For DWARF v5 and beyond, use the smallest strx? form possible.
if (useSegmentedStringOffsetsTable()) {
IxForm = dwarf::DW_FORM_strx1;
OpenPOWER on IntegriCloud