diff options
Diffstat (limited to 'include/llvm/ProfileData/SampleProf.h')
-rw-r--r-- | include/llvm/ProfileData/SampleProf.h | 124 |
1 files changed, 89 insertions, 35 deletions
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index a96f83620f8b5..7a705ca5416da 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -1,4 +1,4 @@ -//=-- SampleProf.h - Sampling profiling format support --------------------===// +//===- SampleProf.h - Sampling profiling format support ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,20 +12,30 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H_ -#define LLVM_PROFILEDATA_SAMPLEPROF_H_ +#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H +#define LLVM_PROFILEDATA_SAMPLEPROF_H +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" -#include "llvm/Support/raw_ostream.h" - +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cstdint> #include <map> +#include <string> #include <system_error> +#include <utility> namespace llvm { +class raw_ostream; + const std::error_category &sampleprof_category(); enum class sampleprof_error { @@ -59,12 +69,13 @@ inline sampleprof_error MergeResult(sampleprof_error &Accumulator, } // end namespace llvm namespace std { + template <> struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {}; -} -namespace llvm { +} // end namespace std +namespace llvm { namespace sampleprof { static inline uint64_t SPMagic() { @@ -87,8 +98,10 @@ static inline uint64_t SPVersion() { return 103; } /// (e.g., the two post-increment instructions in "if (p) x++; else y++;"). struct LineLocation { LineLocation(uint32_t L, uint32_t D) : LineOffset(L), Discriminator(D) {} + void print(raw_ostream &OS) const; void dump() const; + bool operator<(const LineLocation &O) const { return LineOffset < O.LineOffset || (LineOffset == O.LineOffset && Discriminator < O.Discriminator); @@ -114,7 +127,7 @@ class SampleRecord { public: typedef StringMap<uint64_t> CallTargetMap; - SampleRecord() : NumSamples(0), CallTargets() {} + SampleRecord() = default; /// Increment the number of samples for this record by \p S. /// Optionally scale sample count \p S by \p Weight. @@ -144,7 +157,7 @@ public: } /// Return true if this sample record contains function calls. - bool hasCalls() const { return CallTargets.size() > 0; } + bool hasCalls() const { return !CallTargets.empty(); } uint64_t getSamples() const { return NumSamples; } const CallTargetMap &getCallTargets() const { return CallTargets; } @@ -163,7 +176,7 @@ public: void dump() const; private: - uint64_t NumSamples; + uint64_t NumSamples = 0; CallTargetMap CallTargets; }; @@ -171,7 +184,8 @@ raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample); typedef std::map<LineLocation, SampleRecord> BodySampleMap; class FunctionSamples; -typedef std::map<LineLocation, FunctionSamples> CallsiteSampleMap; +typedef StringMap<FunctionSamples> FunctionSamplesMap; +typedef std::map<LineLocation, FunctionSamplesMap> CallsiteSampleMap; /// Representation of the samples collected for a function. /// @@ -180,9 +194,11 @@ typedef std::map<LineLocation, FunctionSamples> CallsiteSampleMap; /// within the body of the function. class FunctionSamples { public: - FunctionSamples() : Name(), TotalSamples(0), TotalHeadSamples(0) {} + FunctionSamples() = default; + void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const; void dump() const; + sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) { bool Overflowed; TotalSamples = @@ -190,6 +206,7 @@ public: return Overflowed ? sampleprof_error::counter_overflow : sampleprof_error::success; } + sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) { bool Overflowed; TotalHeadSamples = @@ -197,11 +214,13 @@ public: return Overflowed ? sampleprof_error::counter_overflow : sampleprof_error::success; } + sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num, uint64_t Weight = 1) { return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples( Num, Weight); } + sampleprof_error addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator, const std::string &FName, @@ -222,34 +241,53 @@ public: return ret->second.getSamples(); } - /// Return the total number of call target samples collected at a given - /// location. Each location is specified by \p LineOffset and - /// \p Discriminator. If the location is not found in profile, return error. - ErrorOr<uint64_t> findCallSamplesAt(uint32_t LineOffset, - uint32_t Discriminator) const { + /// Returns the call target map collected at a given location. + /// Each location is specified by \p LineOffset and \p Discriminator. + /// If the location is not found in profile, return error. + ErrorOr<SampleRecord::CallTargetMap> + findCallTargetMapAt(uint32_t LineOffset, uint32_t Discriminator) const { const auto &ret = BodySamples.find(LineLocation(LineOffset, Discriminator)); if (ret == BodySamples.end()) return std::error_code(); - uint64_t T = 0; - for (const auto &t_c : ret->second.getCallTargets()) { - T += t_c.second; - } - return T; + return ret->second.getCallTargets(); } /// Return the function samples at the given callsite location. - FunctionSamples &functionSamplesAt(const LineLocation &Loc) { + FunctionSamplesMap &functionSamplesAt(const LineLocation &Loc) { return CallsiteSamples[Loc]; } - /// Return a pointer to function samples at the given callsite location. - const FunctionSamples *findFunctionSamplesAt(const LineLocation &Loc) const { + /// Returns the FunctionSamplesMap at the given \p Loc. + const FunctionSamplesMap * + findFunctionSamplesMapAt(const LineLocation &Loc) const { auto iter = CallsiteSamples.find(Loc); - if (iter == CallsiteSamples.end()) { + if (iter == CallsiteSamples.end()) return nullptr; - } else { - return &iter->second; - } + return &iter->second; + } + + /// Returns a pointer to FunctionSamples at the given callsite location \p Loc + /// with callee \p CalleeName. If no callsite can be found, relax the + /// restriction to return the FunctionSamples at callsite location \p Loc + /// with the maximum total sample count. + const FunctionSamples *findFunctionSamplesAt(const LineLocation &Loc, + StringRef CalleeName) const { + auto iter = CallsiteSamples.find(Loc); + if (iter == CallsiteSamples.end()) + return nullptr; + auto FS = iter->second.find(CalleeName); + if (FS != iter->second.end()) + return &FS->getValue(); + // If we cannot find exact match of the callee name, return the FS with + // the max total count. + uint64_t MaxTotalSamples = 0; + const FunctionSamples *R = nullptr; + for (const auto &NameFS : iter->second) + if (NameFS.second.getTotalSamples() >= MaxTotalSamples) { + MaxTotalSamples = NameFS.second.getTotalSamples(); + R = &NameFS.second; + } + return R; } bool empty() const { return TotalSamples == 0; } @@ -283,12 +321,28 @@ public: } for (const auto &I : Other.getCallsiteSamples()) { const LineLocation &Loc = I.first; - const FunctionSamples &Rec = I.second; - MergeResult(Result, functionSamplesAt(Loc).merge(Rec, Weight)); + FunctionSamplesMap &FSMap = functionSamplesAt(Loc); + for (const auto &Rec : I.second) + MergeResult(Result, FSMap[Rec.first()].merge(Rec.second, Weight)); } return Result; } + /// Recursively traverses all children, if the corresponding function is + /// not defined in module \p M, and its total sample is no less than + /// \p Threshold, add its corresponding GUID to \p S. + void findImportedFunctions(DenseSet<GlobalValue::GUID> &S, const Module *M, + uint64_t Threshold) const { + if (TotalSamples <= Threshold) + return; + Function *F = M->getFunction(Name); + if (!F || !F->getSubprogram()) + S.insert(Function::getGUID(Name)); + for (auto CS : CallsiteSamples) + for (const auto &NameFS : CS.second) + NameFS.second.findImportedFunctions(S, M, Threshold); + } + /// Set the name of the function. void setName(StringRef FunctionName) { Name = FunctionName; } @@ -303,12 +357,12 @@ private: /// /// Samples are cumulative, they include all the samples collected /// inside this function and all its inlined callees. - uint64_t TotalSamples; + uint64_t TotalSamples = 0; /// Total number of samples collected at the head of the function. /// This is an approximation of the number of calls made to this function /// at runtime. - uint64_t TotalHeadSamples; + uint64_t TotalHeadSamples = 0; /// Map instruction locations to collected samples. /// @@ -355,6 +409,7 @@ public: return A->first < B->first; }); } + const SamplesWithLocList &get() const { return V; } private: @@ -362,7 +417,6 @@ private: }; } // end namespace sampleprof - } // end namespace llvm -#endif // LLVM_PROFILEDATA_SAMPLEPROF_H_ +#endif // LLVM_PROFILEDATA_SAMPLEPROF_H |