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.h3
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMappingReader.h14
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMappingWriter.h8
-rw-r--r--include/llvm/ProfileData/GCOV.h5
-rw-r--r--include/llvm/ProfileData/InstrProf.h62
-rw-r--r--include/llvm/ProfileData/InstrProfData.inc22
-rw-r--r--include/llvm/ProfileData/InstrProfReader.h4
-rw-r--r--include/llvm/ProfileData/ProfileCommon.h2
-rw-r--r--include/llvm/ProfileData/SampleProf.h44
-rw-r--r--include/llvm/ProfileData/SampleProfReader.h140
-rw-r--r--include/llvm/ProfileData/SampleProfWriter.h46
11 files changed, 238 insertions, 112 deletions
diff --git a/include/llvm/ProfileData/Coverage/CoverageMapping.h b/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 5a4098cf666c..1ca56dcaf9c5 100644
--- a/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/StringRef.h"
@@ -506,7 +507,7 @@ public:
/// This is the main interface to get coverage information, using a profile to
/// fill out execution counts.
class CoverageMapping {
- StringSet<> FunctionNames;
+ DenseMap<size_t, DenseSet<size_t>> RecordProvenance;
std::vector<FunctionRecord> Functions;
std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
std::vector<std::pair<std::string, uint64_t>> FuncCounterMismatches;
diff --git a/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index 633e51565cd2..c88c71a6d6f4 100644
--- a/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -32,7 +32,7 @@ namespace coverage {
class CoverageMappingReader;
-/// \brief Coverage mapping information for a single function.
+/// Coverage mapping information for a single function.
struct CoverageMappingRecord {
StringRef FunctionName;
uint64_t FunctionHash;
@@ -41,7 +41,7 @@ struct CoverageMappingRecord {
ArrayRef<CounterMappingRegion> MappingRegions;
};
-/// \brief A file format agnostic iterator over coverage mapping data.
+/// A file format agnostic iterator over coverage mapping data.
class CoverageMappingIterator
: public std::iterator<std::input_iterator_tag, CoverageMappingRecord> {
CoverageMappingReader *Reader;
@@ -101,7 +101,7 @@ public:
CoverageMappingIterator end() { return CoverageMappingIterator(); }
};
-/// \brief Base class for the raw coverage mapping and filenames data readers.
+/// Base class for the raw coverage mapping and filenames data readers.
class RawCoverageReader {
protected:
StringRef Data;
@@ -114,7 +114,7 @@ protected:
Error readString(StringRef &Result);
};
-/// \brief Reader for the raw coverage filenames.
+/// Reader for the raw coverage filenames.
class RawCoverageFilenamesReader : public RawCoverageReader {
std::vector<StringRef> &Filenames;
@@ -128,7 +128,7 @@ public:
Error read();
};
-/// \brief Checks if the given coverage mapping data is exported for
+/// Checks if the given coverage mapping data is exported for
/// an unused function.
class RawCoverageMappingDummyChecker : public RawCoverageReader {
public:
@@ -138,7 +138,7 @@ public:
Expected<bool> isDummy();
};
-/// \brief Reader for the raw coverage mapping data.
+/// Reader for the raw coverage mapping data.
class RawCoverageMappingReader : public RawCoverageReader {
ArrayRef<StringRef> TranslationUnitFilenames;
std::vector<StringRef> &Filenames;
@@ -169,7 +169,7 @@ private:
unsigned InferredFileID, size_t NumFileIDs);
};
-/// \brief Reader for the coverage mapping data that is emitted by the
+/// Reader for the coverage mapping data that is emitted by the
/// frontend and stored in an object file.
class BinaryCoverageReader : public CoverageMappingReader {
public:
diff --git a/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
index b6f864ab3de3..86fb1bdf1773 100644
--- a/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
@@ -25,7 +25,7 @@ class raw_ostream;
namespace coverage {
-/// \brief Writer of the filenames section for the instrumentation
+/// Writer of the filenames section for the instrumentation
/// based code coverage.
class CoverageFilenamesSectionWriter {
ArrayRef<StringRef> Filenames;
@@ -34,11 +34,11 @@ public:
CoverageFilenamesSectionWriter(ArrayRef<StringRef> Filenames)
: Filenames(Filenames) {}
- /// \brief Write encoded filenames to the given output stream.
+ /// Write encoded filenames to the given output stream.
void write(raw_ostream &OS);
};
-/// \brief Writer for instrumentation based coverage mapping data.
+/// Writer for instrumentation based coverage mapping data.
class CoverageMappingWriter {
ArrayRef<unsigned> VirtualFileMapping;
ArrayRef<CounterExpression> Expressions;
@@ -51,7 +51,7 @@ public:
: VirtualFileMapping(VirtualFileMapping), Expressions(Expressions),
MappingRegions(MappingRegions) {}
- /// \brief Write encoded coverage mapping data to the given output stream.
+ /// Write encoded coverage mapping data to the given output stream.
void write(raw_ostream &OS);
};
diff --git a/include/llvm/ProfileData/GCOV.h b/include/llvm/ProfileData/GCOV.h
index 497f80b87b26..8500401e44ad 100644
--- a/include/llvm/ProfileData/GCOV.h
+++ b/include/llvm/ProfileData/GCOV.h
@@ -41,7 +41,7 @@ namespace GCOV {
enum GCOVVersion { V402, V404, V704 };
-/// \brief A struct for passing gcov options between functions.
+/// A struct for passing gcov options between functions.
struct Options {
Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
: AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
@@ -376,6 +376,7 @@ private:
};
class FileInfo {
+protected:
// It is unlikely--but possible--for multiple functions to be on the same
// line.
// Therefore this typedef allows LineData.Functions to store multiple
@@ -428,7 +429,7 @@ public:
void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
StringRef GCDAFile);
-private:
+protected:
std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h
index b08b78cd593c..206142b3565a 100644
--- a/include/llvm/ProfileData/InstrProf.h
+++ b/include/llvm/ProfileData/InstrProf.h
@@ -425,9 +425,20 @@ private:
// 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;
+ bool Sorted = false;
+
+ static StringRef getExternalSymbol() {
+ return "** External Symbol **";
+ }
+
+ // If the symtab is created by a series of calls to \c addFuncName, \c
+ // finalizeSymtab needs to be called before looking up function names.
+ // This is required because the underlying map is a vector (for space
+ // efficiency) which needs to be sorted.
+ inline void finalizeSymtab();
public:
- InstrProfSymtab() = default;
+ InstrProfSymtab() = default;
/// Create InstrProfSymtab from an object file section which
/// contains function PGO names. When section may contain raw
@@ -456,21 +467,17 @@ public:
/// \p IterRange. This interface is used by IndexedProfReader.
template <typename NameIterRange> Error create(const NameIterRange &IterRange);
- // If the symtab is created by a series of calls to \c addFuncName, \c
- // finalizeSymtab needs to be called before looking up function names.
- // This is required because the underlying map is a vector (for space
- // efficiency) which needs to be sorted.
- inline void finalizeSymtab();
-
/// Update the symtab by adding \p FuncName to the table. This interface
/// is used by the raw and text profile readers.
Error addFuncName(StringRef FuncName) {
if (FuncName.empty())
return make_error<InstrProfError>(instrprof_error::malformed);
auto Ins = NameTab.insert(FuncName);
- if (Ins.second)
+ if (Ins.second) {
MD5NameMap.push_back(std::make_pair(
IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey()));
+ Sorted = false;
+ }
return Error::success();
}
@@ -480,7 +487,8 @@ public:
AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val));
}
- AddrHashMap &getAddrHashMap() { return AddrToMD5Map; }
+ /// Return a function's hash, or 0, if the function isn't in this SymTab.
+ uint64_t getFunctionHashFromAddress(uint64_t Address);
/// Return function's PGO name from the function name's symbol
/// address in the object file. If an error occurs, return
@@ -491,6 +499,16 @@ public:
/// If not found, return an empty string.
inline StringRef getFuncName(uint64_t FuncMD5Hash);
+ /// Just like getFuncName, except that it will return a non-empty StringRef
+ /// if the function is external to this symbol table. All such cases
+ /// will be represented using the same StringRef value.
+ inline StringRef getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash);
+
+ /// True if Symbol is the value used to represent external symbols.
+ static bool isExternalSymbol(const StringRef &Symbol) {
+ return Symbol == InstrProfSymtab::getExternalSymbol();
+ }
+
/// Return function from the name's md5 hash. Return nullptr if not found.
inline Function *getFunction(uint64_t FuncMD5Hash);
@@ -524,14 +542,25 @@ Error InstrProfSymtab::create(const NameIterRange &IterRange) {
}
void InstrProfSymtab::finalizeSymtab() {
- std::sort(MD5NameMap.begin(), MD5NameMap.end(), less_first());
- std::sort(MD5FuncMap.begin(), MD5FuncMap.end(), less_first());
- std::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first());
+ if (Sorted)
+ return;
+ llvm::sort(MD5NameMap.begin(), MD5NameMap.end(), less_first());
+ llvm::sort(MD5FuncMap.begin(), MD5FuncMap.end(), less_first());
+ llvm::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first());
AddrToMD5Map.erase(std::unique(AddrToMD5Map.begin(), AddrToMD5Map.end()),
AddrToMD5Map.end());
+ Sorted = true;
+}
+
+StringRef InstrProfSymtab::getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash) {
+ StringRef ret = getFuncName(FuncMD5Hash);
+ if (ret.empty())
+ return InstrProfSymtab::getExternalSymbol();
+ return ret;
}
StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) {
+ finalizeSymtab();
auto Result =
std::lower_bound(MD5NameMap.begin(), MD5NameMap.end(), FuncMD5Hash,
[](const std::pair<uint64_t, std::string> &LHS,
@@ -542,6 +571,7 @@ StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) {
}
Function* InstrProfSymtab::getFunction(uint64_t FuncMD5Hash) {
+ finalizeSymtab();
auto Result =
std::lower_bound(MD5FuncMap.begin(), MD5FuncMap.end(), FuncMD5Hash,
[](const std::pair<uint64_t, Function*> &LHS,
@@ -614,8 +644,6 @@ struct InstrProfRecord {
return *this;
}
- using ValueMapType = std::vector<std::pair<uint64_t, uint64_t>>;
-
/// Return the number of value profile kinds with non-zero number
/// of profile sites.
inline uint32_t getNumValueKinds() const;
@@ -649,7 +677,7 @@ struct InstrProfRecord {
/// Add ValueData for ValueKind at value Site.
void addValueData(uint32_t ValueKind, uint32_t Site,
InstrProfValueData *VData, uint32_t N,
- ValueMapType *ValueMap);
+ InstrProfSymtab *SymTab);
/// Merge the counts in \p Other into this one.
/// Optionally scale merged counts by \p Weight.
@@ -723,7 +751,7 @@ private:
// Map indirect call target name hash to name string.
uint64_t remapValue(uint64_t Value, uint32_t ValueKind,
- ValueMapType *HashKeys);
+ InstrProfSymtab *SymTab);
// Merge Value Profile data from Src record to this record for ValueKind.
// Scale merged value counts by \p Weight.
@@ -993,7 +1021,7 @@ template <> inline uint64_t getMagic<uint32_t>() {
// compiler-rt/lib/profile/InstrProfiling.h.
// It should also match the synthesized type in
// Transforms/Instrumentation/InstrProfiling.cpp:getOrCreateRegionCounters.
-template <class IntPtrT> struct LLVM_ALIGNAS(8) ProfileData {
+template <class IntPtrT> struct alignas(8) ProfileData {
#define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Type Name;
#include "llvm/ProfileData/InstrProfData.inc"
};
diff --git a/include/llvm/ProfileData/InstrProfData.inc b/include/llvm/ProfileData/InstrProfData.inc
index 6a98dc7b9b85..454620ed997a 100644
--- a/include/llvm/ProfileData/InstrProfData.inc
+++ b/include/llvm/ProfileData/InstrProfData.inc
@@ -178,7 +178,7 @@ VALUE_PROF_FUNC_PARAM(uint64_t, LargeValue, Type::getInt64Ty(Ctx))
* 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.
+ * when 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.
@@ -308,14 +308,14 @@ typedef struct ValueProfRecord {
#ifdef __cplusplus
/*!
- * \brief Return the number of value sites.
+ * Return the number of value sites.
*/
uint32_t getNumValueSites() const { return NumValueSites; }
/*!
- * \brief Read data from this record and save it to Record.
+ * Read data from this record and save it to Record.
*/
void deserializeTo(InstrProfRecord &Record,
- InstrProfRecord::ValueMapType *VMap);
+ InstrProfSymtab *SymTab);
/*
* In-place byte swap:
* Do byte swap for this instance. \c Old is the original order before
@@ -393,7 +393,7 @@ typedef struct ValueProfData {
* Read data from this data and save it to \c Record.
*/
void deserializeTo(InstrProfRecord &Record,
- InstrProfRecord::ValueMapType *VMap);
+ InstrProfSymtab *SymTab);
void operator delete(void *ptr) { ::operator delete(ptr); }
#endif
} ValueProfData;
@@ -458,7 +458,7 @@ getValueProfRecordHeaderSize(uint32_t NumValueSites);
#endif
/*!
- * \brief Return the \c ValueProfRecord header size including the
+ * Return the \c ValueProfRecord header size including the
* padding bytes.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
@@ -471,7 +471,7 @@ uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) {
}
/*!
- * \brief Return the total size of the value profile record including the
+ * Return the total size of the value profile record including the
* header and the value data.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
@@ -482,7 +482,7 @@ uint32_t getValueProfRecordSize(uint32_t NumValueSites,
}
/*!
- * \brief Return the pointer to the start of value data array.
+ * Return the pointer to the start of value data array.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) {
@@ -491,7 +491,7 @@ InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) {
}
/*!
- * \brief Return the total number of value data for \c This record.
+ * Return the total number of value data for \c This record.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) {
@@ -503,7 +503,7 @@ uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) {
}
/*!
- * \brief Use this method to advance to the next \c This \c ValueProfRecord.
+ * Use this method to advance to the next \c This \c ValueProfRecord.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
@@ -514,7 +514,7 @@ ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
}
/*!
- * \brief Return the first \c ValueProfRecord instance.
+ * Return the first \c ValueProfRecord instance.
*/
INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) {
diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h
index aa58ead1eda1..efc22dcd0d9a 100644
--- a/include/llvm/ProfileData/InstrProfReader.h
+++ b/include/llvm/ProfileData/InstrProfReader.h
@@ -101,7 +101,7 @@ protected:
return make_error<InstrProfError>(Err);
}
- Error error(Error E) { return error(InstrProfError::take(std::move(E))); }
+ Error error(Error &&E) { return error(InstrProfError::take(std::move(E))); }
/// Clear the current error and return a successful one.
Error success() { return error(instrprof_error::success); }
@@ -199,8 +199,6 @@ private:
uint32_t ValueKindLast;
uint32_t CurValueDataSize;
- InstrProfRecord::ValueMapType FunctionPtrToNameMap;
-
public:
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)) {}
diff --git a/include/llvm/ProfileData/ProfileCommon.h b/include/llvm/ProfileData/ProfileCommon.h
index 51b065bcdb70..087588f06340 100644
--- a/include/llvm/ProfileData/ProfileCommon.h
+++ b/include/llvm/ProfileData/ProfileCommon.h
@@ -61,7 +61,7 @@ protected:
void computeDetailedSummary();
public:
- /// \brief A vector of useful cutoff values for detailed summary.
+ /// A vector of useful cutoff values for detailed summary.
static const ArrayRef<uint32_t> DefaultCutoffs;
};
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h
index 641631cc4ec9..0cd6dd2c2c0e 100644
--- a/include/llvm/ProfileData/SampleProf.h
+++ b/include/llvm/ProfileData/SampleProf.h
@@ -78,11 +78,29 @@ struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {};
namespace llvm {
namespace sampleprof {
-static inline uint64_t SPMagic() {
+enum SampleProfileFormat {
+ SPF_None = 0,
+ SPF_Text = 0x1,
+ SPF_Compact_Binary = 0x2,
+ SPF_GCC = 0x3,
+ SPF_Binary = 0xff
+};
+
+static inline uint64_t SPMagic(SampleProfileFormat Format = SPF_Binary) {
return uint64_t('S') << (64 - 8) | uint64_t('P') << (64 - 16) |
uint64_t('R') << (64 - 24) | uint64_t('O') << (64 - 32) |
uint64_t('F') << (64 - 40) | uint64_t('4') << (64 - 48) |
- uint64_t('2') << (64 - 56) | uint64_t(0xff);
+ uint64_t('2') << (64 - 56) | uint64_t(Format);
+}
+
+// Get the proper representation of a string in the input Format.
+static inline StringRef getRepInFormat(StringRef Name,
+ SampleProfileFormat Format,
+ std::string &GUIDBuf) {
+ if (Name.empty())
+ return Name;
+ GUIDBuf = std::to_string(Function::getGUID(Name));
+ return (Format == SPF_Compact_Binary) ? StringRef(GUIDBuf) : Name;
}
static inline uint64_t SPVersion() { return 103; }
@@ -359,7 +377,7 @@ public:
/// GUID to \p S. Also traverse the BodySamples to add hot CallTarget's GUID
/// to \p S.
void findInlinedFunctions(DenseSet<GlobalValue::GUID> &S, const Module *M,
- uint64_t Threshold) const {
+ uint64_t Threshold, bool isCompact) const {
if (TotalSamples <= Threshold)
return;
S.insert(Function::getGUID(Name));
@@ -370,11 +388,12 @@ public:
if (TS.getValue() > Threshold) {
Function *Callee = M->getFunction(TS.getKey());
if (!Callee || !Callee->getSubprogram())
- S.insert(Function::getGUID(TS.getKey()));
+ S.insert(isCompact ? std::stol(TS.getKey().data())
+ : Function::getGUID(TS.getKey()));
}
for (const auto &CS : CallsiteSamples)
for (const auto &NameFS : CS.second)
- NameFS.second.findInlinedFunctions(S, M, Threshold);
+ NameFS.second.findInlinedFunctions(S, M, Threshold, isCompact);
}
/// Set the name of the function.
@@ -383,6 +402,21 @@ public:
/// Return the function name.
const StringRef &getName() const { return Name; }
+ /// Returns the line offset to the start line of the subprogram.
+ /// We assume that a single function will not exceed 65535 LOC.
+ static unsigned getOffset(const DILocation *DIL);
+
+ /// Get the FunctionSamples of the inline instance where DIL originates
+ /// from.
+ ///
+ /// The FunctionSamples of the instruction (Machine or IR) associated to
+ /// \p DIL is the inlined instance in which that instruction is coming from.
+ /// We traverse the inline stack of that instruction, and match it with the
+ /// tree nodes in the profile.
+ ///
+ /// \returns the FunctionSamples pointer to the inlined instance.
+ const FunctionSamples *findFunctionSamples(const DILocation *DIL) const;
+
private:
/// Mangled name of the function.
StringRef Name;
diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h
index 0e9ab2dc60ee..0617b05e8d4f 100644
--- a/include/llvm/ProfileData/SampleProfReader.h
+++ b/include/llvm/ProfileData/SampleProfReader.h
@@ -235,7 +235,7 @@ class raw_ostream;
namespace sampleprof {
-/// \brief Sample-based profile reader.
+/// Sample-based profile reader.
///
/// Each profile contains sample counts for all the functions
/// executed. Inside each function, statements are annotated with the
@@ -264,105 +264,113 @@ namespace sampleprof {
/// compact and I/O efficient. They can both be used interchangeably.
class SampleProfileReader {
public:
- SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
- : Profiles(0), Ctx(C), Buffer(std::move(B)) {}
+ SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
+ SampleProfileFormat Format = SPF_None)
+ : Profiles(0), Ctx(C), Buffer(std::move(B)), Format(Format) {}
virtual ~SampleProfileReader() = default;
- /// \brief Read and validate the file header.
+ /// Read and validate the file header.
virtual std::error_code readHeader() = 0;
- /// \brief Read sample profiles from the associated file.
+ /// Read sample profiles from the associated file.
virtual std::error_code read() = 0;
- /// \brief Print the profile for \p FName on stream \p OS.
+ /// Print the profile for \p FName on stream \p OS.
void dumpFunctionProfile(StringRef FName, raw_ostream &OS = dbgs());
- /// \brief Print all the profiles on stream \p OS.
+ /// Print all the profiles on stream \p OS.
void dump(raw_ostream &OS = dbgs());
- /// \brief Return the samples collected for function \p F.
+ /// Return the samples collected for function \p F.
FunctionSamples *getSamplesFor(const Function &F) {
// The function name may have been updated by adding suffix. In sample
// profile, the function names are all stripped, so we need to strip
// the function name suffix before matching with profile.
- if (Profiles.count(F.getName().split('.').first))
- return &Profiles[(F.getName().split('.').first)];
+ StringRef Fname = F.getName().split('.').first;
+ std::string FGUID;
+ Fname = getRepInFormat(Fname, getFormat(), FGUID);
+ if (Profiles.count(Fname))
+ return &Profiles[Fname];
return nullptr;
}
- /// \brief Return all the profiles.
+ /// Return all the profiles.
StringMap<FunctionSamples> &getProfiles() { return Profiles; }
- /// \brief Report a parse error message.
+ /// Report a parse error message.
void reportError(int64_t LineNumber, Twine Msg) const {
Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(),
LineNumber, Msg));
}
- /// \brief Create a sample profile reader appropriate to the file format.
+ /// Create a sample profile reader appropriate to the file format.
static ErrorOr<std::unique_ptr<SampleProfileReader>>
create(const Twine &Filename, LLVMContext &C);
- /// \brief Create a sample profile reader from the supplied memory buffer.
+ /// 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.
+ /// Return the profile summary.
ProfileSummary &getSummary() { return *(Summary.get()); }
+ /// \brief Return the profile format.
+ SampleProfileFormat getFormat() { return Format; }
+
protected:
- /// \brief Map every function to its associated profile.
+ /// Map every function to its associated profile.
///
/// The profile of every function executed at runtime is collected
/// in the structure FunctionSamples. This maps function objects
/// to their corresponding profiles.
StringMap<FunctionSamples> Profiles;
- /// \brief LLVM context used to emit diagnostics.
+ /// LLVM context used to emit diagnostics.
LLVMContext &Ctx;
- /// \brief Memory buffer holding the profile file.
+ /// Memory buffer holding the profile file.
std::unique_ptr<MemoryBuffer> Buffer;
- /// \brief Profile summary information.
+ /// Profile summary information.
std::unique_ptr<ProfileSummary> Summary;
- /// \brief Compute summary for this profile.
+ /// Compute summary for this profile.
void computeSummary();
+
+ /// \brief The format of sample.
+ SampleProfileFormat Format = SPF_None;
};
class SampleProfileReaderText : public SampleProfileReader {
public:
SampleProfileReaderText(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
- : SampleProfileReader(std::move(B), C) {}
+ : SampleProfileReader(std::move(B), C, SPF_Text) {}
- /// \brief Read and validate the file header.
+ /// Read and validate the file header.
std::error_code readHeader() override { return sampleprof_error::success; }
- /// \brief Read sample profiles from the associated file.
+ /// Read sample profiles from the associated file.
std::error_code read() override;
- /// \brief Return true if \p Buffer is in the format supported by this class.
+ /// Return true if \p Buffer is in the format supported by this class.
static bool hasFormat(const MemoryBuffer &Buffer);
};
class SampleProfileReaderBinary : public SampleProfileReader {
public:
- SampleProfileReaderBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
- : SampleProfileReader(std::move(B), C) {}
+ SampleProfileReaderBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
+ SampleProfileFormat Format = SPF_None)
+ : SampleProfileReader(std::move(B), C, Format) {}
- /// \brief Read and validate the file header.
+ /// Read and validate the file header.
std::error_code readHeader() override;
- /// \brief Read sample profiles from the associated file.
+ /// Read sample profiles from the associated file.
std::error_code read() override;
- /// \brief Return true if \p Buffer is in the format supported by this class.
- static bool hasFormat(const MemoryBuffer &Buffer);
-
protected:
- /// \brief Read a numeric value of type T from the profile.
+ /// Read a numeric value of type T from the profile.
///
/// If an error occurs during decoding, a diagnostic message is emitted and
/// EC is set.
@@ -370,7 +378,7 @@ protected:
/// \returns the read value.
template <typename T> ErrorOr<T> readNumber();
- /// \brief Read a string from the profile.
+ /// Read a string from the profile.
///
/// If an error occurs during decoding, a diagnostic message is emitted and
/// EC is set.
@@ -378,29 +386,68 @@ protected:
/// \returns the read value.
ErrorOr<StringRef> readString();
- /// Read a string indirectly via the name table.
- ErrorOr<StringRef> readStringFromTable();
+ /// Read the string index and check whether it overflows the table.
+ template <typename T> inline ErrorOr<uint32_t> readStringIndex(T &Table);
- /// \brief Return true if we've reached the end of file.
+ /// Return true if we've reached the end of file.
bool at_eof() const { return Data >= End; }
/// Read the contents of the given profile instance.
std::error_code readProfile(FunctionSamples &FProfile);
- /// \brief Points to the current location in the buffer.
+ /// Points to the current location in the buffer.
const uint8_t *Data = nullptr;
- /// \brief Points to the end of the buffer.
+ /// Points to the end of the buffer.
const uint8_t *End = nullptr;
+private:
+ std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
+ virtual std::error_code verifySPMagic(uint64_t Magic) = 0;
+
+ /// Read profile summary.
+ std::error_code readSummary();
+
+ /// Read the whole name table.
+ virtual std::error_code readNameTable() = 0;
+
+ /// Read a string indirectly via the name table.
+ virtual ErrorOr<StringRef> readStringFromTable() = 0;
+};
+
+class SampleProfileReaderRawBinary : public SampleProfileReaderBinary {
+private:
/// Function name table.
std::vector<StringRef> NameTable;
+ virtual std::error_code verifySPMagic(uint64_t Magic) override;
+ virtual std::error_code readNameTable() override;
+ /// Read a string indirectly via the name table.
+ virtual ErrorOr<StringRef> readStringFromTable() override;
+
+public:
+ SampleProfileReaderRawBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
+ : SampleProfileReaderBinary(std::move(B), C, SPF_Binary) {}
+
+ /// \brief Return true if \p Buffer is in the format supported by this class.
+ static bool hasFormat(const MemoryBuffer &Buffer);
+};
+class SampleProfileReaderCompactBinary : public SampleProfileReaderBinary {
private:
- std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
+ /// Function name table.
+ std::vector<std::string> NameTable;
+ virtual std::error_code verifySPMagic(uint64_t Magic) override;
+ virtual std::error_code readNameTable() override;
+ /// Read a string indirectly via the name table.
+ virtual ErrorOr<StringRef> readStringFromTable() override;
- /// \brief Read profile summary.
- std::error_code readSummary();
+public:
+ SampleProfileReaderCompactBinary(std::unique_ptr<MemoryBuffer> B,
+ LLVMContext &C)
+ : SampleProfileReaderBinary(std::move(B), C, SPF_Compact_Binary) {}
+
+ /// \brief Return true if \p Buffer is in the format supported by this class.
+ static bool hasFormat(const MemoryBuffer &Buffer);
};
using InlineCallStack = SmallVector<FunctionSamples *, 10>;
@@ -421,15 +468,16 @@ enum HistType {
class SampleProfileReaderGCC : public SampleProfileReader {
public:
SampleProfileReaderGCC(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
- : SampleProfileReader(std::move(B), C), GcovBuffer(Buffer.get()) {}
+ : SampleProfileReader(std::move(B), C, SPF_GCC),
+ GcovBuffer(Buffer.get()) {}
- /// \brief Read and validate the file header.
+ /// Read and validate the file header.
std::error_code readHeader() override;
- /// \brief Read sample profiles from the associated file.
+ /// Read sample profiles from the associated file.
std::error_code read() override;
- /// \brief Return true if \p Buffer is in the format supported by this class.
+ /// Return true if \p Buffer is in the format supported by this class.
static bool hasFormat(const MemoryBuffer &Buffer);
protected:
@@ -441,7 +489,7 @@ protected:
template <typename T> ErrorOr<T> readNumber();
ErrorOr<StringRef> readString();
- /// \brief Read the section tag and check that it's the same as \p Expected.
+ /// Read the section tag and check that it's the same as \p Expected.
std::error_code readSectionTag(uint32_t Expected);
/// GCOV buffer containing the profile.
diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h
index 86af1038d74e..74dc839ff049 100644
--- a/include/llvm/ProfileData/SampleProfWriter.h
+++ b/include/llvm/ProfileData/SampleProfWriter.h
@@ -23,14 +23,13 @@
#include <algorithm>
#include <cstdint>
#include <memory>
+#include <set>
#include <system_error>
namespace llvm {
namespace sampleprof {
-enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC };
-
-/// \brief Sample-based profile writer. Base class.
+/// Sample-based profile writer. Base class.
class SampleProfileWriter {
public:
virtual ~SampleProfileWriter() = default;
@@ -62,21 +61,21 @@ protected:
SampleProfileWriter(std::unique_ptr<raw_ostream> &OS)
: OutputStream(std::move(OS)) {}
- /// \brief Write a file header for the profile file.
+ /// Write a file header for the profile file.
virtual std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) = 0;
- /// \brief Output stream where to emit the profile to.
+ /// Output stream where to emit the profile to.
std::unique_ptr<raw_ostream> OutputStream;
- /// \brief Profile summary.
+ /// Profile summary.
std::unique_ptr<ProfileSummary> Summary;
- /// \brief Compute summary for this profile.
+ /// Compute summary for this profile.
void computeSummary(const StringMap<FunctionSamples> &ProfileMap);
};
-/// \brief Sample-based profile writer (text format).
+/// Sample-based profile writer (text format).
class SampleProfileWriterText : public SampleProfileWriter {
public:
std::error_code write(const FunctionSamples &S) override;
@@ -101,32 +100,49 @@ private:
SampleProfileFormat Format);
};
-/// \brief Sample-based profile writer (binary format).
+/// Sample-based profile writer (binary format).
class SampleProfileWriterBinary : public SampleProfileWriter {
public:
std::error_code write(const FunctionSamples &S) override;
-
-protected:
SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
: SampleProfileWriter(OS) {}
- std::error_code
- writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
+protected:
+ virtual std::error_code writeNameTable() = 0;
+ virtual std::error_code writeMagicIdent() = 0;
+ std::error_code writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
std::error_code writeSummary();
std::error_code writeNameIdx(StringRef FName);
std::error_code writeBody(const FunctionSamples &S);
+ inline void stablizeNameTable(std::set<StringRef> &V);
+
+ MapVector<StringRef, uint32_t> NameTable;
private:
void addName(StringRef FName);
void addNames(const FunctionSamples &S);
- MapVector<StringRef, uint32_t> NameTable;
-
friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
SampleProfileFormat Format);
};
+class SampleProfileWriterRawBinary : public SampleProfileWriterBinary {
+ using SampleProfileWriterBinary::SampleProfileWriterBinary;
+
+protected:
+ virtual std::error_code writeNameTable() override;
+ virtual std::error_code writeMagicIdent() override;
+};
+
+class SampleProfileWriterCompactBinary : public SampleProfileWriterBinary {
+ using SampleProfileWriterBinary::SampleProfileWriterBinary;
+
+protected:
+ virtual std::error_code writeNameTable() override;
+ virtual std::error_code writeMagicIdent() override;
+};
+
} // end namespace sampleprof
} // end namespace llvm