diff options
author | Adrian Prantl <aprantl@apple.com> | 2016-04-15 15:57:41 +0000 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2016-04-15 15:57:41 +0000 |
commit | 75819aedf6d774a424e35793b266442708e57050 (patch) | |
tree | e4eabf3bd19e9dee6ed3aefc8f4e2cb16d6bb285 /llvm/lib/Bitcode/Reader/BitcodeReader.cpp | |
parent | e76bda544bbf52d9ff3b55e6018b494a1e6bbc00 (diff) | |
download | bcm5719-llvm-75819aedf6d774a424e35793b266442708e57050.tar.gz bcm5719-llvm-75819aedf6d774a424e35793b266442708e57050.zip |
[PR27284] Reverse the ownership between DICompileUnit and DISubprogram.
Currently each Function points to a DISubprogram and DISubprogram has a
scope field. For member functions the scope is a DICompositeType. DIScopes
point to the DICompileUnit to facilitate type uniquing.
Distinct DISubprograms (with isDefinition: true) are not part of the type
hierarchy and cannot be uniqued. This change removes the subprograms
list from DICompileUnit and instead adds a pointer to the owning compile
unit to distinct DISubprograms. This would make it easy for ThinLTO to
strip unneeded DISubprograms and their transitively referenced debug info.
Motivation
----------
Materializing DISubprograms is currently the most expensive operation when
doing a ThinLTO build of clang.
We want the DISubprogram to be stored in a separate Bitcode block (or the
same block as the function body) so we can avoid having to expensively
deserialize all DISubprograms together with the global metadata. If a
function has been inlined into another subprogram we need to store a
reference the block containing the inlined subprogram.
Attached to https://llvm.org/bugs/show_bug.cgi?id=27284 is a python script
that updates LLVM IR testcases to the new format.
http://reviews.llvm.org/D19034
<rdar://problem/25256815>
llvm-svn: 266446
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 321c775531e..c8322830766 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1948,6 +1948,7 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) { if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID)) return error("Invalid record"); + std::vector<std::pair<DICompileUnit *, Metadata *>> CUSubprograms; SmallVector<uint64_t, 64> Record; auto getMD = [&](unsigned ID) -> Metadata * { @@ -1976,6 +1977,13 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) { case BitstreamEntry::Error: return error("Malformed block"); case BitstreamEntry::EndBlock: + // Upgrade old-style CU <-> SP pointers to point from SP to CU. + for (auto CU_SP : CUSubprograms) + if (auto *SPs = dyn_cast_or_null<MDTuple>(CU_SP.second)) + for (auto &Op : SPs->operands()) + if (auto *SP = dyn_cast_or_null<MDNode>(Op)) + SP->replaceOperandWith(7, CU_SP.first); + MetadataList.tryToResolveCycles(); return std::error_code(); case BitstreamEntry::Record: @@ -2232,24 +2240,32 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) { // Ignore Record[0], which indicates whether this compile unit is // distinct. It's always distinct. - MetadataList.assignValue( - DICompileUnit::getDistinct( - Context, Record[1], getMDOrNull(Record[2]), - getMDString(Record[3]), Record[4], getMDString(Record[5]), - Record[6], getMDString(Record[7]), Record[8], - getMDOrNull(Record[9]), getMDOrNull(Record[10]), - getMDOrNull(Record[11]), getMDOrNull(Record[12]), - getMDOrNull(Record[13]), - Record.size() <= 15 ? nullptr : getMDOrNull(Record[15]), - Record.size() <= 14 ? 0 : Record[14]), - NextMetadataNo++); + auto *CU = DICompileUnit::getDistinct( + Context, Record[1], getMDOrNull(Record[2]), getMDString(Record[3]), + Record[4], getMDString(Record[5]), Record[6], getMDString(Record[7]), + Record[8], getMDOrNull(Record[9]), getMDOrNull(Record[10]), + getMDOrNull(Record[12]), getMDOrNull(Record[13]), + Record.size() <= 15 ? nullptr : getMDOrNull(Record[15]), + Record.size() <= 14 ? 0 : Record[14]); + + MetadataList.assignValue(CU, NextMetadataNo++); + + // Move the Upgrade the list of subprograms. + if (Metadata *SPs = getMDOrNull(Record[11])) + CUSubprograms.push_back({CU, SPs}); break; } case bitc::METADATA_SUBPROGRAM: { if (Record.size() != 18 && Record.size() != 19) return error("Invalid record"); - bool HasFn = Record.size() == 19; + // Version 1 has a Function as Record[15]. + // Version 2 has removed Record[15]. + // Version 3 has the Unit as Record[15]. + Metadata *CUorFn = getMDOrNull(Record[15]); + unsigned Offset = Record.size() == 19 ? 1 : 0; + bool HasFn = Offset && dyn_cast_or_null<ConstantAsMetadata>(CUorFn); + bool HasCU = Offset && !HasFn; DISubprogram *SP = GET_OR_DISTINCT( DISubprogram, Record[0] || Record[8], // All definitions should be distinct. @@ -2257,13 +2273,14 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) { getMDString(Record[3]), getMDOrNull(Record[4]), Record[5], getMDOrNull(Record[6]), Record[7], Record[8], Record[9], getMDOrNull(Record[10]), Record[11], Record[12], Record[13], - Record[14], getMDOrNull(Record[15 + HasFn]), - getMDOrNull(Record[16 + HasFn]), getMDOrNull(Record[17 + HasFn]))); + Record[14], HasCU ? CUorFn : nullptr, + getMDOrNull(Record[15 + Offset]), getMDOrNull(Record[16 + Offset]), + getMDOrNull(Record[17 + Offset]))); MetadataList.assignValue(SP, NextMetadataNo++); // Upgrade sp->function mapping to function->sp mapping. - if (HasFn && Record[15]) { - if (auto *CMD = dyn_cast<ConstantAsMetadata>(getMDOrNull(Record[15]))) + if (HasFn) { + if (auto *CMD = dyn_cast<ConstantAsMetadata>(CUorFn)) if (auto *F = dyn_cast<Function>(CMD->getValue())) { if (F->isMaterializable()) // Defer until materialized; unmaterialized functions may not have |