aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ProfileData/SampleProfReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ProfileData/SampleProfReader.cpp')
-rw-r--r--llvm/lib/ProfileData/SampleProfReader.cpp126
1 files changed, 92 insertions, 34 deletions
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index fbdd9a3..0b47082 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -61,9 +61,9 @@ static cl::opt<bool> ProfileIsFSDisciminator(
///
/// \param FContext Name + context of the function to print.
/// \param OS Stream to emit the output to.
-void SampleProfileReader::dumpFunctionProfile(SampleContext FContext,
+void SampleProfileReader::dumpFunctionProfile(const FunctionSamples &FS,
raw_ostream &OS) {
- OS << "Function: " << FContext.toString() << ": " << Profiles[FContext];
+ OS << "Function: " << FS.getContext().toString() << ": " << FS;
}
/// Dump all the function profiles found on stream \p OS.
@@ -71,7 +71,7 @@ void SampleProfileReader::dump(raw_ostream &OS) {
std::vector<NameFunctionSamples> V;
sortFuncProfiles(Profiles, V);
for (const auto &I : V)
- dumpFunctionProfile(I.first, OS);
+ dumpFunctionProfile(*I.second, OS);
}
static void dumpFunctionProfileJson(const FunctionSamples &S,
@@ -355,9 +355,7 @@ std::error_code SampleProfileReaderText::readImpl() {
SampleContext FContext(FName, CSNameTable);
if (FContext.hasContext())
++CSProfileCount;
- Profiles[FContext] = FunctionSamples();
- FunctionSamples &FProfile = Profiles[FContext];
- FProfile.setContext(FContext);
+ FunctionSamples &FProfile = Profiles.Create(FContext);
MergeResult(Result, FProfile.addTotalSamples(NumSamples));
MergeResult(Result, FProfile.addHeadSamples(NumHeadSamples));
InlineStack.clear();
@@ -525,7 +523,8 @@ inline ErrorOr<size_t> SampleProfileReaderBinary::readStringIndex(T &Table) {
return *Idx;
}
-ErrorOr<StringRef> SampleProfileReaderBinary::readStringFromTable() {
+ErrorOr<StringRef>
+SampleProfileReaderBinary::readStringFromTable(size_t *RetIdx) {
auto Idx = readStringIndex(NameTable);
if (std::error_code EC = Idx.getError())
return EC;
@@ -543,30 +542,52 @@ ErrorOr<StringRef> SampleProfileReaderBinary::readStringFromTable() {
MD5NameMemStart + (*Idx) * sizeof(uint64_t));
SR = MD5StringBuf.emplace_back(std::to_string(FID));
}
+ if (RetIdx)
+ *RetIdx = *Idx;
return SR;
}
-ErrorOr<SampleContextFrames> SampleProfileReaderBinary::readContextFromTable() {
+ErrorOr<SampleContextFrames>
+SampleProfileReaderBinary::readContextFromTable(size_t *RetIdx) {
auto ContextIdx = readNumber<size_t>();
if (std::error_code EC = ContextIdx.getError())
return EC;
if (*ContextIdx >= CSNameTable.size())
return sampleprof_error::truncated_name_table;
+ if (RetIdx)
+ *RetIdx = *ContextIdx;
return CSNameTable[*ContextIdx];
}
-ErrorOr<SampleContext> SampleProfileReaderBinary::readSampleContextFromTable() {
+ErrorOr<std::pair<SampleContext, hash_code>>
+SampleProfileReaderBinary::readSampleContextFromTable() {
+ SampleContext Context;
+ size_t Idx;
if (ProfileIsCS) {
- auto FContext(readContextFromTable());
+ auto FContext(readContextFromTable(&Idx));
if (std::error_code EC = FContext.getError())
return EC;
- return SampleContext(*FContext);
+ Context = SampleContext(*FContext);
} else {
- auto FName(readStringFromTable());
+ auto FName(readStringFromTable(&Idx));
if (std::error_code EC = FName.getError())
return EC;
- return SampleContext(*FName);
+ Context = SampleContext(*FName);
+ }
+ // Since MD5SampleContextStart may point to the profile's file data, need to
+ // make sure it is reading the same value on big endian CPU.
+ hash_code Hash =
+ support::endian::read<hash_code, support::little, support::unaligned>(
+ MD5SampleContextStart + Idx);
+ // Lazy computing of hash value, write back to the table to cache it. Only
+ // compute the context's hash value if it is being referenced for the first
+ // time.
+ if (Hash == hash_code(0)) {
+ assert(MD5SampleContextStart == MD5SampleContextTable.data());
+ Hash = Context.getHashCode();
+ support::endian::write(&MD5SampleContextTable[Idx], Hash, support::little);
}
+ return std::make_pair(Context, Hash);
}
std::error_code
@@ -659,16 +680,18 @@ SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start) {
if (std::error_code EC = NumHeadSamples.getError())
return EC;
- ErrorOr<SampleContext> FContext(readSampleContextFromTable());
- if (std::error_code EC = FContext.getError())
+ auto FContextHash(readSampleContextFromTable());
+ if (std::error_code EC = FContextHash.getError())
return EC;
- Profiles[*FContext] = FunctionSamples();
- FunctionSamples &FProfile = Profiles[*FContext];
- FProfile.setContext(*FContext);
+ auto &[FContext, Hash] = *FContextHash;
+ // Use the cached hash value for insertion instead of recalculating it.
+ auto Res = Profiles.try_emplace(Hash, FContext, FunctionSamples());
+ FunctionSamples &FProfile = Res.first->second;
+ FProfile.setContext(FContext);
FProfile.addHeadSamples(*NumHeadSamples);
- if (FContext->hasContext())
+ if (FContext.hasContext())
CSProfileCount++;
if (std::error_code EC = readProfile(FProfile))
@@ -816,18 +839,21 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() {
FuncOffsetTable.reserve(*Size);
for (uint64_t I = 0; I < *Size; ++I) {
- auto FContext(readSampleContextFromTable());
- if (std::error_code EC = FContext.getError())
+ auto FContextHash(readSampleContextFromTable());
+ if (std::error_code EC = FContextHash.getError())
return EC;
+ auto &[FContext, Hash] = *FContextHash;
auto Offset = readNumber<uint64_t>();
if (std::error_code EC = Offset.getError())
return EC;
if (UseFuncOffsetList)
- FuncOffsetList.emplace_back(*FContext, *Offset);
+ FuncOffsetList.emplace_back(FContext, *Offset);
else
- FuncOffsetTable[*FContext] = *Offset;
+ // Because Porfiles replace existing value with new value if collision
+ // happens, we also use the latest offset so that they are consistent.
+ FuncOffsetTable[Hash] = *Offset;
}
return sampleprof_error::success;
@@ -900,8 +926,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
} else if (useMD5()) {
assert(!useFuncOffsetList());
for (auto Name : FuncsToUse) {
- auto GUID = std::to_string(MD5Hash(Name));
- auto iter = FuncOffsetTable.find(StringRef(GUID));
+ auto GUID = MD5Hash(Name);
+ auto iter = FuncOffsetTable.find(GUID);
if (iter == FuncOffsetTable.end())
continue;
const uint8_t *FuncProfileAddr = Start + iter->second;
@@ -922,7 +948,7 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
} else {
assert(!useFuncOffsetList());
for (auto Name : FuncsToUse) {
- auto iter = FuncOffsetTable.find(Name);
+ auto iter = FuncOffsetTable.find(MD5Hash(Name));
if (iter == FuncOffsetTable.end())
continue;
const uint8_t *FuncProfileAddr = Start + iter->second;
@@ -1050,17 +1076,30 @@ std::error_code SampleProfileReaderBinary::readNameTable() {
NameTable.clear();
NameTable.reserve(*Size);
+ if (!ProfileIsCS) {
+ MD5SampleContextTable.clear();
+ if (UseMD5)
+ MD5SampleContextTable.reserve(*Size);
+ else
+ // If we are using strings, delay MD5 computation since only a portion of
+ // names are used by top level functions. Use 0 to indicate MD5 value is
+ // to be calculated as no known string has a MD5 value of 0.
+ MD5SampleContextTable.resize(*Size);
+ }
for (size_t I = 0; I < *Size; ++I) {
auto Name(readString());
if (std::error_code EC = Name.getError())
return EC;
if (UseMD5) {
- uint64_t FID = MD5Hash(*Name);
+ uint64_t FID = hashFuncName(*Name);
+ if (!ProfileIsCS)
+ MD5SampleContextTable.emplace_back(FID);
NameTable.emplace_back(MD5StringBuf.emplace_back(std::to_string(FID)));
} else
NameTable.push_back(*Name);
}
-
+ if (!ProfileIsCS)
+ MD5SampleContextStart = MD5SampleContextTable.data();
return sampleprof_error::success;
}
@@ -1088,6 +1127,8 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
NameTable.clear();
NameTable.resize(*Size);
MD5NameMemStart = Data;
+ if (!ProfileIsCS)
+ MD5SampleContextStart = reinterpret_cast<const hash_code *>(Data);
Data = Data + (*Size) * sizeof(uint64_t);
return sampleprof_error::success;
}
@@ -1101,12 +1142,19 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
MD5StringBuf.reserve(MD5StringBuf.size() + *Size);
NameTable.clear();
NameTable.reserve(*Size);
+ if (!ProfileIsCS)
+ MD5SampleContextTable.resize(*Size);
for (size_t I = 0; I < *Size; ++I) {
auto FID = readNumber<uint64_t>();
if (std::error_code EC = FID.getError())
return EC;
+ if (!ProfileIsCS)
+ support::endian::write(&MD5SampleContextTable[I], *FID,
+ support::little);
NameTable.emplace_back(MD5StringBuf.emplace_back(std::to_string(*FID)));
}
+ if (!ProfileIsCS)
+ MD5SampleContextStart = MD5SampleContextTable.data();
return sampleprof_error::success;
}
@@ -1124,6 +1172,14 @@ std::error_code SampleProfileReaderExtBinaryBase::readCSNameTableSec() {
CSNameTable.clear();
CSNameTable.reserve(*Size);
+ if (ProfileIsCS) {
+ // Delay MD5 computation of CS context until they are needed. Use 0 to
+ // indicate MD5 value is to be calculated as no known string has a MD5
+ // value of 0.
+ MD5SampleContextTable.clear();
+ MD5SampleContextTable.resize(*Size);
+ MD5SampleContextStart = MD5SampleContextTable.data();
+ }
for (size_t I = 0; I < *Size; ++I) {
CSNameTable.emplace_back(SampleContextFrameVector());
auto ContextSize = readNumber<uint32_t>();
@@ -1187,16 +1243,17 @@ SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute,
if (std::error_code EC = Discriminator.getError())
return EC;
- auto FContext(readSampleContextFromTable());
- if (std::error_code EC = FContext.getError())
+ auto FContextHash(readSampleContextFromTable());
+ if (std::error_code EC = FContextHash.getError())
return EC;
+ auto &[FContext, Hash] = *FContextHash;
FunctionSamples *CalleeProfile = nullptr;
if (FProfile) {
CalleeProfile = const_cast<FunctionSamples *>(
&FProfile->functionSamplesAt(LineLocation(
*LineOffset,
- *Discriminator))[std::string(FContext.get().getName())]);
+ *Discriminator))[std::string(FContext.getName())]);
}
if (std::error_code EC =
readFuncMetadata(ProfileHasAttribute, CalleeProfile))
@@ -1211,11 +1268,12 @@ SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute,
std::error_code
SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute) {
while (Data < End) {
- auto FContext(readSampleContextFromTable());
- if (std::error_code EC = FContext.getError())
+ auto FContextHash(readSampleContextFromTable());
+ if (std::error_code EC = FContextHash.getError())
return EC;
+ auto &[FContext, Hash] = *FContextHash;
FunctionSamples *FProfile = nullptr;
- auto It = Profiles.find(*FContext);
+ auto It = Profiles.find(FContext);
if (It != Profiles.end())
FProfile = &It->second;