Skip to content

Commit 0d2f55a

Browse files
committed
Update format to reduce bitcode size and thin link memory overhead.
1 parent 8d960cf commit 0d2f55a

File tree

8 files changed

+120
-134
lines changed

8 files changed

+120
-134
lines changed

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ enum GlobalValueSummarySymtabCodes {
308308
FS_PERMODULE_CALLSITE_INFO = 26,
309309
// Summary of per-module allocation memprof metadata.
310310
// [nummib, nummib x (alloc type, numstackids, numstackids x stackidindex),
311-
// [nummib x (numcontext x contextsizeindex)]?]
311+
// [nummib x (numcontext x total size)]?]
312312
FS_PERMODULE_ALLOC_INFO = 27,
313313
// Summary of combined index memprof callsite metadata.
314314
// [valueid, numstackindices, numver,
@@ -322,10 +322,15 @@ enum GlobalValueSummarySymtabCodes {
322322
// List of all stack ids referenced by index in the callsite and alloc infos.
323323
// [n x stack id]
324324
FS_STACK_IDS = 30,
325-
// List of all (full stack id, total size) pairs optionally referenced by
326-
// index from the alloc info records.
327-
// [n x (full stack id, total size)]
328-
FS_CONTEXT_SIZE_INFO = 31,
325+
// List of all full stack id pairs corresponding to the total sizes recorded
326+
// at the end of the alloc info when reporting of hinted bytes is enabled.
327+
// We use a fixed-width array, which is more efficient as these ids typically
328+
// are close to 64 bits in size. The max fixed width value supported is 32
329+
// bits so each 64-bit context id hash is recorded as a pair (upper 32 bits
330+
// first). This record must immediately precede the associated alloc info, and
331+
// the entries must be in the exact same order as the corresponding sizes.
332+
// [nummib x (numcontext x full stack id)]
333+
FS_ALLOC_CONTEXT_IDS = 31,
329334
};
330335

331336
enum MetadataCodes {

llvm/include/llvm/IR/ModuleSummaryIndex.h

Lines changed: 13 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,8 @@ struct AllocInfo {
421421
// MIBs vector, if non-empty. Note that each MIB in the summary can have
422422
// multiple of these as we trim the contexts when possible during matching.
423423
// For hinted size reporting we, however, want the original pre-trimmed full
424-
// stack context id for better correlation with the profile. Note that these
425-
// are indexes into the ContextSizeInfos list in the index, to enable
426-
// deduplication.
427-
std::vector<std::vector<unsigned>> ContextSizeInfoIndices;
424+
// stack context id for better correlation with the profile.
425+
std::vector<std::vector<ContextTotalSize>> ContextSizeInfos;
428426

429427
AllocInfo(std::vector<MIBInfo> MIBs) : MIBs(std::move(MIBs)) {
430428
Versions.push_back(0);
@@ -446,19 +444,16 @@ inline raw_ostream &operator<<(raw_ostream &OS, const AllocInfo &AE) {
446444
for (auto &M : AE.MIBs) {
447445
OS << "\t\t" << M << "\n";
448446
}
449-
if (!AE.ContextSizeInfoIndices.empty()) {
450-
OS << " ContextSizeInfo index per MIB:\n\t\t";
451-
First = true;
452-
for (auto Indices : AE.ContextSizeInfoIndices) {
453-
if (!First)
454-
OS << ", ";
455-
First = false;
456-
bool FirstIndex = true;
457-
for (uint64_t Index : Indices) {
458-
if (!FirstIndex)
447+
if (!AE.ContextSizeInfos.empty()) {
448+
OS << "\tContextSizeInfo per MIB:\n";
449+
for (auto Infos : AE.ContextSizeInfos) {
450+
OS << "\t\t";
451+
bool FirstInfo = true;
452+
for (auto [FullStackId, TotalSize] : Infos) {
453+
if (!FirstInfo)
459454
OS << ", ";
460-
FirstIndex = false;
461-
OS << Index;
455+
FirstInfo = false;
456+
OS << "{ " << FullStackId << ", " << TotalSize << " }";
462457
}
463458
OS << "\n";
464459
}
@@ -1447,19 +1442,6 @@ class ModuleSummaryIndex {
14471442
// built via releaseTemporaryMemory.
14481443
DenseMap<uint64_t, unsigned> StackIdToIndex;
14491444

1450-
// List of unique ContextTotalSize structs (pair of the full stack id hash and
1451-
// its associated total profiled size). We use an index into this vector when
1452-
// referencing from the alloc summary to reduce the overall memory and size
1453-
// requirements, since often allocations may be duplicated due to inlining.
1454-
std::vector<ContextTotalSize> ContextSizeInfos;
1455-
1456-
// Temporary map while building the ContextSizeInfos list. Clear when index is
1457-
// completely built via releaseTemporaryMemory.
1458-
// Maps from full stack id to a map of total size to the assigned index.
1459-
// We need size in here too because due to stack truncation in the profile we
1460-
// can have the same full stack id and different sizes.
1461-
DenseMap<uint64_t, DenseMap<uint64_t, unsigned>> ContextToTotalSizeAndIndex;
1462-
14631445
// YAML I/O support.
14641446
friend yaml::MappingTraits<ModuleSummaryIndex>;
14651447

@@ -1504,9 +1486,6 @@ class ModuleSummaryIndex {
15041486
size_t size() const { return GlobalValueMap.size(); }
15051487

15061488
const std::vector<uint64_t> &stackIds() const { return StackIds; }
1507-
const std::vector<ContextTotalSize> &contextSizeInfos() const {
1508-
return ContextSizeInfos;
1509-
}
15101489

15111490
unsigned addOrGetStackIdIndex(uint64_t StackId) {
15121491
auto Inserted = StackIdToIndex.insert({StackId, StackIds.size()});
@@ -1520,36 +1499,15 @@ class ModuleSummaryIndex {
15201499
return StackIds[Index];
15211500
}
15221501

1523-
unsigned addOrGetContextSizeIndex(ContextTotalSize ContextSizeInfo) {
1524-
auto &Entry = ContextToTotalSizeAndIndex[ContextSizeInfo.FullStackId];
1525-
auto Inserted =
1526-
Entry.insert({ContextSizeInfo.TotalSize, ContextSizeInfos.size()});
1527-
if (Inserted.second)
1528-
ContextSizeInfos.push_back(
1529-
{ContextSizeInfo.FullStackId, ContextSizeInfo.TotalSize});
1530-
else
1531-
assert(Inserted.first->first == ContextSizeInfo.TotalSize);
1532-
return Inserted.first->second;
1533-
}
1534-
1535-
ContextTotalSize getContextSizeInfoAtIndex(unsigned Index) const {
1536-
assert(ContextSizeInfos.size() > Index);
1537-
return ContextSizeInfos[Index];
1538-
}
1539-
15401502
// Facility to release memory from data structures only needed during index
1541-
// construction (including while building combined index). Currently this
1503+
// construction (including while building combined index). Currently this only
15421504
// releases the temporary map used while constructing a correspondence between
1543-
// stack ids and their index in the StackIds vector, and a similar map used
1544-
// while constructing the ContextSizeInfos vector. Mostly impactful when
1505+
// stack ids and their index in the StackIds vector. Mostly impactful when
15451506
// building a large combined index.
15461507
void releaseTemporaryMemory() {
15471508
assert(StackIdToIndex.size() == StackIds.size());
15481509
StackIdToIndex.clear();
15491510
StackIds.shrink_to_fit();
1550-
assert(ContextToTotalSizeAndIndex.size() == ContextSizeInfos.size());
1551-
ContextToTotalSizeAndIndex.clear();
1552-
ContextSizeInfos.shrink_to_fit();
15531511
}
15541512

15551513
/// Convenience function for doing a DFS on a ValueInfo. Marks the function in

llvm/lib/Analysis/ModuleSummaryAnalysis.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ static void computeFunctionSummary(
523523
if (MemProfMD) {
524524
std::vector<MIBInfo> MIBs;
525525
std::vector<uint64_t> TotalSizes;
526-
std::vector<std::vector<unsigned>> ContextSizeInfoIndices;
526+
std::vector<std::vector<ContextTotalSize>> ContextSizeInfos;
527527
for (auto &MDOp : MemProfMD->operands()) {
528528
auto *MIBMD = cast<const MDNode>(MDOp);
529529
MDNode *StackNode = getMIBStackNode(MIBMD);
@@ -545,7 +545,7 @@ static void computeFunctionSummary(
545545
// the summary.
546546
assert(MIBMD->getNumOperands() > 2 || !MemProfReportHintedSizes);
547547
if (MIBMD->getNumOperands() > 2) {
548-
std::vector<unsigned> ContextSizeIndices;
548+
std::vector<ContextTotalSize> ContextSizes;
549549
for (unsigned I = 2; I < MIBMD->getNumOperands(); I++) {
550550
MDNode *ContextSizePair = dyn_cast<MDNode>(MIBMD->getOperand(I));
551551
assert(ContextSizePair->getNumOperands() == 2);
@@ -555,20 +555,18 @@ static void computeFunctionSummary(
555555
uint64_t TS = mdconst::dyn_extract<ConstantInt>(
556556
ContextSizePair->getOperand(1))
557557
->getZExtValue();
558-
ContextSizeIndices.push_back(
559-
Index.addOrGetContextSizeIndex({FullStackId, TS}));
558+
ContextSizes.push_back({FullStackId, TS});
560559
}
561-
ContextSizeInfoIndices.push_back(std::move(ContextSizeIndices));
560+
ContextSizeInfos.push_back(std::move(ContextSizes));
562561
}
563562
MIBs.push_back(
564563
MIBInfo(getMIBAllocType(MIBMD), std::move(StackIdIndices)));
565564
}
566565
Allocs.push_back(AllocInfo(std::move(MIBs)));
567-
assert(!ContextSizeInfoIndices.empty() || !MemProfReportHintedSizes);
568-
if (!ContextSizeInfoIndices.empty()) {
569-
assert(Allocs.back().MIBs.size() == ContextSizeInfoIndices.size());
570-
Allocs.back().ContextSizeInfoIndices =
571-
std::move(ContextSizeInfoIndices);
566+
assert(!ContextSizeInfos.empty() || !MemProfReportHintedSizes);
567+
if (!ContextSizeInfos.empty()) {
568+
assert(Allocs.back().MIBs.size() == ContextSizeInfos.size());
569+
Allocs.back().ContextSizeInfos = std::move(ContextSizeInfos);
572570
}
573571
} else if (!InstCallsite.empty()) {
574572
SmallVector<unsigned> StackIdIndices;

llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ GetCodeName(unsigned CodeID, unsigned BlockID,
328328
STRINGIFY_CODE(FS, COMBINED_CALLSITE_INFO)
329329
STRINGIFY_CODE(FS, COMBINED_ALLOC_INFO)
330330
STRINGIFY_CODE(FS, STACK_IDS)
331-
STRINGIFY_CODE(FS, CONTEXT_SIZE_INFO)
331+
STRINGIFY_CODE(FS, ALLOC_CONTEXT_IDS)
332332
}
333333
case bitc::METADATA_ATTACHMENT_ID:
334334
switch (CodeID) {

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -987,11 +987,6 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase {
987987
/// ids from the lists in the callsite and alloc entries to the index.
988988
std::vector<uint64_t> StackIds;
989989

990-
// Saves the context total size information from the CONTEXT_SIZE_INFO record
991-
// to consult when adding this from the lists in the alloc entries to the
992-
// index.
993-
std::vector<ContextTotalSize> ContextSizeInfos;
994-
995990
public:
996991
ModuleSummaryIndexBitcodeReader(
997992
BitstreamCursor Stream, StringRef Strtab, ModuleSummaryIndex &TheIndex,
@@ -7608,6 +7603,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
76087603

76097604
std::vector<CallsiteInfo> PendingCallsites;
76107605
std::vector<AllocInfo> PendingAllocs;
7606+
std::vector<uint64_t> PendingContextIds;
76117607

76127608
while (true) {
76137609
Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
@@ -8002,14 +7998,6 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
80027998
break;
80037999
}
80048000

8005-
case bitc::FS_CONTEXT_SIZE_INFO: { // [n x (fullstackid, totalsize)]
8006-
// Save context size infos in the reader to consult when adding them from
8007-
// the lists in the alloc node entries.
8008-
for (auto R = Record.begin(); R != Record.end(); R += 2)
8009-
ContextSizeInfos.push_back({*R, *(R + 1)});
8010-
break;
8011-
}
8012-
80138001
case bitc::FS_PERMODULE_CALLSITE_INFO: {
80148002
unsigned ValueID = Record[0];
80158003
SmallVector<unsigned> StackIdList;
@@ -8044,6 +8032,16 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
80448032
break;
80458033
}
80468034

8035+
case bitc::FS_ALLOC_CONTEXT_IDS: {
8036+
// This is an array of 32-bit fixed-width values, holding each 64-bit
8037+
// context id as a pair of adjacent (most significant first) 32-bit words.
8038+
assert(!(Record.size() % 2));
8039+
PendingContextIds.reserve(Record.size() / 2);
8040+
for (auto R = Record.begin(); R != Record.end(); R += 2)
8041+
PendingContextIds.push_back(*R << 32 | *(R + 1));
8042+
break;
8043+
}
8044+
80478045
case bitc::FS_PERMODULE_ALLOC_INFO: {
80488046
unsigned I = 0;
80498047
std::vector<MIBInfo> MIBs;
@@ -8066,30 +8064,40 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
80668064
MIBs.push_back(MIBInfo(AllocType, std::move(StackIdList)));
80678065
}
80688066
// We either have nothing left or at least NumMIBs context size info
8069-
// indices left.
8067+
// indices left (for the total sizes included when reporting of hinted
8068+
// bytes is enabled).
80708069
assert(I == Record.size() || Record.size() - I >= NumMIBs);
8071-
std::vector<std::vector<unsigned>> AllContextSizeIndices;
8070+
std::vector<std::vector<ContextTotalSize>> AllContextSizes;
80728071
if (I < Record.size()) {
8072+
assert(!PendingContextIds.empty() &&
8073+
"Missing context ids for alloc sizes");
8074+
unsigned ContextIdIndex = 0;
80738075
MIBsRead = 0;
8076+
// The sizes are a linearized array of sizes, where for each MIB there
8077+
// is 1 or more sizes (due to context trimming, each MIB in the metadata
8078+
// and summarized here can correspond to more than one original context
8079+
// from the profile).
80748080
while (MIBsRead++ < NumMIBs) {
8081+
// First read the number of contexts recorded for this MIB.
80758082
unsigned NumContextSizeInfoEntries = Record[I++];
80768083
assert(Record.size() - I >= NumContextSizeInfoEntries);
8077-
std::vector<unsigned> ContextSizeIndices;
8078-
ContextSizeIndices.reserve(NumContextSizeInfoEntries);
8084+
std::vector<ContextTotalSize> ContextSizes;
8085+
ContextSizes.reserve(NumContextSizeInfoEntries);
80798086
for (unsigned J = 0; J < NumContextSizeInfoEntries; J++) {
8080-
assert(Record[I] < ContextSizeInfos.size());
8081-
ContextSizeIndices.push_back(TheIndex.addOrGetContextSizeIndex(
8082-
ContextSizeInfos[Record[I++]]));
8087+
assert(ContextIdIndex < PendingContextIds.size());
8088+
// PendingContextIds read from the preceding FS_ALLOC_CONTEXT_IDS
8089+
// should be in the same order as the total sizes.
8090+
ContextSizes.push_back(
8091+
{PendingContextIds[ContextIdIndex++], Record[I++]});
80838092
}
8084-
AllContextSizeIndices.push_back(std::move(ContextSizeIndices));
8093+
AllContextSizes.push_back(std::move(ContextSizes));
80858094
}
8095+
PendingContextIds.clear();
80868096
}
80878097
PendingAllocs.push_back(AllocInfo(std::move(MIBs)));
8088-
if (!AllContextSizeIndices.empty()) {
8089-
assert(PendingAllocs.back().MIBs.size() ==
8090-
AllContextSizeIndices.size());
8091-
PendingAllocs.back().ContextSizeInfoIndices =
8092-
std::move(AllContextSizeIndices);
8098+
if (!AllContextSizes.empty()) {
8099+
assert(PendingAllocs.back().MIBs.size() == AllContextSizes.size());
8100+
PendingAllocs.back().ContextSizeInfos = std::move(AllContextSizes);
80938101
}
80948102
break;
80958103
}

0 commit comments

Comments
 (0)