1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 11:42:57 +01:00

Bitcode: Fix major regression: large files w/ debug info

The metadata/value split introduced a major regression reading large
bitcode files that contain debug info (or other cyclic (non-self
reference) metadata graphs).  For the first time in a while, I dropped
from libLTO.dylib down to `llvm-lto` with a non-trivial bitcode file
(~350MB), and I hit this when reading the result of ld64's `-save-temps`
in `llvm-lto`.

Here's pseudo-code for what was going on:

    read-main-metadata-block:
      for each md:
        if has-fwd-ref: // Only true for cyclic graphs.
          any-fwd-refs <- true
      if any-fwd-refs:
        foreach md:
          resolve-cycles(md) // Handle cycles.

    foreach function:
      read-function-metadata-block: // Such as !alias, !loop
        if any-fwd-refs:
          foreach md: // (all metadata, not just this block)
            resolve-cycles(md) // A no-op, but the loop is expensive!!

This commit resets the `AnyFwdRefs` flag to `false`.  This on its own
was enough to change my Release+Asserts `llvm-lto` time for reading this
bitcode from over 20 minutes (I gave up on it) to 20 seconds.  I've gone
further by tracking the min/max metadata forward-references in a
metadata block.  This protects against a schema that has lots of
functions that each reference their own metadata cycle.

Unfortunately, this regression is in the 3.6 branch as well.

llvm-svn: 229421
This commit is contained in:
Duncan P. N. Exon Smith 2015-02-16 19:18:01 +00:00
parent 4da38e22ad
commit 29a6fcc535
2 changed files with 17 additions and 3 deletions

View File

@ -555,9 +555,17 @@ Metadata *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
if (Metadata *MD = MDValuePtrs[Idx]) if (Metadata *MD = MDValuePtrs[Idx])
return MD; return MD;
// Create and return a placeholder, which will later be RAUW'd. // Track forward refs to be resolved later.
AnyFwdRefs = true; if (AnyFwdRefs) {
MinFwdRef = std::min(MinFwdRef, Idx);
MaxFwdRef = std::max(MaxFwdRef, Idx);
} else {
AnyFwdRefs = true;
MinFwdRef = MaxFwdRef = Idx;
}
++NumFwdRefs; ++NumFwdRefs;
// Create and return a placeholder, which will later be RAUW'd.
Metadata *MD = MDNode::getTemporary(Context, None).release(); Metadata *MD = MDNode::getTemporary(Context, None).release();
MDValuePtrs[Idx].reset(MD); MDValuePtrs[Idx].reset(MD);
return MD; return MD;
@ -573,7 +581,8 @@ void BitcodeReaderMDValueList::tryToResolveCycles() {
return; return;
// Resolve any cycles. // Resolve any cycles.
for (auto &MD : MDValuePtrs) { for (unsigned I = MinFwdRef, E = MaxFwdRef + 1; I != E; ++I) {
auto &MD = MDValuePtrs[I];
auto *N = dyn_cast_or_null<MDNode>(MD); auto *N = dyn_cast_or_null<MDNode>(MD);
if (!N) if (!N)
continue; continue;
@ -581,6 +590,9 @@ void BitcodeReaderMDValueList::tryToResolveCycles() {
assert(!N->isTemporary() && "Unexpected forward reference"); assert(!N->isTemporary() && "Unexpected forward reference");
N->resolveCycles(); N->resolveCycles();
} }
// Make sure we return early again until there's another forward ref.
AnyFwdRefs = false;
} }
Type *BitcodeReader::getTypeByID(unsigned ID) { Type *BitcodeReader::getTypeByID(unsigned ID) {

View File

@ -99,6 +99,8 @@ public:
class BitcodeReaderMDValueList { class BitcodeReaderMDValueList {
unsigned NumFwdRefs; unsigned NumFwdRefs;
bool AnyFwdRefs; bool AnyFwdRefs;
unsigned MinFwdRef;
unsigned MaxFwdRef;
std::vector<TrackingMDRef> MDValuePtrs; std::vector<TrackingMDRef> MDValuePtrs;
LLVMContext &Context; LLVMContext &Context;