aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/ProfileData/SampleProf.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/ProfileData/SampleProf.h')
-rw-r--r--include/llvm/ProfileData/SampleProf.h178
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