summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-02-16 19:18:01 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-02-16 19:18:01 +0000
commit060ee625b8a72cf4b85958e2e6d895d509403306 (patch)
tree912b8231c86ede31853480cb829104c00e2666b6
parent8b77454dff820832259acefe45e4254203760f19 (diff)
downloadbcm5719-llvm-060ee625b8a72cf4b85958e2e6d895d509403306.tar.gz
bcm5719-llvm-060ee625b8a72cf4b85958e2e6d895d509403306.zip
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
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp18
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.h2
2 files changed, 17 insertions, 3 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 4fe054de370..ca4d66a540b 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<MDNode>(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) {
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.h b/llvm/lib/Bitcode/Reader/BitcodeReader.h
index 7f7eb70bce9..5090be48450 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.h
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.h
@@ -99,6 +99,8 @@ public:
class BitcodeReaderMDValueList {
unsigned NumFwdRefs;
bool AnyFwdRefs;
+ unsigned MinFwdRef;
+ unsigned MaxFwdRef;
std::vector<TrackingMDRef> MDValuePtrs;
LLVMContext &Context;
OpenPOWER on IntegriCloud