41 #include <system_error> 45 using namespace sampleprof;
53 OS <<
"Function: " << FName <<
": " <<
Profiles[FName];
70 uint64_t &NumSamples, uint64_t &NumHeadSamples) {
73 size_t n2 = Input.
rfind(
':');
74 size_t n1 = Input.
rfind(
':', n2 - 1);
75 FName = Input.
substr(0, n1);
98 uint64_t &NumSamples,
uint32_t &LineOffset,
101 for (Depth = 0; Input[
Depth] ==
' '; Depth++)
106 size_t n1 = Input.
find(
':');
108 size_t n2 = Loc.
find(
'.');
121 if (Rest[0] >=
'0' && Rest[0] <=
'9') {
123 size_t n3 = Rest.
find(
' ');
156 Target = Rest.
substr(0, n3);
172 TargetCountMap[Target] =
count;
173 if (n4 == Rest.
size())
181 CalleeName = Rest.
substr(0, n3);
201 if ((*LineIt)[(*LineIt).find_first_not_of(
' ')] ==
'#')
215 if ((*LineIt)[0] !=
' ') {
216 uint64_t NumSamples, NumHeadSamples;
218 if (!
ParseHead(*LineIt, FName, NumSamples, NumHeadSamples)) {
220 "Expected 'mangled_name:NUM:NUM', found " + *LineIt);
236 if (!
ParseLine(*LineIt, IsCallsite, Depth, NumSamples, LineOffset,
237 Discriminator, FName, TargetCountMap)) {
239 "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " +
257 for (
const auto &name_count : TargetCountMap) {
259 LineOffset, Discriminator, name_count.first,
279 if ((*LineIt)[0] !=
' ') {
280 uint64_t NumSamples, NumHeadSamples;
282 result =
ParseHead(*LineIt, FName, NumSamples, NumHeadSamples);
290 unsigned NumBytesRead = 0;
296 else if (
Data + NumBytesRead > End)
306 Data += NumBytesRead;
307 return static_cast<T>(Val);
323 template <
typename T>
327 if (
Data +
sizeof(
T) > End) {
333 using namespace support;
334 T Val = endian::readNext<T, little, unaligned>(
Data);
338 template <
typename T>
341 auto Idx = readNumber<uint32_t>();
342 if (std::error_code EC = Idx.getError())
344 if (*Idx >= Table.size())
350 auto Idx = readStringIndex(NameTable);
351 if (std::error_code EC = Idx.getError())
354 return NameTable[*Idx];
358 auto Idx = readStringIndex(NameTable);
359 if (std::error_code EC = Idx.getError())
367 auto NumSamples = readNumber<uint64_t>();
368 if (std::error_code EC = NumSamples.getError())
373 auto NumRecords = readNumber<uint32_t>();
374 if (std::error_code EC = NumRecords.getError())
378 auto LineOffset = readNumber<uint64_t>();
379 if (std::error_code EC = LineOffset.getError())
383 return std::error_code();
386 auto Discriminator = readNumber<uint64_t>();
387 if (std::error_code EC = Discriminator.getError())
390 auto NumSamples = readNumber<uint64_t>();
391 if (std::error_code EC = NumSamples.getError())
394 auto NumCalls = readNumber<uint32_t>();
395 if (std::error_code EC = NumCalls.getError())
398 for (
uint32_t J = 0; J < *NumCalls; ++J) {
399 auto CalledFunction(readStringFromTable());
400 if (std::error_code EC = CalledFunction.getError())
403 auto CalledFunctionSamples = readNumber<uint64_t>();
404 if (std::error_code EC = CalledFunctionSamples.getError())
408 *CalledFunction, *CalledFunctionSamples);
411 FProfile.
addBodySamples(*LineOffset, *Discriminator, *NumSamples);
415 auto NumCallsites = readNumber<uint32_t>();
416 if (std::error_code EC = NumCallsites.getError())
419 for (
uint32_t J = 0; J < *NumCallsites; ++J) {
420 auto LineOffset = readNumber<uint64_t>();
421 if (std::error_code EC = LineOffset.getError())
424 auto Discriminator = readNumber<uint64_t>();
425 if (std::error_code EC = Discriminator.getError())
428 auto FName(readStringFromTable());
429 if (std::error_code EC = FName.getError())
435 if (std::error_code EC = readProfile(CalleeProfile))
443 auto NumHeadSamples = readNumber<uint64_t>();
444 if (std::error_code EC = NumHeadSamples.getError())
447 auto FName(readStringFromTable());
448 if (std::error_code EC = FName.getError())
457 if (std::error_code EC = readProfile(FProfile))
464 if (std::error_code EC = readFuncProfile())
472 for (
auto Name : FuncsToUse) {
474 auto iter = FuncOffsetTable.find(
StringRef(GUID));
475 if (iter == FuncOffsetTable.end())
477 const uint8_t *SavedData =
Data;
478 Data =
reinterpret_cast<const uint8_t *
>(
Buffer->getBufferStart()) +
480 if (std::error_code EC = readFuncProfile())
487 std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t
Magic) {
494 SampleProfileReaderCompactBinary::verifySPMagic(uint64_t
Magic) {
500 std::error_code SampleProfileReaderRawBinary::readNameTable() {
501 auto Size = readNumber<uint32_t>();
502 if (std::error_code EC =
Size.getError())
504 NameTable.reserve(*
Size);
507 if (std::error_code EC =
Name.getError())
509 NameTable.push_back(*
Name);
515 std::error_code SampleProfileReaderCompactBinary::readNameTable() {
516 auto Size = readNumber<uint64_t>();
517 if (std::error_code EC =
Size.getError())
519 NameTable.reserve(*
Size);
521 auto FID = readNumber<uint64_t>();
522 if (std::error_code EC = FID.getError())
530 Data =
reinterpret_cast<const uint8_t *
>(
Buffer->getBufferStart());
534 auto Magic = readNumber<uint64_t>();
535 if (std::error_code EC =
Magic.getError())
537 else if (std::error_code EC = verifySPMagic(*
Magic))
541 auto Version = readNumber<uint64_t>();
542 if (std::error_code EC =
Version.getError())
547 if (std::error_code EC = readSummary())
550 if (std::error_code EC = readNameTable())
555 std::error_code SampleProfileReaderCompactBinary::readHeader() {
557 if (std::error_code EC = readFuncOffsetTable())
562 std::error_code SampleProfileReaderCompactBinary::readFuncOffsetTable() {
563 auto TableOffset = readUnencodedNumber<uint64_t>();
564 if (std::error_code EC = TableOffset.getError())
567 const uint8_t *SavedData =
Data;
568 const uint8_t *TableStart =
569 reinterpret_cast<const uint8_t *
>(
Buffer->getBufferStart()) +
573 auto Size = readNumber<uint64_t>();
574 if (std::error_code EC =
Size.getError())
577 FuncOffsetTable.reserve(*
Size);
579 auto FName(readStringFromTable());
580 if (std::error_code EC = FName.getError())
583 auto Offset = readNumber<uint64_t>();
584 if (std::error_code EC =
Offset.getError())
587 FuncOffsetTable[*FName] = *
Offset;
597 StringRef Fname =
F.getName().split(
'.').first;
598 FuncsToUse.insert(Fname);
602 std::error_code SampleProfileReaderBinary::readSummaryEntry(
603 std::vector<ProfileSummaryEntry> &Entries) {
604 auto Cutoff = readNumber<uint64_t>();
605 if (std::error_code EC = Cutoff.getError())
608 auto MinBlockCount = readNumber<uint64_t>();
609 if (std::error_code EC = MinBlockCount.getError())
612 auto NumBlocks = readNumber<uint64_t>();
613 if (std::error_code EC = NumBlocks.getError())
616 Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks);
620 std::error_code SampleProfileReaderBinary::readSummary() {
621 auto TotalCount = readNumber<uint64_t>();
622 if (std::error_code EC = TotalCount.getError())
625 auto MaxBlockCount = readNumber<uint64_t>();
626 if (std::error_code EC = MaxBlockCount.getError())
629 auto MaxFunctionCount = readNumber<uint64_t>();
630 if (std::error_code EC = MaxFunctionCount.getError())
633 auto NumBlocks = readNumber<uint64_t>();
634 if (std::error_code EC = NumBlocks.getError())
637 auto NumFunctions = readNumber<uint64_t>();
638 if (std::error_code EC = NumFunctions.getError())
641 auto NumSummaryEntries = readNumber<uint64_t>();
642 if (std::error_code EC = NumSummaryEntries.getError())
645 std::vector<ProfileSummaryEntry> Entries;
646 for (
unsigned i = 0; i < *NumSummaryEntries; i++) {
647 std::error_code EC = readSummaryEntry(Entries);
651 Summary = llvm::make_unique<ProfileSummary>(
653 *MaxFunctionCount, *NumBlocks, *NumFunctions);
659 const uint8_t *
Data =
666 const uint8_t *
Data =
674 if (!GcovBuffer.readInt(dummy))
683 return static_cast<T>(Val);
684 }
else if (
sizeof(
T) <=
sizeof(uint64_t)) {
687 return static_cast<T>(Val);
697 if (!GcovBuffer.readString(Str))
704 if (!GcovBuffer.readGCDAFormat())
710 if (!GcovBuffer.readGCOVVersion(version))
717 if (std::error_code EC = skipNextWord())
725 if (!GcovBuffer.readInt(Tag))
731 if (std::error_code EC = skipNextWord())
738 if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames))
742 if (!GcovBuffer.readInt(Size))
747 if (!GcovBuffer.readString(Str))
749 Names.push_back(Str);
756 if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction))
760 if (!GcovBuffer.readInt(NumFunctions))
765 if (std::error_code EC = readOneFunctionProfile(Stack,
true, 0))
774 uint64_t HeadCount = 0;
775 if (InlineStack.
size() == 0)
776 if (!GcovBuffer.readInt64(HeadCount))
780 if (!GcovBuffer.readInt(NameIdx))
786 if (!GcovBuffer.readInt(NumPosCounts))
790 if (!GcovBuffer.readInt(NumCallsites))
794 if (InlineStack.
size() == 0) {
811 uint32_t Discriminator = Offset & 0xffff;
819 if (!GcovBuffer.readInt(Offset))
823 if (!GcovBuffer.readInt(NumTargets))
827 if (!GcovBuffer.readInt64(Count))
834 uint32_t Discriminator = Offset & 0xffff;
842 for (
auto CallerProfile : NewStack)
843 CallerProfile->addTotalSamples(Count);
852 for (
uint32_t J = 0; J < NumTargets; J++) {
854 if (!GcovBuffer.readInt(HistVal))
861 if (!GcovBuffer.readInt64(TargetIdx))
865 uint64_t TargetCount;
866 if (!GcovBuffer.readInt64(TargetCount))
871 TargetName, TargetCount);
882 if (!GcovBuffer.readInt(Offset))
887 if (std::error_code EC = readOneFunctionProfile(NewStack, Update, Offset))
900 if (std::error_code EC = readNameTable())
904 if (std::error_code EC = readFunctionProfiles())
912 return Magic ==
"adcg*704";
920 Buffer->getBufferIdentifier(),
921 "Profile data remapping cannot be applied to profile data " 922 "in compact format (original mangled names are not available).",
936 if (
auto Key = Remappings.insert(Sample.first()))
937 SampleMap.insert({
Key, &Sample.second});
944 if (
auto Key = Remappings.lookup(Fname))
945 return SampleMap.lookup(
Key);
955 if (std::error_code EC = BufferOrErr.getError())
957 auto Buffer = std::move(BufferOrErr.get());
976 if (std::error_code EC = BufferOrError.getError())
978 return create(BufferOrError.get(),
C);
994 std::unique_ptr<SampleProfileReader>
Underlying) {
996 if (std::error_code EC = BufferOrError.getError())
998 return llvm::make_unique<SampleProfileReaderItaniumRemapper>(
999 std::move(BufferOrError.get()), C, std::move(Underlying));
1011 std::unique_ptr<SampleProfileReader> Reader;
1024 if (std::error_code EC = Reader->readHeader())
1027 return std::move(Reader);
std::unique_ptr< MemoryBuffer > Buffer
Memory buffer holding the profile file.
Represents either an error or a value T.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
FunctionSamples * getSamplesFor(StringRef FunctionName) override
Return the samples collected for function F.
std::error_code read() override
Read remapping file and apply it to the sample profile.
void collectFuncsToUse(const Module &M) override
Collect functions to be used when compiling Module M.
This class represents lattice values for constants.
A Module instance is used to store all the information related to an LLVM module. ...
LLVM_NODISCARD size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
std::error_code read() override
Read sample profiles from the associated file.
void push_back(const T &Elt)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
virtual std::error_code readHeader() override
Read and validate the file header.
uint64_t MD5Hash(StringRef Str)
Helper to compute and return lower 64 bits of the given string's MD5 hash.
LLVM_NODISCARD size_t find_last_of(char C, size_t From=npos) const
Find the last character in the string that is C, or npos if not found.
static ErrorOr< std::unique_ptr< SampleProfileReader > > create(const Twine &Filename, LLVMContext &C)
Create a sample profile reader appropriate to the file format.
std::error_code read() override
Read sample profiles from the associated file.
A forward iterator which reads text lines from a buffer.
static const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
std::error_code readProfile(FunctionSamples &FProfile)
Read the contents of the given profile instance.
static SampleProfileFormat Format
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if Buffer is in the format supported by this class.
Representation of the samples collected for a function.
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
StringRef getMessage() const
StringMap< FunctionSamples > Profiles
Map every function to its associated profile.
Tagged union holding either a T or a Error.
bool is_at_eof() const
Return true if we've reached EOF or are an "end" iterator.
SampleProfileFormat getFormat()
Return the profile format.
ErrorOr< T > readNumber()
std::error_code readNameTable()
static bool ParseHead(const StringRef &Input, StringRef &FName, uint64_t &NumSamples, uint64_t &NumHeadSamples)
Parse Input as function head.
void setName(StringRef FunctionName)
Set the name of the function.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
std::error_code readFunctionProfiles()
static uint64_t SPVersion()
static bool ParseLine(const StringRef &Input, bool &IsCallsite, uint32_t &Depth, uint64_t &NumSamples, uint32_t &LineOffset, uint32_t &Discriminator, StringRef &CalleeName, DenseMap< StringRef, uint64_t > &TargetCountMap)
Parse Input as line sample.
auto count(R &&Range, const E &Element) -> typename std::iterator_traits< decltype(adl_begin(Range))>::difference_type
Wrapper function around std::count to count the number of times an element Element occurs in the give...
int64_t line_number() const
Return the current line number. May return any number at EOF.
std::error_code readOneFunctionProfile(const InlineCallStack &InlineStack, bool Update, uint32_t Offset)
int64_t getLineNum() const
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
This is an important class for using LLVM in a threaded context.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if Buffer is in the format supported by this class.
FunctionSamples * getSamplesFor(const Function &F)
Return the samples collected for function F.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num, uint64_t Weight=1)
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
ErrorOr< T > readNumber()
Read a numeric value of type T from the profile.
LLVM_NODISCARD size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
LLVMContext & Ctx
LLVM context used to emit diagnostics.
std::underlying_type< E >::type Underlying(E Val)
Check that Val is in range for E, and return Val cast to E's underlying type.
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
ErrorOr< StringRef > readString()
Read a string from the profile.
std::error_code readFuncProfile()
Read the next function profile instance.
void dumpFunctionProfile(StringRef FName, raw_ostream &OS=dbgs())
Print the profile for FName on stream OS.
static const char *const Magic
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight=1)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
void addRecord(const sampleprof::FunctionSamples &FS)
FunctionSamplesMap & functionSamplesAt(const LineLocation &Loc)
Return the function samples at the given callsite location.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
static StringRef readString(WasmObjectFile::ReadContext &Ctx)
Target - Wrapper for Target specific information.
StringMap< FunctionSamples > & getProfiles()
Return all the profiles.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if Buffer is in the format supported by this class.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if Buffer is in the format supported by this class.
iterator insert(iterator I, T &&Elt)
std::unique_ptr< ProfileSummary > getSummary()
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
ErrorOr< T > readUnencodedNumber()
Read a numeric value of type T from the profile.
ErrorOr< StringRef > readString()
Represents the relative location of an instruction.
LLVM_NODISCARD size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
const char * getBufferStart() const
static uint64_t SPMagic(SampleProfileFormat Format=SPF_Binary)
sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight=1)
const std::string to_string(const T &Value)
Provides ErrorOr<T> smart pointer.
std::error_code readSectionTag(uint32_t Expected)
Read the section tag and check that it's the same as Expected.
static ErrorOr< std::unique_ptr< MemoryBuffer > > setupMemoryBuffer(const Twine &Filename)
Prepare a memory buffer for the contents of Filename.
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
Lightweight error class with error context and mandatory checking.
ErrorOr< uint32_t > readStringIndex(T &Table)
Read the string index and check whether it overflows the table.
void reportError(int64_t LineNumber, Twine Msg) const
Report a parse error message.
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
Diagnostic information for the sample profiler.
std::error_code readHeader() override
Read and validate the file header.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t find(char C, size_t From=0) const
Search for the first character C in the string.
void computeSummary()
Compute summary for this profile.
void dump(raw_ostream &OS=dbgs())
Print all the profiles on stream OS.
std::error_code read() override
Read sample profiles from the associated file.
static bool isOffsetLegal(unsigned L)
Returns true if line offset L is legal (only has 16 bits).
sampleprof_error addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator, StringRef FName, uint64_t Num, uint64_t Weight=1)
std::error_code skipNextWord()
sampleprof_error MergeResult(sampleprof_error &Accumulator, sampleprof_error Result)
std::unique_ptr< ProfileSummary > Summary
Profile summary information.
static ErrorOr< std::unique_ptr< SampleProfileReader > > create(const Twine &Filename, LLVMContext &C, std::unique_ptr< SampleProfileReader > Underlying)
Create a remapped sample profile from the given remapping file and underlying samples.
std::error_code read() override
Read samples only for functions to use.