diff options
Diffstat (limited to 'include/llvm/ProfileData/SampleProf.h')
-rw-r--r-- | include/llvm/ProfileData/SampleProf.h | 178 |
1 files changed, 135 insertions, 43 deletions
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index 7fbc857b7230..55418d9d0f9c 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -18,15 +18,18 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.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/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstdint> #include <map> +#include <set> #include <string> #include <system_error> #include <utility> @@ -49,7 +52,10 @@ enum class sampleprof_error { truncated_name_table, not_implemented, counter_overflow, - ostream_seek_unsupported + ostream_seek_unsupported, + compress_failed, + uncompress_failed, + zlib_unavailable }; inline std::error_code make_error_code(sampleprof_error E) { @@ -83,6 +89,7 @@ enum SampleProfileFormat { SPF_Text = 0x1, SPF_Compact_Binary = 0x2, SPF_GCC = 0x3, + SPF_Ext_Binary = 0x4, SPF_Binary = 0xff }; @@ -105,6 +112,61 @@ static inline StringRef getRepInFormat(StringRef Name, static inline uint64_t SPVersion() { return 103; } +// Section Type used by SampleProfileExtBinaryBaseReader and +// SampleProfileExtBinaryBaseWriter. Never change the existing +// value of enum. Only append new ones. +enum SecType { + SecInValid = 0, + SecProfSummary = 1, + SecNameTable = 2, + SecProfileSymbolList = 3, + SecFuncOffsetTable = 4, + // marker for the first type of profile. + SecFuncProfileFirst = 32, + SecLBRProfile = SecFuncProfileFirst +}; + +static inline std::string getSecName(SecType Type) { + switch (Type) { + case SecInValid: + return "InvalidSection"; + case SecProfSummary: + return "ProfileSummarySection"; + case SecNameTable: + return "NameTableSection"; + case SecProfileSymbolList: + return "ProfileSymbolListSection"; + case SecFuncOffsetTable: + return "FuncOffsetTableSection"; + case SecLBRProfile: + return "LBRProfileSection"; + } + llvm_unreachable("A SecType has no name for output"); +} + +// Entry type of section header table used by SampleProfileExtBinaryBaseReader +// and SampleProfileExtBinaryBaseWriter. +struct SecHdrTableEntry { + SecType Type; + uint64_t Flags; + uint64_t Offset; + uint64_t Size; +}; + +enum SecFlags { SecFlagInValid = 0, SecFlagCompress = (1 << 0) }; + +static inline void addSecFlags(SecHdrTableEntry &Entry, uint64_t Flags) { + Entry.Flags |= Flags; +} + +static inline void removeSecFlags(SecHdrTableEntry &Entry, uint64_t Flags) { + Entry.Flags &= ~Flags; +} + +static inline bool hasSecFlag(SecHdrTableEntry &Entry, SecFlags Flag) { + return Entry.Flags & Flag; +} + /// Represents the relative location of an instruction. /// /// Instruction locations are specified by the line offset from the @@ -143,8 +205,18 @@ raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc); /// will be a list of one or more functions. class SampleRecord { public: - using CallTargetMap = StringMap<uint64_t>; + using CallTarget = std::pair<StringRef, uint64_t>; + struct CallTargetComparator { + bool operator()(const CallTarget &LHS, const CallTarget &RHS) const { + if (LHS.second != RHS.second) + return LHS.second > RHS.second; + + return LHS.first < RHS.first; + } + }; + using SortedCallTargetSet = std::set<CallTarget, CallTargetComparator>; + using CallTargetMap = StringMap<uint64_t>; SampleRecord() = default; /// Increment the number of samples for this record by \p S. @@ -179,6 +251,18 @@ public: uint64_t getSamples() const { return NumSamples; } const CallTargetMap &getCallTargets() const { return CallTargets; } + const SortedCallTargetSet getSortedCallTargets() const { + return SortCallTargets(CallTargets); + } + + /// Sort call targets in descending order of call frequency. + static const SortedCallTargetSet SortCallTargets(const CallTargetMap &Targets) { + SortedCallTargetSet SortedTargets; + for (const auto &I : Targets) { + SortedTargets.emplace(I.first(), I.second); + } + return SortedTargets; + } /// Merge the samples in \p Other into this record. /// Optionally scale sample counts by \p Weight. @@ -205,7 +289,7 @@ class FunctionSamples; using BodySampleMap = std::map<LineLocation, SampleRecord>; // NOTE: Using a StringMap here makes parsed profiles consume around 17% more // memory, which is *very* significant for large profiles. -using FunctionSamplesMap = std::map<std::string, FunctionSamples>; +using FunctionSamplesMap = std::map<std::string, FunctionSamples, std::less<>>; using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>; /// Representation of the samples collected for a function. @@ -447,11 +531,10 @@ public: StringRef getNameInModule(StringRef Name, const Module *M) const { if (Format != SPF_Compact_Binary) return Name; - // Expect CurrentModule to be initialized by GUIDToFuncNameMapper. - if (M != CurrentModule) - llvm_unreachable("Input Module should be the same as CurrentModule"); - auto iter = GUIDToFuncNameMap.find(std::stoull(Name.data())); - if (iter == GUIDToFuncNameMap.end()) + + assert(GUIDToFuncNameMap && "GUIDToFuncNameMap needs to be popluated first"); + auto iter = GUIDToFuncNameMap->find(std::stoull(Name.data())); + if (iter == GUIDToFuncNameMap->end()) return StringRef(); return iter->second; } @@ -472,42 +555,10 @@ public: const FunctionSamples *findFunctionSamples(const DILocation *DIL) const; static SampleProfileFormat Format; - /// GUIDToFuncNameMap saves the mapping from GUID to the symbol name, for - /// all the function symbols defined or declared in CurrentModule. - static DenseMap<uint64_t, StringRef> GUIDToFuncNameMap; - static Module *CurrentModule; - - class GUIDToFuncNameMapper { - public: - GUIDToFuncNameMapper(Module &M) { - if (Format != SPF_Compact_Binary) - return; - - for (const auto &F : M) { - StringRef OrigName = F.getName(); - GUIDToFuncNameMap.insert({Function::getGUID(OrigName), OrigName}); - /// Local to global var promotion used by optimization like thinlto - /// will rename the var and add suffix like ".llvm.xxx" to the - /// original local name. In sample profile, the suffixes of function - /// names are all stripped. Since it is possible that the mapper is - /// built in post-thin-link phase and var promotion has been done, - /// we need to add the substring of function name without the suffix - /// into the GUIDToFuncNameMap. - StringRef CanonName = getCanonicalFnName(F); - if (CanonName != OrigName) - GUIDToFuncNameMap.insert({Function::getGUID(CanonName), CanonName}); - } - CurrentModule = &M; - } - - ~GUIDToFuncNameMapper() { - if (Format != SPF_Compact_Binary) - return; - GUIDToFuncNameMap.clear(); - CurrentModule = nullptr; - } - }; + /// GUIDToFuncNameMap saves the mapping from GUID to the symbol name, for + /// all the function symbols defined or declared in current module. + DenseMap<uint64_t, StringRef> *GUIDToFuncNameMap = nullptr; // Assume the input \p Name is a name coming from FunctionSamples itself. // If the format is SPF_Compact_Binary, the name is already a GUID and we @@ -583,6 +634,47 @@ private: SamplesWithLocList V; }; +/// ProfileSymbolList records the list of function symbols shown up +/// in the binary used to generate the profile. It is useful to +/// to discriminate a function being so cold as not to shown up +/// in the profile and a function newly added. +class ProfileSymbolList { +public: + /// copy indicates whether we need to copy the underlying memory + /// for the input Name. + void add(StringRef Name, bool copy = false) { + if (!copy) { + Syms.insert(Name); + return; + } + Syms.insert(Name.copy(Allocator)); + } + + bool contains(StringRef Name) { return Syms.count(Name); } + + void merge(const ProfileSymbolList &List) { + for (auto Sym : List.Syms) + add(Sym, true); + } + + unsigned size() { return Syms.size(); } + + void setToCompress(bool TC) { ToCompress = TC; } + bool toCompress() { return ToCompress; } + + std::error_code read(const uint8_t *Data, uint64_t ListSize); + std::error_code write(raw_ostream &OS); + void dump(raw_ostream &OS = dbgs()) const; + +private: + // Determine whether or not to compress the symbol list when + // writing it into profile. The variable is unused when the symbol + // list is read from an existing profile. + bool ToCompress = false; + DenseSet<StringRef> Syms; + BumpPtrAllocator Allocator; +}; + } // end namespace sampleprof } // end namespace llvm |