summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Bitcode
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2016-04-23 04:15:56 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2016-04-23 04:15:56 +0000
commit4b1bc647f05341a959c6f6a433791d4ce62e7de4 (patch)
tree04c21c05428558205be92fe4388e8f97ebf70efc /llvm/lib/Bitcode
parent2923a432ab09bb83ed4a84547937be531e36e514 (diff)
downloadbcm5719-llvm-4b1bc647f05341a959c6f6a433791d4ce62e7de4.tar.gz
bcm5719-llvm-4b1bc647f05341a959c6f6a433791d4ce62e7de4.zip
BitcodeReader: Avoid referencing unresolved nodes from distinct ones
Each reference to an unresolved MDNode is expensive, since the RAUW support in MDNode uses a separate allocation and side map. Since a distinct MDNode doesn't require its operands on creation (unlike uniuqed nodes, there's no need to check for structural equivalence), use nullptr for any of its unresolved operands. Besides reducing the burden on MDNode maps, this can avoid allocating temporary MDNodes in the first place. We need some way to track operands. Invent DistinctMDOperandPlaceholder for this purpose, which is a Metadata subclass that holds an ID and points at its single user. DistinctMDOperandPlaceholder::replaceUseWith is just like RAUW, but its name highlights that there is only ever exactly one use. There is no support for moving (or, obviously, copying) these. Move support would be possible but expensive; leaving it unimplemented prevents user error. In the BitcodeReader I originally considered allocating on a BumpPtrAllocator and keeping a vector of pointers to them, and then I realized that std::deque implements exactly this. A couple of obvious follow-ups: - Change ValueEnumerator to emit distinct nodes first to take more advantage of this optimization. (How convenient... I think I might have a couple of patches for this.) - Change DIBuilder and its consumers (like CGDebugInfo in clang) to use something like this when constructing debug info in the first place. llvm-svn: 267270
Diffstat (limited to 'llvm/lib/Bitcode')
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp67
1 files changed, 61 insertions, 6 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index ba26b2778ad..d4df9b4d551 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -133,13 +133,26 @@ public:
return MetadataPtrs[i];
}
+ Metadata *lookup(unsigned I) const {
+ return I < MetadataPtrs.size() ? MetadataPtrs[I] : nullptr;
+ }
+
void shrinkTo(unsigned N) {
assert(N <= size() && "Invalid shrinkTo request!");
assert(!AnyFwdRefs && "Unexpected forward refs");
MetadataPtrs.resize(N);
}
+ /// Return the given metadata, creating a replaceable forward reference if
+ /// necessary.
Metadata *getMetadataFwdRef(unsigned Idx);
+
+ /// Return the the given metadata only if it is fully resolved.
+ ///
+ /// Gives the same result as \a lookup(), unless \a MDNode::isResolved()
+ /// would give \c false.
+ Metadata *getMetadataIfResolved(unsigned Idx);
+
MDNode *getMDNodeFwdRefOrNull(unsigned Idx);
void assignValue(Metadata *MD, unsigned Idx);
void tryToResolveCycles();
@@ -1090,6 +1103,14 @@ Metadata *BitcodeReaderMetadataList::getMetadataFwdRef(unsigned Idx) {
return MD;
}
+Metadata *BitcodeReaderMetadataList::getMetadataIfResolved(unsigned Idx) {
+ Metadata *MD = lookup(Idx);
+ if (auto *N = dyn_cast_or_null<MDNode>(MD))
+ if (!N->isResolved())
+ return nullptr;
+ return MD;
+}
+
MDNode *BitcodeReaderMetadataList::getMDNodeFwdRefOrNull(unsigned Idx) {
return dyn_cast_or_null<MDNode>(getMetadataFwdRef(Idx));
}
@@ -1933,6 +1954,31 @@ std::error_code BitcodeReader::parseMetadataStrings(ArrayRef<uint64_t> Record,
return std::error_code();
}
+namespace {
+class PlaceholderQueue {
+ // Placeholders would thrash around when moved, so store in a std::deque
+ // instead of some sort of vector.
+ std::deque<DistinctMDOperandPlaceholder> PHs;
+
+public:
+ DistinctMDOperandPlaceholder &getPlaceholderOp(unsigned ID);
+ void flush(BitcodeReaderMetadataList &MetadataList);
+};
+} // end namespace
+
+DistinctMDOperandPlaceholder &PlaceholderQueue::getPlaceholderOp(unsigned ID) {
+ PHs.emplace_back(ID);
+ return PHs.back();
+}
+
+void PlaceholderQueue::flush(BitcodeReaderMetadataList &MetadataList) {
+ while (!PHs.empty()) {
+ PHs.front().replaceUseWith(
+ MetadataList.getMetadataFwdRef(PHs.front().getID()));
+ PHs.pop_front();
+ }
+}
+
/// Parse a METADATA_BLOCK. If ModuleLevel is true then we are parsing
/// module level metadata.
std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
@@ -1948,12 +1994,19 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
std::vector<std::pair<DICompileUnit *, Metadata *>> CUSubprograms;
SmallVector<uint64_t, 64> Record;
- auto getMD = [&](unsigned ID) -> Metadata * {
- return MetadataList.getMetadataFwdRef(ID);
+ PlaceholderQueue Placeholders;
+ bool IsDistinct;
+ auto getMD = [&](unsigned ID, bool AllowPlaceholders = true) -> Metadata * {
+ if (!IsDistinct || !AllowPlaceholders)
+ return MetadataList.getMetadataFwdRef(ID);
+ if (auto *MD = MetadataList.getMetadataIfResolved(ID))
+ return MD;
+ return &Placeholders.getPlaceholderOp(ID);
};
- auto getMDOrNull = [&](unsigned ID) -> Metadata *{
+ auto getMDOrNull = [&](unsigned ID,
+ bool AllowPlaceholders = true) -> Metadata * {
if (ID)
- return getMD(ID - 1);
+ return getMD(ID - 1, AllowPlaceholders);
return nullptr;
};
auto getMDString = [&](unsigned ID) -> MDString *{
@@ -1982,6 +2035,7 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
SP->replaceOperandWith(7, CU_SP.first);
MetadataList.tryToResolveCycles();
+ Placeholders.flush(MetadataList);
return std::error_code();
case BitstreamEntry::Record:
// The interesting case.
@@ -1992,7 +2046,7 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
Record.clear();
StringRef Blob;
unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
- bool IsDistinct = false;
+ IsDistinct = false;
switch (Code) {
default: // Default behavior: ignore.
break;
@@ -2275,7 +2329,8 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
MetadataList.assignValue(CU, NextMetadataNo++);
// Move the Upgrade the list of subprograms.
- if (Metadata *SPs = getMDOrNull(Record[11]))
+ if (Metadata *SPs =
+ getMDOrNull(Record[11], /* AllowPlaceholders = */ false))
CUSubprograms.push_back({CU, SPs});
break;
}
OpenPOWER on IntegriCloud