Skip to content

Commit f4d7058

Browse files
[MemProf] Determine stack id references in BitcodeWriter without sorting (#94285)
A cycle profile of a thin link showed a lot of time spent in sort called from the BitcodeWriter, which was being used to compute the unique references to stack ids in the summaries emitted for each backend in a distributed thinlto build. We were also frequently invoking lower_bound to locate stack id indices in the resulting vector when writing out the referencing memprof records. Change this to use a map to uniquify the references, and to hold the index of the corresponding stack id in the StackIds vector, which is now populated at the same time. This reduced the time of a large thin link by about 10%.
1 parent d041343 commit f4d7058

File tree

1 file changed

+31
-21
lines changed

1 file changed

+31
-21
lines changed

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -437,10 +437,14 @@ class IndexBitcodeWriter : public BitcodeWriterBase {
437437
/// index and a value id generated by this class to use in references.
438438
std::map<GlobalValue::GUID, unsigned> GUIDToValueIdMap;
439439

440-
// The sorted stack id indices actually used in the summary entries being
441-
// written, which will be a subset of those in the full index in the case of
442-
// distributed indexes.
443-
std::vector<unsigned> StackIdIndices;
440+
// The stack ids used by this index, which will be a subset of those in
441+
// the full index in the case of distributed indexes.
442+
std::vector<uint64_t> StackIds;
443+
444+
// Keep a map of the stack id indices used by records being written for this
445+
// index to the index of the corresponding stack id in the above StackIds
446+
// vector. Ensures we write each referenced stack id once.
447+
DenseMap<unsigned, unsigned> StackIdIndicesToIndex;
444448

445449
/// Tracks the last value id recorded in the GUIDToValueMap.
446450
unsigned GlobalValueId = 0;
@@ -464,6 +468,19 @@ class IndexBitcodeWriter : public BitcodeWriterBase {
464468
: BitcodeWriterBase(Stream, StrtabBuilder), Index(Index),
465469
DecSummaries(DecSummaries),
466470
ModuleToSummariesForIndex(ModuleToSummariesForIndex) {
471+
472+
// See if the StackIdIndex was already added to the StackId map and
473+
// vector. If not, record it.
474+
auto RecordStackIdReference = [&](unsigned StackIdIndex) {
475+
// If the StackIdIndex is not yet in the map, the below insert ensures
476+
// that it will point to the new StackIds vector entry we push to just
477+
// below.
478+
auto Inserted =
479+
StackIdIndicesToIndex.insert({StackIdIndex, StackIds.size()});
480+
if (Inserted.second)
481+
StackIds.push_back(Index.getStackIdAtIndex(StackIdIndex));
482+
};
483+
467484
// Assign unique value ids to all summaries to be written, for use
468485
// in writing out the call graph edges. Save the mapping from GUID
469486
// to the new global value id to use when writing those edges, which
@@ -494,17 +511,13 @@ class IndexBitcodeWriter : public BitcodeWriterBase {
494511
continue;
495512
}
496513
for (auto Idx : CI.StackIdIndices)
497-
StackIdIndices.push_back(Idx);
514+
RecordStackIdReference(Idx);
498515
}
499516
for (auto &AI : FS->allocs())
500517
for (auto &MIB : AI.MIBs)
501518
for (auto Idx : MIB.StackIdIndices)
502-
StackIdIndices.push_back(Idx);
519+
RecordStackIdReference(Idx);
503520
});
504-
llvm::sort(StackIdIndices);
505-
StackIdIndices.erase(
506-
std::unique(StackIdIndices.begin(), StackIdIndices.end()),
507-
StackIdIndices.end());
508521
}
509522

510523
/// The below iterator returns the GUID and associated summary.
@@ -4492,18 +4505,15 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
44924505
ArrayRef<uint64_t>{GVI.second, GVI.first});
44934506
}
44944507

4495-
if (!StackIdIndices.empty()) {
4508+
// Write the stack ids used by this index, which will be a subset of those in
4509+
// the full index in the case of distributed indexes.
4510+
if (!StackIds.empty()) {
44964511
auto StackIdAbbv = std::make_shared<BitCodeAbbrev>();
44974512
StackIdAbbv->Add(BitCodeAbbrevOp(bitc::FS_STACK_IDS));
44984513
// numids x stackid
44994514
StackIdAbbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
45004515
StackIdAbbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
45014516
unsigned StackIdAbbvId = Stream.EmitAbbrev(std::move(StackIdAbbv));
4502-
// Write the stack ids used by this index, which will be a subset of those in
4503-
// the full index in the case of distributed indexes.
4504-
std::vector<uint64_t> StackIds;
4505-
for (auto &I : StackIdIndices)
4506-
StackIds.push_back(Index.getStackIdAtIndex(I));
45074517
Stream.EmitRecord(bitc::FS_STACK_IDS, StackIds, StackIdAbbvId);
45084518
}
45094519

@@ -4669,11 +4679,11 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
46694679
return *ValueID;
46704680
},
46714681
/*GetStackIndex*/ [&](unsigned I) {
4672-
// Get the corresponding index into the list of StackIdIndices
4673-
// actually being written for this combined index (which may be a
4674-
// subset in the case of distributed indexes).
4675-
auto Lower = llvm::lower_bound(StackIdIndices, I);
4676-
return std::distance(StackIdIndices.begin(), Lower);
4682+
// Get the corresponding index into the list of StackIds actually
4683+
// being written for this combined index (which may be a subset in
4684+
// the case of distributed indexes).
4685+
assert(StackIdIndicesToIndex.contains(I));
4686+
return StackIdIndicesToIndex[I];
46774687
});
46784688

46794689
NameVals.push_back(*ValueId);

0 commit comments

Comments
 (0)