32 using namespace llvm::sampleprof;
41 OS <<
"Function: " << FName <<
": " << Profiles[FName];
46 for (
const auto &
I : Profiles)
47 dumpFunctionProfile(
I.getKey(), OS);
58 uint64_t &NumSamples, uint64_t &NumHeadSamples) {
61 size_t n2 = Input.
rfind(
':');
62 size_t n1 = Input.
rfind(
':', n2 - 1);
63 FName = Input.
substr(0, n1);
86 uint64_t &NumSamples,
uint32_t &LineOffset,
89 for (Depth = 0; Input[
Depth] ==
' '; Depth++)
94 size_t n1 = Input.
find(
':');
96 size_t n2 = Loc.
find(
'.');
109 if (Rest[0] >=
'0' && Rest[0] <=
'9') {
111 size_t n3 = Rest.
find(
' ');
125 pair = Rest.
substr(0, n3);
127 size_t n4 = pair.
find(
':');
136 CalleeName = Rest.
substr(0, n3);
156 if ((*LineIt)[(*LineIt).find_first_not_of(
' ')] ==
'#')
170 if ((*LineIt)[0] !=
' ') {
171 uint64_t NumSamples, NumHeadSamples;
173 if (!
ParseHead(*LineIt, FName, NumSamples, NumHeadSamples)) {
175 "Expected 'mangled_name:NUM:NUM', found " + *LineIt);
191 if (!
ParseLine(*LineIt, IsCallsite, Depth, NumSamples, LineOffset,
192 Discriminator, FName, TargetCountMap)) {
194 "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " +
212 for (
const auto &name_count : TargetCountMap) {
214 LineOffset, Discriminator, name_count.first,
234 if ((*LineIt)[0] !=
' ') {
235 uint64_t NumSamples, NumHeadSamples;
237 result =
ParseHead(*LineIt, FName, NumSamples, NumHeadSamples);
245 unsigned NumBytesRead = 0;
249 if (Val > std::numeric_limits<T>::max())
251 else if (Data + NumBytesRead >
End)
261 Data += NumBytesRead;
262 return static_cast<T>(Val);
267 StringRef Str(reinterpret_cast<const char *>(Data));
268 if (Data + Str.
size() + 1 >
End) {
274 Data += Str.
size() + 1;
280 auto Idx = readNumber<uint32_t>();
281 if (std::error_code EC = Idx.getError())
283 if (*Idx >= NameTable.size())
285 return NameTable[*Idx];
290 auto NumSamples = readNumber<uint64_t>();
291 if (std::error_code EC = NumSamples.getError())
296 auto NumRecords = readNumber<uint32_t>();
297 if (std::error_code EC = NumRecords.getError())
301 auto LineOffset = readNumber<uint64_t>();
302 if (std::error_code EC = LineOffset.getError())
306 return std::error_code();
309 auto Discriminator = readNumber<uint64_t>();
310 if (std::error_code EC = Discriminator.getError())
313 auto NumSamples = readNumber<uint64_t>();
314 if (std::error_code EC = NumSamples.getError())
317 auto NumCalls = readNumber<uint32_t>();
318 if (std::error_code EC = NumCalls.getError())
321 for (
uint32_t J = 0; J < *NumCalls; ++J) {
322 auto CalledFunction(readStringFromTable());
323 if (std::error_code EC = CalledFunction.getError())
326 auto CalledFunctionSamples = readNumber<uint64_t>();
327 if (std::error_code EC = CalledFunctionSamples.getError())
331 *CalledFunction, *CalledFunctionSamples);
334 FProfile.
addBodySamples(*LineOffset, *Discriminator, *NumSamples);
338 auto NumCallsites = readNumber<uint32_t>();
339 if (std::error_code EC = NumCallsites.getError())
342 for (
uint32_t J = 0; J < *NumCallsites; ++J) {
343 auto LineOffset = readNumber<uint64_t>();
344 if (std::error_code EC = LineOffset.getError())
347 auto Discriminator = readNumber<uint64_t>();
348 if (std::error_code EC = Discriminator.getError())
351 auto FName(readStringFromTable());
352 if (std::error_code EC = FName.getError())
358 if (std::error_code EC = readProfile(CalleeProfile))
367 auto NumHeadSamples = readNumber<uint64_t>();
368 if (std::error_code EC = NumHeadSamples.getError())
371 auto FName(readStringFromTable());
372 if (std::error_code EC = FName.getError())
381 if (std::error_code EC = readProfile(FProfile))
389 Data =
reinterpret_cast<const uint8_t *
>(Buffer->getBufferStart());
390 End = Data + Buffer->getBufferSize();
393 auto Magic = readNumber<uint64_t>();
394 if (std::error_code EC =
Magic.getError())
400 auto Version = readNumber<uint64_t>();
401 if (std::error_code EC =
Version.getError())
406 if (std::error_code EC = readSummary())
410 auto Size = readNumber<uint32_t>();
411 if (std::error_code EC = Size.getError())
413 NameTable.reserve(*Size);
415 auto Name(readString());
416 if (std::error_code EC =
Name.getError())
418 NameTable.push_back(*
Name);
424 std::error_code SampleProfileReaderBinary::readSummaryEntry(
425 std::vector<ProfileSummaryEntry> &Entries) {
426 auto Cutoff = readNumber<uint64_t>();
427 if (std::error_code EC = Cutoff.getError())
430 auto MinBlockCount = readNumber<uint64_t>();
431 if (std::error_code EC = MinBlockCount.getError())
434 auto NumBlocks = readNumber<uint64_t>();
435 if (std::error_code EC = NumBlocks.getError())
438 Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks);
442 std::error_code SampleProfileReaderBinary::readSummary() {
443 auto TotalCount = readNumber<uint64_t>();
444 if (std::error_code EC = TotalCount.getError())
447 auto MaxBlockCount = readNumber<uint64_t>();
448 if (std::error_code EC = MaxBlockCount.getError())
451 auto MaxFunctionCount = readNumber<uint64_t>();
452 if (std::error_code EC = MaxFunctionCount.getError())
455 auto NumBlocks = readNumber<uint64_t>();
456 if (std::error_code EC = NumBlocks.getError())
459 auto NumFunctions = readNumber<uint64_t>();
460 if (std::error_code EC = NumFunctions.getError())
463 auto NumSummaryEntries = readNumber<uint64_t>();
464 if (std::error_code EC = NumSummaryEntries.getError())
467 std::vector<ProfileSummaryEntry> Entries;
468 for (
unsigned i = 0;
i < *NumSummaryEntries;
i++) {
469 std::error_code EC = readSummaryEntry(Entries);
473 Summary = llvm::make_unique<ProfileSummary>(
475 *MaxFunctionCount, *NumBlocks, *NumFunctions);
481 const uint8_t *Data =
489 if (!GcovBuffer.readInt(dummy))
497 if (GcovBuffer.readInt(Val) && Val <= std::numeric_limits<T>::max())
498 return static_cast<T>(Val);
499 }
else if (
sizeof(
T) <=
sizeof(uint64_t)) {
501 if (GcovBuffer.readInt64(Val) && Val <= std::numeric_limits<T>::max())
502 return static_cast<T>(Val);
512 if (!GcovBuffer.readString(Str))
519 if (!GcovBuffer.readGCDAFormat())
525 if (!GcovBuffer.readGCOVVersion(version))
532 if (std::error_code EC = skipNextWord())
540 if (!GcovBuffer.readInt(Tag))
546 if (std::error_code EC = skipNextWord())
553 if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames))
557 if (!GcovBuffer.readInt(Size))
562 if (!GcovBuffer.readString(Str))
564 Names.push_back(Str);
571 if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction))
575 if (!GcovBuffer.readInt(NumFunctions))
580 if (std::error_code EC = readOneFunctionProfile(Stack,
true, 0))
589 uint64_t HeadCount = 0;
590 if (InlineStack.
size() == 0)
591 if (!GcovBuffer.readInt64(HeadCount))
595 if (!GcovBuffer.readInt(NameIdx))
601 if (!GcovBuffer.readInt(NumPosCounts))
605 if (!GcovBuffer.readInt(NumCallsites))
609 if (InlineStack.
size() == 0) {
616 FProfile = &Profiles[
Name];
626 uint32_t Discriminator = Offset & 0xffff;
634 if (!GcovBuffer.readInt(Offset))
638 if (!GcovBuffer.readInt(NumTargets))
642 if (!GcovBuffer.readInt64(Count))
649 uint32_t Discriminator = Offset & 0xffff;
657 for (
auto CallerProfile : NewStack)
658 CallerProfile->addTotalSamples(Count);
667 for (
uint32_t J = 0; J < NumTargets; J++) {
669 if (!GcovBuffer.readInt(HistVal))
676 if (!GcovBuffer.readInt64(TargetIdx))
680 uint64_t TargetCount;
681 if (!GcovBuffer.readInt64(TargetCount))
687 TargetName, TargetCount);
699 if (!GcovBuffer.readInt(Offset))
704 if (std::error_code EC = readOneFunctionProfile(NewStack, Update, Offset))
717 if (std::error_code EC = readNameTable())
721 if (std::error_code EC = readFunctionProfiles())
729 return Magic ==
"adcg*704";
738 if (std::error_code EC = BufferOrErr.getError())
740 auto Buffer = std::move(BufferOrErr.get());
743 if (Buffer->getBufferSize() > std::numeric_limits<uint32_t>::max())
746 return std::move(Buffer);
761 if (std::error_code EC = BufferOrError.getError())
763 return create(BufferOrError.get(),
C);
777 std::unique_ptr<SampleProfileReader> Reader;
787 if (std::error_code EC = Reader->readHeader())
790 return std::move(Reader);
797 for (
const auto &
I : Profiles) {
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 push_back(const T &Elt)
Represents either an error or a value T.
const char * getBufferStart() const
int64_t line_number() const
Return the current line number. May return any number at EOF.
std::error_code read() override
Read sample profiles from the associated file.
std::error_code readHeader() override
Read and validate the file header.
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 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.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Tagged union holding either a T or a Error.
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.
static bool hasFormat(const MemoryBuffer &Buffer)
Return true if Buffer is in the format supported by this class.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
auto count(R &&Range, const E &Element) -> typename std::iterator_traits< decltype(std::begin(Range))>::difference_type
Wrapper function around std::count to count the number of times an element Element occurs in the give...
std::error_code readFunctionProfiles()
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
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.
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr)
Utility function to decode a ULEB128 value.
std::error_code readOneFunctionProfile(const InlineCallStack &InlineStack, bool Update, uint32_t Offset)
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.
This is an important class for using LLVM in a threaded context.
sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num, uint64_t Weight=1)
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
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.
ErrorOr< T > readNumber()
Read a numeric value of type T from the profile.
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).
static const unsigned End
ErrorOr< StringRef > readString()
Read a string from the profile.
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
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.
void dumpFunctionProfile(StringRef FName, raw_ostream &OS=dbgs())
Print the profile for FName on stream OS.
LLVM_NODISCARD size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
static const char *const Magic
sampleprof_error addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator, const std::string &FName, uint64_t Num, uint64_t Weight=1)
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)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
This interface provides simple read-only access to a block of memory, and provides simple methods for...
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 int reportError(const char *ProgName, Twine Msg)
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 "-".
static uint64_t SPMagic()
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
ErrorOr< StringRef > readString()
Represents the relative location of an instruction.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight=1)
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.
bool is_at_eof() const
Return true if we've reached EOF or are an "end" iterator.
This class implements an extremely fast bulk output stream that can only output to a stream...
ErrorOr< StringRef > readStringFromTable()
Read a string indirectly via the name table.
StringRef - Represent a constant reference to a string, i.e.
std::error_code readHeader() override
Read and validate the file header.
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).
std::error_code skipNextWord()
sampleprof_error MergeResult(sampleprof_error &Accumulator, sampleprof_error Result)
FunctionSamples & functionSamplesAt(const LineLocation &Loc)
Return the function samples at the given callsite location.