X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FProfileData%2FSampleProfReader.cpp;h=93cd87bb82f8b554842d435c11c69fcd640f80b2;hb=6f28d52e9d3f87875732a0f2c1f3b03ef56be2db;hp=6149c6c3506b95835353fb2c344a60ae4e79f56b;hpb=b61e5a3617169aa2b0e2b3bad1c544b61e2d34d1;p=oota-llvm.git diff --git a/lib/ProfileData/SampleProfReader.cpp b/lib/ProfileData/SampleProfReader.cpp index 6149c6c3506..93cd87bb82f 100644 --- a/lib/ProfileData/SampleProfReader.cpp +++ b/lib/ProfileData/SampleProfReader.cpp @@ -21,56 +21,24 @@ //===----------------------------------------------------------------------===// #include "llvm/ProfileData/SampleProfReader.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" using namespace llvm::sampleprof; using namespace llvm; -/// \brief Print the samples collected for a function on stream \p OS. -/// -/// \param OS Stream to emit the output to. -void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const { - OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size() - << " sampled lines\n"; - for (const auto &SI : BodySamples) { - LineLocation Loc = SI.first; - const SampleRecord &Sample = SI.second; - OS.indent(Indent); - OS << "line offset: " << Loc.LineOffset - << ", discriminator: " << Loc.Discriminator - << ", number of samples: " << Sample.getSamples(); - if (Sample.hasCalls()) { - OS << ", calls:"; - for (const auto &I : Sample.getCallTargets()) - OS << " " << I.first() << ":" << I.second; - } - OS << "\n"; - } - for (const auto &CS : CallsiteSamples) { - CallsiteLocation Loc = CS.first; - const FunctionSamples &CalleeSamples = CS.second; - OS.indent(Indent); - OS << "line offset: " << Loc.LineOffset - << ", discriminator: " << Loc.Discriminator - << ", inlined callee: " << Loc.CalleeName << ": "; - CalleeSamples.print(OS, Indent + 2); - } -} - /// \brief Dump the function profile for \p FName. /// /// \param FName Name of the function to print. /// \param OS Stream to emit the output to. void SampleProfileReader::dumpFunctionProfile(StringRef FName, raw_ostream &OS) { - OS << "Function: " << FName << ": "; - Profiles[FName].print(OS); + OS << "Function: " << FName << ": " << Profiles[FName]; } /// \brief Dump all the function profiles found on stream \p OS. @@ -87,7 +55,7 @@ void SampleProfileReader::dump(raw_ostream &OS) { /// /// \returns true if parsing is successful. static bool ParseHead(const StringRef &Input, StringRef &FName, - unsigned &NumSamples, unsigned &NumHeadSamples) { + uint64_t &NumSamples, uint64_t &NumHeadSamples) { if (Input[0] == ' ') return false; size_t n2 = Input.rfind(':'); @@ -100,6 +68,12 @@ static bool ParseHead(const StringRef &Input, StringRef &FName, return true; } + +/// \brief Returns true if line offset \p L is legal (only has 16 bits). +static bool isOffsetLegal(unsigned L) { + return (L & 0xffff) == L; +} + /// \brief Parse \p Input as line sample. /// /// \param Input input line. @@ -111,10 +85,10 @@ static bool ParseHead(const StringRef &Input, StringRef &FName, /// \param TargetCountMap map from indirect call target to count. /// /// returns true if parsing is successful. -static bool ParseLine(const StringRef &Input, bool &IsCallsite, unsigned &Depth, - unsigned &NumSamples, unsigned &LineOffset, - unsigned &Discriminator, StringRef &CalleeName, - DenseMap &TargetCountMap) { +static bool ParseLine(const StringRef &Input, bool &IsCallsite, uint32_t &Depth, + uint64_t &NumSamples, uint32_t &LineOffset, + uint32_t &Discriminator, StringRef &CalleeName, + DenseMap &TargetCountMap) { for (Depth = 0; Input[Depth] == ' '; Depth++) ; if (Depth == 0) @@ -124,7 +98,7 @@ static bool ParseLine(const StringRef &Input, bool &IsCallsite, unsigned &Depth, StringRef Loc = Input.substr(Depth, n1 - Depth); size_t n2 = Loc.find('.'); if (n2 == StringRef::npos) { - if (Loc.getAsInteger(10, LineOffset)) + if (Loc.getAsInteger(10, LineOffset) || !isOffsetLegal(LineOffset)) return false; Discriminator = 0; } else { @@ -153,15 +127,15 @@ static bool ParseLine(const StringRef &Input, bool &IsCallsite, unsigned &Depth, if (n3 != StringRef::npos) { pair = Rest.substr(0, n3); } - int n4 = pair.find(':'); - unsigned count; + size_t n4 = pair.find(':'); + uint64_t count; if (pair.substr(n4 + 1).getAsInteger(10, count)) return false; TargetCountMap[pair.substr(0, n4)] = count; } } else { IsCallsite = true; - int n3 = Rest.find_last_of(':'); + size_t n3 = Rest.find_last_of(':'); CalleeName = Rest.substr(0, n3); if (Rest.substr(n3 + 1).getAsInteger(10, NumSamples)) return false; @@ -177,6 +151,7 @@ static bool ParseLine(const StringRef &Input, bool &IsCallsite, unsigned &Depth, /// \returns true if the file was loaded successfully, false otherwise. std::error_code SampleProfileReaderText::read() { line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#'); + sampleprof_error Result = sampleprof_error::success; InlineCallStack InlineStack; @@ -196,7 +171,7 @@ std::error_code SampleProfileReaderText::read() { // The only requirement we place on the identifier, then, is that it // should not begin with a number. if ((*LineIt)[0] != ' ') { - unsigned NumSamples, NumHeadSamples; + uint64_t NumSamples, NumHeadSamples; StringRef FName; if (!ParseHead(*LineIt, FName, NumSamples, NumHeadSamples)) { reportError(LineIt.line_number(), @@ -205,16 +180,16 @@ std::error_code SampleProfileReaderText::read() { } Profiles[FName] = FunctionSamples(); FunctionSamples &FProfile = Profiles[FName]; - FProfile.addTotalSamples(NumSamples); - FProfile.addHeadSamples(NumHeadSamples); + MergeResult(Result, FProfile.addTotalSamples(NumSamples)); + MergeResult(Result, FProfile.addHeadSamples(NumHeadSamples)); InlineStack.clear(); InlineStack.push_back(&FProfile); } else { - unsigned NumSamples; + uint64_t NumSamples; StringRef FName; - DenseMap TargetCountMap; + DenseMap TargetCountMap; bool IsCallsite; - unsigned Depth, LineOffset, Discriminator; + uint32_t Depth, LineOffset, Discriminator; if (!ParseLine(*LineIt, IsCallsite, Depth, NumSamples, LineOffset, Discriminator, FName, TargetCountMap)) { reportError(LineIt.line_number(), @@ -228,7 +203,7 @@ std::error_code SampleProfileReaderText::read() { } FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt( CallsiteLocation(LineOffset, Discriminator, FName)); - FSamples.addTotalSamples(NumSamples); + MergeResult(Result, FSamples.addTotalSamples(NumSamples)); InlineStack.push_back(&FSamples); } else { while (InlineStack.size() > Depth) { @@ -236,15 +211,33 @@ std::error_code SampleProfileReaderText::read() { } FunctionSamples &FProfile = *InlineStack.back(); for (const auto &name_count : TargetCountMap) { - FProfile.addCalledTargetSamples(LineOffset, Discriminator, - name_count.first, name_count.second); + MergeResult(Result, FProfile.addCalledTargetSamples( + LineOffset, Discriminator, name_count.first, + name_count.second)); } - FProfile.addBodySamples(LineOffset, Discriminator, NumSamples); + MergeResult(Result, FProfile.addBodySamples(LineOffset, Discriminator, + NumSamples)); } } } - return sampleprof_error::success; + return Result; +} + +bool SampleProfileReaderText::hasFormat(const MemoryBuffer &Buffer) { + bool result = false; + + // Check that the first non-comment line is a valid function header. + line_iterator LineIt(Buffer, /*SkipBlanks=*/true, '#'); + if (!LineIt.is_at_eof()) { + if ((*LineIt)[0] != ' ') { + uint64_t NumSamples, NumHeadSamples; + StringRef FName; + result = ParseHead(*LineIt, FName, NumSamples, NumHeadSamples); + } + } + + return result; } template ErrorOr SampleProfileReaderBinary::readNumber() { @@ -283,7 +276,7 @@ ErrorOr SampleProfileReaderBinary::readString() { ErrorOr SampleProfileReaderBinary::readStringFromTable() { std::error_code EC; - auto Idx = readNumber(); + auto Idx = readNumber(); if (std::error_code EC = Idx.getError()) return EC; if (*Idx >= NameTable.size()) @@ -293,26 +286,25 @@ ErrorOr SampleProfileReaderBinary::readStringFromTable() { std::error_code SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { - auto Val = readNumber(); - if (std::error_code EC = Val.getError()) - return EC; - FProfile.addTotalSamples(*Val); - - Val = readNumber(); - if (std::error_code EC = Val.getError()) + auto NumSamples = readNumber(); + if (std::error_code EC = NumSamples.getError()) return EC; - FProfile.addHeadSamples(*Val); + FProfile.addTotalSamples(*NumSamples); // Read the samples in the body. - auto NumRecords = readNumber(); + auto NumRecords = readNumber(); if (std::error_code EC = NumRecords.getError()) return EC; - for (unsigned I = 0; I < *NumRecords; ++I) { + for (uint32_t I = 0; I < *NumRecords; ++I) { auto LineOffset = readNumber(); if (std::error_code EC = LineOffset.getError()) return EC; + if (!isOffsetLegal(*LineOffset)) { + return std::error_code(); + } + auto Discriminator = readNumber(); if (std::error_code EC = Discriminator.getError()) return EC; @@ -321,11 +313,11 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { if (std::error_code EC = NumSamples.getError()) return EC; - auto NumCalls = readNumber(); + auto NumCalls = readNumber(); if (std::error_code EC = NumCalls.getError()) return EC; - for (unsigned J = 0; J < *NumCalls; ++J) { + for (uint32_t J = 0; J < *NumCalls; ++J) { auto CalledFunction(readStringFromTable()); if (std::error_code EC = CalledFunction.getError()) return EC; @@ -342,11 +334,11 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { } // Read all the samples for inlined function calls. - auto NumCallsites = readNumber(); + auto NumCallsites = readNumber(); if (std::error_code EC = NumCallsites.getError()) return EC; - for (unsigned J = 0; J < *NumCallsites; ++J) { + for (uint32_t J = 0; J < *NumCallsites; ++J) { auto LineOffset = readNumber(); if (std::error_code EC = LineOffset.getError()) return EC; @@ -370,6 +362,10 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { std::error_code SampleProfileReaderBinary::read() { while (!at_eof()) { + auto NumHeadSamples = readNumber(); + if (std::error_code EC = NumHeadSamples.getError()) + return EC; + auto FName(readStringFromTable()); if (std::error_code EC = FName.getError()) return EC; @@ -377,6 +373,8 @@ std::error_code SampleProfileReaderBinary::read() { Profiles[*FName] = FunctionSamples(); FunctionSamples &FProfile = Profiles[*FName]; + FProfile.addHeadSamples(*NumHeadSamples); + if (std::error_code EC = readProfile(FProfile)) return EC; } @@ -403,11 +401,11 @@ std::error_code SampleProfileReaderBinary::readHeader() { return sampleprof_error::unsupported_version; // Read the name table. - auto Size = readNumber(); + auto Size = readNumber(); if (std::error_code EC = Size.getError()) return EC; NameTable.reserve(*Size); - for (size_t I = 0; I < *Size; ++I) { + for (uint32_t I = 0; I < *Size; ++I) { auto Name(readString()); if (std::error_code EC = Name.getError()) return EC; @@ -678,7 +676,7 @@ setupMemoryBuffer(std::string Filename) { auto Buffer = std::move(BufferOrErr.get()); // Sanity check the file. - if (Buffer->getBufferSize() > std::numeric_limits::max()) + if (Buffer->getBufferSize() > std::numeric_limits::max()) return sampleprof_error::too_large; return std::move(Buffer); @@ -698,15 +696,29 @@ SampleProfileReader::create(StringRef Filename, LLVMContext &C) { auto BufferOrError = setupMemoryBuffer(Filename); if (std::error_code EC = BufferOrError.getError()) return EC; + return create(BufferOrError.get(), C); +} - auto Buffer = std::move(BufferOrError.get()); +/// \brief Create a sample profile reader based on the format of the input data. +/// +/// \param B The memory buffer to create the reader from (assumes ownership). +/// +/// \param Reader The reader to instantiate according to \p Filename's format. +/// +/// \param C The LLVM context to use to emit diagnostics. +/// +/// \returns an error code indicating the status of the created reader. +ErrorOr> +SampleProfileReader::create(std::unique_ptr &B, LLVMContext &C) { std::unique_ptr Reader; - if (SampleProfileReaderBinary::hasFormat(*Buffer)) - Reader.reset(new SampleProfileReaderBinary(std::move(Buffer), C)); - else if (SampleProfileReaderGCC::hasFormat(*Buffer)) - Reader.reset(new SampleProfileReaderGCC(std::move(Buffer), C)); + if (SampleProfileReaderBinary::hasFormat(*B)) + Reader.reset(new SampleProfileReaderBinary(std::move(B), C)); + else if (SampleProfileReaderGCC::hasFormat(*B)) + Reader.reset(new SampleProfileReaderGCC(std::move(B), C)); + else if (SampleProfileReaderText::hasFormat(*B)) + Reader.reset(new SampleProfileReaderText(std::move(B), C)); else - Reader.reset(new SampleProfileReaderText(std::move(Buffer), C)); + return sampleprof_error::unrecognized_format; if (std::error_code EC = Reader->readHeader()) return EC;