From 060ee625b8a72cf4b85958e2e6d895d509403306 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Mon, 16 Feb 2015 19:18:01 +0000 Subject: 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 --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp') diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 4fe054d..ca4d66a 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -555,9 +555,17 @@ Metadata *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) { if (Metadata *MD = MDValuePtrs[Idx]) return MD; - // Create and return a placeholder, which will later be RAUW'd. - AnyFwdRefs = true; + // Track forward refs to be resolved later. + if (AnyFwdRefs) { + MinFwdRef = std::min(MinFwdRef, Idx); + MaxFwdRef = std::max(MaxFwdRef, Idx); + } else { + AnyFwdRefs = true; + MinFwdRef = MaxFwdRef = Idx; + } ++NumFwdRefs; + + // Create and return a placeholder, which will later be RAUW'd. Metadata *MD = MDNode::getTemporary(Context, None).release(); MDValuePtrs[Idx].reset(MD); return MD; @@ -573,7 +581,8 @@ void BitcodeReaderMDValueList::tryToResolveCycles() { return; // 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(MD); if (!N) continue; @@ -581,6 +590,9 @@ void BitcodeReaderMDValueList::tryToResolveCycles() { assert(!N->isTemporary() && "Unexpected forward reference"); N->resolveCycles(); } + + // Make sure we return early again until there's another forward ref. + AnyFwdRefs = false; } Type *BitcodeReader::getTypeByID(unsigned ID) { -- cgit v1.1