summaryrefslogtreecommitdiff
path: root/include/llvm/ProfileData
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/ProfileData')
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMapping.h (renamed from include/llvm/ProfileData/CoverageMapping.h)126
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMappingReader.h (renamed from include/llvm/ProfileData/CoverageMappingReader.h)41
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMappingWriter.h (renamed from include/llvm/ProfileData/CoverageMappingWriter.h)2
-rw-r--r--include/llvm/ProfileData/InstrProf.h545
-rw-r--r--include/llvm/ProfileData/InstrProfData.inc338
-rw-r--r--include/llvm/ProfileData/InstrProfReader.h135
-rw-r--r--include/llvm/ProfileData/InstrProfWriter.h30
-rw-r--r--include/llvm/ProfileData/ProfileCommon.h102
-rw-r--r--include/llvm/ProfileData/SampleProf.h44
-rw-r--r--include/llvm/ProfileData/SampleProfReader.h42
-rw-r--r--include/llvm/ProfileData/SampleProfWriter.h22
11 files changed, 938 insertions, 489 deletions
diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 92a991eb39bab..6afde56122f00 100644
--- a/include/llvm/ProfileData/CoverageMapping.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -23,13 +23,13 @@
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/raw_ostream.h"
#include <system_error>
#include <tuple>
namespace llvm {
namespace coverage {
+
enum class coveragemap_error {
success = 0,
eof,
@@ -38,14 +38,37 @@ enum class coveragemap_error {
truncated,
malformed
};
-} // end of coverage namespace.
+
+const std::error_category &coveragemap_category();
+
+inline std::error_code make_error_code(coveragemap_error E) {
+ return std::error_code(static_cast<int>(E), coveragemap_category());
}
-namespace std {
-template <>
-struct is_error_code_enum<llvm::coverage::coveragemap_error> : std::true_type {
+class CoverageMapError : public ErrorInfo<CoverageMapError> {
+public:
+ CoverageMapError(coveragemap_error Err) : Err(Err) {
+ assert(Err != coveragemap_error::success && "Not an error");
+ }
+
+ std::string message() const override;
+
+ void log(raw_ostream &OS) const override { OS << message(); }
+
+ std::error_code convertToErrorCode() const override {
+ return make_error_code(Err);
+ }
+
+ coveragemap_error get() const { return Err; }
+
+ static char ID;
+
+private:
+ coveragemap_error Err;
};
-}
+
+} // end of coverage namespace.
+} // end of llvm namespace
namespace llvm {
class IndexedInstrProfReader;
@@ -265,7 +288,7 @@ public:
/// \brief Return the number of times that a region of code associated with
/// this counter was executed.
- ErrorOr<int64_t> evaluate(const Counter &C) const;
+ Expected<int64_t> evaluate(const Counter &C) const;
};
/// \brief Code coverage information for a single function.
@@ -370,13 +393,6 @@ struct CoverageSegment {
return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry) ==
std::tie(R.Line, R.Col, R.Count, R.HasCount, R.IsRegionEntry);
}
-
- void setCount(uint64_t NewCount) {
- Count = NewCount;
- HasCount = true;
- }
-
- void addCount(uint64_t NewCount) { setCount(Count + NewCount); }
};
/// \brief Coverage information to be processed or displayed.
@@ -400,14 +416,14 @@ public:
Expansions(std::move(RHS.Expansions)) {}
/// \brief Get the name of the file this data covers.
- StringRef getFilename() { return Filename; }
+ StringRef getFilename() const { return Filename; }
std::vector<CoverageSegment>::iterator begin() { return Segments.begin(); }
std::vector<CoverageSegment>::iterator end() { return Segments.end(); }
bool empty() { return Segments.empty(); }
/// \brief Expansions that can be further processed.
- std::vector<ExpansionRecord> getExpansions() { return Expansions; }
+ ArrayRef<ExpansionRecord> getExpansions() { return Expansions; }
};
/// \brief The mapping of profile information to coverage data.
@@ -422,12 +438,12 @@ class CoverageMapping {
public:
/// \brief Load the coverage mapping using the given readers.
- static ErrorOr<std::unique_ptr<CoverageMapping>>
+ static Expected<std::unique_ptr<CoverageMapping>>
load(CoverageMappingReader &CoverageReader,
IndexedInstrProfReader &ProfileReader);
/// \brief Load the coverage mapping from the given files.
- static ErrorOr<std::unique_ptr<CoverageMapping>>
+ static Expected<std::unique_ptr<CoverageMapping>>
load(StringRef ObjectFilename, StringRef ProfileFilename,
StringRef Arch = StringRef());
@@ -445,7 +461,7 @@ public:
/// The given filename must be the name as recorded in the coverage
/// information. That is, only names returned from getUniqueSourceFiles will
/// yield a result.
- CoverageData getCoverageForFile(StringRef Filename);
+ CoverageData getCoverageForFile(StringRef Filename) const;
/// \brief Gets all of the functions covered by this profile.
iterator_range<FunctionRecordIterator> getCoveredFunctions() const {
@@ -464,21 +480,16 @@ public:
///
/// Functions that are instantiated more than once, such as C++ template
/// specializations, have distinct coverage records for each instantiation.
- std::vector<const FunctionRecord *> getInstantiations(StringRef Filename);
+ std::vector<const FunctionRecord *>
+ getInstantiations(StringRef Filename) const;
/// \brief Get the coverage for a particular function.
- CoverageData getCoverageForFunction(const FunctionRecord &Function);
+ CoverageData getCoverageForFunction(const FunctionRecord &Function) const;
/// \brief Get the coverage for an expansion within a coverage set.
- CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion);
+ CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const;
};
-const std::error_category &coveragemap_category();
-
-inline std::error_code make_error_code(coveragemap_error E) {
- return std::error_code(static_cast<int>(E), coveragemap_category());
-}
-
// Profile coverage map has the following layout:
// [CoverageMapFileHeader]
// [ArrayStart]
@@ -488,9 +499,11 @@ inline std::error_code make_error_code(coveragemap_error E) {
// [ArrayEnd]
// [Encoded Region Mapping Data]
LLVM_PACKED_START
-template <class IntPtrT> struct CovMapFunctionRecord {
+template <class IntPtrT> struct CovMapFunctionRecordV1 {
+#define COVMAP_V1
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
#include "llvm/ProfileData/InstrProfData.inc"
+#undef COVMAP_V1
// Return the structural hash associated with the function.
template <support::endianness Endian> uint64_t getFuncHash() const {
@@ -506,16 +519,41 @@ template <class IntPtrT> struct CovMapFunctionRecord {
}
// Return the PGO name of the function */
template <support::endianness Endian>
- std::error_code getFuncName(InstrProfSymtab &ProfileNames,
- StringRef &FuncName) const {
+ Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
IntPtrT NameRef = getFuncNameRef<Endian>();
uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize);
FuncName = ProfileNames.getFuncName(NameRef, NameS);
if (NameS && FuncName.empty())
- return coveragemap_error::malformed;
- return std::error_code();
+ return make_error<CoverageMapError>(coveragemap_error::malformed);
+ return Error::success();
+ }
+};
+
+struct CovMapFunctionRecord {
+#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
+#include "llvm/ProfileData/InstrProfData.inc"
+
+ // Return the structural hash associated with the function.
+ template <support::endianness Endian> uint64_t getFuncHash() const {
+ return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
+ }
+ // Return the coverage map data size for the funciton.
+ template <support::endianness Endian> uint32_t getDataSize() const {
+ return support::endian::byte_swap<uint32_t, Endian>(DataSize);
+ }
+ // Return function lookup key. The value is consider opaque.
+ template <support::endianness Endian> uint64_t getFuncNameRef() const {
+ return support::endian::byte_swap<uint64_t, Endian>(NameRef);
+ }
+ // Return the PGO name of the function */
+ template <support::endianness Endian>
+ Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
+ uint64_t NameRef = getFuncNameRef<Endian>();
+ FuncName = ProfileNames.getFuncName(NameRef);
+ return Error::success();
}
};
+
// Per module coverage mapping data header, i.e. CoverageMapFileHeader
// documented above.
struct CovMapHeader {
@@ -537,10 +575,24 @@ struct CovMapHeader {
LLVM_PACKED_END
-enum CoverageMappingVersion {
- CoverageMappingVersion1 = 0,
- // The current versin is Version1
- CoverageMappingCurrentVersion = INSTR_PROF_COVMAP_VERSION
+enum CovMapVersion {
+ Version1 = 0,
+ // Function's name reference from CovMapFuncRecord is changed from raw
+ // name string pointer to MD5 to support name section compression. Name
+ // section is also compressed.
+ Version2 = 1,
+ // The current version is Version2
+ CurrentVersion = INSTR_PROF_COVMAP_VERSION
+};
+
+template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
+ typedef CovMapFunctionRecord CovMapFuncRecordType;
+ typedef uint64_t NameRefType;
+};
+
+template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> {
+ typedef CovMapFunctionRecordV1<IntPtrT> CovMapFuncRecordType;
+ typedef IntPtrT NameRefType;
};
} // end namespace coverage
diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index 38fb4680476be..db907f128d931 100644
--- a/include/llvm/ProfileData/CoverageMappingReader.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -19,7 +19,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/ObjectFile.h"
-#include "llvm/ProfileData/CoverageMapping.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -69,7 +69,7 @@ public:
class CoverageMappingReader {
public:
- virtual std::error_code readNextRecord(CoverageMappingRecord &Record) = 0;
+ virtual Error readNextRecord(CoverageMappingRecord &Record) = 0;
CoverageMappingIterator begin() { return CoverageMappingIterator(this); }
CoverageMappingIterator end() { return CoverageMappingIterator(); }
virtual ~CoverageMappingReader() {}
@@ -82,10 +82,10 @@ protected:
RawCoverageReader(StringRef Data) : Data(Data) {}
- std::error_code readULEB128(uint64_t &Result);
- std::error_code readIntMax(uint64_t &Result, uint64_t MaxPlus1);
- std::error_code readSize(uint64_t &Result);
- std::error_code readString(StringRef &Result);
+ Error readULEB128(uint64_t &Result);
+ Error readIntMax(uint64_t &Result, uint64_t MaxPlus1);
+ Error readSize(uint64_t &Result);
+ Error readString(StringRef &Result);
};
/// \brief Reader for the raw coverage filenames.
@@ -100,7 +100,17 @@ public:
RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames)
: RawCoverageReader(Data), Filenames(Filenames) {}
- std::error_code read();
+ Error read();
+};
+
+/// \brief Checks if the given coverage mapping data is exported for
+/// an unused function.
+class RawCoverageMappingDummyChecker : public RawCoverageReader {
+public:
+ RawCoverageMappingDummyChecker(StringRef MappingData)
+ : RawCoverageReader(MappingData) {}
+
+ Expected<bool> isDummy();
};
/// \brief Reader for the raw coverage mapping data.
@@ -125,12 +135,12 @@ public:
Filenames(Filenames), Expressions(Expressions),
MappingRegions(MappingRegions) {}
- std::error_code read();
+ Error read();
private:
- std::error_code decodeCounter(unsigned Value, Counter &C);
- std::error_code readCounter(Counter &C);
- std::error_code
+ Error decodeCounter(unsigned Value, Counter &C);
+ Error readCounter(Counter &C);
+ Error
readMappingRegionsSubArray(std::vector<CounterMappingRegion> &MappingRegions,
unsigned InferredFileID, size_t NumFileIDs);
};
@@ -140,14 +150,14 @@ private:
class BinaryCoverageReader : public CoverageMappingReader {
public:
struct ProfileMappingRecord {
- CoverageMappingVersion Version;
+ CovMapVersion Version;
StringRef FunctionName;
uint64_t FunctionHash;
StringRef CoverageMapping;
size_t FilenamesBegin;
size_t FilenamesSize;
- ProfileMappingRecord(CoverageMappingVersion Version, StringRef FunctionName,
+ ProfileMappingRecord(CovMapVersion Version, StringRef FunctionName,
uint64_t FunctionHash, StringRef CoverageMapping,
size_t FilenamesBegin, size_t FilenamesSize)
: Version(Version), FunctionName(FunctionName),
@@ -158,6 +168,7 @@ public:
private:
std::vector<StringRef> Filenames;
std::vector<ProfileMappingRecord> MappingRecords;
+ InstrProfSymtab ProfileNames;
size_t CurrentRecord;
std::vector<StringRef> FunctionsFilenames;
std::vector<CounterExpression> Expressions;
@@ -169,11 +180,11 @@ private:
BinaryCoverageReader() : CurrentRecord(0) {}
public:
- static ErrorOr<std::unique_ptr<BinaryCoverageReader>>
+ static Expected<std::unique_ptr<BinaryCoverageReader>>
create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
StringRef Arch);
- std::error_code readNextRecord(CoverageMappingRecord &Record) override;
+ Error readNextRecord(CoverageMappingRecord &Record) override;
};
} // end namespace coverage
diff --git a/include/llvm/ProfileData/CoverageMappingWriter.h b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
index 2e3b0378d032f..10269cc50f353 100644
--- a/include/llvm/ProfileData/CoverageMappingWriter.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
@@ -17,7 +17,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/ProfileData/CoverageMapping.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h
index c84d8d24f2061..75646b7616592 100644
--- a/include/llvm/ProfileData/InstrProf.h
+++ b/include/llvm/ProfileData/InstrProf.h
@@ -1,4 +1,4 @@
-//=-- InstrProf.h - Instrumented profiling format support ---------*- C++ -*-=//
+//===-- InstrProf.h - Instrumented profiling format support -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,18 +13,20 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_INSTRPROF_H_
-#define LLVM_PROFILEDATA_INSTRPROF_H_
+#ifndef LLVM_PROFILEDATA_INSTRPROF_H
+#define LLVM_PROFILEDATA_INSTRPROF_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/ProfileData/InstrProfData.inc"
+#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MD5.h"
+#include "llvm/Support/MathExtras.h"
#include <cstdint>
#include <list>
#include <system_error>
@@ -56,6 +58,20 @@ inline StringRef getInstrProfDataSectionName(bool AddSegment) {
: INSTR_PROF_DATA_SECT_NAME_STR;
}
+/// Return the name of data section containing pointers to value profile
+/// counters/nodes.
+inline StringRef getInstrProfValuesSectionName(bool AddSegment) {
+ return AddSegment ? "__DATA," INSTR_PROF_VALS_SECT_NAME_STR
+ : INSTR_PROF_VALS_SECT_NAME_STR;
+}
+
+/// Return the name of data section containing nodes holdling value
+/// profiling data.
+inline StringRef getInstrProfVNodesSectionName(bool AddSegment) {
+ return AddSegment ? "__DATA," INSTR_PROF_VNODES_SECT_NAME_STR
+ : INSTR_PROF_VNODES_SECT_NAME_STR;
+}
+
/// Return the name profile runtime entry point to do value profiling
/// for a given site.
inline StringRef getInstrProfValueProfFuncName() {
@@ -78,10 +94,22 @@ inline StringRef getInstrProfDataVarPrefix() { return "__profd_"; }
/// Return the name prefix of profile counter variables.
inline StringRef getInstrProfCountersVarPrefix() { return "__profc_"; }
+/// Return the name prefix of value profile variables.
+inline StringRef getInstrProfValuesVarPrefix() { return "__profvp_"; }
+
+/// Return the name of value profile node array variables:
+inline StringRef getInstrProfVNodesVarName() { return "__llvm_prf_vnodes"; }
+
/// Return the name prefix of the COMDAT group for instrumentation variables
/// associated with a COMDAT function.
inline StringRef getInstrProfComdatPrefix() { return "__profv_"; }
+/// Return the name of the variable holding the strings (possibly compressed)
+/// of all function's PGO names.
+inline StringRef getInstrProfNamesVarName() {
+ return "__llvm_prf_nm";
+}
+
/// Return the name of a covarage mapping variable (internal linkage)
/// for each instrumented source module. Such variables are allocated
/// in the __llvm_covmap section.
@@ -90,10 +118,12 @@ inline StringRef getCoverageMappingVarName() {
}
/// Return the name of the internal variable recording the array
-/// of PGO name vars referenced by the coverage mapping, The owning
+/// of PGO name vars referenced by the coverage mapping. The owning
/// functions of those names are not emitted by FE (e.g, unused inline
/// functions.)
-inline StringRef getCoverageNamesVarName() { return "__llvm_coverage_names"; }
+inline StringRef getCoverageUnusedNamesVarName() {
+ return "__llvm_coverage_names";
+}
/// Return the name of function that registers all the per-function control
/// data at program startup time by calling __llvm_register_function. This
@@ -110,6 +140,11 @@ inline StringRef getInstrProfRegFuncName() {
return "__llvm_profile_register_function";
}
+/// Return the name of the runtime interface that registers the PGO name strings.
+inline StringRef getInstrProfNamesRegFuncName() {
+ return "__llvm_profile_register_names_function";
+}
+
/// Return the name of the runtime initialization method that is generated by
/// the compiler. The function calls __llvm_profile_register_functions and
/// __llvm_profile_override_default_filename functions if needed. This function
@@ -135,9 +170,13 @@ inline StringRef getInstrProfFileOverriderFuncName() {
return "__llvm_profile_override_default_filename";
}
+/// Return the marker used to separate PGO names during serialization.
+inline StringRef getInstrProfNameSeparator() { return "\01"; }
+
/// Return the modified name for function \c F suitable to be
-/// used the key for profile lookup.
-std::string getPGOFuncName(const Function &F,
+/// used the key for profile lookup. Variable \c InLTO indicates if this
+/// is called in LTO optimization passes.
+std::string getPGOFuncName(const Function &F, bool InLTO = false,
uint64_t Version = INSTR_PROF_INDEX_VERSION);
/// Return the modified name for a function suitable to be
@@ -149,10 +188,16 @@ std::string getPGOFuncName(StringRef RawFuncName,
StringRef FileName,
uint64_t Version = INSTR_PROF_INDEX_VERSION);
+/// Return the name of the global variable used to store a function
+/// name in PGO instrumentation. \c FuncName is the name of the function
+/// returned by the \c getPGOFuncName call.
+std::string getPGOFuncNameVarName(StringRef FuncName,
+ GlobalValue::LinkageTypes Linkage);
+
/// Create and return the global variable for function name used in PGO
/// instrumentation. \c FuncName is the name of the function returned
/// by \c getPGOFuncName call.
-GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName);
+GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName);
/// Create and return the global variable for function name used in PGO
/// instrumentation. /// \c FuncName is the name of the function
@@ -160,13 +205,14 @@ GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName);
/// and \c Linkage is the linkage of the instrumented function.
GlobalVariable *createPGOFuncNameVar(Module &M,
GlobalValue::LinkageTypes Linkage,
- StringRef FuncName);
+ StringRef PGOFuncName);
/// Return the initializer in string of the PGO name var \c NameVar.
StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar);
/// Given a PGO function name, remove the filename prefix and return
/// the original (static) function name.
-StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName);
+StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName,
+ StringRef FileName = "<unknown>");
/// Given a vector of strings (function PGO names) \c NameStrs, the
/// method generates a combined string \c Result thatis ready to be
@@ -174,22 +220,59 @@ StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName);
/// The first field is the legnth of the uncompressed strings, and the
/// the second field is the length of the zlib-compressed string.
/// Both fields are encoded in ULEB128. If \c doCompress is false, the
-/// third field is the uncompressed strings; otherwise it is the
-/// compressed string. When the string compression is off, the
+/// third field is the uncompressed strings; otherwise it is the
+/// compressed string. When the string compression is off, the
/// second field will have value zero.
-int collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
- bool doCompression, std::string &Result);
+Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
+ bool doCompression, std::string &Result);
/// Produce \c Result string with the same format described above. The input
/// is vector of PGO function name variables that are referenced.
-int collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars,
- std::string &Result);
+Error collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars,
+ std::string &Result, bool doCompression = true);
class InstrProfSymtab;
/// \c NameStrings is a string composed of one of more sub-strings encoded in
-/// the
-/// format described above. The substrings are seperated by 0 or more zero
-/// bytes.
-/// This method decodes the string and populates the \c Symtab.
-int readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab);
+/// the format described above. The substrings are seperated by 0 or more zero
+/// bytes. This method decodes the string and populates the \c Symtab.
+Error readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab);
+
+enum InstrProfValueKind : uint32_t {
+#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
+#include "llvm/ProfileData/InstrProfData.inc"
+};
+
+struct InstrProfRecord;
+
+/// Get the value profile data for value site \p SiteIdx from \p InstrProfR
+/// and annotate the instruction \p Inst with the value profile meta data.
+/// Annotate up to \p MaxMDCount (default 3) number of records per value site.
+void annotateValueSite(Module &M, Instruction &Inst,
+ const InstrProfRecord &InstrProfR,
+ InstrProfValueKind ValueKind, uint32_t SiteIndx,
+ uint32_t MaxMDCount = 3);
+/// Same as the above interface but using an ArrayRef, as well as \p Sum.
+void annotateValueSite(Module &M, Instruction &Inst,
+ ArrayRef<InstrProfValueData> VDs,
+ uint64_t Sum, InstrProfValueKind ValueKind,
+ uint32_t MaxMDCount);
+
+/// Extract the value profile data from \p Inst which is annotated with
+/// value profile meta data. Return false if there is no value data annotated,
+/// otherwise return true.
+bool getValueProfDataFromInst(const Instruction &Inst,
+ InstrProfValueKind ValueKind,
+ uint32_t MaxNumValueData,
+ InstrProfValueData ValueData[],
+ uint32_t &ActualNumValueData, uint64_t &TotalC);
+
+inline StringRef getPGOFuncNameMetadataName() { return "PGOFuncName"; }
+
+/// Return the PGOFuncName meta data associated with a function.
+MDNode *getPGOFuncNameMetadata(const Function &F);
+
+/// Create the PGOFuncName meta data if PGOFuncName is different from
+/// function's raw name. This should only apply to internal linkage functions
+/// declared by users only.
+void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName);
const std::error_category &instrprof_category();
@@ -208,26 +291,104 @@ enum class instrprof_error {
hash_mismatch,
count_mismatch,
counter_overflow,
- value_site_count_mismatch
+ value_site_count_mismatch,
+ compress_failed,
+ uncompress_failed
};
inline std::error_code make_error_code(instrprof_error E) {
return std::error_code(static_cast<int>(E), instrprof_category());
}
-inline instrprof_error MergeResult(instrprof_error &Accumulator,
- instrprof_error Result) {
- // Prefer first error encountered as later errors may be secondary effects of
- // the initial problem.
- if (Accumulator == instrprof_error::success &&
- Result != instrprof_error::success)
- Accumulator = Result;
- return Accumulator;
-}
+class InstrProfError : public ErrorInfo<InstrProfError> {
+public:
+ InstrProfError(instrprof_error Err) : Err(Err) {
+ assert(Err != instrprof_error::success && "Not an error");
+ }
-enum InstrProfValueKind : uint32_t {
-#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
-#include "llvm/ProfileData/InstrProfData.inc"
+ std::string message() const override;
+
+ void log(raw_ostream &OS) const override { OS << message(); }
+
+ std::error_code convertToErrorCode() const override {
+ return make_error_code(Err);
+ }
+
+ instrprof_error get() const { return Err; }
+
+ /// Consume an Error and return the raw enum value contained within it. The
+ /// Error must either be a success value, or contain a single InstrProfError.
+ static instrprof_error take(Error E) {
+ auto Err = instrprof_error::success;
+ handleAllErrors(std::move(E), [&Err](const InstrProfError &IPE) {
+ assert(Err == instrprof_error::success && "Multiple errors encountered");
+ Err = IPE.get();
+ });
+ return Err;
+ }
+
+ static char ID;
+
+private:
+ instrprof_error Err;
+};
+
+class SoftInstrProfErrors {
+ /// Count the number of soft instrprof_errors encountered and keep track of
+ /// the first such error for reporting purposes.
+
+ /// The first soft error encountered.
+ instrprof_error FirstError;
+
+ /// The number of hash mismatches.
+ unsigned NumHashMismatches;
+
+ /// The number of count mismatches.
+ unsigned NumCountMismatches;
+
+ /// The number of counter overflows.
+ unsigned NumCounterOverflows;
+
+ /// The number of value site count mismatches.
+ unsigned NumValueSiteCountMismatches;
+
+public:
+ SoftInstrProfErrors()
+ : FirstError(instrprof_error::success), NumHashMismatches(0),
+ NumCountMismatches(0), NumCounterOverflows(0),
+ NumValueSiteCountMismatches(0) {}
+
+ ~SoftInstrProfErrors() {
+ assert(FirstError == instrprof_error::success &&
+ "Unchecked soft error encountered");
+ }
+
+ /// Track a soft error (\p IE) and increment its associated counter.
+ void addError(instrprof_error IE);
+
+ /// Get the number of hash mismatches.
+ unsigned getNumHashMismatches() const { return NumHashMismatches; }
+
+ /// Get the number of count mismatches.
+ unsigned getNumCountMismatches() const { return NumCountMismatches; }
+
+ /// Get the number of counter overflows.
+ unsigned getNumCounterOverflows() const { return NumCounterOverflows; }
+
+ /// Get the number of value site count mismatches.
+ unsigned getNumValueSiteCountMismatches() const {
+ return NumValueSiteCountMismatches;
+ }
+
+ /// Return the first encountered error and reset FirstError to a success
+ /// value.
+ Error takeError() {
+ if (FirstError == instrprof_error::success)
+ return Error::success();
+ auto E = make_error<InstrProfError>(FirstError);
+ FirstError = instrprof_error::success;
+ return E;
+ }
};
namespace object {
@@ -250,27 +411,41 @@ public:
private:
StringRef Data;
uint64_t Address;
- // A map from MD5 hash keys to function name strings.
- std::vector<std::pair<uint64_t, std::string>> HashNameMap;
+ // Unique name strings.
+ StringSet<> NameTab;
+ // A map from MD5 keys to function name strings.
+ std::vector<std::pair<uint64_t, StringRef>> MD5NameMap;
+ // A map from MD5 keys to function define. We only populate this map
+ // when build the Symtab from a Module.
+ std::vector<std::pair<uint64_t, Function *>> MD5FuncMap;
// A map from function runtime address to function name MD5 hash.
// This map is only populated and used by raw instr profile reader.
AddrHashMap AddrToMD5Map;
public:
- InstrProfSymtab() : Data(), Address(0), HashNameMap(), AddrToMD5Map() {}
+ InstrProfSymtab()
+ : Data(), Address(0), NameTab(), MD5NameMap(), MD5FuncMap(),
+ AddrToMD5Map() {}
/// Create InstrProfSymtab from an object file section which
- /// contains function PGO names that are uncompressed.
- /// This interface is used by CoverageMappingReader.
- std::error_code create(object::SectionRef &Section);
+ /// contains function PGO names. When section may contain raw
+ /// string data or string data in compressed form. This method
+ /// only initialize the symtab with reference to the data and
+ /// the section base address. The decompression will be delayed
+ /// until before it is used. See also \c create(StringRef) method.
+ Error create(object::SectionRef &Section);
/// This interface is used by reader of CoverageMapping test
/// format.
- inline std::error_code create(StringRef D, uint64_t BaseAddr);
+ inline Error create(StringRef D, uint64_t BaseAddr);
/// \c NameStrings is a string composed of one of more sub-strings
- /// encoded in the format described above. The substrings are
- /// seperated by 0 or more zero bytes. This method decodes the
- /// string and populates the \c Symtab.
- inline std::error_code create(StringRef NameStrings);
+ /// encoded in the format described in \c collectPGOFuncNameStrings.
+ /// This method is a wrapper to \c readPGOFuncNameStrings method.
+ inline Error create(StringRef NameStrings);
+ /// A wrapper interface to populate the PGO symtab with functions
+ /// decls from module \c M. This interface is used by transformation
+ /// passes such as indirect function call promotion. Variable \c InLTO
+ /// indicates if this is called from LTO optimization passes.
+ void create(Module &M, bool InLTO = false);
/// Create InstrProfSymtab from a set of names iteratable from
/// \p IterRange. This interface is used by IndexedProfReader.
template <typename NameIterRange> void create(const NameIterRange &IterRange);
@@ -282,8 +457,10 @@ public:
/// Update the symtab by adding \p FuncName to the table. This interface
/// is used by the raw and text profile readers.
void addFuncName(StringRef FuncName) {
- HashNameMap.push_back(std::make_pair(
- IndexedInstrProf::ComputeHash(FuncName), FuncName.str()));
+ auto Ins = NameTab.insert(FuncName);
+ if (Ins.second)
+ MD5NameMap.push_back(std::make_pair(
+ IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey()));
}
/// Map a function address to its name's MD5 hash. This interface
/// is only used by the raw profiler reader.
@@ -298,32 +475,37 @@ public:
/// Return function's PGO name from the name's md5 hash value.
/// If not found, return an empty string.
inline StringRef getFuncName(uint64_t FuncMD5Hash);
+ /// Return function from the name's md5 hash. Return nullptr if not found.
+ inline Function *getFunction(uint64_t FuncMD5Hash);
+ /// Return the function's original assembly name by stripping off
+ /// the prefix attached (to symbols with priviate linkage). For
+ /// global functions, it returns the same string as getFuncName.
+ inline StringRef getOrigFuncName(uint64_t FuncMD5Hash);
+ /// Return the name section data.
+ inline StringRef getNameData() const { return Data; }
};
-std::error_code InstrProfSymtab::create(StringRef D, uint64_t BaseAddr) {
+Error InstrProfSymtab::create(StringRef D, uint64_t BaseAddr) {
Data = D;
Address = BaseAddr;
- return std::error_code();
+ return Error::success();
}
-std::error_code InstrProfSymtab::create(StringRef NameStrings) {
- if (readPGOFuncNameStrings(NameStrings, *this))
- return make_error_code(instrprof_error::malformed);
- return std::error_code();
+Error InstrProfSymtab::create(StringRef NameStrings) {
+ return readPGOFuncNameStrings(NameStrings, *this);
}
template <typename NameIterRange>
void InstrProfSymtab::create(const NameIterRange &IterRange) {
for (auto Name : IterRange)
- HashNameMap.push_back(
- std::make_pair(IndexedInstrProf::ComputeHash(Name), Name.str()));
+ addFuncName(Name);
+
finalizeSymtab();
}
void InstrProfSymtab::finalizeSymtab() {
- std::sort(HashNameMap.begin(), HashNameMap.end(), less_first());
- HashNameMap.erase(std::unique(HashNameMap.begin(), HashNameMap.end()),
- HashNameMap.end());
+ std::sort(MD5NameMap.begin(), MD5NameMap.end(), less_first());
+ std::sort(MD5FuncMap.begin(), MD5FuncMap.end(), less_first());
std::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first());
AddrToMD5Map.erase(std::unique(AddrToMD5Map.begin(), AddrToMD5Map.end()),
AddrToMD5Map.end());
@@ -331,14 +513,34 @@ void InstrProfSymtab::finalizeSymtab() {
StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) {
auto Result =
- std::lower_bound(HashNameMap.begin(), HashNameMap.end(), FuncMD5Hash,
+ std::lower_bound(MD5NameMap.begin(), MD5NameMap.end(), FuncMD5Hash,
[](const std::pair<uint64_t, std::string> &LHS,
uint64_t RHS) { return LHS.first < RHS; });
- if (Result != HashNameMap.end())
+ if (Result != MD5NameMap.end() && Result->first == FuncMD5Hash)
return Result->second;
return StringRef();
}
+Function* InstrProfSymtab::getFunction(uint64_t FuncMD5Hash) {
+ auto Result =
+ std::lower_bound(MD5FuncMap.begin(), MD5FuncMap.end(), FuncMD5Hash,
+ [](const std::pair<uint64_t, Function*> &LHS,
+ uint64_t RHS) { return LHS.first < RHS; });
+ if (Result != MD5FuncMap.end() && Result->first == FuncMD5Hash)
+ return Result->second;
+ return nullptr;
+}
+
+// See also getPGOFuncName implementation. These two need to be
+// matched.
+StringRef InstrProfSymtab::getOrigFuncName(uint64_t FuncMD5Hash) {
+ StringRef PGOName = getFuncName(FuncMD5Hash);
+ size_t S = PGOName.find_first_of(':');
+ if (S == StringRef::npos)
+ return PGOName;
+ return PGOName.drop_front(S + 1);
+}
+
struct InstrProfValueSiteRecord {
/// Value profiling data pairs at a given value site.
std::list<InstrProfValueData> ValueData;
@@ -360,19 +562,21 @@ struct InstrProfValueSiteRecord {
/// Merge data from another InstrProfValueSiteRecord
/// Optionally scale merged counts by \p Weight.
- instrprof_error merge(InstrProfValueSiteRecord &Input, uint64_t Weight = 1);
+ void merge(SoftInstrProfErrors &SIPE, InstrProfValueSiteRecord &Input,
+ uint64_t Weight = 1);
/// Scale up value profile data counts.
- instrprof_error scale(uint64_t Weight);
+ void scale(SoftInstrProfErrors &SIPE, uint64_t Weight);
};
/// Profiling information for a single function.
struct InstrProfRecord {
- InstrProfRecord() {}
+ InstrProfRecord() : SIPE() {}
InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts)
- : Name(Name), Hash(Hash), Counts(std::move(Counts)) {}
+ : Name(Name), Hash(Hash), Counts(std::move(Counts)), SIPE() {}
StringRef Name;
uint64_t Hash;
std::vector<uint64_t> Counts;
+ SoftInstrProfErrors SIPE;
typedef std::vector<std::pair<uint64_t, uint64_t>> ValueMapType;
@@ -387,13 +591,17 @@ struct InstrProfRecord {
/// site: Site.
inline uint32_t getNumValueDataForSite(uint32_t ValueKind,
uint32_t Site) const;
- /// Return the array of profiled values at \p Site.
+ /// Return the array of profiled values at \p Site. If \p TotalC
+ /// is not null, the total count of all target values at this site
+ /// will be stored in \c *TotalC.
inline std::unique_ptr<InstrProfValueData[]>
getValueForSite(uint32_t ValueKind, uint32_t Site,
- uint64_t (*ValueMapper)(uint32_t, uint64_t) = 0) const;
- inline void
- getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind, uint32_t Site,
- uint64_t (*ValueMapper)(uint32_t, uint64_t) = 0) const;
+ uint64_t *TotalC = 0) const;
+ /// Get the target value/counts of kind \p ValueKind collected at site
+ /// \p Site and store the result in array \p Dest. Return the total
+ /// counts of all target values at this site.
+ inline uint64_t getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind,
+ uint32_t Site) const;
/// Reserve space for NumValueSites sites.
inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites);
/// Add ValueData for ValueKind at value Site.
@@ -403,11 +611,11 @@ struct InstrProfRecord {
/// Merge the counts in \p Other into this one.
/// Optionally scale merged counts by \p Weight.
- instrprof_error merge(InstrProfRecord &Other, uint64_t Weight = 1);
+ void merge(InstrProfRecord &Other, uint64_t Weight = 1);
/// Scale up profile counts (including value profile data) by
/// \p Weight.
- instrprof_error scale(uint64_t Weight);
+ void scale(uint64_t Weight);
/// Sort value profile data (per site) by count.
void sortValueData() {
@@ -424,6 +632,9 @@ struct InstrProfRecord {
getValueSitesForKind(Kind).clear();
}
+ /// Get the error contained within the record's soft error counter.
+ Error takeError() { return SIPE.takeError(); }
+
private:
std::vector<InstrProfValueSiteRecord> IndirectCallSites;
const std::vector<InstrProfValueSiteRecord> &
@@ -450,10 +661,10 @@ private:
// Merge Value Profile data from Src record to this record for ValueKind.
// Scale merged value counts by \p Weight.
- instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
- uint64_t Weight);
+ void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
+ uint64_t Weight);
// Scale up value profile data count.
- instrprof_error scaleValueProfData(uint32_t ValueKind, uint64_t Weight);
+ void scaleValueProfData(uint32_t ValueKind, uint64_t Weight);
};
uint32_t InstrProfRecord::getNumValueKinds() const {
@@ -482,29 +693,35 @@ uint32_t InstrProfRecord::getNumValueDataForSite(uint32_t ValueKind,
return getValueSitesForKind(ValueKind)[Site].ValueData.size();
}
-std::unique_ptr<InstrProfValueData[]> InstrProfRecord::getValueForSite(
- uint32_t ValueKind, uint32_t Site,
- uint64_t (*ValueMapper)(uint32_t, uint64_t)) const {
+std::unique_ptr<InstrProfValueData[]>
+InstrProfRecord::getValueForSite(uint32_t ValueKind, uint32_t Site,
+ uint64_t *TotalC) const {
+ uint64_t Dummy;
+ uint64_t &TotalCount = (TotalC == 0 ? Dummy : *TotalC);
uint32_t N = getNumValueDataForSite(ValueKind, Site);
- if (N == 0)
+ if (N == 0) {
+ TotalCount = 0;
return std::unique_ptr<InstrProfValueData[]>(nullptr);
+ }
auto VD = llvm::make_unique<InstrProfValueData[]>(N);
- getValueForSite(VD.get(), ValueKind, Site, ValueMapper);
+ TotalCount = getValueForSite(VD.get(), ValueKind, Site);
return VD;
}
-void InstrProfRecord::getValueForSite(InstrProfValueData Dest[],
- uint32_t ValueKind, uint32_t Site,
- uint64_t (*ValueMapper)(uint32_t,
- uint64_t)) const {
+uint64_t InstrProfRecord::getValueForSite(InstrProfValueData Dest[],
+ uint32_t ValueKind,
+ uint32_t Site) const {
uint32_t I = 0;
+ uint64_t TotalCount = 0;
for (auto V : getValueSitesForKind(ValueKind)[Site].ValueData) {
- Dest[I].Value = ValueMapper ? ValueMapper(ValueKind, V.Value) : V.Value;
+ Dest[I].Value = V.Value;
Dest[I].Count = V.Count;
+ TotalCount = SaturatingAdd(TotalCount, V.Count);
I++;
}
+ return TotalCount;
}
void InstrProfRecord::reserveSites(uint32_t ValueKind, uint32_t NumValueSites) {
@@ -532,27 +749,6 @@ void InstrProfValueSiteRecord::sortByCount() {
ValueData.resize(max_s);
}
-/*
-* Initialize the record for runtime value profile data.
-* Return 0 if the initialization is successful, otherwise
-* return 1.
-*/
-int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord,
- const uint16_t *NumValueSites,
- ValueProfNode **Nodes);
-
-/* Release memory allocated for the runtime record. */
-void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord);
-
-/* Return the size of ValueProfData structure that can be used to store
- the value profile data collected at runtime. */
-uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record);
-
-/* Return a ValueProfData instance that stores the data collected at runtime. */
-ValueProfData *
-serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
- ValueProfData *Dst);
-
namespace IndexedInstrProf {
enum class HashT : uint32_t {
@@ -561,27 +757,38 @@ enum class HashT : uint32_t {
Last = MD5
};
-static inline uint64_t MD5Hash(StringRef Str) {
- MD5 Hash;
- Hash.update(Str);
- llvm::MD5::MD5Result Result;
- Hash.final(Result);
- // Return the least significant 8 bytes. Our MD5 implementation returns the
- // result in little endian, so we may need to swap bytes.
- using namespace llvm::support;
- return endian::read<uint64_t, little, unaligned>(Result);
-}
-
inline uint64_t ComputeHash(HashT Type, StringRef K) {
switch (Type) {
case HashT::MD5:
- return IndexedInstrProf::MD5Hash(K);
+ return MD5Hash(K);
}
llvm_unreachable("Unhandled hash type");
}
const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81"
-const uint64_t Version = INSTR_PROF_INDEX_VERSION;
+
+enum ProfVersion {
+ // Version 1 is the first version. In this version, the value of
+ // a key/value pair can only include profile data of a single function.
+ // Due to this restriction, the number of block counters for a given
+ // function is not recorded but derived from the length of the value.
+ Version1 = 1,
+ // The version 2 format supports recording profile data of multiple
+ // functions which share the same key in one value field. To support this,
+ // the number block counters is recorded as an uint64_t field right after the
+ // function structural hash.
+ Version2 = 2,
+ // Version 3 supports value profile data. The value profile data is expected
+ // to follow the block counter profile data.
+ Version3 = 3,
+ // In this version, profile summary data \c IndexedInstrProf::Summary is
+ // stored after the profile header.
+ Version4 = 4,
+ // The current version is 4.
+ CurrentVersion = INSTR_PROF_INDEX_VERSION
+};
+const uint64_t Version = ProfVersion::CurrentVersion;
+
const HashT HashType = HashT::MD5;
inline uint64_t ComputeHash(StringRef K) { return ComputeHash(HashType, K); }
@@ -591,15 +798,104 @@ inline uint64_t ComputeHash(StringRef K) { return ComputeHash(HashType, K); }
struct Header {
uint64_t Magic;
uint64_t Version;
- uint64_t MaxFunctionCount;
+ uint64_t Unused; // Becomes unused since version 4
uint64_t HashType;
uint64_t HashOffset;
};
+// Profile summary data recorded in the profile data file in indexed
+// format. It is introduced in version 4. The summary data follows
+// right after the profile file header.
+struct Summary {
+
+ struct Entry {
+ uint64_t Cutoff; ///< The required percentile of total execution count.
+ uint64_t
+ MinBlockCount; ///< The minimum execution count for this percentile.
+ uint64_t NumBlocks; ///< Number of blocks >= the minumum execution count.
+ };
+ // The field kind enumerator to assigned value mapping should remain
+ // unchanged when a new kind is added or an old kind gets deleted in
+ // the future.
+ enum SummaryFieldKind {
+ /// The total number of functions instrumented.
+ TotalNumFunctions = 0,
+ /// Total number of instrumented blocks/edges.
+ TotalNumBlocks = 1,
+ /// The maximal execution count among all functions.
+ /// This field does not exist for profile data from IR based
+ /// instrumentation.
+ MaxFunctionCount = 2,
+ /// Max block count of the program.
+ MaxBlockCount = 3,
+ /// Max internal block count of the program (excluding entry blocks).
+ MaxInternalBlockCount = 4,
+ /// The sum of all instrumented block counts.
+ TotalBlockCount = 5,
+ NumKinds = TotalBlockCount + 1
+ };
+
+ // The number of summmary fields following the summary header.
+ uint64_t NumSummaryFields;
+ // The number of Cutoff Entries (Summary::Entry) following summary fields.
+ uint64_t NumCutoffEntries;
+
+ static uint32_t getSize(uint32_t NumSumFields, uint32_t NumCutoffEntries) {
+ return sizeof(Summary) + NumCutoffEntries * sizeof(Entry) +
+ NumSumFields * sizeof(uint64_t);
+ }
+
+ const uint64_t *getSummaryDataBase() const {
+ return reinterpret_cast<const uint64_t *>(this + 1);
+ }
+ uint64_t *getSummaryDataBase() {
+ return reinterpret_cast<uint64_t *>(this + 1);
+ }
+ const Entry *getCutoffEntryBase() const {
+ return reinterpret_cast<const Entry *>(
+ &getSummaryDataBase()[NumSummaryFields]);
+ }
+ Entry *getCutoffEntryBase() {
+ return reinterpret_cast<Entry *>(&getSummaryDataBase()[NumSummaryFields]);
+ }
+
+ uint64_t get(SummaryFieldKind K) const {
+ return getSummaryDataBase()[K];
+ }
+
+ void set(SummaryFieldKind K, uint64_t V) {
+ getSummaryDataBase()[K] = V;
+ }
+
+ const Entry &getEntry(uint32_t I) const { return getCutoffEntryBase()[I]; }
+ void setEntry(uint32_t I, const ProfileSummaryEntry &E) {
+ Entry &ER = getCutoffEntryBase()[I];
+ ER.Cutoff = E.Cutoff;
+ ER.MinBlockCount = E.MinCount;
+ ER.NumBlocks = E.NumCounts;
+ }
+
+ Summary(uint32_t Size) { memset(this, 0, Size); }
+ void operator delete(void *ptr) { ::operator delete(ptr); }
+
+ Summary() = delete;
+};
+
+inline std::unique_ptr<Summary> allocSummary(uint32_t TotalSize) {
+ return std::unique_ptr<Summary>(new (::operator new(TotalSize))
+ Summary(TotalSize));
+}
} // end namespace IndexedInstrProf
namespace RawInstrProf {
+// Version 1: First version
+// Version 2: Added value profile data section. Per-function control data
+// struct has more fields to describe value profile information.
+// Version 3: Compressed name section support. Function PGO name reference
+// from control data struct is changed from raw pointer to Name's MD5 value.
+// Version 4: ValueDataBegin and ValueDataSizes fields are removed from the
+// raw header.
const uint64_t Version = INSTR_PROF_RAW_VERSION;
template <class IntPtrT> inline uint64_t getMagic();
@@ -630,13 +926,8 @@ struct Header {
#include "llvm/ProfileData/InstrProfData.inc"
};
-} // end namespace RawInstrProf
+} // end namespace RawInstrProf
} // end namespace llvm
-namespace std {
-template <>
-struct is_error_code_enum<llvm::instrprof_error> : std::true_type {};
-}
-
-#endif // LLVM_PROFILEDATA_INSTRPROF_H_
+#endif // LLVM_PROFILEDATA_INSTRPROF_H
diff --git a/include/llvm/ProfileData/InstrProfData.inc b/include/llvm/ProfileData/InstrProfData.inc
index 33c7d94aea2a2..4138e18fa22f9 100644
--- a/include/llvm/ProfileData/InstrProfData.inc
+++ b/include/llvm/ProfileData/InstrProfData.inc
@@ -57,6 +57,12 @@
*
\*===----------------------------------------------------------------------===*/
+/* Functions marked with INSTR_PROF_VISIBILITY must have hidden visibility in
+ * the compiler runtime. */
+#ifndef INSTR_PROF_VISIBILITY
+#define INSTR_PROF_VISIBILITY
+#endif
+
/* INSTR_PROF_DATA start. */
/* Definition of member fields of the per-function control structure. */
#ifndef INSTR_PROF_DATA
@@ -64,29 +70,57 @@
#else
#define INSTR_PROF_DATA_DEFINED
#endif
-
-INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \
- ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \
- NamePtr->getType()->getPointerElementType()->getArrayNumElements()))
-INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \
- ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters))
+INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \
+ ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
+ IndexedInstrProf::ComputeHash(getPGOFuncNameVarInitializer(Inc->getName()))))
INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \
ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
Inc->getHash()->getZExtValue()))
-INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), NamePtr, \
- ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)))
INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt64PtrTy(Ctx), CounterPtr, \
ConstantExpr::getBitCast(CounterPtr, \
llvm::Type::getInt64PtrTy(Ctx)))
+/* This is used to map function pointers for the indirect call targets to
+ * function name hashes during the conversion from raw to merged profile
+ * data.
+ */
INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), FunctionPointer, \
FunctionAddr)
INSTR_PROF_DATA(IntPtrT, llvm::Type::getInt8PtrTy(Ctx), Values, \
- ConstantPointerNull::get(Int8PtrTy))
+ ValuesPtrExpr)
+INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \
+ ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters))
INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \
ConstantArray::get(Int16ArrayTy, Int16ArrayVals))
#undef INSTR_PROF_DATA
/* INSTR_PROF_DATA end. */
+
+/* This is an internal data structure used by value profiler. It
+ * is defined here to allow serialization code sharing by LLVM
+ * to be used in unit test.
+ *
+ * typedef struct ValueProfNode {
+ * // InstrProfValueData VData;
+ * uint64_t Value;
+ * uint64_t Count;
+ * struct ValueProfNode *Next;
+ * } ValueProfNode;
+ */
+/* INSTR_PROF_VALUE_NODE start. */
+#ifndef INSTR_PROF_VALUE_NODE
+#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer)
+#else
+#define INSTR_PROF_DATA_DEFINED
+#endif
+INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Value, \
+ ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
+INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Count, \
+ ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
+INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \
+ ConstantInt::get(llvm::Type::GetInt8PtrTy(Ctx), 0))
+#undef INSTR_PROF_VALUE_NODE
+/* INSTR_PROF_VALUE_NODE end. */
+
/* INSTR_PROF_RAW_HEADER start */
/* Definition of member fields of the raw profile header data structure. */
#ifndef INSTR_PROF_RAW_HEADER
@@ -102,8 +136,6 @@ INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
-INSTR_PROF_RAW_HEADER(uint64_t, ValueDataSize, ValueDataSize)
-INSTR_PROF_RAW_HEADER(uint64_t, ValueDataDelta, (uintptr_t)ValueDataBegin)
#undef INSTR_PROF_RAW_HEADER
/* INSTR_PROF_RAW_HEADER end */
@@ -132,6 +164,15 @@ VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
#else
#define INSTR_PROF_DATA_DEFINED
#endif
+/* For indirect function call value profiling, the addresses of the target
+ * functions are profiled by the instrumented code. The target addresses are
+ * written in the raw profile data and converted to target function name's MD5
+ * hash by the profile reader during deserialization. Typically, this happens
+ * when the the raw profile data is read during profile merging.
+ *
+ * For this remapping the ProfData is used. ProfData contains both the function
+ * name hash and the function address.
+ */
VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0)
/* These two kinds must be the last to be
* declared. This is to make sure the string
@@ -153,12 +194,18 @@ VALUE_PROF_KIND(IPVK_Last, IPVK_IndirectCallTarget)
#else
#define INSTR_PROF_DATA_DEFINED
#endif
+#ifdef COVMAP_V1
COVMAP_FUNC_RECORD(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), \
NamePtr, llvm::ConstantExpr::getBitCast(NamePtr, \
llvm::Type::getInt8PtrTy(Ctx)))
COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx),\
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \
NameValue.size()))
+#else
+COVMAP_FUNC_RECORD(const int64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
+ llvm::IndexedInstrProf::ComputeHash(NameValue)))
+#endif
COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), DataSize, \
llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx),\
CoverageMapping.size()))
@@ -182,7 +229,7 @@ COVMAP_HEADER(uint32_t, Int32Ty, FilenamesSize, \
COVMAP_HEADER(uint32_t, Int32Ty, CoverageSize, \
llvm::ConstantInt::get(Int32Ty, CoverageMappingSize))
COVMAP_HEADER(uint32_t, Int32Ty, Version, \
- llvm::ConstantInt::get(Int32Ty, CoverageMappingCurrentVersion))
+ llvm::ConstantInt::get(Int32Ty, CovMapVersion::CurrentVersion))
#undef COVMAP_HEADER
/* COVMAP_HEADER end. */
@@ -281,16 +328,15 @@ typedef struct ValueProfData {
static std::unique_ptr<ValueProfData>
serializeFrom(const InstrProfRecord &Record);
/*!
- * Check the integrity of the record. Return the error code when
- * an error is detected, otherwise return instrprof_error::success.
+ * Check the integrity of the record.
*/
- instrprof_error checkIntegrity();
+ Error checkIntegrity();
/*!
* Return a pointer to \c ValueProfileData instance ready to be read.
* All data in the instance are properly byte swapped. The input
* data is assumed to be in little endian order.
*/
- static ErrorOr<std::unique_ptr<ValueProfData>>
+ static Expected<std::unique_ptr<ValueProfData>>
getValueProfData(const unsigned char *SrcBuffer,
const unsigned char *const SrcBufferEnd,
support::endianness SrcDataEndianness);
@@ -343,46 +389,18 @@ typedef struct ValueProfRecordClosure {
*/
uint64_t (*RemapValueData)(uint32_t, uint64_t Value);
void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K,
- uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t));
+ uint32_t S);
ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes);
} ValueProfRecordClosure;
-/*
- * A wrapper struct that represents value profile runtime data.
- * Like InstrProfRecord class which is used by profiling host tools,
- * ValueProfRuntimeRecord also implements the abstract intefaces defined in
- * ValueProfRecordClosure so that the runtime data can be serialized using
- * shared C implementation. In this structure, NumValueSites and Nodes
- * members are the primary fields while other fields hold the derived
- * information for fast implementation of closure interfaces.
- */
-typedef struct ValueProfRuntimeRecord {
- /* Number of sites for each value profile kind. */
- const uint16_t *NumValueSites;
- /* An array of linked-list headers. The size of of the array is the
- * total number of value profile sites : sum(NumValueSites[*])). Each
- * linked-list stores the values profiled for a value profile site. */
- ValueProfNode **Nodes;
-
- /* Total number of value profile kinds which have at least one
- * value profile sites. */
- uint32_t NumValueKinds;
- /* An array recording the number of values tracked at each site.
- * The size of the array is TotalNumValueSites. */
- uint8_t *SiteCountArray[IPVK_Last + 1];
- ValueProfNode **NodesKind[IPVK_Last + 1];
-} ValueProfRuntimeRecord;
-
-/* Forward declarations of C interfaces. */
-int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord,
- const uint16_t *NumValueSites,
- ValueProfNode **Nodes);
-void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord);
-uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record);
-ValueProfData *
-serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
- ValueProfData *Dst);
-uint32_t getNumValueKindsRT(const void *R);
+INSTR_PROF_VISIBILITY ValueProfRecord *
+getFirstValueProfRecord(ValueProfData *VPD);
+INSTR_PROF_VISIBILITY ValueProfRecord *
+getValueProfRecordNext(ValueProfRecord *VPR);
+INSTR_PROF_VISIBILITY InstrProfValueData *
+getValueProfRecordValueData(ValueProfRecord *VPR);
+INSTR_PROF_VISIBILITY uint32_t
+getValueProfRecordHeaderSize(uint32_t NumValueSites);
#undef INSTR_PROF_VALUE_PROF_DATA
#endif /* INSTR_PROF_VALUE_PROF_DATA */
@@ -392,8 +410,10 @@ uint32_t getNumValueKindsRT(const void *R);
#define INSTR_PROF_DATA_DEFINED
#ifdef __cplusplus
#define INSTR_PROF_INLINE inline
+#define INSTR_PROF_NULLPTR nullptr
#else
#define INSTR_PROF_INLINE
+#define INSTR_PROF_NULLPTR NULL
#endif
#ifndef offsetof
@@ -404,7 +424,7 @@ uint32_t getNumValueKindsRT(const void *R);
* \brief Return the \c ValueProfRecord header size including the
* padding bytes.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) {
uint32_t Size = offsetof(ValueProfRecord, SiteCountArray) +
sizeof(uint8_t) * NumValueSites;
@@ -417,7 +437,7 @@ uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) {
* \brief Return the total size of the value profile record including the
* header and the value data.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
uint32_t getValueProfRecordSize(uint32_t NumValueSites,
uint32_t NumValueData) {
return getValueProfRecordHeaderSize(NumValueSites) +
@@ -427,7 +447,7 @@ uint32_t getValueProfRecordSize(uint32_t NumValueSites,
/*!
* \brief Return the pointer to the start of value data array.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) {
return (InstrProfValueData *)((char *)This + getValueProfRecordHeaderSize(
This->NumValueSites));
@@ -436,7 +456,7 @@ InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) {
/*!
* \brief Return the total number of value data for \c This record.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) {
uint32_t NumValueData = 0;
uint32_t I;
@@ -448,7 +468,7 @@ uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) {
/*!
* \brief Use this method to advance to the next \c This \c ValueProfRecord.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
uint32_t NumValueData = getValueProfRecordNumValueData(This);
return (ValueProfRecord *)((char *)This +
@@ -459,7 +479,7 @@ ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
/*!
* \brief Return the first \c ValueProfRecord instance.
*/
-INSTR_PROF_INLINE
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) {
return (ValueProfRecord *)((char *)This + sizeof(ValueProfData));
}
@@ -470,13 +490,11 @@ ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) {
* Return the total size in bytes of the on-disk value profile data
* given the data stored in Record.
*/
-uint32_t getValueProfDataSize(ValueProfRecordClosure *Closure) {
+INSTR_PROF_VISIBILITY uint32_t
+getValueProfDataSize(ValueProfRecordClosure *Closure) {
uint32_t Kind;
uint32_t TotalSize = sizeof(ValueProfData);
const void *Record = Closure->Record;
- uint32_t NumValueKinds = Closure->GetNumValueKinds(Record);
- if (NumValueKinds == 0)
- return TotalSize;
for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind);
@@ -492,9 +510,10 @@ uint32_t getValueProfDataSize(ValueProfRecordClosure *Closure) {
* Extract value profile data of a function for the profile kind \c ValueKind
* from the \c Closure and serialize the data into \c This record instance.
*/
-void serializeValueProfRecordFrom(ValueProfRecord *This,
- ValueProfRecordClosure *Closure,
- uint32_t ValueKind, uint32_t NumValueSites) {
+INSTR_PROF_VISIBILITY void
+serializeValueProfRecordFrom(ValueProfRecord *This,
+ ValueProfRecordClosure *Closure,
+ uint32_t ValueKind, uint32_t NumValueSites) {
uint32_t S;
const void *Record = Closure->Record;
This->Kind = ValueKind;
@@ -504,8 +523,7 @@ void serializeValueProfRecordFrom(ValueProfRecord *This,
for (S = 0; S < NumValueSites; S++) {
uint32_t ND = Closure->GetNumValueDataForSite(Record, ValueKind, S);
This->SiteCountArray[S] = ND;
- Closure->GetValueForSite(Record, DstVD, ValueKind, S,
- Closure->RemapValueData);
+ Closure->GetValueForSite(Record, DstVD, ValueKind, S);
DstVD += ND;
}
}
@@ -513,12 +531,16 @@ void serializeValueProfRecordFrom(ValueProfRecord *This,
/*!
* Extract value profile data of a function from the \c Closure
* and serialize the data into \c DstData if it is not NULL or heap
- * memory allocated by the \c Closure's allocator method.
+ * memory allocated by the \c Closure's allocator method. If \c
+ * DstData is not null, the caller is expected to set the TotalSize
+ * in DstData.
*/
-ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
- ValueProfData *DstData) {
+INSTR_PROF_VISIBILITY ValueProfData *
+serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
+ ValueProfData *DstData) {
uint32_t Kind;
- uint32_t TotalSize = getValueProfDataSize(Closure);
+ uint32_t TotalSize =
+ DstData ? DstData->TotalSize : getValueProfDataSize(Closure);
ValueProfData *VPD =
DstData ? DstData : Closure->AllocValueProfData(TotalSize);
@@ -536,144 +558,15 @@ ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
return VPD;
}
-/*
- * The value profiler runtime library stores the value profile data
- * for a given function in \c NumValueSites and \c Nodes structures.
- * \c ValueProfRuntimeRecord class is used to encapsulate the runtime
- * profile data and provides fast interfaces to retrieve the profile
- * information. This interface is used to initialize the runtime record
- * and pre-compute the information needed for efficient implementation
- * of callbacks required by ValueProfRecordClosure class.
- */
-int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord,
- const uint16_t *NumValueSites,
- ValueProfNode **Nodes) {
- unsigned I, J, S = 0, NumValueKinds = 0;
- RuntimeRecord->NumValueSites = NumValueSites;
- RuntimeRecord->Nodes = Nodes;
- for (I = 0; I <= IPVK_Last; I++) {
- uint16_t N = NumValueSites[I];
- if (!N) {
- RuntimeRecord->SiteCountArray[I] = 0;
- continue;
- }
- NumValueKinds++;
- RuntimeRecord->SiteCountArray[I] = (uint8_t *)calloc(N, 1);
- if (!RuntimeRecord->SiteCountArray[I])
- return 1;
- RuntimeRecord->NodesKind[I] = Nodes ? &Nodes[S] : NULL;
- for (J = 0; J < N; J++) {
- /* Compute value count for each site. */
- uint32_t C = 0;
- ValueProfNode *Site = Nodes ? RuntimeRecord->NodesKind[I][J] : NULL;
- while (Site) {
- C++;
- Site = Site->Next;
- }
- if (C > UCHAR_MAX)
- C = UCHAR_MAX;
- RuntimeRecord->SiteCountArray[I][J] = C;
- }
- S += N;
- }
- RuntimeRecord->NumValueKinds = NumValueKinds;
- return 0;
-}
-
-void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord) {
- unsigned I;
- for (I = 0; I <= IPVK_Last; I++) {
- if (RuntimeRecord->SiteCountArray[I])
- free(RuntimeRecord->SiteCountArray[I]);
- }
-}
-
-/* ValueProfRecordClosure Interface implementation for
- * ValueProfDataRuntimeRecord. */
-uint32_t getNumValueKindsRT(const void *R) {
- return ((const ValueProfRuntimeRecord *)R)->NumValueKinds;
-}
-
-uint32_t getNumValueSitesRT(const void *R, uint32_t VK) {
- return ((const ValueProfRuntimeRecord *)R)->NumValueSites[VK];
-}
-
-uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK, uint32_t S) {
- const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
- return Record->SiteCountArray[VK][S];
-}
-
-uint32_t getNumValueDataRT(const void *R, uint32_t VK) {
- unsigned I, S = 0;
- const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
- if (Record->SiteCountArray[VK] == 0)
- return 0;
- for (I = 0; I < Record->NumValueSites[VK]; I++)
- S += Record->SiteCountArray[VK][I];
- return S;
-}
-
-void getValueForSiteRT(const void *R, InstrProfValueData *Dst, uint32_t VK,
- uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t)) {
- unsigned I, N = 0;
- const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
- N = getNumValueDataForSiteRT(R, VK, S);
- if (N == 0)
- return;
- ValueProfNode *VNode = Record->NodesKind[VK][S];
- for (I = 0; I < N; I++) {
- Dst[I] = VNode->VData;
- VNode = VNode->Next;
- }
-}
-
-ValueProfData *allocValueProfDataRT(size_t TotalSizeInBytes) {
- return (ValueProfData *)calloc(TotalSizeInBytes, 1);
-}
-
-static ValueProfRecordClosure RTRecordClosure = {0,
- getNumValueKindsRT,
- getNumValueSitesRT,
- getNumValueDataRT,
- getNumValueDataForSiteRT,
- 0,
- getValueForSiteRT,
- allocValueProfDataRT};
-
-/*
- * Return the size of ValueProfData structure to store data
- * recorded in the runtime record.
- */
-uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record) {
- RTRecordClosure.Record = Record;
- return getValueProfDataSize(&RTRecordClosure);
-}
-
-/*
- * Return a ValueProfData instance that stores the data collected
- * from runtime. If \c DstData is provided by the caller, the value
- * profile data will be store in *DstData and DstData is returned,
- * otherwise the method will allocate space for the value data and
- * return pointer to the newly allocated space.
- */
-ValueProfData *
-serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
- ValueProfData *DstData) {
- RTRecordClosure.Record = Record;
- return serializeValueProfDataFrom(&RTRecordClosure, DstData);
-}
-
-
#undef INSTR_PROF_COMMON_API_IMPL
#endif /* INSTR_PROF_COMMON_API_IMPL */
/*============================================================================*/
-
#ifndef INSTR_PROF_DATA_DEFINED
-#ifndef INSTR_PROF_DATA_INC_
-#define INSTR_PROF_DATA_INC_
+#ifndef INSTR_PROF_DATA_INC
+#define INSTR_PROF_DATA_INC
/* Helper macros. */
#define INSTR_PROF_SIMPLE_QUOTE(x) #x
@@ -695,23 +588,33 @@ serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
(uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
-/* Raw profile format version. */
-#define INSTR_PROF_RAW_VERSION 2
-#define INSTR_PROF_INDEX_VERSION 3
-#define INSTR_PROF_COVMAP_VERSION 0
+/* Raw profile format version (start from 1). */
+#define INSTR_PROF_RAW_VERSION 4
+/* Indexed profile format version (start from 1). */
+#define INSTR_PROF_INDEX_VERSION 4
+/* Coverage mapping format vresion (start from 0). */
+#define INSTR_PROF_COVMAP_VERSION 1
-/* Profile version is always of type uint_64_t. Reserve the upper 8 bits in the
+/* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
* version for other variants of profile. We set the lowest bit of the upper 8
* bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentaiton
* generated profile, and 0 if this is a Clang FE generated profile.
-*/
+ */
#define VARIANT_MASKS_ALL 0xff00000000000000ULL
#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL)
+#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
+#define IR_LEVEL_PROF_VERSION_VAR __llvm_profile_raw_version
/* Runtime section names and name strings. */
#define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data
#define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names
#define INSTR_PROF_CNTS_SECT_NAME __llvm_prf_cnts
+/* Array of pointers. Each pointer points to a list
+ * of value nodes associated with one value site.
+ */
+#define INSTR_PROF_VALS_SECT_NAME __llvm_prf_vals
+/* Value profile nodes section. */
+#define INSTR_PROF_VNODES_SECT_NAME __llvm_prf_vnds
#define INSTR_PROF_COVMAP_SECT_NAME __llvm_covmap
#define INSTR_PROF_DATA_SECT_NAME_STR \
@@ -722,6 +625,10 @@ serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
INSTR_PROF_QUOTE(INSTR_PROF_CNTS_SECT_NAME)
#define INSTR_PROF_COVMAP_SECT_NAME_STR \
INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_SECT_NAME)
+#define INSTR_PROF_VALS_SECT_NAME_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_VALS_SECT_NAME)
+#define INSTR_PROF_VNODES_SECT_NAME_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_VNODES_SECT_NAME)
/* Macros to define start/stop section symbol for a given
* section on Linux. For instance
@@ -751,16 +658,7 @@ typedef struct InstrProfValueData {
uint64_t Count;
} InstrProfValueData;
-/* This is an internal data structure used by value profiler. It
- * is defined here to allow serialization code sharing by LLVM
- * to be used in unit test.
- */
-typedef struct ValueProfNode {
- InstrProfValueData VData;
- struct ValueProfNode *Next;
-} ValueProfNode;
-
-#endif /* INSTR_PROF_DATA_INC_ */
+#endif /* INSTR_PROF_DATA_INC */
#else
#undef INSTR_PROF_DATA_DEFINED
diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h
index fed3e693e7a05..65b11f61d10bc 100644
--- a/include/llvm/ProfileData/InstrProfReader.h
+++ b/include/llvm/ProfileData/InstrProfReader.h
@@ -19,7 +19,6 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/EndianStream.h"
-#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
@@ -51,19 +50,20 @@ public:
/// Base class and interface for reading profiling data of any known instrprof
/// format. Provides an iterator over InstrProfRecords.
class InstrProfReader {
- std::error_code LastError;
+ instrprof_error LastError;
public:
InstrProfReader() : LastError(instrprof_error::success), Symtab() {}
virtual ~InstrProfReader() {}
/// Read the header. Required before reading first record.
- virtual std::error_code readHeader() = 0;
+ virtual Error readHeader() = 0;
/// Read a single record.
- virtual std::error_code readNextRecord(InstrProfRecord &Record) = 0;
+ virtual Error readNextRecord(InstrProfRecord &Record) = 0;
/// Iterator over profile data.
InstrProfIterator begin() { return InstrProfIterator(this); }
InstrProfIterator end() { return InstrProfIterator(); }
+ virtual bool isIRLevelProfile() const = 0;
/// Return the PGO symtab. There are three different readers:
/// Raw, Text, and Indexed profile readers. The first two types
@@ -79,28 +79,35 @@ public:
protected:
std::unique_ptr<InstrProfSymtab> Symtab;
- /// Set the current std::error_code and return same.
- std::error_code error(std::error_code EC) {
- LastError = EC;
- return EC;
+ /// Set the current error and return same.
+ Error error(instrprof_error Err) {
+ LastError = Err;
+ if (Err == instrprof_error::success)
+ return Error::success();
+ return make_error<InstrProfError>(Err);
}
+ Error error(Error E) { return error(InstrProfError::take(std::move(E))); }
- /// Clear the current error code and return a successful one.
- std::error_code success() { return error(instrprof_error::success); }
+ /// Clear the current error and return a successful one.
+ Error success() { return error(instrprof_error::success); }
public:
/// Return true if the reader has finished reading the profile data.
bool isEOF() { return LastError == instrprof_error::eof; }
/// Return true if the reader encountered an error reading profiling data.
- bool hasError() { return LastError && !isEOF(); }
- /// Get the current error code.
- std::error_code getError() { return LastError; }
+ bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
+ /// Get the current error.
+ Error getError() {
+ if (hasError())
+ return make_error<InstrProfError>(LastError);
+ return Error::success();
+ }
/// Factory method to create an appropriately typed reader for the given
/// instrprof file.
- static ErrorOr<std::unique_ptr<InstrProfReader>> create(std::string Path);
+ static Expected<std::unique_ptr<InstrProfReader>> create(const Twine &Path);
- static ErrorOr<std::unique_ptr<InstrProfReader>>
+ static Expected<std::unique_ptr<InstrProfReader>>
create(std::unique_ptr<MemoryBuffer> Buffer);
};
@@ -118,22 +125,26 @@ private:
std::unique_ptr<MemoryBuffer> DataBuffer;
/// Iterator over the profile data.
line_iterator Line;
+ bool IsIRLevelProfile;
TextInstrProfReader(const TextInstrProfReader &) = delete;
TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
- std::error_code readValueProfileData(InstrProfRecord &Record);
+ Error readValueProfileData(InstrProfRecord &Record);
public:
TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
- : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
+ : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#'),
+ IsIRLevelProfile(false) {}
/// Return true if the given buffer is in text instrprof format.
static bool hasFormat(const MemoryBuffer &Buffer);
+ bool isIRLevelProfile() const override { return IsIRLevelProfile; }
+
/// Read the header.
- std::error_code readHeader() override;
+ Error readHeader() override;
/// Read a single record.
- std::error_code readNextRecord(InstrProfRecord &Record) override;
+ Error readNextRecord(InstrProfRecord &Record) override;
InstrProfSymtab &getSymtab() override {
assert(Symtab.get());
@@ -154,14 +165,20 @@ private:
/// The profile data file contents.
std::unique_ptr<MemoryBuffer> DataBuffer;
bool ShouldSwapBytes;
+ // The value of the version field of the raw profile data header. The lower 56
+ // bits specifies the format version and the most significant 8 bits specify
+ // the variant types of the profile.
+ uint64_t Version;
uint64_t CountersDelta;
uint64_t NamesDelta;
const RawInstrProf::ProfileData<IntPtrT> *Data;
const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
const uint64_t *CountersStart;
const char *NamesStart;
+ uint64_t NamesSize;
+ // After value profile is all read, this pointer points to
+ // the header of next profile data (if exists)
const uint8_t *ValueDataStart;
- const char *ProfileEnd;
uint32_t ValueKindLast;
uint32_t CurValueDataSize;
@@ -174,8 +191,11 @@ public:
: DataBuffer(std::move(DataBuffer)) { }
static bool hasFormat(const MemoryBuffer &DataBuffer);
- std::error_code readHeader() override;
- std::error_code readNextRecord(InstrProfRecord &Record) override;
+ Error readHeader() override;
+ Error readNextRecord(InstrProfRecord &Record) override;
+ bool isIRLevelProfile() const override {
+ return (Version & VARIANT_MASK_IR_PROF) != 0;
+ }
InstrProfSymtab &getSymtab() override {
assert(Symtab.get());
@@ -183,9 +203,9 @@ public:
}
private:
- void createSymtab(InstrProfSymtab &Symtab);
- std::error_code readNextHeader(const char *CurrentPos);
- std::error_code readHeader(const RawInstrProf::Header &Header);
+ Error createSymtab(InstrProfSymtab &Symtab);
+ Error readNextHeader(const char *CurrentPos);
+ Error readHeader(const RawInstrProf::Header &Header);
template <class IntT> IntT swap(IntT Int) const {
return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
}
@@ -202,23 +222,26 @@ private:
inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
}
- std::error_code readName(InstrProfRecord &Record);
- std::error_code readFuncHash(InstrProfRecord &Record);
- std::error_code readRawCounts(InstrProfRecord &Record);
- std::error_code readValueProfilingData(InstrProfRecord &Record);
+ Error readName(InstrProfRecord &Record);
+ Error readFuncHash(InstrProfRecord &Record);
+ Error readRawCounts(InstrProfRecord &Record);
+ Error readValueProfilingData(InstrProfRecord &Record);
bool atEnd() const { return Data == DataEnd; }
void advanceData() {
Data++;
ValueDataStart += CurValueDataSize;
}
+ const char *getNextHeaderPos() const {
+ assert(atEnd());
+ return (const char *)ValueDataStart;
+ }
const uint64_t *getCounter(IntPtrT CounterPtr) const {
ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
return CountersStart + Offset;
}
- const char *getName(IntPtrT NamePtr) const {
- ptrdiff_t Offset = (swap(NamePtr) - NamesDelta) / sizeof(char);
- return NamesStart + Offset;
+ StringRef getName(uint64_t NameRef) const {
+ return Symtab->getFuncName(swap(NameRef));
}
};
@@ -283,15 +306,16 @@ public:
struct InstrProfReaderIndexBase {
// Read all the profile records with the same key pointed to the current
// iterator.
- virtual std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
+ virtual Error getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
// Read all the profile records with the key equal to FuncName
- virtual std::error_code getRecords(StringRef FuncName,
+ virtual Error getRecords(StringRef FuncName,
ArrayRef<InstrProfRecord> &Data) = 0;
virtual void advanceToNextKey() = 0;
virtual bool atEnd() const = 0;
virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
virtual ~InstrProfReaderIndexBase() {}
virtual uint64_t getVersion() const = 0;
+ virtual bool isIRLevelProfile() const = 0;
virtual void populateSymtab(InstrProfSymtab &) = 0;
};
@@ -312,9 +336,9 @@ public:
const unsigned char *const Base,
IndexedInstrProf::HashT HashType, uint64_t Version);
- std::error_code getRecords(ArrayRef<InstrProfRecord> &Data) override;
- std::error_code getRecords(StringRef FuncName,
- ArrayRef<InstrProfRecord> &Data) override;
+ Error getRecords(ArrayRef<InstrProfRecord> &Data) override;
+ Error getRecords(StringRef FuncName,
+ ArrayRef<InstrProfRecord> &Data) override;
void advanceToNextKey() override { RecordIterator++; }
bool atEnd() const override {
return RecordIterator == HashTable->data_end();
@@ -323,7 +347,10 @@ public:
HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
}
~InstrProfReaderIndex() override {}
- uint64_t getVersion() const override { return FormatVersion; }
+ uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
+ bool isIRLevelProfile() const override {
+ return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
+ }
void populateSymtab(InstrProfSymtab &Symtab) override {
Symtab.create(HashTable->keys());
}
@@ -336,14 +363,21 @@ private:
std::unique_ptr<MemoryBuffer> DataBuffer;
/// The index into the profile data.
std::unique_ptr<InstrProfReaderIndexBase> Index;
- /// The maximal execution count among all functions.
- uint64_t MaxFunctionCount;
+ /// Profile summary data.
+ std::unique_ptr<ProfileSummary> Summary;
IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
+ // Read the profile summary. Return a pointer pointing to one byte past the
+ // end of the summary data if it exists or the input \c Cur.
+ const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
+ const unsigned char *Cur);
+
public:
+ /// Return the profile version.
uint64_t getVersion() const { return Index->getVersion(); }
+ bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)), Index(nullptr) {}
@@ -351,27 +385,27 @@ public:
static bool hasFormat(const MemoryBuffer &DataBuffer);
/// Read the file header.
- std::error_code readHeader() override;
+ Error readHeader() override;
/// Read a single record.
- std::error_code readNextRecord(InstrProfRecord &Record) override;
+ Error readNextRecord(InstrProfRecord &Record) override;
/// Return the pointer to InstrProfRecord associated with FuncName
/// and FuncHash
- ErrorOr<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
- uint64_t FuncHash);
+ Expected<InstrProfRecord> getInstrProfRecord(StringRef FuncName,
+ uint64_t FuncHash);
/// Fill Counts with the profile data for the given function name.
- std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
- std::vector<uint64_t> &Counts);
+ Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
+ std::vector<uint64_t> &Counts);
/// Return the maximum of all known function counts.
- uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
+ uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); }
/// Factory method to create an indexed reader.
- static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
- create(std::string Path);
+ static Expected<std::unique_ptr<IndexedInstrProfReader>>
+ create(const Twine &Path);
- static ErrorOr<std::unique_ptr<IndexedInstrProfReader>>
+ static Expected<std::unique_ptr<IndexedInstrProfReader>>
create(std::unique_ptr<MemoryBuffer> Buffer);
// Used for testing purpose only.
@@ -383,6 +417,7 @@ public:
// to be used by llvm-profdata (for dumping). Avoid using this when
// the client is the compiler.
InstrProfSymtab &getSymtab() override;
+ ProfileSummary &getSummary() { return *(Summary.get()); }
};
} // end namespace llvm
diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h
index e7f53de051c3c..7d292731cccb8 100644
--- a/include/llvm/ProfileData/InstrProfWriter.h
+++ b/include/llvm/ProfileData/InstrProfWriter.h
@@ -24,21 +24,29 @@
namespace llvm {
/// Writer for instrumentation based profile data.
+class ProfOStream;
+class InstrProfRecordWriterTrait;
+
class InstrProfWriter {
public:
typedef SmallDenseMap<uint64_t, InstrProfRecord, 1> ProfilingData;
+ enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel };
private:
+ bool Sparse;
StringMap<ProfilingData> FunctionData;
- uint64_t MaxFunctionCount;
+ ProfKind ProfileKind;
+ // Use raw pointer here for the incomplete type object.
+ InstrProfRecordWriterTrait *InfoObj;
public:
- InstrProfWriter() : MaxFunctionCount(0) {}
+ InstrProfWriter(bool Sparse = false);
+ ~InstrProfWriter();
/// Add function counts for the given function. If there are already counts
/// for this function and the hash and number of counts match, each counter is
/// summed. Optionally scale counts by \p Weight.
- std::error_code addRecord(InstrProfRecord &&I, uint64_t Weight = 1);
+ Error addRecord(InstrProfRecord &&I, uint64_t Weight = 1);
/// Write the profile to \c OS
void write(raw_fd_ostream &OS);
/// Write the profile in text format to \c OS
@@ -49,11 +57,25 @@ public:
/// Write the profile, returning the raw data. For testing.
std::unique_ptr<MemoryBuffer> writeBuffer();
+ /// Set the ProfileKind. Report error if mixing FE and IR level profiles.
+ Error setIsIRLevelProfile(bool IsIRLevel) {
+ if (ProfileKind == PF_Unknown) {
+ ProfileKind = IsIRLevel ? PF_IRLevel: PF_FE;
+ return Error::success();
+ }
+ return (IsIRLevel == (ProfileKind == PF_IRLevel))
+ ? Error::success()
+ : make_error<InstrProfError>(
+ instrprof_error::unsupported_version);
+ }
+
// Internal interface for testing purpose only.
void setValueProfDataEndianness(support::endianness Endianness);
+ void setOutputSparse(bool Sparse);
private:
- std::pair<uint64_t, uint64_t> writeImpl(raw_ostream &OS);
+ bool shouldEncodeData(const ProfilingData &PD);
+ void writeImpl(ProfOStream &OS);
};
} // end namespace llvm
diff --git a/include/llvm/ProfileData/ProfileCommon.h b/include/llvm/ProfileData/ProfileCommon.h
new file mode 100644
index 0000000000000..ecb228ca59c47
--- /dev/null
+++ b/include/llvm/ProfileData/ProfileCommon.h
@@ -0,0 +1,102 @@
+//===-- ProfileCommon.h - Common profiling APIs. ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains data structures and functions common to both instrumented
+// and sample profiling.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PROFILEDATA_PROFILE_COMMON_H
+#define LLVM_PROFILEDATA_PROFILE_COMMON_H
+
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "llvm/IR/ProfileSummary.h"
+#include "llvm/Support/Error.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace llvm {
+class Function;
+namespace IndexedInstrProf {
+struct Summary;
+}
+namespace sampleprof {
+class FunctionSamples;
+}
+struct InstrProfRecord;
+class LLVMContext;
+class Metadata;
+class MDTuple;
+class MDNode;
+
+inline const char *getHotSectionPrefix() { return ".hot"; }
+inline const char *getUnlikelySectionPrefix() { return ".unlikely"; }
+
+class ProfileSummaryBuilder {
+
+private:
+ // We keep track of the number of times a count (block count or samples)
+ // appears in the profile. The map is kept sorted in the descending order of
+ // counts.
+ std::map<uint64_t, uint32_t, std::greater<uint64_t>> CountFrequencies;
+ std::vector<uint32_t> DetailedSummaryCutoffs;
+
+protected:
+ SummaryEntryVector DetailedSummary;
+ ProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
+ : DetailedSummaryCutoffs(std::move(Cutoffs)), TotalCount(0), MaxCount(0),
+ MaxFunctionCount(0), NumCounts(0), NumFunctions(0) {}
+ inline void addCount(uint64_t Count);
+ ~ProfileSummaryBuilder() = default;
+ void computeDetailedSummary();
+ uint64_t TotalCount, MaxCount, MaxFunctionCount;
+ uint32_t NumCounts, NumFunctions;
+
+public:
+ /// \brief A vector of useful cutoff values for detailed summary.
+ static const ArrayRef<uint32_t> DefaultCutoffs;
+};
+
+class InstrProfSummaryBuilder final : public ProfileSummaryBuilder {
+ uint64_t MaxInternalBlockCount;
+ inline void addEntryCount(uint64_t Count);
+ inline void addInternalCount(uint64_t Count);
+
+public:
+ InstrProfSummaryBuilder(std::vector<uint32_t> Cutoffs)
+ : ProfileSummaryBuilder(std::move(Cutoffs)), MaxInternalBlockCount(0) {}
+ void addRecord(const InstrProfRecord &);
+ std::unique_ptr<ProfileSummary> getSummary();
+};
+
+class SampleProfileSummaryBuilder final : public ProfileSummaryBuilder {
+
+public:
+ void addRecord(const sampleprof::FunctionSamples &FS);
+ SampleProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
+ : ProfileSummaryBuilder(std::move(Cutoffs)) {}
+ std::unique_ptr<ProfileSummary> getSummary();
+};
+
+// This is called when a count is seen in the profile.
+void ProfileSummaryBuilder::addCount(uint64_t Count) {
+ TotalCount += Count;
+ if (Count > MaxCount)
+ MaxCount = Count;
+ NumCounts++;
+ CountFrequencies[Count]++;
+}
+
+
+} // end namespace llvm
+#endif
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h
index 6c39cf9458dcb..9fefefa627b1d 100644
--- a/include/llvm/ProfileData/SampleProf.h
+++ b/include/llvm/ProfileData/SampleProf.h
@@ -74,7 +74,7 @@ static inline uint64_t SPMagic() {
uint64_t('2') << (64 - 56) | uint64_t(0xff);
}
-static inline uint64_t SPVersion() { return 102; }
+static inline uint64_t SPVersion() { return 103; }
/// Represents the relative location of an instruction.
///
@@ -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<LineLocation, SampleRecord> BodySampleMap;
class FunctionSamples;
-typedef std::map<CallsiteLocation, FunctionSamples> CallsiteSampleMap;
+typedef std::map<LineLocation, FunctionSamples> CallsiteSampleMap;
/// Representation of the samples collected for a function.
///
@@ -197,7 +180,7 @@ typedef std::map<CallsiteLocation, FunctionSamples> 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) {
@@ -221,8 +204,8 @@ public:
}
sampleprof_error addCalledTargetSamples(uint32_t LineOffset,
uint32_t Discriminator,
- std::string FName, uint64_t Num,
- uint64_t Weight = 1) {
+ const std::string &FName,
+ uint64_t Num, uint64_t Weight = 1) {
return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
FName, Num, Weight);
}
@@ -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/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h
index 6db0fbb0e7abf..bf86721709c7b 100644
--- a/include/llvm/ProfileData/SampleProfReader.h
+++ b/include/llvm/ProfileData/SampleProfReader.h
@@ -129,6 +129,30 @@
// VERSION (uint32_t)
// File format version number computed by SPVersion()
//
+// SUMMARY
+// TOTAL_COUNT (uint64_t)
+// Total number of samples in the profile.
+// MAX_COUNT (uint64_t)
+// Maximum value of samples on a line.
+// MAX_FUNCTION_COUNT (uint64_t)
+// Maximum number of samples at function entry (head samples).
+// NUM_COUNTS (uint64_t)
+// Number of lines with samples.
+// NUM_FUNCTIONS (uint64_t)
+// Number of functions with samples.
+// NUM_DETAILED_SUMMARY_ENTRIES (size_t)
+// Number of entries in detailed summary
+// DETAILED_SUMMARY
+// A list of detailed summary entry. Each entry consists of
+// CUTOFF (uint32_t)
+// Required percentile of total sample count expressed as a fraction
+// multiplied by 1000000.
+// MIN_COUNT (uint64_t)
+// The minimum number of samples required to reach the target
+// CUTOFF.
+// NUM_COUNTS (uint64_t)
+// Number of samples to get to the desrired percentile.
+//
// NAME TABLE
// SIZE (uint32_t)
// Number of entries in the name table.
@@ -190,6 +214,7 @@
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -264,12 +289,15 @@ public:
/// \brief Create a sample profile reader appropriate to the file format.
static ErrorOr<std::unique_ptr<SampleProfileReader>>
- create(StringRef Filename, LLVMContext &C);
+ create(const Twine &Filename, LLVMContext &C);
/// \brief Create a sample profile reader from the supplied memory buffer.
static ErrorOr<std::unique_ptr<SampleProfileReader>>
create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C);
+ /// \brief Return the profile summary.
+ ProfileSummary &getSummary() { return *(Summary.get()); }
+
protected:
/// \brief Map every function to its associated profile.
///
@@ -283,6 +311,12 @@ protected:
/// \brief Memory buffer holding the profile file.
std::unique_ptr<MemoryBuffer> Buffer;
+
+ /// \brief Profile summary information.
+ std::unique_ptr<ProfileSummary> Summary;
+
+ /// \brief Compute summary for this profile.
+ void computeSummary();
};
class SampleProfileReaderText : public SampleProfileReader {
@@ -348,6 +382,12 @@ protected:
/// Function name table.
std::vector<StringRef> NameTable;
+
+private:
+ std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
+
+ /// \brief Read profile summary.
+ std::error_code readSummary();
};
typedef SmallVector<FunctionSamples *, 10> InlineCallStack;
diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h
index 029dd2ebacb07..f6f2e2702e316 100644
--- a/include/llvm/ProfileData/SampleProfWriter.h
+++ b/include/llvm/ProfileData/SampleProfWriter.h
@@ -15,6 +15,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
@@ -31,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.
///
@@ -42,11 +43,9 @@ public:
std::error_code write(const StringMap<FunctionSamples> &ProfileMap) {
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;
@@ -75,12 +74,18 @@ protected:
/// \brief Output stream where to emit the profile to.
std::unique_ptr<raw_ostream> OutputStream;
+
+ /// \brief Profile summary.
+ std::unique_ptr<ProfileSummary> Summary;
+
+ /// \brief Compute summary for this profile.
+ void computeSummary(const StringMap<FunctionSamples> &ProfileMap);
};
/// \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<raw_ostream> &OS)
@@ -105,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<raw_ostream> &OS)
@@ -113,8 +118,9 @@ protected:
std::error_code
writeHeader(const StringMap<FunctionSamples> &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);