summaryrefslogtreecommitdiff
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.cpp297
1 files changed, 216 insertions, 81 deletions
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index c42931174bc0..6058eddb13dc 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -26,6 +26,7 @@
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/LEB128.h"
@@ -38,12 +39,22 @@
#include <cstdint>
#include <limits>
#include <memory>
+#include <set>
#include <system_error>
#include <vector>
using namespace llvm;
using namespace sampleprof;
+#define DEBUG_TYPE "samplepgo-reader"
+
+// This internal option specifies if the profile uses FS discriminators.
+// It only applies to text, binary and compact binary format profiles.
+// For ext-binary format profiles, the flag is set in the summary.
+static cl::opt<bool> ProfileIsFSDisciminator(
+ "profile-isfs", cl::Hidden, cl::init(false),
+ cl::desc("Profile uses flow senstive discriminators"));
+
/// Dump the function profile for \p FName.
///
/// \param FName Name of the function to print.
@@ -87,13 +98,22 @@ static bool isOffsetLegal(unsigned L) { return (L & 0xffff) == L; }
/// Possible metadata:
/// - CFG Checksum information:
/// !CFGChecksum: 12345
+/// - CFG Checksum information:
+/// !Attributes: 1
/// Stores the FunctionHash (a.k.a. CFG Checksum) into \p FunctionHash.
-static bool parseMetadata(const StringRef &Input, uint64_t &FunctionHash) {
- if (!Input.startswith("!CFGChecksum:"))
- return false;
+static bool parseMetadata(const StringRef &Input, uint64_t &FunctionHash,
+ uint32_t &Attributes) {
+ if (Input.startswith("!CFGChecksum:")) {
+ StringRef CFGInfo = Input.substr(strlen("!CFGChecksum:")).trim();
+ return !CFGInfo.getAsInteger(10, FunctionHash);
+ }
+
+ if (Input.startswith("!Attributes:")) {
+ StringRef Attrib = Input.substr(strlen("!Attributes:")).trim();
+ return !Attrib.getAsInteger(10, Attributes);
+ }
- StringRef CFGInfo = Input.substr(strlen("!CFGChecksum:")).trim();
- return !CFGInfo.getAsInteger(10, FunctionHash);
+ return false;
}
enum class LineType {
@@ -118,7 +138,7 @@ static bool ParseLine(const StringRef &Input, LineType &LineTy, uint32_t &Depth,
uint64_t &NumSamples, uint32_t &LineOffset,
uint32_t &Discriminator, StringRef &CalleeName,
DenseMap<StringRef, uint64_t> &TargetCountMap,
- uint64_t &FunctionHash) {
+ uint64_t &FunctionHash, uint32_t &Attributes) {
for (Depth = 0; Input[Depth] == ' '; Depth++)
;
if (Depth == 0)
@@ -126,7 +146,7 @@ static bool ParseLine(const StringRef &Input, LineType &LineTy, uint32_t &Depth,
if (Depth == 1 && Input[Depth] == '!') {
LineTy = LineType::Metadata;
- return parseMetadata(Input.substr(Depth), FunctionHash);
+ return parseMetadata(Input.substr(Depth), FunctionHash, Attributes);
}
size_t n1 = Input.find(':');
@@ -222,14 +242,13 @@ std::error_code SampleProfileReaderText::readImpl() {
sampleprof_error Result = sampleprof_error::success;
InlineCallStack InlineStack;
- int CSProfileCount = 0;
- int RegularProfileCount = 0;
uint32_t ProbeProfileCount = 0;
// SeenMetadata tracks whether we have processed metadata for the current
// top-level function profile.
bool SeenMetadata = false;
+ ProfileIsFS = ProfileIsFSDisciminator;
for (; !LineIt.is_at_eof(); ++LineIt) {
if ((*LineIt)[(*LineIt).find_first_not_of(' ')] == '#')
continue;
@@ -257,11 +276,9 @@ std::error_code SampleProfileReaderText::readImpl() {
SampleContext FContext(FName);
if (FContext.hasContext())
++CSProfileCount;
- else
- ++RegularProfileCount;
Profiles[FContext] = FunctionSamples();
FunctionSamples &FProfile = Profiles[FContext];
- FProfile.setName(FContext.getName());
+ FProfile.setName(FContext.getNameWithoutContext());
FProfile.setContext(FContext);
MergeResult(Result, FProfile.addTotalSamples(NumSamples));
MergeResult(Result, FProfile.addHeadSamples(NumHeadSamples));
@@ -273,9 +290,11 @@ std::error_code SampleProfileReaderText::readImpl() {
DenseMap<StringRef, uint64_t> TargetCountMap;
uint32_t Depth, LineOffset, Discriminator;
LineType LineTy;
- uint64_t FunctionHash;
+ uint64_t FunctionHash = 0;
+ uint32_t Attributes = 0;
if (!ParseLine(*LineIt, LineTy, Depth, NumSamples, LineOffset,
- Discriminator, FName, TargetCountMap, FunctionHash)) {
+ Discriminator, FName, TargetCountMap, FunctionHash,
+ Attributes)) {
reportError(LineIt.line_number(),
"Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " +
*LineIt);
@@ -287,6 +306,10 @@ std::error_code SampleProfileReaderText::readImpl() {
"Found non-metadata after metadata: " + *LineIt);
return sampleprof_error::malformed;
}
+
+ // Here we handle FS discriminators.
+ Discriminator &= getDiscriminatorMask();
+
while (InlineStack.size() > Depth) {
InlineStack.pop_back();
}
@@ -315,8 +338,12 @@ std::error_code SampleProfileReaderText::readImpl() {
}
case LineType::Metadata: {
FunctionSamples &FProfile = *InlineStack.back();
- FProfile.setFunctionHash(FunctionHash);
- ++ProbeProfileCount;
+ if (FunctionHash) {
+ FProfile.setFunctionHash(FunctionHash);
+ ++ProbeProfileCount;
+ }
+ if (Attributes)
+ FProfile.getContext().setAllAttributes(Attributes);
SeenMetadata = true;
break;
}
@@ -324,13 +351,14 @@ std::error_code SampleProfileReaderText::readImpl() {
}
}
- assert((RegularProfileCount == 0 || CSProfileCount == 0) &&
+ assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) &&
"Cannot have both context-sensitive and regular profile");
ProfileIsCS = (CSProfileCount > 0);
assert((ProbeProfileCount == 0 || ProbeProfileCount == Profiles.size()) &&
"Cannot have both probe-based profiles and regular profiles");
ProfileIsProbeBased = (ProbeProfileCount > 0);
FunctionSamples::ProfileIsProbeBased = ProfileIsProbeBased;
+ FunctionSamples::ProfileIsCS = ProfileIsCS;
if (Result == sampleprof_error::success)
computeSummary();
@@ -491,6 +519,9 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
if (std::error_code EC = NumCalls.getError())
return EC;
+ // Here we handle FS discriminators:
+ uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
+
for (uint32_t J = 0; J < *NumCalls; ++J) {
auto CalledFunction(readStringFromTable());
if (std::error_code EC = CalledFunction.getError())
@@ -500,11 +531,11 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
if (std::error_code EC = CalledFunctionSamples.getError())
return EC;
- FProfile.addCalledTargetSamples(*LineOffset, *Discriminator,
+ FProfile.addCalledTargetSamples(*LineOffset, DiscriminatorVal,
*CalledFunction, *CalledFunctionSamples);
}
- FProfile.addBodySamples(*LineOffset, *Discriminator, *NumSamples);
+ FProfile.addBodySamples(*LineOffset, DiscriminatorVal, *NumSamples);
}
// Read all the samples for inlined function calls.
@@ -525,8 +556,11 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
if (std::error_code EC = FName.getError())
return EC;
+ // Here we handle FS discriminators:
+ uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
+
FunctionSamples &CalleeProfile = FProfile.functionSamplesAt(
- LineLocation(*LineOffset, *Discriminator))[std::string(*FName)];
+ LineLocation(*LineOffset, DiscriminatorVal))[std::string(*FName)];
CalleeProfile.setName(*FName);
if (std::error_code EC = readProfile(CalleeProfile))
return EC;
@@ -546,18 +580,23 @@ SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start) {
if (std::error_code EC = FName.getError())
return EC;
- Profiles[*FName] = FunctionSamples();
- FunctionSamples &FProfile = Profiles[*FName];
- FProfile.setName(*FName);
-
+ SampleContext FContext(*FName);
+ Profiles[FContext] = FunctionSamples();
+ FunctionSamples &FProfile = Profiles[FContext];
+ FProfile.setName(FContext.getNameWithoutContext());
+ FProfile.setContext(FContext);
FProfile.addHeadSamples(*NumHeadSamples);
+ if (FContext.hasContext())
+ CSProfileCount++;
+
if (std::error_code EC = readProfile(FProfile))
return EC;
return sampleprof_error::success;
}
std::error_code SampleProfileReaderBinary::readImpl() {
+ ProfileIsFS = ProfileIsFSDisciminator;
while (!at_eof()) {
if (std::error_code EC = readFuncProfile(Data))
return EC;
@@ -576,6 +615,10 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
return EC;
if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial))
Summary->setPartialProfile(true);
+ if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFullContext))
+ FunctionSamples::ProfileIsCS = ProfileIsCS = true;
+ if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFSDiscriminator))
+ FunctionSamples::ProfileIsFS = ProfileIsFS = true;
break;
case SecNameTable: {
FixedLengthMD5 =
@@ -583,6 +626,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
bool UseMD5 = hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name);
assert((!FixedLengthMD5 || UseMD5) &&
"If FixedLengthMD5 is true, UseMD5 has to be true");
+ FunctionSamples::HasUniqSuffix =
+ hasSecFlag(Entry, SecNameTableFlags::SecFlagUniqSuffix);
if (std::error_code EC = readNameTableSec(UseMD5))
return EC;
break;
@@ -595,13 +640,16 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
if (std::error_code EC = readFuncOffsetTable())
return EC;
break;
- case SecFuncMetadata:
+ case SecFuncMetadata: {
ProfileIsProbeBased =
hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagIsProbeBased);
FunctionSamples::ProfileIsProbeBased = ProfileIsProbeBased;
- if (std::error_code EC = readFuncMetadata())
+ bool HasAttribute =
+ hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagHasAttribute);
+ if (std::error_code EC = readFuncMetadata(HasAttribute))
return EC;
break;
+ }
case SecProfileSymbolList:
if (std::error_code EC = readProfileSymbolList())
return EC;
@@ -614,11 +662,13 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
return sampleprof_error::success;
}
-void SampleProfileReaderExtBinaryBase::collectFuncsFrom(const Module &M) {
- UseAllFuncs = false;
+bool SampleProfileReaderExtBinaryBase::collectFuncsFromModule() {
+ if (!M)
+ return false;
FuncsToUse.clear();
- for (auto &F : M)
+ for (auto &F : *M)
FuncsToUse.insert(FunctionSamples::getCanonicalFnName(F));
+ return true;
}
std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() {
@@ -647,47 +697,100 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() {
}
std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
+ // Collect functions used by current module if the Reader has been
+ // given a module.
+ // collectFuncsFromModule uses FunctionSamples::getCanonicalFnName
+ // which will query FunctionSamples::HasUniqSuffix, so it has to be
+ // called after FunctionSamples::HasUniqSuffix is set, i.e. after
+ // NameTable section is read.
+ bool LoadFuncsToBeUsed = collectFuncsFromModule();
+
+ // When LoadFuncsToBeUsed is false, load all the function profiles.
const uint8_t *Start = Data;
- if (UseAllFuncs) {
+ if (!LoadFuncsToBeUsed) {
while (Data < End) {
if (std::error_code EC = readFuncProfile(Data))
return EC;
}
assert(Data == End && "More data is read than expected");
- return sampleprof_error::success;
- }
-
- if (Remapper) {
- for (auto Name : FuncsToUse) {
- Remapper->insert(Name);
+ } else {
+ // Load function profiles on demand.
+ if (Remapper) {
+ for (auto Name : FuncsToUse) {
+ Remapper->insert(Name);
+ }
}
- }
- if (useMD5()) {
- for (auto Name : FuncsToUse) {
- auto GUID = std::to_string(MD5Hash(Name));
- auto iter = FuncOffsetTable.find(StringRef(GUID));
- if (iter == FuncOffsetTable.end())
- continue;
- const uint8_t *FuncProfileAddr = Start + iter->second;
- assert(FuncProfileAddr < End && "out of LBRProfile section");
- if (std::error_code EC = readFuncProfile(FuncProfileAddr))
- return EC;
- }
- } else {
- for (auto NameOffset : FuncOffsetTable) {
- auto FuncName = NameOffset.first;
- if (!FuncsToUse.count(FuncName) &&
- (!Remapper || !Remapper->exist(FuncName)))
- continue;
- const uint8_t *FuncProfileAddr = Start + NameOffset.second;
- assert(FuncProfileAddr < End && "out of LBRProfile section");
- if (std::error_code EC = readFuncProfile(FuncProfileAddr))
- return EC;
+ if (useMD5()) {
+ for (auto Name : FuncsToUse) {
+ auto GUID = std::to_string(MD5Hash(Name));
+ auto iter = FuncOffsetTable.find(StringRef(GUID));
+ if (iter == FuncOffsetTable.end())
+ continue;
+ const uint8_t *FuncProfileAddr = Start + iter->second;
+ assert(FuncProfileAddr < End && "out of LBRProfile section");
+ if (std::error_code EC = readFuncProfile(FuncProfileAddr))
+ return EC;
+ }
+ } else if (FunctionSamples::ProfileIsCS) {
+ // Compute the ordered set of names, so we can
+ // get all context profiles under a subtree by
+ // iterating through the ordered names.
+ struct Comparer {
+ // Ignore the closing ']' when ordering context
+ bool operator()(const StringRef &L, const StringRef &R) const {
+ return L.substr(0, L.size() - 1) < R.substr(0, R.size() - 1);
+ }
+ };
+ std::set<StringRef, Comparer> OrderedNames;
+ for (auto Name : FuncOffsetTable) {
+ OrderedNames.insert(Name.first);
+ }
+
+ // For each function in current module, load all
+ // context profiles for the function.
+ for (auto NameOffset : FuncOffsetTable) {
+ StringRef ContextName = NameOffset.first;
+ SampleContext FContext(ContextName);
+ auto FuncName = FContext.getNameWithoutContext();
+ if (!FuncsToUse.count(FuncName) &&
+ (!Remapper || !Remapper->exist(FuncName)))
+ continue;
+
+ // For each context profile we need, try to load
+ // all context profile in the subtree. This can
+ // help profile guided importing for ThinLTO.
+ auto It = OrderedNames.find(ContextName);
+ while (It != OrderedNames.end() &&
+ It->startswith(ContextName.substr(0, ContextName.size() - 1))) {
+ const uint8_t *FuncProfileAddr = Start + FuncOffsetTable[*It];
+ assert(FuncProfileAddr < End && "out of LBRProfile section");
+ if (std::error_code EC = readFuncProfile(FuncProfileAddr))
+ return EC;
+ // Remove loaded context profile so we won't
+ // load it repeatedly.
+ It = OrderedNames.erase(It);
+ }
+ }
+ } else {
+ for (auto NameOffset : FuncOffsetTable) {
+ SampleContext FContext(NameOffset.first);
+ auto FuncName = FContext.getNameWithoutContext();
+ if (!FuncsToUse.count(FuncName) &&
+ (!Remapper || !Remapper->exist(FuncName)))
+ continue;
+ const uint8_t *FuncProfileAddr = Start + NameOffset.second;
+ assert(FuncProfileAddr < End && "out of LBRProfile section");
+ if (std::error_code EC = readFuncProfile(FuncProfileAddr))
+ return EC;
+ }
}
+ Data = End;
}
-
- Data = End;
+ assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) &&
+ "Cannot have both context-sensitive and regular profile");
+ assert(ProfileIsCS == (CSProfileCount > 0) &&
+ "Section flag should be consistent with actual profile");
return sampleprof_error::success;
}
@@ -778,13 +881,18 @@ std::error_code SampleProfileReaderExtBinaryBase::readImpl() {
}
std::error_code SampleProfileReaderCompactBinary::readImpl() {
+ // Collect functions used by current module if the Reader has been
+ // given a module.
+ bool LoadFuncsToBeUsed = collectFuncsFromModule();
+ ProfileIsFS = ProfileIsFSDisciminator;
std::vector<uint64_t> OffsetsToUse;
- if (UseAllFuncs) {
+ if (!LoadFuncsToBeUsed) {
+ // load all the function profiles.
for (auto FuncEntry : FuncOffsetTable) {
OffsetsToUse.push_back(FuncEntry.second);
}
- }
- else {
+ } else {
+ // load function profiles on demand.
for (auto Name : FuncsToUse) {
auto GUID = std::to_string(MD5Hash(Name));
auto iter = FuncOffsetTable.find(StringRef(GUID));
@@ -875,20 +983,34 @@ std::error_code SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5) {
return SampleProfileReaderBinary::readNameTable();
}
-std::error_code SampleProfileReaderExtBinaryBase::readFuncMetadata() {
- if (!ProfileIsProbeBased)
- return sampleprof_error::success;
- for (unsigned I = 0; I < Profiles.size(); ++I) {
+std::error_code
+SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute) {
+ while (Data < End) {
auto FName(readStringFromTable());
if (std::error_code EC = FName.getError())
return EC;
- auto Checksum = readNumber<uint64_t>();
- if (std::error_code EC = Checksum.getError())
- return EC;
+ SampleContext FContext(*FName);
+ bool ProfileInMap = Profiles.count(FContext);
- Profiles[*FName].setFunctionHash(*Checksum);
+ if (ProfileIsProbeBased) {
+ auto Checksum = readNumber<uint64_t>();
+ if (std::error_code EC = Checksum.getError())
+ return EC;
+ if (ProfileInMap)
+ Profiles[FContext].setFunctionHash(*Checksum);
+ }
+
+ if (ProfileHasAttribute) {
+ auto Attributes = readNumber<uint32_t>();
+ if (std::error_code EC = Attributes.getError())
+ return EC;
+ if (ProfileInMap)
+ Profiles[FContext].getContext().setAllAttributes(*Attributes);
+ }
}
+
+ assert(Data == End && "More data is read than expected");
return sampleprof_error::success;
}
@@ -999,10 +1121,16 @@ static std::string getSecFlagsStr(const SecHdrTableEntry &Entry) {
Flags.append("fixlenmd5,");
else if (hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name))
Flags.append("md5,");
+ if (hasSecFlag(Entry, SecNameTableFlags::SecFlagUniqSuffix))
+ Flags.append("uniq,");
break;
case SecProfSummary:
if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial))
Flags.append("partial,");
+ if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFullContext))
+ Flags.append("context,");
+ if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFSDiscriminator))
+ Flags.append("fs-discriminator,");
break;
default:
break;
@@ -1106,11 +1234,13 @@ std::error_code SampleProfileReaderCompactBinary::readFuncOffsetTable() {
return sampleprof_error::success;
}
-void SampleProfileReaderCompactBinary::collectFuncsFrom(const Module &M) {
- UseAllFuncs = false;
+bool SampleProfileReaderCompactBinary::collectFuncsFromModule() {
+ if (!M)
+ return false;
FuncsToUse.clear();
- for (auto &F : M)
+ for (auto &F : *M)
FuncsToUse.insert(FunctionSamples::getCanonicalFnName(F));
+ return true;
}
std::error_code SampleProfileReaderBinary::readSummaryEntry(
@@ -1417,6 +1547,7 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
/// This format is generated by the Linux Perf conversion tool at
/// https://github.com/google/autofdo.
std::error_code SampleProfileReaderGCC::readImpl() {
+ assert(!ProfileIsFSDisciminator && "Gcc profiles not support FSDisciminator");
// Read the string table.
if (std::error_code EC = readNameTable())
return EC;
@@ -1471,7 +1602,7 @@ SampleProfileReaderItaniumRemapper::lookUpNameInProfile(StringRef Fname) {
/// \returns an error code indicating the status of the buffer.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
setupMemoryBuffer(const Twine &Filename) {
- auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(Filename);
+ auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
if (std::error_code EC = BufferOrErr.getError())
return EC;
auto Buffer = std::move(BufferOrErr.get());
@@ -1489,16 +1620,19 @@ setupMemoryBuffer(const Twine &Filename) {
///
/// \param C The LLVM context to use to emit diagnostics.
///
+/// \param P The FSDiscriminatorPass.
+///
/// \param RemapFilename The file used for profile remapping.
///
/// \returns an error code indicating the status of the created reader.
ErrorOr<std::unique_ptr<SampleProfileReader>>
SampleProfileReader::create(const std::string Filename, LLVMContext &C,
+ FSDiscriminatorPass P,
const std::string RemapFilename) {
auto BufferOrError = setupMemoryBuffer(Filename);
if (std::error_code EC = BufferOrError.getError())
return EC;
- return create(BufferOrError.get(), C, RemapFilename);
+ return create(BufferOrError.get(), C, P, RemapFilename);
}
/// Create a sample profile remapper from the given input, to remap the
@@ -1556,11 +1690,14 @@ SampleProfileReaderItaniumRemapper::create(std::unique_ptr<MemoryBuffer> &B,
///
/// \param C The LLVM context to use to emit diagnostics.
///
+/// \param P The FSDiscriminatorPass.
+///
/// \param RemapFilename The file used for profile remapping.
///
/// \returns an error code indicating the status of the created reader.
ErrorOr<std::unique_ptr<SampleProfileReader>>
SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C,
+ FSDiscriminatorPass P,
const std::string RemapFilename) {
std::unique_ptr<SampleProfileReader> Reader;
if (SampleProfileReaderRawBinary::hasFormat(*B))
@@ -1592,6 +1729,8 @@ SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C,
return EC;
}
+ Reader->setDiscriminatorMaskedBitFrom(P);
+
return std::move(Reader);
}
@@ -1599,9 +1738,5 @@ SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C,
// profile. Binary format has the profile summary in its header.
void SampleProfileReader::computeSummary() {
SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
- for (const auto &I : Profiles) {
- const FunctionSamples &Profile = I.second;
- Builder.addRecord(Profile);
- }
- Summary = Builder.getSummary();
+ Summary = Builder.computeSummaryForProfiles(Profiles);
}