From 57d1dda5581594ebdfabcb899bd224d037105a1a Mon Sep 17 00:00:00 2001 From: Dehao Chen Date: Thu, 3 Mar 2016 18:09:32 +0000 Subject: [PATCH] Use LineLocation instead of CallsiteLocation to index callsite profile. Summary: With discriminator, LineLocation can uniquely identify a callsite without the need to specifying callee name. Remove Callee function name from the key, and put it in the value (FunctionSamples). Reviewers: davidxl, dnovillo Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D17827 llvm-svn: 262634 --- llvm/include/llvm/ProfileData/SampleProf.h | 38 ++++++++++-------------- llvm/include/llvm/ProfileData/SampleProfWriter.h | 13 ++++---- llvm/lib/ProfileData/SampleProf.cpp | 17 ++--------- llvm/lib/ProfileData/SampleProfReader.cpp | 18 ++++++----- llvm/lib/ProfileData/SampleProfWriter.cpp | 29 ++++++++---------- llvm/lib/Transforms/IPO/SampleProfile.cpp | 20 ++++--------- llvm/unittests/ProfileData/SampleProfTest.cpp | 2 ++ 7 files changed, 53 insertions(+), 84 deletions(-) diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h index a4223b4..d731dec 100644 --- a/llvm/include/llvm/ProfileData/SampleProf.h +++ b/llvm/include/llvm/ProfileData/SampleProf.h @@ -100,23 +100,6 @@ struct LineLocation { raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc); -/// Represents the relative location of a callsite. -/// -/// Callsite locations are specified by the line offset from the -/// beginning of the function (marked by the line where the function -/// head is), the discriminator value within that line, and the callee -/// function name. -struct CallsiteLocation : public LineLocation { - CallsiteLocation(uint32_t L, uint32_t D, StringRef N) - : LineLocation(L, D), CalleeName(N) {} - void print(raw_ostream &OS) const; - void dump() const; - - StringRef CalleeName; -}; - -raw_ostream &operator<<(raw_ostream &OS, const CallsiteLocation &Loc); - /// Representation of a single sample record. /// /// A sample record is represented by a positive integer value, which @@ -188,7 +171,7 @@ raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample); typedef std::map BodySampleMap; class FunctionSamples; -typedef std::map CallsiteSampleMap; +typedef std::map CallsiteSampleMap; /// Representation of the samples collected for a function. /// @@ -197,7 +180,7 @@ typedef std::map CallsiteSampleMap; /// within the body of the function. class FunctionSamples { public: - FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {} + FunctionSamples() : Name(), TotalSamples(0), TotalHeadSamples(0) {} void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const; void dump() const; sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) { @@ -240,13 +223,12 @@ public: } /// Return the function samples at the given callsite location. - FunctionSamples &functionSamplesAt(const CallsiteLocation &Loc) { + FunctionSamples &functionSamplesAt(const LineLocation &Loc) { return CallsiteSamples[Loc]; } /// Return a pointer to function samples at the given callsite location. - const FunctionSamples * - findFunctionSamplesAt(const CallsiteLocation &Loc) const { + const FunctionSamples *findFunctionSamplesAt(const LineLocation &Loc) const { auto iter = CallsiteSamples.find(Loc); if (iter == CallsiteSamples.end()) { return nullptr; @@ -276,6 +258,7 @@ public: /// Optionally scale samples by \p Weight. sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight = 1) { sampleprof_error Result = sampleprof_error::success; + Name = Other.getName(); MergeResult(Result, addTotalSamples(Other.getTotalSamples(), Weight)); MergeResult(Result, addHeadSamples(Other.getHeadSamples(), Weight)); for (const auto &I : Other.getBodySamples()) { @@ -284,14 +267,23 @@ public: MergeResult(Result, BodySamples[Loc].merge(Rec, Weight)); } for (const auto &I : Other.getCallsiteSamples()) { - const CallsiteLocation &Loc = I.first; + const LineLocation &Loc = I.first; const FunctionSamples &Rec = I.second; MergeResult(Result, functionSamplesAt(Loc).merge(Rec, Weight)); } return Result; } + /// Set the name of the function. + void setName(StringRef FunctionName) { Name = FunctionName; } + + /// Return the function name. + const StringRef &getName() const { return Name; } + private: + /// Mangled name of the function. + StringRef Name; + /// Total number of samples collected inside this function. /// /// Samples are cumulative, they include all the samples collected diff --git a/llvm/include/llvm/ProfileData/SampleProfWriter.h b/llvm/include/llvm/ProfileData/SampleProfWriter.h index 03bbf48..b605d45 100644 --- a/llvm/include/llvm/ProfileData/SampleProfWriter.h +++ b/llvm/include/llvm/ProfileData/SampleProfWriter.h @@ -32,10 +32,10 @@ class SampleProfileWriter { public: virtual ~SampleProfileWriter() {} - /// Write sample profiles in \p S for function \p FName. + /// Write sample profiles in \p S. /// /// \returns status code of the file update operation. - virtual std::error_code write(StringRef FName, const FunctionSamples &S) = 0; + virtual std::error_code write(const FunctionSamples &S) = 0; /// Write all the sample profiles in the given map of samples. /// @@ -44,9 +44,8 @@ public: if (std::error_code EC = writeHeader(ProfileMap)) return EC; for (const auto &I : ProfileMap) { - StringRef FName = I.first(); const FunctionSamples &Profile = I.second; - if (std::error_code EC = write(FName, Profile)) + if (std::error_code EC = write(Profile)) return EC; } return sampleprof_error::success; @@ -86,7 +85,7 @@ protected: /// \brief Sample-based profile writer (text format). class SampleProfileWriterText : public SampleProfileWriter { public: - std::error_code write(StringRef FName, const FunctionSamples &S) override; + std::error_code write(const FunctionSamples &S) override; protected: SampleProfileWriterText(std::unique_ptr &OS) @@ -111,7 +110,7 @@ private: /// \brief Sample-based profile writer (binary format). class SampleProfileWriterBinary : public SampleProfileWriter { public: - std::error_code write(StringRef F, const FunctionSamples &S) override; + std::error_code write(const FunctionSamples &S) override; protected: SampleProfileWriterBinary(std::unique_ptr &OS) @@ -121,7 +120,7 @@ protected: writeHeader(const StringMap &ProfileMap) override; std::error_code writeSummary(); std::error_code writeNameIdx(StringRef FName); - std::error_code writeBody(StringRef FName, const FunctionSamples &S); + std::error_code writeBody(const FunctionSamples &S); private: void addName(StringRef FName); diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp index 5a69bb9..45e1679 100644 --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -73,19 +73,6 @@ raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS, LLVM_DUMP_METHOD void LineLocation::dump() const { print(dbgs()); } -void CallsiteLocation::print(raw_ostream &OS) const { - LineLocation::print(OS); - OS << ": inlined callee: " << CalleeName; -} - -LLVM_DUMP_METHOD void CallsiteLocation::dump() const { print(dbgs()); } - -inline raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS, - const CallsiteLocation &Loc) { - Loc.print(OS); - return OS; -} - /// \brief Print the sample record to the stream \p OS indented by \p Indent. void SampleRecord::print(raw_ostream &OS, unsigned Indent) const { OS << NumSamples; @@ -127,11 +114,11 @@ void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const { OS.indent(Indent); if (CallsiteSamples.size() > 0) { OS << "Samples collected in inlined callsites {\n"; - SampleSorter SortedCallsiteSamples( + SampleSorter SortedCallsiteSamples( CallsiteSamples); for (const auto &CS : SortedCallsiteSamples.get()) { OS.indent(Indent + 2); - OS << CS->first << ": "; + OS << CS->first << ": inlined callee: " << CS->second.getName() << ": "; CS->second.print(OS, Indent + 4); } OS << "}\n"; diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp index 205e34d..a96c4fc 100644 --- a/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/llvm/lib/ProfileData/SampleProfReader.cpp @@ -69,11 +69,8 @@ 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; -} +static bool isOffsetLegal(unsigned L) { return (L & 0xffff) == L; } /// \brief Parse \p Input as line sample. /// @@ -181,6 +178,7 @@ std::error_code SampleProfileReaderText::read() { } Profiles[FName] = FunctionSamples(); FunctionSamples &FProfile = Profiles[FName]; + FProfile.setName(FName); MergeResult(Result, FProfile.addTotalSamples(NumSamples)); MergeResult(Result, FProfile.addHeadSamples(NumHeadSamples)); InlineStack.clear(); @@ -203,7 +201,8 @@ std::error_code SampleProfileReaderText::read() { InlineStack.pop_back(); } FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt( - CallsiteLocation(LineOffset, Discriminator, FName)); + LineLocation(LineOffset, Discriminator)); + FSamples.setName(FName); MergeResult(Result, FSamples.addTotalSamples(NumSamples)); InlineStack.push_back(&FSamples); } else { @@ -354,8 +353,9 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { if (std::error_code EC = FName.getError()) return EC; - FunctionSamples &CalleeProfile = FProfile.functionSamplesAt( - CallsiteLocation(*LineOffset, *Discriminator, *FName)); + FunctionSamples &CalleeProfile = + FProfile.functionSamplesAt(LineLocation(*LineOffset, *Discriminator)); + CalleeProfile.setName(*FName); if (std::error_code EC = readProfile(CalleeProfile)) return EC; } @@ -375,6 +375,7 @@ std::error_code SampleProfileReaderBinary::read() { Profiles[*FName] = FunctionSamples(); FunctionSamples &FProfile = Profiles[*FName]; + FProfile.setName(*FName); FProfile.addHeadSamples(*NumHeadSamples); @@ -625,8 +626,9 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile( uint32_t LineOffset = Offset >> 16; uint32_t Discriminator = Offset & 0xffff; FProfile = &CallerProfile->functionSamplesAt( - CallsiteLocation(LineOffset, Discriminator, Name)); + LineLocation(LineOffset, Discriminator)); } + FProfile->setName(Name); for (uint32_t I = 0; I < NumPosCounts; ++I) { uint32_t Offset; diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp index a8c542c..2acb538 100644 --- a/llvm/lib/ProfileData/SampleProfWriter.cpp +++ b/llvm/lib/ProfileData/SampleProfWriter.cpp @@ -37,11 +37,9 @@ using namespace llvm; /// /// The format used here is more structured and deliberate because /// it needs to be parsed by the SampleProfileReaderText class. -std::error_code SampleProfileWriterText::write(StringRef FName, - const FunctionSamples &S) { +std::error_code SampleProfileWriterText::write(const FunctionSamples &S) { auto &OS = *OutputStream; - - OS << FName << ":" << S.getTotalSamples(); + OS << S.getName() << ":" << S.getTotalSamples(); if (Indent == 0) OS << ":" << S.getHeadSamples(); OS << "\n"; @@ -63,18 +61,18 @@ std::error_code SampleProfileWriterText::write(StringRef FName, OS << "\n"; } - SampleSorter SortedCallsiteSamples( + SampleSorter SortedCallsiteSamples( S.getCallsiteSamples()); Indent += 1; for (const auto &I : SortedCallsiteSamples.get()) { - CallsiteLocation Loc = I->first; + LineLocation Loc = I->first; const FunctionSamples &CalleeSamples = I->second; OS.indent(Indent); if (Loc.Discriminator == 0) OS << Loc.LineOffset << ": "; else OS << Loc.LineOffset << "." << Loc.Discriminator << ": "; - if (std::error_code EC = write(Loc.CalleeName, CalleeSamples)) + if (std::error_code EC = write(CalleeSamples)) return EC; } Indent -= 1; @@ -105,9 +103,8 @@ void SampleProfileWriterBinary::addNames(const FunctionSamples &S) { // Recursively add all the names for inlined callsites. for (const auto &J : S.getCallsiteSamples()) { - CallsiteLocation Loc = J.first; const FunctionSamples &CalleeSamples = J.second; - addName(Loc.CalleeName); + addName(CalleeSamples.getName()); addNames(CalleeSamples); } } @@ -155,11 +152,10 @@ std::error_code SampleProfileWriterBinary::writeSummary() { } return sampleprof_error::success; } -std::error_code SampleProfileWriterBinary::writeBody(StringRef FName, - const FunctionSamples &S) { +std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S) { auto &OS = *OutputStream; - if (std::error_code EC = writeNameIdx(FName)) + if (std::error_code EC = writeNameIdx(S.getName())) return EC; encodeULEB128(S.getTotalSamples(), OS); @@ -185,11 +181,11 @@ std::error_code SampleProfileWriterBinary::writeBody(StringRef FName, // Recursively emit all the callsite samples. encodeULEB128(S.getCallsiteSamples().size(), OS); for (const auto &J : S.getCallsiteSamples()) { - CallsiteLocation Loc = J.first; + LineLocation Loc = J.first; const FunctionSamples &CalleeSamples = J.second; encodeULEB128(Loc.LineOffset, OS); encodeULEB128(Loc.Discriminator, OS); - if (std::error_code EC = writeBody(Loc.CalleeName, CalleeSamples)) + if (std::error_code EC = writeBody(CalleeSamples)) return EC; } @@ -199,10 +195,9 @@ std::error_code SampleProfileWriterBinary::writeBody(StringRef FName, /// \brief Write samples of a top-level function to a binary file. /// /// \returns true if the samples were written successfully, false otherwise. -std::error_code SampleProfileWriterBinary::write(StringRef FName, - const FunctionSamples &S) { +std::error_code SampleProfileWriterBinary::write(const FunctionSamples &S) { encodeULEB128(S.getHeadSamples(), *OutputStream); - return writeBody(FName, S); + return writeBody(S); } /// \brief Create a sample profile file writer based on the specified format. diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index 97530a5..4a4020e 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -47,8 +47,8 @@ #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/Utils/Cloning.h" #include using namespace llvm; @@ -285,7 +285,6 @@ bool callsiteIsHot(const FunctionSamples *CallerFS, (double)CallsiteTotalSamples / (double)ParentTotalSamples * 100.0; return PercentSamples >= SampleProfileHotThreshold; } - } /// Mark as used the sample record for the given function samples at @@ -549,19 +548,12 @@ SampleProfileLoader::findCalleeFunctionSamples(const CallInst &Inst) const { if (!SP) return nullptr; - Function *CalleeFunc = Inst.getCalledFunction(); - if (!CalleeFunc) { - return nullptr; - } - - StringRef CalleeName = CalleeFunc->getName(); const FunctionSamples *FS = findFunctionSamples(Inst); if (FS == nullptr) return nullptr; - return FS->findFunctionSamplesAt( - CallsiteLocation(getOffset(DIL->getLine(), SP->getLine()), - DIL->getDiscriminator(), CalleeName)); + return FS->findFunctionSamplesAt(LineLocation( + getOffset(DIL->getLine(), SP->getLine()), DIL->getDiscriminator())); } /// \brief Get the FunctionSamples for an instruction. @@ -575,7 +567,7 @@ SampleProfileLoader::findCalleeFunctionSamples(const CallInst &Inst) const { /// \returns the FunctionSamples pointer to the inlined instance. const FunctionSamples * SampleProfileLoader::findFunctionSamples(const Instruction &Inst) const { - SmallVector S; + SmallVector S; const DILocation *DIL = Inst.getDebugLoc(); if (!DIL) { return Samples; @@ -587,8 +579,8 @@ SampleProfileLoader::findFunctionSamples(const Instruction &Inst) const { if (!SP) return nullptr; if (!CalleeName.empty()) { - S.push_back(CallsiteLocation(getOffset(DIL->getLine(), SP->getLine()), - DIL->getDiscriminator(), CalleeName)); + S.push_back(LineLocation(getOffset(DIL->getLine(), SP->getLine()), + DIL->getDiscriminator())); } CalleeName = SP->getLinkageName(); } diff --git a/llvm/unittests/ProfileData/SampleProfTest.cpp b/llvm/unittests/ProfileData/SampleProfTest.cpp index 8d88ff3..5ab4f56 100644 --- a/llvm/unittests/ProfileData/SampleProfTest.cpp +++ b/llvm/unittests/ProfileData/SampleProfTest.cpp @@ -53,6 +53,7 @@ struct SampleProfTest : ::testing::Test { StringRef FooName("_Z3fooi"); FunctionSamples FooSamples; + FooSamples.setName(FooName); FooSamples.addTotalSamples(7711); FooSamples.addHeadSamples(610); FooSamples.addBodySamples(1, 0, 610); @@ -63,6 +64,7 @@ struct SampleProfTest : ::testing::Test { StringRef BarName("_Z3bari"); FunctionSamples BarSamples; + BarSamples.setName(BarName); BarSamples.addTotalSamples(20301); BarSamples.addHeadSamples(1437); BarSamples.addBodySamples(1, 0, 1437); -- 2.7.4