[llvm] [DebugInfo] Add fast path for parsing DW_TAG_compile_unit abbrevs (PR #108757)
Daniel Bertalan via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 17 02:06:23 PDT 2024
================
@@ -34,36 +34,49 @@ bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint64_t *OffsetPtr,
return false;
}
assert(DebugInfoData.isValidOffset(UEndOffset - 1));
+ AbbrevDecl = nullptr;
+
uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
if (0 == AbbrCode) {
// NULL debug tag entry.
- AbbrevDecl = nullptr;
return true;
}
- const auto *AbbrevSet = U.getAbbreviations();
- if (!AbbrevSet) {
- U.getContext().getWarningHandler()(
- createStringError(errc::invalid_argument,
- "DWARF unit at offset 0x%8.8" PRIx64 " "
- "contains invalid abbreviation set offset 0x%" PRIx64,
- U.getOffset(), U.getAbbreviationsOffset()));
- // Restore the original offset.
- *OffsetPtr = Offset;
- return false;
+
+ // Fast path: parsing the entire abbreviation table is wasteful if we only
+ // need the unit DIE (typically AbbrCode == 1).
+ if (1 == AbbrCode) {
----------------
BertalanD wrote:
> or change abbrev parsing to be lazy in general?
I have considered this, but this would likely pessimize the general case.
Profiling shows that the majority of `ld64.lld`'s DWARF parsing time is split evenly between ULEB128 parsing and appending to the `DWARFAbbreviationDeclaration::attribute_specs` vector.
As far as I can tell, everything is ULEB128-encoded in the abbrev table, so if we do it lazily, we'll end up constantly re-parsing the abbrev declarations that come before the one we're looking for. So we'd parse these numbers `O(n^2)` times instead of `O(n)`. I guess we could do a first pass where we only note down the begin offsets of the abbreviations, but that would bring us back to the situation with the large number of vector appends.
And if we *do* need everything, the total cost of building e.g. an `std::map` would end up being larger than the vector appends' cost. For the use cases where everything is needed (LLDB, dsymutil, etc.), constructing the single sorted vector upfront (i.e. what `DWARFAbbreviationDeclarationSet` does) is faster than the above approach.
> Could this either generalize this to check the first abbrev in the table
Do you mean always trying to parse the first abbreviation (so no `AbbrCode == 1` check), and checking afterwards if the code happens to be what we need? That sounds okay to me, since after the first call, the value is cached, so its cost would be a single `std::map` lookup.
Just out of curiosity, how common is the first abbreviation code not being 1 or code 1 not being `DW_TAG_compile_unit`?
https://github.com/llvm/llvm-project/pull/108757
More information about the llvm-commits
mailing list