[ProfileData] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC).

llvm-svn: 296846
This commit is contained in:
Eugene Zelenko 2017-03-03 01:07:34 +00:00
parent 1516423f95
commit 67da950fbc
19 changed files with 548 additions and 278 deletions

View File

@ -1,4 +1,4 @@
//=-- CoverageMapping.h - Code coverage mapping support ---------*- C++ -*-=// //===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,25 +12,42 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_PROFILEDATA_COVERAGEMAPPING_H_ #ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
#define LLVM_PROFILEDATA_COVERAGEMAPPING_H_ #define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h" #include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ProfileData/InstrProf.h" #include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <iterator>
#include <memory>
#include <string>
#include <system_error> #include <system_error>
#include <tuple> #include <tuple>
#include <utility>
#include <vector>
namespace llvm { namespace llvm {
class IndexedInstrProfReader;
namespace coverage { namespace coverage {
class CoverageMappingReader;
struct CoverageMappingRecord;
enum class coveragemap_error { enum class coveragemap_error {
success = 0, success = 0,
eof, eof,
@ -68,19 +85,6 @@ private:
coveragemap_error Err; coveragemap_error Err;
}; };
} // end of coverage namespace.
} // end of llvm namespace
namespace llvm {
class IndexedInstrProfReader;
namespace coverage {
class CoverageMappingReader;
struct CoverageMappingRecord;
class CoverageMapping;
struct CounterExpressions;
/// \brief A Counter is an abstract value that describes how to compute the /// \brief A Counter is an abstract value that describes how to compute the
/// execution count for a region of code using the collected profile count data. /// execution count for a region of code using the collected profile count data.
struct Counter { struct Counter {
@ -91,13 +95,13 @@ struct Counter {
EncodingTagBits + 1; EncodingTagBits + 1;
private: private:
CounterKind Kind; CounterKind Kind = Zero;
unsigned ID; unsigned ID = 0;
Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
public: public:
Counter() : Kind(Zero), ID(0) {} Counter() = default;
CounterKind getKind() const { return Kind; } CounterKind getKind() const { return Kind; }
@ -153,8 +157,9 @@ struct CounterExpression {
class CounterExpressionBuilder { class CounterExpressionBuilder {
/// \brief A list of all the counter expressions /// \brief A list of all the counter expressions
std::vector<CounterExpression> Expressions; std::vector<CounterExpression> Expressions;
/// \brief A lookup table for the index of a given expression. /// \brief A lookup table for the index of a given expression.
llvm::DenseMap<CounterExpression, unsigned> ExpressionIndices; DenseMap<CounterExpression, unsigned> ExpressionIndices;
/// \brief Return the counter which corresponds to the given expression. /// \brief Return the counter which corresponds to the given expression.
/// ///
@ -238,7 +243,6 @@ struct CounterMappingRegion {
LineEnd, ColumnEnd, SkippedRegion); LineEnd, ColumnEnd, SkippedRegion);
} }
inline std::pair<unsigned, unsigned> startLoc() const { inline std::pair<unsigned, unsigned> startLoc() const {
return std::pair<unsigned, unsigned>(LineStart, ColumnStart); return std::pair<unsigned, unsigned>(LineStart, ColumnStart);
} }
@ -269,7 +273,7 @@ public:
void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; } void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
void dump(const Counter &C, llvm::raw_ostream &OS) const; void dump(const Counter &C, raw_ostream &OS) const;
void dump(const Counter &C) const { dump(C, dbgs()); } void dump(const Counter &C) const { dump(C, dbgs()); }
/// \brief Return the number of times that a region of code associated with /// \brief Return the number of times that a region of code associated with
@ -390,13 +394,14 @@ struct CoverageSegment {
/// provides a sequence of CoverageSegments to iterate through, as well as the /// provides a sequence of CoverageSegments to iterate through, as well as the
/// list of expansions that can be further processed. /// list of expansions that can be further processed.
class CoverageData { class CoverageData {
friend class CoverageMapping;
std::string Filename; std::string Filename;
std::vector<CoverageSegment> Segments; std::vector<CoverageSegment> Segments;
std::vector<ExpansionRecord> Expansions; std::vector<ExpansionRecord> Expansions;
friend class CoverageMapping;
public: public:
CoverageData() {} CoverageData() = default;
CoverageData(StringRef Filename) : Filename(Filename) {} CoverageData(StringRef Filename) : Filename(Filename) {}
@ -422,18 +427,17 @@ public:
class CoverageMapping { class CoverageMapping {
StringSet<> FunctionNames; StringSet<> FunctionNames;
std::vector<FunctionRecord> Functions; std::vector<FunctionRecord> Functions;
unsigned MismatchedFunctionCount; unsigned MismatchedFunctionCount = 0;
CoverageMapping() : MismatchedFunctionCount(0) {}
CoverageMapping(const CoverageMapping &) = delete;
const CoverageMapping &operator=(const CoverageMapping &) = delete;
CoverageMapping() = default;
/// \brief Add a function record corresponding to \p Record. /// \brief Add a function record corresponding to \p Record.
Error loadFunctionRecord(const CoverageMappingRecord &Record, Error loadFunctionRecord(const CoverageMappingRecord &Record,
IndexedInstrProfReader &ProfileReader); IndexedInstrProfReader &ProfileReader);
public: public:
CoverageMapping(const CoverageMapping &) = delete;
CoverageMapping &operator=(const CoverageMapping &) = delete;
/// \brief Load the coverage mapping using the given readers. /// \brief Load the coverage mapping using the given readers.
static Expected<std::unique_ptr<CoverageMapping>> static Expected<std::unique_ptr<CoverageMapping>>
load(CoverageMappingReader &CoverageReader, load(CoverageMappingReader &CoverageReader,
@ -517,14 +521,17 @@ template <class IntPtrT> struct CovMapFunctionRecordV1 {
template <support::endianness Endian> uint64_t getFuncHash() const { template <support::endianness Endian> uint64_t getFuncHash() const {
return support::endian::byte_swap<uint64_t, Endian>(FuncHash); return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
} }
// Return the coverage map data size for the funciton. // Return the coverage map data size for the funciton.
template <support::endianness Endian> uint32_t getDataSize() const { template <support::endianness Endian> uint32_t getDataSize() const {
return support::endian::byte_swap<uint32_t, Endian>(DataSize); return support::endian::byte_swap<uint32_t, Endian>(DataSize);
} }
// Return function lookup key. The value is consider opaque. // Return function lookup key. The value is consider opaque.
template <support::endianness Endian> IntPtrT getFuncNameRef() const { template <support::endianness Endian> IntPtrT getFuncNameRef() const {
return support::endian::byte_swap<IntPtrT, Endian>(NamePtr); return support::endian::byte_swap<IntPtrT, Endian>(NamePtr);
} }
// Return the PGO name of the function */ // Return the PGO name of the function */
template <support::endianness Endian> template <support::endianness Endian>
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
@ -545,14 +552,17 @@ struct CovMapFunctionRecord {
template <support::endianness Endian> uint64_t getFuncHash() const { template <support::endianness Endian> uint64_t getFuncHash() const {
return support::endian::byte_swap<uint64_t, Endian>(FuncHash); return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
} }
// Return the coverage map data size for the funciton. // Return the coverage map data size for the funciton.
template <support::endianness Endian> uint32_t getDataSize() const { template <support::endianness Endian> uint32_t getDataSize() const {
return support::endian::byte_swap<uint32_t, Endian>(DataSize); return support::endian::byte_swap<uint32_t, Endian>(DataSize);
} }
// Return function lookup key. The value is consider opaque. // Return function lookup key. The value is consider opaque.
template <support::endianness Endian> uint64_t getFuncNameRef() const { template <support::endianness Endian> uint64_t getFuncNameRef() const {
return support::endian::byte_swap<uint64_t, Endian>(NameRef); return support::endian::byte_swap<uint64_t, Endian>(NameRef);
} }
// Return the PGO name of the function */ // Return the PGO name of the function */
template <support::endianness Endian> template <support::endianness Endian>
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
@ -570,12 +580,15 @@ struct CovMapHeader {
template <support::endianness Endian> uint32_t getNRecords() const { template <support::endianness Endian> uint32_t getNRecords() const {
return support::endian::byte_swap<uint32_t, Endian>(NRecords); return support::endian::byte_swap<uint32_t, Endian>(NRecords);
} }
template <support::endianness Endian> uint32_t getFilenamesSize() const { template <support::endianness Endian> uint32_t getFilenamesSize() const {
return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize); return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize);
} }
template <support::endianness Endian> uint32_t getCoverageSize() const { template <support::endianness Endian> uint32_t getCoverageSize() const {
return support::endian::byte_swap<uint32_t, Endian>(CoverageSize); return support::endian::byte_swap<uint32_t, Endian>(CoverageSize);
} }
template <support::endianness Endian> uint32_t getVersion() const { template <support::endianness Endian> uint32_t getVersion() const {
return support::endian::byte_swap<uint32_t, Endian>(Version); return support::endian::byte_swap<uint32_t, Endian>(Version);
} }
@ -635,4 +648,4 @@ template<> struct DenseMapInfo<coverage::CounterExpression> {
} // end namespace llvm } // end namespace llvm
#endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_ #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H

View File

@ -1,4 +1,4 @@
//=-- CoverageMappingReader.h - Code coverage mapping reader ------*- C++ -*-=// //===- CoverageMappingReader.h - Code coverage mapping reader ---*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,18 +12,20 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H #ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
#define LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H #define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h" #include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/ProfileData/InstrProf.h" #include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include <cstddef>
#include <cstdint>
#include <iterator> #include <iterator>
#include <memory>
#include <vector>
namespace llvm { namespace llvm {
namespace coverage { namespace coverage {
@ -42,13 +44,14 @@ struct CoverageMappingRecord {
/// \brief A file format agnostic iterator over coverage mapping data. /// \brief A file format agnostic iterator over coverage mapping data.
class CoverageMappingIterator class CoverageMappingIterator
: public std::iterator<std::input_iterator_tag, CoverageMappingRecord> { : public std::iterator<std::input_iterator_tag, CoverageMappingRecord> {
CoverageMappingReader *Reader; CoverageMappingReader *Reader = nullptr;
CoverageMappingRecord Record; CoverageMappingRecord Record;
void increment(); void increment();
public: public:
CoverageMappingIterator() : Reader(nullptr) {} CoverageMappingIterator() = default;
CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) { CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) {
increment(); increment();
} }
@ -69,10 +72,11 @@ public:
class CoverageMappingReader { class CoverageMappingReader {
public: public:
virtual ~CoverageMappingReader() = default;
virtual Error readNextRecord(CoverageMappingRecord &Record) = 0; virtual Error readNextRecord(CoverageMappingRecord &Record) = 0;
CoverageMappingIterator begin() { return CoverageMappingIterator(this); } CoverageMappingIterator begin() { return CoverageMappingIterator(this); }
CoverageMappingIterator end() { return CoverageMappingIterator(); } CoverageMappingIterator end() { return CoverageMappingIterator(); }
virtual ~CoverageMappingReader() {}
}; };
/// \brief Base class for the raw coverage mapping and filenames data readers. /// \brief Base class for the raw coverage mapping and filenames data readers.
@ -92,13 +96,12 @@ protected:
class RawCoverageFilenamesReader : public RawCoverageReader { class RawCoverageFilenamesReader : public RawCoverageReader {
std::vector<StringRef> &Filenames; std::vector<StringRef> &Filenames;
RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
RawCoverageFilenamesReader &
operator=(const RawCoverageFilenamesReader &) = delete;
public: public:
RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames) RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames)
: RawCoverageReader(Data), Filenames(Filenames) {} : RawCoverageReader(Data), Filenames(Filenames) {}
RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
RawCoverageFilenamesReader &
operator=(const RawCoverageFilenamesReader &) = delete;
Error read(); Error read();
}; };
@ -120,10 +123,6 @@ class RawCoverageMappingReader : public RawCoverageReader {
std::vector<CounterExpression> &Expressions; std::vector<CounterExpression> &Expressions;
std::vector<CounterMappingRegion> &MappingRegions; std::vector<CounterMappingRegion> &MappingRegions;
RawCoverageMappingReader(const RawCoverageMappingReader &) = delete;
RawCoverageMappingReader &
operator=(const RawCoverageMappingReader &) = delete;
public: public:
RawCoverageMappingReader(StringRef MappingData, RawCoverageMappingReader(StringRef MappingData,
ArrayRef<StringRef> TranslationUnitFilenames, ArrayRef<StringRef> TranslationUnitFilenames,
@ -134,6 +133,9 @@ public:
TranslationUnitFilenames(TranslationUnitFilenames), TranslationUnitFilenames(TranslationUnitFilenames),
Filenames(Filenames), Expressions(Expressions), Filenames(Filenames), Expressions(Expressions),
MappingRegions(MappingRegions) {} MappingRegions(MappingRegions) {}
RawCoverageMappingReader(const RawCoverageMappingReader &) = delete;
RawCoverageMappingReader &
operator=(const RawCoverageMappingReader &) = delete;
Error read(); Error read();
@ -169,17 +171,17 @@ private:
std::vector<StringRef> Filenames; std::vector<StringRef> Filenames;
std::vector<ProfileMappingRecord> MappingRecords; std::vector<ProfileMappingRecord> MappingRecords;
InstrProfSymtab ProfileNames; InstrProfSymtab ProfileNames;
size_t CurrentRecord; size_t CurrentRecord = 0;
std::vector<StringRef> FunctionsFilenames; std::vector<StringRef> FunctionsFilenames;
std::vector<CounterExpression> Expressions; std::vector<CounterExpression> Expressions;
std::vector<CounterMappingRegion> MappingRegions; std::vector<CounterMappingRegion> MappingRegions;
BinaryCoverageReader() = default;
public:
BinaryCoverageReader(const BinaryCoverageReader &) = delete; BinaryCoverageReader(const BinaryCoverageReader &) = delete;
BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete;
BinaryCoverageReader() : CurrentRecord(0) {}
public:
static Expected<std::unique_ptr<BinaryCoverageReader>> static Expected<std::unique_ptr<BinaryCoverageReader>>
create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
StringRef Arch); StringRef Arch);
@ -190,4 +192,4 @@ public:
} // end namespace coverage } // end namespace coverage
} // end namespace llvm } // end namespace llvm
#endif #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H

View File

@ -1,4 +1,4 @@
//=-- CoverageMappingWriter.h - Code coverage mapping writer ------*- C++ -*-=// //===- CoverageMappingWriter.h - Code coverage mapping writer ---*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,15 +12,17 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H #ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H
#define LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H #define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h" #include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm { namespace llvm {
class raw_ostream;
namespace coverage { namespace coverage {
/// \brief Writer of the filenames section for the instrumentation /// \brief Writer of the filenames section for the instrumentation
@ -54,6 +56,7 @@ public:
}; };
} // end namespace coverage } // end namespace coverage
} // end namespace llvm } // end namespace llvm
#endif #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H

View File

@ -1,4 +1,4 @@
//===-- InstrProf.h - Instrumented profiling format support -----*- C++ -*-===// //===- InstrProf.h - Instrumented profiling format support ------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -16,26 +16,41 @@
#ifndef LLVM_PROFILEDATA_INSTRPROF_H #ifndef LLVM_PROFILEDATA_INSTRPROF_H
#define LLVM_PROFILEDATA_INSTRPROF_H #define LLVM_PROFILEDATA_INSTRPROF_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSet.h"
#include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Metadata.h" #include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProfData.inc" #include "llvm/ProfileData/InstrProfData.inc"
#include "llvm/ProfileData/ProfileCommon.h" #include "llvm/Support/Compiler.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MD5.h" #include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstring>
#include <list> #include <list>
#include <memory>
#include <string>
#include <system_error> #include <system_error>
#include <utility>
#include <vector> #include <vector>
namespace llvm { namespace llvm {
class Function; class Function;
class GlobalVariable; class GlobalVariable;
struct InstrProfRecord;
class InstrProfSymtab;
class Instruction;
class MDNode;
class Module; class Module;
/// Return the name of data section containing profile counter variables. /// Return the name of data section containing profile counter variables.
@ -201,6 +216,7 @@ GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName);
GlobalVariable *createPGOFuncNameVar(Module &M, GlobalVariable *createPGOFuncNameVar(Module &M,
GlobalValue::LinkageTypes Linkage, GlobalValue::LinkageTypes Linkage,
StringRef PGOFuncName); StringRef PGOFuncName);
/// Return the initializer in string of the PGO name var \c NameVar. /// Return the initializer in string of the PGO name var \c NameVar.
StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar); StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar);
@ -220,11 +236,12 @@ StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName,
/// second field will have value zero. /// second field will have value zero.
Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs, Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
bool doCompression, std::string &Result); bool doCompression, std::string &Result);
/// Produce \c Result string with the same format described above. The input /// Produce \c Result string with the same format described above. The input
/// is vector of PGO function name variables that are referenced. /// is vector of PGO function name variables that are referenced.
Error collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars, Error collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars,
std::string &Result, bool doCompression = true); std::string &Result, bool doCompression = true);
class InstrProfSymtab;
/// \c NameStrings is a string composed of one of more sub-strings encoded in /// \c NameStrings is a string composed of one of more sub-strings encoded in
/// the format described above. The substrings are separated by 0 or more zero /// the format described above. The substrings are separated by 0 or more zero
/// bytes. This method decodes the string and populates the \c Symtab. /// bytes. This method decodes the string and populates the \c Symtab.
@ -244,8 +261,6 @@ enum InstrProfValueKind : uint32_t {
#include "llvm/ProfileData/InstrProfData.inc" #include "llvm/ProfileData/InstrProfData.inc"
}; };
struct InstrProfRecord;
/// Get the value profile data for value site \p SiteIdx from \p InstrProfR /// 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. /// 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. /// Annotate up to \p MaxMDCount (default 3) number of records per value site.
@ -253,6 +268,7 @@ void annotateValueSite(Module &M, Instruction &Inst,
const InstrProfRecord &InstrProfR, const InstrProfRecord &InstrProfR,
InstrProfValueKind ValueKind, uint32_t SiteIndx, InstrProfValueKind ValueKind, uint32_t SiteIndx,
uint32_t MaxMDCount = 3); uint32_t MaxMDCount = 3);
/// Same as the above interface but using an ArrayRef, as well as \p Sum. /// Same as the above interface but using an ArrayRef, as well as \p Sum.
void annotateValueSite(Module &M, Instruction &Inst, void annotateValueSite(Module &M, Instruction &Inst,
ArrayRef<InstrProfValueData> VDs, ArrayRef<InstrProfValueData> VDs,
@ -347,25 +363,22 @@ class SoftInstrProfErrors {
/// the first such error for reporting purposes. /// the first such error for reporting purposes.
/// The first soft error encountered. /// The first soft error encountered.
instrprof_error FirstError; instrprof_error FirstError = instrprof_error::success;
/// The number of hash mismatches. /// The number of hash mismatches.
unsigned NumHashMismatches; unsigned NumHashMismatches = 0;
/// The number of count mismatches. /// The number of count mismatches.
unsigned NumCountMismatches; unsigned NumCountMismatches = 0;
/// The number of counter overflows. /// The number of counter overflows.
unsigned NumCounterOverflows; unsigned NumCounterOverflows = 0;
/// The number of value site count mismatches. /// The number of value site count mismatches.
unsigned NumValueSiteCountMismatches; unsigned NumValueSiteCountMismatches = 0;
public: public:
SoftInstrProfErrors() SoftInstrProfErrors() = default;
: FirstError(instrprof_error::success), NumHashMismatches(0),
NumCountMismatches(0), NumCounterOverflows(0),
NumValueSiteCountMismatches(0) {}
~SoftInstrProfErrors() { ~SoftInstrProfErrors() {
assert(FirstError == instrprof_error::success && assert(FirstError == instrprof_error::success &&
@ -401,12 +414,16 @@ public:
}; };
namespace object { namespace object {
class SectionRef; class SectionRef;
}
} // end namespace object
namespace IndexedInstrProf { namespace IndexedInstrProf {
uint64_t ComputeHash(StringRef K); uint64_t ComputeHash(StringRef K);
}
} // end namespace IndexedInstrProf
/// A symbol table used for function PGO name look-up with keys /// A symbol table used for function PGO name look-up with keys
/// (such as pointers, md5hash values) to the function. A function's /// (such as pointers, md5hash values) to the function. A function's
@ -419,7 +436,7 @@ public:
private: private:
StringRef Data; StringRef Data;
uint64_t Address; uint64_t Address = 0;
// Unique name strings. // Unique name strings.
StringSet<> NameTab; StringSet<> NameTab;
// A map from MD5 keys to function name strings. // A map from MD5 keys to function name strings.
@ -432,9 +449,7 @@ private:
AddrHashMap AddrToMD5Map; AddrHashMap AddrToMD5Map;
public: public:
InstrProfSymtab() InstrProfSymtab() = default;
: Data(), Address(0), NameTab(), MD5NameMap(), MD5FuncMap(),
AddrToMD5Map() {}
/// Create InstrProfSymtab from an object file section which /// Create InstrProfSymtab from an object file section which
/// contains function PGO names. When section may contain raw /// contains function PGO names. When section may contain raw
@ -443,26 +458,32 @@ public:
/// the section base address. The decompression will be delayed /// the section base address. The decompression will be delayed
/// until before it is used. See also \c create(StringRef) method. /// until before it is used. See also \c create(StringRef) method.
Error create(object::SectionRef &Section); Error create(object::SectionRef &Section);
/// This interface is used by reader of CoverageMapping test /// This interface is used by reader of CoverageMapping test
/// format. /// format.
inline Error 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 /// \c NameStrings is a string composed of one of more sub-strings
/// encoded in the format described in \c collectPGOFuncNameStrings. /// encoded in the format described in \c collectPGOFuncNameStrings.
/// This method is a wrapper to \c readPGOFuncNameStrings method. /// This method is a wrapper to \c readPGOFuncNameStrings method.
inline Error create(StringRef NameStrings); inline Error create(StringRef NameStrings);
/// A wrapper interface to populate the PGO symtab with functions /// A wrapper interface to populate the PGO symtab with functions
/// decls from module \c M. This interface is used by transformation /// decls from module \c M. This interface is used by transformation
/// passes such as indirect function call promotion. Variable \c InLTO /// passes such as indirect function call promotion. Variable \c InLTO
/// indicates if this is called from LTO optimization passes. /// indicates if this is called from LTO optimization passes.
void create(Module &M, bool InLTO = false); void create(Module &M, bool InLTO = false);
/// Create InstrProfSymtab from a set of names iteratable from /// Create InstrProfSymtab from a set of names iteratable from
/// \p IterRange. This interface is used by IndexedProfReader. /// \p IterRange. This interface is used by IndexedProfReader.
template <typename NameIterRange> void create(const NameIterRange &IterRange); template <typename NameIterRange> void create(const NameIterRange &IterRange);
// If the symtab is created by a series of calls to \c addFuncName, \c // If the symtab is created by a series of calls to \c addFuncName, \c
// finalizeSymtab needs to be called before looking up function names. // finalizeSymtab needs to be called before looking up function names.
// This is required because the underlying map is a vector (for space // This is required because the underlying map is a vector (for space
// efficiency) which needs to be sorted. // efficiency) which needs to be sorted.
inline void finalizeSymtab(); inline void finalizeSymtab();
/// Update the symtab by adding \p FuncName to the table. This interface /// Update the symtab by adding \p FuncName to the table. This interface
/// is used by the raw and text profile readers. /// is used by the raw and text profile readers.
void addFuncName(StringRef FuncName) { void addFuncName(StringRef FuncName) {
@ -471,25 +492,32 @@ public:
MD5NameMap.push_back(std::make_pair( MD5NameMap.push_back(std::make_pair(
IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey())); IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey()));
} }
/// Map a function address to its name's MD5 hash. This interface /// Map a function address to its name's MD5 hash. This interface
/// is only used by the raw profiler reader. /// is only used by the raw profiler reader.
void mapAddress(uint64_t Addr, uint64_t MD5Val) { void mapAddress(uint64_t Addr, uint64_t MD5Val) {
AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val)); AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val));
} }
AddrHashMap &getAddrHashMap() { return AddrToMD5Map; } AddrHashMap &getAddrHashMap() { return AddrToMD5Map; }
/// Return function's PGO name from the function name's symbol /// Return function's PGO name from the function name's symbol
/// address in the object file. If an error occurs, return /// address in the object file. If an error occurs, return
/// an empty string. /// an empty string.
StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize); StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize);
/// Return function's PGO name from the name's md5 hash value. /// Return function's PGO name from the name's md5 hash value.
/// If not found, return an empty string. /// If not found, return an empty string.
inline StringRef getFuncName(uint64_t FuncMD5Hash); inline StringRef getFuncName(uint64_t FuncMD5Hash);
/// Return function from the name's md5 hash. Return nullptr if not found. /// Return function from the name's md5 hash. Return nullptr if not found.
inline Function *getFunction(uint64_t FuncMD5Hash); inline Function *getFunction(uint64_t FuncMD5Hash);
/// Return the function's original assembly name by stripping off /// Return the function's original assembly name by stripping off
/// the prefix attached (to symbols with priviate linkage). For /// the prefix attached (to symbols with priviate linkage). For
/// global functions, it returns the same string as getFuncName. /// global functions, it returns the same string as getFuncName.
inline StringRef getOrigFuncName(uint64_t FuncMD5Hash); inline StringRef getOrigFuncName(uint64_t FuncMD5Hash);
/// Return the name section data. /// Return the name section data.
inline StringRef getNameData() const { return Data; } inline StringRef getNameData() const { return Data; }
}; };
@ -579,40 +607,48 @@ struct InstrProfValueSiteRecord {
/// Profiling information for a single function. /// Profiling information for a single function.
struct InstrProfRecord { struct InstrProfRecord {
InstrProfRecord() : SIPE() {}
InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts)
: Name(Name), Hash(Hash), Counts(std::move(Counts)), SIPE() {}
StringRef Name; StringRef Name;
uint64_t Hash; uint64_t Hash;
std::vector<uint64_t> Counts; std::vector<uint64_t> Counts;
SoftInstrProfErrors SIPE; SoftInstrProfErrors SIPE;
InstrProfRecord() = default;
InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts)
: Name(Name), Hash(Hash), Counts(std::move(Counts)) {}
typedef std::vector<std::pair<uint64_t, uint64_t>> ValueMapType; typedef std::vector<std::pair<uint64_t, uint64_t>> ValueMapType;
/// Return the number of value profile kinds with non-zero number /// Return the number of value profile kinds with non-zero number
/// of profile sites. /// of profile sites.
inline uint32_t getNumValueKinds() const; inline uint32_t getNumValueKinds() const;
/// Return the number of instrumented sites for ValueKind. /// Return the number of instrumented sites for ValueKind.
inline uint32_t getNumValueSites(uint32_t ValueKind) const; inline uint32_t getNumValueSites(uint32_t ValueKind) const;
/// Return the total number of ValueData for ValueKind. /// Return the total number of ValueData for ValueKind.
inline uint32_t getNumValueData(uint32_t ValueKind) const; inline uint32_t getNumValueData(uint32_t ValueKind) const;
/// Return the number of value data collected for ValueKind at profiling /// Return the number of value data collected for ValueKind at profiling
/// site: Site. /// site: Site.
inline uint32_t getNumValueDataForSite(uint32_t ValueKind, inline uint32_t getNumValueDataForSite(uint32_t ValueKind,
uint32_t Site) const; uint32_t Site) const;
/// Return the array of profiled values at \p Site. If \p TotalC /// 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 /// is not null, the total count of all target values at this site
/// will be stored in \c *TotalC. /// will be stored in \c *TotalC.
inline std::unique_ptr<InstrProfValueData[]> inline std::unique_ptr<InstrProfValueData[]>
getValueForSite(uint32_t ValueKind, uint32_t Site, getValueForSite(uint32_t ValueKind, uint32_t Site,
uint64_t *TotalC = 0) const; uint64_t *TotalC = nullptr) const;
/// Get the target value/counts of kind \p ValueKind collected at site /// 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 /// \p Site and store the result in array \p Dest. Return the total
/// counts of all target values at this site. /// counts of all target values at this site.
inline uint64_t getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind, inline uint64_t getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind,
uint32_t Site) const; uint32_t Site) const;
/// Reserve space for NumValueSites sites. /// Reserve space for NumValueSites sites.
inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites); inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites);
/// Add ValueData for ValueKind at value Site. /// Add ValueData for ValueKind at value Site.
void addValueData(uint32_t ValueKind, uint32_t Site, void addValueData(uint32_t ValueKind, uint32_t Site,
InstrProfValueData *VData, uint32_t N, InstrProfValueData *VData, uint32_t N,
@ -647,6 +683,7 @@ struct InstrProfRecord {
private: private:
std::vector<InstrProfValueSiteRecord> IndirectCallSites; std::vector<InstrProfValueSiteRecord> IndirectCallSites;
const std::vector<InstrProfValueSiteRecord> & const std::vector<InstrProfValueSiteRecord> &
getValueSitesForKind(uint32_t ValueKind) const { getValueSitesForKind(uint32_t ValueKind) const {
switch (ValueKind) { switch (ValueKind) {
case IPVK_IndirectCallTarget: case IPVK_IndirectCallTarget:
@ -672,6 +709,7 @@ private:
// Scale merged value counts by \p Weight. // Scale merged value counts by \p Weight.
void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src, void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
uint64_t Weight); uint64_t Weight);
// Scale up value profile data count. // Scale up value profile data count.
void scaleValueProfData(uint32_t ValueKind, uint64_t Weight); void scaleValueProfData(uint32_t ValueKind, uint64_t Weight);
}; };
@ -706,7 +744,7 @@ std::unique_ptr<InstrProfValueData[]>
InstrProfRecord::getValueForSite(uint32_t ValueKind, uint32_t Site, InstrProfRecord::getValueForSite(uint32_t ValueKind, uint32_t Site,
uint64_t *TotalC) const { uint64_t *TotalC) const {
uint64_t Dummy; uint64_t Dummy;
uint64_t &TotalCount = (TotalC == 0 ? Dummy : *TotalC); uint64_t &TotalCount = (TotalC == nullptr ? Dummy : *TotalC);
uint32_t N = getNumValueDataForSite(ValueKind, Site); uint32_t N = getNumValueDataForSite(ValueKind, Site);
if (N == 0) { if (N == 0) {
TotalCount = 0; TotalCount = 0;
@ -762,7 +800,6 @@ namespace IndexedInstrProf {
enum class HashT : uint32_t { enum class HashT : uint32_t {
MD5, MD5,
Last = MD5 Last = MD5
}; };
@ -816,7 +853,6 @@ struct Header {
// format. It is introduced in version 4. The summary data follows // format. It is introduced in version 4. The summary data follows
// right after the profile file header. // right after the profile file header.
struct Summary { struct Summary {
struct Entry { struct Entry {
uint64_t Cutoff; ///< The required percentile of total execution count. uint64_t Cutoff; ///< The required percentile of total execution count.
uint64_t uint64_t
@ -857,13 +893,16 @@ struct Summary {
const uint64_t *getSummaryDataBase() const { const uint64_t *getSummaryDataBase() const {
return reinterpret_cast<const uint64_t *>(this + 1); return reinterpret_cast<const uint64_t *>(this + 1);
} }
uint64_t *getSummaryDataBase() { uint64_t *getSummaryDataBase() {
return reinterpret_cast<uint64_t *>(this + 1); return reinterpret_cast<uint64_t *>(this + 1);
} }
const Entry *getCutoffEntryBase() const { const Entry *getCutoffEntryBase() const {
return reinterpret_cast<const Entry *>( return reinterpret_cast<const Entry *>(
&getSummaryDataBase()[NumSummaryFields]); &getSummaryDataBase()[NumSummaryFields]);
} }
Entry *getCutoffEntryBase() { Entry *getCutoffEntryBase() {
return reinterpret_cast<Entry *>(&getSummaryDataBase()[NumSummaryFields]); return reinterpret_cast<Entry *>(&getSummaryDataBase()[NumSummaryFields]);
} }
@ -877,6 +916,7 @@ struct Summary {
} }
const Entry &getEntry(uint32_t I) const { return getCutoffEntryBase()[I]; } const Entry &getEntry(uint32_t I) const { return getCutoffEntryBase()[I]; }
void setEntry(uint32_t I, const ProfileSummaryEntry &E) { void setEntry(uint32_t I, const ProfileSummaryEntry &E) {
Entry &ER = getCutoffEntryBase()[I]; Entry &ER = getCutoffEntryBase()[I];
ER.Cutoff = E.Cutoff; ER.Cutoff = E.Cutoff;
@ -894,6 +934,7 @@ inline std::unique_ptr<Summary> allocSummary(uint32_t TotalSize) {
return std::unique_ptr<Summary>(new (::operator new(TotalSize)) return std::unique_ptr<Summary>(new (::operator new(TotalSize))
Summary(TotalSize)); Summary(TotalSize));
} }
} // end namespace IndexedInstrProf } // end namespace IndexedInstrProf
namespace RawInstrProf { namespace RawInstrProf {

View File

@ -1,4 +1,4 @@
//=-- InstrProfReader.h - Instrumented profiling readers ----------*- C++ -*-=// //===- InstrProfReader.h - Instrumented profiling readers -------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -16,14 +16,23 @@
#define LLVM_PROFILEDATA_INSTRPROFREADER_H #define LLVM_PROFILEDATA_INSTRPROFREADER_H
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProf.h" #include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/EndianStream.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/LineIterator.h" #include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/SwapByteOrder.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator> #include <iterator>
#include <memory>
#include <utility>
#include <vector>
namespace llvm { namespace llvm {
@ -32,12 +41,13 @@ class InstrProfReader;
/// A file format agnostic iterator over profiling data. /// A file format agnostic iterator over profiling data.
class InstrProfIterator : public std::iterator<std::input_iterator_tag, class InstrProfIterator : public std::iterator<std::input_iterator_tag,
InstrProfRecord> { InstrProfRecord> {
InstrProfReader *Reader; InstrProfReader *Reader = nullptr;
InstrProfRecord Record; InstrProfRecord Record;
void Increment(); void Increment();
public: public:
InstrProfIterator() : Reader(nullptr) {} InstrProfIterator() = default;
InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); } InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }
InstrProfIterator &operator++() { Increment(); return *this; } InstrProfIterator &operator++() { Increment(); return *this; }
@ -50,19 +60,22 @@ public:
/// Base class and interface for reading profiling data of any known instrprof /// Base class and interface for reading profiling data of any known instrprof
/// format. Provides an iterator over InstrProfRecords. /// format. Provides an iterator over InstrProfRecords.
class InstrProfReader { class InstrProfReader {
instrprof_error LastError; instrprof_error LastError = instrprof_error::success;
public: public:
InstrProfReader() : LastError(instrprof_error::success), Symtab() {} InstrProfReader() = default;
virtual ~InstrProfReader() {} virtual ~InstrProfReader() = default;
/// Read the header. Required before reading first record. /// Read the header. Required before reading first record.
virtual Error readHeader() = 0; virtual Error readHeader() = 0;
/// Read a single record. /// Read a single record.
virtual Error readNextRecord(InstrProfRecord &Record) = 0; virtual Error readNextRecord(InstrProfRecord &Record) = 0;
/// Iterator over profile data. /// Iterator over profile data.
InstrProfIterator begin() { return InstrProfIterator(this); } InstrProfIterator begin() { return InstrProfIterator(this); }
InstrProfIterator end() { return InstrProfIterator(); } InstrProfIterator end() { return InstrProfIterator(); }
virtual bool isIRLevelProfile() const = 0; virtual bool isIRLevelProfile() const = 0;
/// Return the PGO symtab. There are three different readers: /// Return the PGO symtab. There are three different readers:
@ -86,6 +99,7 @@ protected:
return Error::success(); return Error::success();
return make_error<InstrProfError>(Err); 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. /// Clear the current error and return a successful one.
@ -94,8 +108,10 @@ protected:
public: public:
/// Return true if the reader has finished reading the profile data. /// Return true if the reader has finished reading the profile data.
bool isEOF() { return LastError == instrprof_error::eof; } bool isEOF() { return LastError == instrprof_error::eof; }
/// Return true if the reader encountered an error reading profiling data. /// Return true if the reader encountered an error reading profiling data.
bool hasError() { return LastError != instrprof_error::success && !isEOF(); } bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
/// Get the current error. /// Get the current error.
Error getError() { Error getError() {
if (hasError()) if (hasError())
@ -125,16 +141,15 @@ private:
std::unique_ptr<MemoryBuffer> DataBuffer; std::unique_ptr<MemoryBuffer> DataBuffer;
/// Iterator over the profile data. /// Iterator over the profile data.
line_iterator Line; line_iterator Line;
bool IsIRLevelProfile; bool IsIRLevelProfile = false;
TextInstrProfReader(const TextInstrProfReader &) = delete;
TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
Error readValueProfileData(InstrProfRecord &Record); Error readValueProfileData(InstrProfRecord &Record);
public: public:
TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_) TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
: DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#'), : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
IsIRLevelProfile(false) {} TextInstrProfReader(const TextInstrProfReader &) = delete;
TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
/// Return true if the given buffer is in text instrprof format. /// Return true if the given buffer is in text instrprof format.
static bool hasFormat(const MemoryBuffer &Buffer); static bool hasFormat(const MemoryBuffer &Buffer);
@ -143,6 +158,7 @@ public:
/// Read the header. /// Read the header.
Error readHeader() override; Error readHeader() override;
/// Read a single record. /// Read a single record.
Error readNextRecord(InstrProfRecord &Record) override; Error readNextRecord(InstrProfRecord &Record) override;
@ -184,15 +200,16 @@ private:
InstrProfRecord::ValueMapType FunctionPtrToNameMap; InstrProfRecord::ValueMapType FunctionPtrToNameMap;
RawInstrProfReader(const RawInstrProfReader &) = delete;
RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
public: public:
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)) { } : DataBuffer(std::move(DataBuffer)) { }
RawInstrProfReader(const RawInstrProfReader &) = delete;
RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
static bool hasFormat(const MemoryBuffer &DataBuffer); static bool hasFormat(const MemoryBuffer &DataBuffer);
Error readHeader() override; Error readHeader() override;
Error readNextRecord(InstrProfRecord &Record) override; Error readNextRecord(InstrProfRecord &Record) override;
bool isIRLevelProfile() const override { bool isIRLevelProfile() const override {
return (Version & VARIANT_MASK_IR_PROF) != 0; return (Version & VARIANT_MASK_IR_PROF) != 0;
} }
@ -206,9 +223,11 @@ private:
Error createSymtab(InstrProfSymtab &Symtab); Error createSymtab(InstrProfSymtab &Symtab);
Error readNextHeader(const char *CurrentPos); Error readNextHeader(const char *CurrentPos);
Error readHeader(const RawInstrProf::Header &Header); Error readHeader(const RawInstrProf::Header &Header);
template <class IntT> IntT swap(IntT Int) const { template <class IntT> IntT swap(IntT Int) const {
return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int; return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
} }
support::endianness getDataEndianness() const { support::endianness getDataEndianness() const {
support::endianness HostEndian = getHostEndianness(); support::endianness HostEndian = getHostEndianness();
if (!ShouldSwapBytes) if (!ShouldSwapBytes)
@ -222,15 +241,18 @@ private:
inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) { inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
} }
Error readName(InstrProfRecord &Record); Error readName(InstrProfRecord &Record);
Error readFuncHash(InstrProfRecord &Record); Error readFuncHash(InstrProfRecord &Record);
Error readRawCounts(InstrProfRecord &Record); Error readRawCounts(InstrProfRecord &Record);
Error readValueProfilingData(InstrProfRecord &Record); Error readValueProfilingData(InstrProfRecord &Record);
bool atEnd() const { return Data == DataEnd; } bool atEnd() const { return Data == DataEnd; }
void advanceData() { void advanceData() {
Data++; Data++;
ValueDataStart += CurValueDataSize; ValueDataStart += CurValueDataSize;
} }
const char *getNextHeaderPos() const { const char *getNextHeaderPos() const {
assert(atEnd()); assert(atEnd());
return (const char *)ValueDataStart; return (const char *)ValueDataStart;
@ -240,6 +262,7 @@ private:
ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t); ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
return CountersStart + Offset; return CountersStart + Offset;
} }
StringRef getName(uint64_t NameRef) const { StringRef getName(uint64_t NameRef) const {
return Symtab->getFuncName(swap(NameRef)); return Symtab->getFuncName(swap(NameRef));
} }
@ -249,8 +272,10 @@ typedef RawInstrProfReader<uint32_t> RawInstrProfReader32;
typedef RawInstrProfReader<uint64_t> RawInstrProfReader64; typedef RawInstrProfReader<uint64_t> RawInstrProfReader64;
namespace IndexedInstrProf { namespace IndexedInstrProf {
enum class HashT : uint32_t; enum class HashT : uint32_t;
}
} // end namespace IndexedInstrProf
/// Trait for lookups into the on-disk hash table for the binary instrprof /// Trait for lookups into the on-disk hash table for the binary instrprof
/// format. /// format.
@ -261,12 +286,11 @@ class InstrProfLookupTrait {
// Endianness of the input value profile data. // Endianness of the input value profile data.
// It should be LE by default, but can be changed // It should be LE by default, but can be changed
// for testing purpose. // for testing purpose.
support::endianness ValueProfDataEndianness; support::endianness ValueProfDataEndianness = support::little;
public: public:
InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion) InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
: HashType(HashType), FormatVersion(FormatVersion), : HashType(HashType), FormatVersion(FormatVersion) {}
ValueProfDataEndianness(support::little) {}
typedef ArrayRef<InstrProfRecord> data_type; typedef ArrayRef<InstrProfRecord> data_type;
@ -284,6 +308,7 @@ public:
static std::pair<offset_type, offset_type> static std::pair<offset_type, offset_type>
ReadKeyDataLength(const unsigned char *&D) { ReadKeyDataLength(const unsigned char *&D) {
using namespace support; using namespace support;
offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D); offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D); offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
return std::make_pair(KeyLen, DataLen); return std::make_pair(KeyLen, DataLen);
@ -304,16 +329,18 @@ public:
}; };
struct InstrProfReaderIndexBase { struct InstrProfReaderIndexBase {
virtual ~InstrProfReaderIndexBase() = default;
// Read all the profile records with the same key pointed to the current // Read all the profile records with the same key pointed to the current
// iterator. // iterator.
virtual Error getRecords(ArrayRef<InstrProfRecord> &Data) = 0; virtual Error getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
// Read all the profile records with the key equal to FuncName // Read all the profile records with the key equal to FuncName
virtual Error getRecords(StringRef FuncName, virtual Error getRecords(StringRef FuncName,
ArrayRef<InstrProfRecord> &Data) = 0; ArrayRef<InstrProfRecord> &Data) = 0;
virtual void advanceToNextKey() = 0; virtual void advanceToNextKey() = 0;
virtual bool atEnd() const = 0; virtual bool atEnd() const = 0;
virtual void setValueProfDataEndianness(support::endianness Endianness) = 0; virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
virtual ~InstrProfReaderIndexBase() {}
virtual uint64_t getVersion() const = 0; virtual uint64_t getVersion() const = 0;
virtual bool isIRLevelProfile() const = 0; virtual bool isIRLevelProfile() const = 0;
virtual void populateSymtab(InstrProfSymtab &) = 0; virtual void populateSymtab(InstrProfSymtab &) = 0;
@ -335,22 +362,27 @@ public:
const unsigned char *const Payload, const unsigned char *const Payload,
const unsigned char *const Base, const unsigned char *const Base,
IndexedInstrProf::HashT HashType, uint64_t Version); IndexedInstrProf::HashT HashType, uint64_t Version);
~InstrProfReaderIndex() override = default;
Error getRecords(ArrayRef<InstrProfRecord> &Data) override; Error getRecords(ArrayRef<InstrProfRecord> &Data) override;
Error getRecords(StringRef FuncName, Error getRecords(StringRef FuncName,
ArrayRef<InstrProfRecord> &Data) override; ArrayRef<InstrProfRecord> &Data) override;
void advanceToNextKey() override { RecordIterator++; } void advanceToNextKey() override { RecordIterator++; }
bool atEnd() const override { bool atEnd() const override {
return RecordIterator == HashTable->data_end(); return RecordIterator == HashTable->data_end();
} }
void setValueProfDataEndianness(support::endianness Endianness) override { void setValueProfDataEndianness(support::endianness Endianness) override {
HashTable->getInfoObj().setValueProfDataEndianness(Endianness); HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
} }
~InstrProfReaderIndex() override {}
uint64_t getVersion() const override { return GET_VERSION(FormatVersion); } uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
bool isIRLevelProfile() const override { bool isIRLevelProfile() const override {
return (FormatVersion & VARIANT_MASK_IR_PROF) != 0; return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
} }
void populateSymtab(InstrProfSymtab &Symtab) override { void populateSymtab(InstrProfSymtab &Symtab) override {
Symtab.create(HashTable->keys()); Symtab.create(HashTable->keys());
} }
@ -366,20 +398,20 @@ private:
/// Profile summary data. /// Profile summary data.
std::unique_ptr<ProfileSummary> Summary; 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 // 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. // end of the summary data if it exists or the input \c Cur.
const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version, const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
const unsigned char *Cur); const unsigned char *Cur);
public: public:
IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)) {}
IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
/// Return the profile version. /// Return the profile version.
uint64_t getVersion() const { return Index->getVersion(); } uint64_t getVersion() const { return Index->getVersion(); }
bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); } bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)), Index(nullptr) {}
/// Return true if the given buffer is in an indexed instrprof format. /// Return true if the given buffer is in an indexed instrprof format.
static bool hasFormat(const MemoryBuffer &DataBuffer); static bool hasFormat(const MemoryBuffer &DataBuffer);
@ -422,4 +454,4 @@ public:
} // end namespace llvm } // end namespace llvm
#endif #endif // LLVM_PROFILEDATA_INSTRPROFREADER_H

View File

@ -1,4 +1,4 @@
//=-- InstrProfWriter.h - Instrumented profiling writer -----------*- C++ -*-=// //===- InstrProfWriter.h - Instrumented profiling writer --------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -16,16 +16,19 @@
#define LLVM_PROFILEDATA_INSTRPROFWRITER_H #define LLVM_PROFILEDATA_INSTRPROFWRITER_H
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ProfileData/InstrProf.h" #include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h" #include <cstdint>
#include <memory>
namespace llvm { namespace llvm {
/// Writer for instrumentation based profile data. /// Writer for instrumentation based profile data.
class ProfOStream;
class InstrProfRecordWriterTrait; class InstrProfRecordWriterTrait;
class ProfOStream;
class InstrProfWriter { class InstrProfWriter {
public: public:
@ -35,7 +38,7 @@ public:
private: private:
bool Sparse; bool Sparse;
StringMap<ProfilingData> FunctionData; StringMap<ProfilingData> FunctionData;
ProfKind ProfileKind; ProfKind ProfileKind = PF_Unknown;
// Use raw pointer here for the incomplete type object. // Use raw pointer here for the incomplete type object.
InstrProfRecordWriterTrait *InfoObj; InstrProfRecordWriterTrait *InfoObj;
@ -47,15 +50,20 @@ public:
/// for this function and the hash and number of counts match, each counter is /// for this function and the hash and number of counts match, each counter is
/// summed. Optionally scale counts by \p Weight. /// summed. Optionally scale counts by \p Weight.
Error addRecord(InstrProfRecord &&I, uint64_t Weight = 1); Error addRecord(InstrProfRecord &&I, uint64_t Weight = 1);
/// Merge existing function counts from the given writer. /// Merge existing function counts from the given writer.
Error mergeRecordsFromWriter(InstrProfWriter &&IPW); Error mergeRecordsFromWriter(InstrProfWriter &&IPW);
/// Write the profile to \c OS /// Write the profile to \c OS
void write(raw_fd_ostream &OS); void write(raw_fd_ostream &OS);
/// Write the profile in text format to \c OS /// Write the profile in text format to \c OS
void writeText(raw_fd_ostream &OS); void writeText(raw_fd_ostream &OS);
/// Write \c Record in text format to \c OS /// Write \c Record in text format to \c OS
static void writeRecordInText(const InstrProfRecord &Record, static void writeRecordInText(const InstrProfRecord &Record,
InstrProfSymtab &Symtab, raw_fd_ostream &OS); InstrProfSymtab &Symtab, raw_fd_ostream &OS);
/// Write the profile, returning the raw data. For testing. /// Write the profile, returning the raw data. For testing.
std::unique_ptr<MemoryBuffer> writeBuffer(); std::unique_ptr<MemoryBuffer> writeBuffer();
@ -82,4 +90,4 @@ private:
} // end namespace llvm } // end namespace llvm
#endif #endif // LLVM_PROFILEDATA_INSTRPROFWRITER_H

View File

@ -1,4 +1,4 @@
//===-- ProfileCommon.h - Common profiling APIs. ----------------*- C++ -*-===// //===- ProfileCommon.h - Common profiling APIs. -----------------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,38 +12,33 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_PROFILEDATA_PROFILE_COMMON_H #ifndef LLVM_PROFILEDATA_PROFILECOMMON_H
#define LLVM_PROFILEDATA_PROFILE_COMMON_H #define LLVM_PROFILEDATA_PROFILECOMMON_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/Support/Error.h"
#include <algorithm>
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <map> #include <map>
#include <utility> #include <memory>
#include <vector> #include <vector>
#include "llvm/IR/ProfileSummary.h"
#include "llvm/Support/Error.h"
#include "llvm/ADT/ArrayRef.h"
namespace llvm { namespace llvm {
class Function;
namespace IndexedInstrProf {
struct Summary;
}
namespace sampleprof {
class FunctionSamples;
}
struct InstrProfRecord; struct InstrProfRecord;
class LLVMContext;
class Metadata; namespace sampleprof {
class MDTuple;
class MDNode; class FunctionSamples;
} // end namespace sampleprof
inline const char *getHotSectionPrefix() { return ".hot"; } inline const char *getHotSectionPrefix() { return ".hot"; }
inline const char *getUnlikelySectionPrefix() { return ".unlikely"; } inline const char *getUnlikelySectionPrefix() { return ".unlikely"; }
class ProfileSummaryBuilder { class ProfileSummaryBuilder {
private: private:
/// We keep track of the number of times a count (block count or samples) /// 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 /// appears in the profile. The map is kept sorted in the descending order of
@ -53,13 +48,18 @@ private:
protected: protected:
SummaryEntryVector DetailedSummary; SummaryEntryVector DetailedSummary;
uint64_t TotalCount = 0;
uint64_t MaxCount = 0;
uint64_t MaxFunctionCount = 0;
uint32_t NumCounts = 0;
uint32_t NumFunctions = 0;
ProfileSummaryBuilder(std::vector<uint32_t> Cutoffs) ProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
: DetailedSummaryCutoffs(std::move(Cutoffs)) {} : DetailedSummaryCutoffs(std::move(Cutoffs)) {}
inline void addCount(uint64_t Count);
~ProfileSummaryBuilder() = default; ~ProfileSummaryBuilder() = default;
inline void addCount(uint64_t Count);
void computeDetailedSummary(); void computeDetailedSummary();
uint64_t TotalCount = 0, MaxCount = 0, MaxFunctionCount = 0;
uint32_t NumCounts = 0, NumFunctions = 0;
public: public:
/// \brief A vector of useful cutoff values for detailed summary. /// \brief A vector of useful cutoff values for detailed summary.
@ -68,22 +68,24 @@ public:
class InstrProfSummaryBuilder final : public ProfileSummaryBuilder { class InstrProfSummaryBuilder final : public ProfileSummaryBuilder {
uint64_t MaxInternalBlockCount = 0; uint64_t MaxInternalBlockCount = 0;
inline void addEntryCount(uint64_t Count); inline void addEntryCount(uint64_t Count);
inline void addInternalCount(uint64_t Count); inline void addInternalCount(uint64_t Count);
public: public:
InstrProfSummaryBuilder(std::vector<uint32_t> Cutoffs) InstrProfSummaryBuilder(std::vector<uint32_t> Cutoffs)
: ProfileSummaryBuilder(std::move(Cutoffs)) {} : ProfileSummaryBuilder(std::move(Cutoffs)) {}
void addRecord(const InstrProfRecord &); void addRecord(const InstrProfRecord &);
std::unique_ptr<ProfileSummary> getSummary(); std::unique_ptr<ProfileSummary> getSummary();
}; };
class SampleProfileSummaryBuilder final : public ProfileSummaryBuilder { class SampleProfileSummaryBuilder final : public ProfileSummaryBuilder {
public: public:
void addRecord(const sampleprof::FunctionSamples &FS);
SampleProfileSummaryBuilder(std::vector<uint32_t> Cutoffs) SampleProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
: ProfileSummaryBuilder(std::move(Cutoffs)) {} : ProfileSummaryBuilder(std::move(Cutoffs)) {}
void addRecord(const sampleprof::FunctionSamples &FS);
std::unique_ptr<ProfileSummary> getSummary(); std::unique_ptr<ProfileSummary> getSummary();
}; };
@ -96,6 +98,6 @@ void ProfileSummaryBuilder::addCount(uint64_t Count) {
CountFrequencies[Count]++; CountFrequencies[Count]++;
} }
} // end namespace llvm } // end namespace llvm
#endif
#endif // LLVM_PROFILEDATA_PROFILECOMMON_H

View File

@ -1,4 +1,4 @@
//=-- SampleProf.h - Sampling profiling format support --------------------===// //===- SampleProf.h - Sampling profiling format support ---------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,23 +12,30 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H_ #ifndef LLVM_PROFILEDATA_SAMPLEPROF_H
#define LLVM_PROFILEDATA_SAMPLEPROF_H_ #define LLVM_PROFILEDATA_SAMPLEPROF_H
#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h" #include "llvm/Support/ErrorOr.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cstdint>
#include <map> #include <map>
#include <string>
#include <system_error> #include <system_error>
#include <utility>
namespace llvm { namespace llvm {
class raw_ostream;
const std::error_category &sampleprof_category(); const std::error_category &sampleprof_category();
enum class sampleprof_error { enum class sampleprof_error {
@ -62,12 +69,13 @@ inline sampleprof_error MergeResult(sampleprof_error &Accumulator,
} // end namespace llvm } // end namespace llvm
namespace std { namespace std {
template <> template <>
struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {}; struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {};
}
} // end namespace std
namespace llvm { namespace llvm {
namespace sampleprof { namespace sampleprof {
static inline uint64_t SPMagic() { static inline uint64_t SPMagic() {
@ -90,8 +98,10 @@ static inline uint64_t SPVersion() { return 103; }
/// (e.g., the two post-increment instructions in "if (p) x++; else y++;"). /// (e.g., the two post-increment instructions in "if (p) x++; else y++;").
struct LineLocation { struct LineLocation {
LineLocation(uint32_t L, uint32_t D) : LineOffset(L), Discriminator(D) {} LineLocation(uint32_t L, uint32_t D) : LineOffset(L), Discriminator(D) {}
void print(raw_ostream &OS) const; void print(raw_ostream &OS) const;
void dump() const; void dump() const;
bool operator<(const LineLocation &O) const { bool operator<(const LineLocation &O) const {
return LineOffset < O.LineOffset || return LineOffset < O.LineOffset ||
(LineOffset == O.LineOffset && Discriminator < O.Discriminator); (LineOffset == O.LineOffset && Discriminator < O.Discriminator);
@ -117,7 +127,7 @@ class SampleRecord {
public: public:
typedef StringMap<uint64_t> CallTargetMap; typedef StringMap<uint64_t> CallTargetMap;
SampleRecord() : NumSamples(0), CallTargets() {} SampleRecord() = default;
/// Increment the number of samples for this record by \p S. /// Increment the number of samples for this record by \p S.
/// Optionally scale sample count \p S by \p Weight. /// Optionally scale sample count \p S by \p Weight.
@ -147,7 +157,7 @@ public:
} }
/// Return true if this sample record contains function calls. /// Return true if this sample record contains function calls.
bool hasCalls() const { return CallTargets.size() > 0; } bool hasCalls() const { return !CallTargets.empty(); }
uint64_t getSamples() const { return NumSamples; } uint64_t getSamples() const { return NumSamples; }
const CallTargetMap &getCallTargets() const { return CallTargets; } const CallTargetMap &getCallTargets() const { return CallTargets; }
@ -166,7 +176,7 @@ public:
void dump() const; void dump() const;
private: private:
uint64_t NumSamples; uint64_t NumSamples = 0;
CallTargetMap CallTargets; CallTargetMap CallTargets;
}; };
@ -183,9 +193,11 @@ typedef std::map<LineLocation, FunctionSamples> CallsiteSampleMap;
/// within the body of the function. /// within the body of the function.
class FunctionSamples { class FunctionSamples {
public: public:
FunctionSamples() : Name(), TotalSamples(0), TotalHeadSamples(0) {} FunctionSamples() = default;
void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const; void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const;
void dump() const; void dump() const;
sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) { sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
bool Overflowed; bool Overflowed;
TotalSamples = TotalSamples =
@ -193,6 +205,7 @@ public:
return Overflowed ? sampleprof_error::counter_overflow return Overflowed ? sampleprof_error::counter_overflow
: sampleprof_error::success; : sampleprof_error::success;
} }
sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) { sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) {
bool Overflowed; bool Overflowed;
TotalHeadSamples = TotalHeadSamples =
@ -200,11 +213,13 @@ public:
return Overflowed ? sampleprof_error::counter_overflow return Overflowed ? sampleprof_error::counter_overflow
: sampleprof_error::success; : sampleprof_error::success;
} }
sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator, sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator,
uint64_t Num, uint64_t Weight = 1) { uint64_t Num, uint64_t Weight = 1) {
return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples( return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(
Num, Weight); Num, Weight);
} }
sampleprof_error addCalledTargetSamples(uint32_t LineOffset, sampleprof_error addCalledTargetSamples(uint32_t LineOffset,
uint32_t Discriminator, uint32_t Discriminator,
const std::string &FName, const std::string &FName,
@ -331,12 +346,12 @@ private:
/// ///
/// Samples are cumulative, they include all the samples collected /// Samples are cumulative, they include all the samples collected
/// inside this function and all its inlined callees. /// inside this function and all its inlined callees.
uint64_t TotalSamples; uint64_t TotalSamples = 0;
/// Total number of samples collected at the head of the function. /// Total number of samples collected at the head of the function.
/// This is an approximation of the number of calls made to this function /// This is an approximation of the number of calls made to this function
/// at runtime. /// at runtime.
uint64_t TotalHeadSamples; uint64_t TotalHeadSamples = 0;
/// Map instruction locations to collected samples. /// Map instruction locations to collected samples.
/// ///
@ -383,6 +398,7 @@ public:
return A->first < B->first; return A->first < B->first;
}); });
} }
const SamplesWithLocList &get() const { return V; } const SamplesWithLocList &get() const { return V; }
private: private:
@ -390,7 +406,6 @@ private:
}; };
} // end namespace sampleprof } // end namespace sampleprof
} // end namespace llvm } // end namespace llvm
#endif // LLVM_PROFILEDATA_SAMPLEPROF_H_ #endif // LLVM_PROFILEDATA_SAMPLEPROF_H

View File

@ -1,4 +1,4 @@
//===- SampleProfReader.h - Read LLVM sample profile data -----------------===// //===- SampleProfReader.h - Read LLVM sample profile data -------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -205,26 +205,34 @@
// FUNCTION BODY // FUNCTION BODY
// A FUNCTION BODY entry describing the inlined function. // A FUNCTION BODY entry describing the inlined function.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_PROFILEDATA_SAMPLEPROFREADER_H #ifndef LLVM_PROFILEDATA_SAMPLEPROFREADER_H
#define LLVM_PROFILEDATA_SAMPLEPROFREADER_H #define LLVM_PROFILEDATA_SAMPLEPROFREADER_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"
#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
#include "llvm/ProfileData/ProfileCommon.h" #include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/SampleProf.h" #include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h" #include "llvm/Support/ErrorOr.h"
#include "llvm/Support/GCOV.h" #include "llvm/Support/GCOV.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h" #include <algorithm>
#include <cstdint>
#include <memory>
#include <string>
#include <system_error>
#include <vector>
namespace llvm { namespace llvm {
class raw_ostream;
namespace sampleprof { namespace sampleprof {
/// \brief Sample-based profile reader. /// \brief Sample-based profile reader.
@ -259,7 +267,7 @@ public:
SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
: Profiles(0), Ctx(C), Buffer(std::move(B)) {} : Profiles(0), Ctx(C), Buffer(std::move(B)) {}
virtual ~SampleProfileReader() {} virtual ~SampleProfileReader() = default;
/// \brief Read and validate the file header. /// \brief Read and validate the file header.
virtual std::error_code readHeader() = 0; virtual std::error_code readHeader() = 0;
@ -442,8 +450,8 @@ protected:
static const uint32_t GCOVTagAFDOFunction = 0xac000000; static const uint32_t GCOVTagAFDOFunction = 0xac000000;
}; };
} // End namespace sampleprof } // end namespace sampleprof
} // End namespace llvm } // end namespace llvm
#endif // LLVM_PROFILEDATA_SAMPLEPROFREADER_H #endif // LLVM_PROFILEDATA_SAMPLEPROFREADER_H

View File

@ -1,4 +1,4 @@
//===- SampleProfWriter.h - Write LLVM sample profile data ----------------===// //===- SampleProfWriter.h - Write LLVM sample profile data ------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -14,15 +14,18 @@
#define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H #define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
#include "llvm/ADT/MapVector.h" #include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ProfileData/ProfileCommon.h" #include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/SampleProf.h" #include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/ErrorOr.h" #include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdint>
#include <memory>
#include <system_error>
namespace llvm { namespace llvm {
namespace sampleprof { namespace sampleprof {
enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC }; enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC };
@ -30,7 +33,7 @@ enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC };
/// \brief Sample-based profile writer. Base class. /// \brief Sample-based profile writer. Base class.
class SampleProfileWriter { class SampleProfileWriter {
public: public:
virtual ~SampleProfileWriter() {} virtual ~SampleProfileWriter() = default;
/// Write sample profiles in \p S. /// Write sample profiles in \p S.
/// ///
@ -114,7 +117,7 @@ public:
protected: protected:
SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS) SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
: SampleProfileWriter(OS), NameTable() {} : SampleProfileWriter(OS) {}
std::error_code std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) override; writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
@ -133,8 +136,7 @@ private:
SampleProfileFormat Format); SampleProfileFormat Format);
}; };
} // End namespace sampleprof } // end namespace sampleprof
} // end namespace llvm
} // End namespace llvm
#endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H #endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H

View File

@ -1,4 +1,4 @@
//=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=// //===- CoverageMapping.cpp - Code coverage mapping support ------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,18 +12,32 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ProfileData/Coverage/CoverageMapping.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h" #include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/ProfileData/Coverage/CoverageMappingReader.h" #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
#include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h" #include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <memory>
#include <string>
#include <system_error>
#include <utility>
#include <vector>
using namespace llvm; using namespace llvm;
using namespace coverage; using namespace coverage;
@ -59,7 +73,7 @@ void CounterExpressionBuilder::extractTerms(
Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) { Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
// Gather constant terms. // Gather constant terms.
llvm::SmallVector<std::pair<unsigned, int>, 32> Terms; SmallVector<std::pair<unsigned, int>, 32> Terms;
extractTerms(ExpressionTree, +1, Terms); extractTerms(ExpressionTree, +1, Terms);
// If there are no terms, this is just a zero. The algorithm below assumes at // If there are no terms, this is just a zero. The algorithm below assumes at
@ -120,8 +134,7 @@ Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
get(CounterExpression(CounterExpression::Subtract, LHS, RHS))); get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
} }
void CounterMappingContext::dump(const Counter &C, void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {
llvm::raw_ostream &OS) const {
switch (C.getKind()) { switch (C.getKind()) {
case Counter::Zero: case Counter::Zero:
OS << '0'; OS << '0';
@ -145,7 +158,7 @@ void CounterMappingContext::dump(const Counter &C,
return; return;
Expected<int64_t> Value = evaluate(C); Expected<int64_t> Value = evaluate(C);
if (auto E = Value.takeError()) { if (auto E = Value.takeError()) {
llvm::consumeError(std::move(E)); consumeError(std::move(E));
return; return;
} }
OS << '[' << *Value << ']'; OS << '[' << *Value << ']';
@ -217,7 +230,7 @@ Error CoverageMapping::loadFunctionRecord(
for (const auto &Region : Record.MappingRegions) { for (const auto &Region : Record.MappingRegions) {
Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count); Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
if (auto E = ExecutionCount.takeError()) { if (auto E = ExecutionCount.takeError()) {
llvm::consumeError(std::move(E)); consumeError(std::move(E));
return Error::success(); return Error::success();
} }
Function.pushRegion(Region, *ExecutionCount); Function.pushRegion(Region, *ExecutionCount);
@ -281,6 +294,7 @@ CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames,
} }
namespace { namespace {
/// \brief Distributes functions into instantiation sets. /// \brief Distributes functions into instantiation sets.
/// ///
/// An instantiation set is a collection of functions that have the same source /// An instantiation set is a collection of functions that have the same source
@ -326,7 +340,7 @@ class SegmentBuilder {
Segments.pop_back(); Segments.pop_back();
DEBUG(dbgs() << "Segment at " << Line << ":" << Col); DEBUG(dbgs() << "Segment at " << Line << ":" << Col);
// Set this region's count. // Set this region's count.
if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) { if (Region.Kind != CounterMappingRegion::SkippedRegion) {
DEBUG(dbgs() << " with count " << Region.ExecutionCount); DEBUG(dbgs() << " with count " << Region.ExecutionCount);
Segments.emplace_back(Line, Col, Region.ExecutionCount, IsRegionEntry); Segments.emplace_back(Line, Col, Region.ExecutionCount, IsRegionEntry);
} else } else
@ -380,10 +394,10 @@ class SegmentBuilder {
// in combineRegions(). Because we accumulate counter values only from // in combineRegions(). Because we accumulate counter values only from
// regions of the same kind as the first region of the area, prefer // regions of the same kind as the first region of the area, prefer
// CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion. // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
static_assert(coverage::CounterMappingRegion::CodeRegion < static_assert(CounterMappingRegion::CodeRegion <
coverage::CounterMappingRegion::ExpansionRegion && CounterMappingRegion::ExpansionRegion &&
coverage::CounterMappingRegion::ExpansionRegion < CounterMappingRegion::ExpansionRegion <
coverage::CounterMappingRegion::SkippedRegion, CounterMappingRegion::SkippedRegion,
"Unexpected order of region kind values"); "Unexpected order of region kind values");
return LHS.Kind < RHS.Kind; return LHS.Kind < RHS.Kind;
}); });
@ -437,7 +451,8 @@ public:
return Segments; return Segments;
} }
}; };
}
} // end anonymous namespace
std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const { std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
std::vector<StringRef> Filenames; std::vector<StringRef> Filenames;
@ -487,7 +502,7 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
CoverageData FileCoverage(Filename); CoverageData FileCoverage(Filename);
std::vector<coverage::CountedRegion> Regions; std::vector<CountedRegion> Regions;
for (const auto &Function : Functions) { for (const auto &Function : Functions) {
auto MainFileID = findMainViewFileID(Filename, Function); auto MainFileID = findMainViewFileID(Filename, Function);
@ -533,7 +548,7 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
return CoverageData(); return CoverageData();
CoverageData FunctionCoverage(Function.Filenames[*MainFileID]); CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
std::vector<coverage::CountedRegion> Regions; std::vector<CountedRegion> Regions;
for (const auto &CR : Function.CountedRegions) for (const auto &CR : Function.CountedRegions)
if (CR.FileID == *MainFileID) { if (CR.FileID == *MainFileID) {
Regions.push_back(CR); Regions.push_back(CR);
@ -551,7 +566,7 @@ CoverageData CoverageMapping::getCoverageForExpansion(
const ExpansionRecord &Expansion) const { const ExpansionRecord &Expansion) const {
CoverageData ExpansionCoverage( CoverageData ExpansionCoverage(
Expansion.Function.Filenames[Expansion.FileID]); Expansion.Function.Filenames[Expansion.FileID]);
std::vector<coverage::CountedRegion> Regions; std::vector<CountedRegion> Regions;
for (const auto &CR : Expansion.Function.CountedRegions) for (const auto &CR : Expansion.Function.CountedRegions)
if (CR.FileID == Expansion.FileID) { if (CR.FileID == Expansion.FileID) {
Regions.push_back(CR); Regions.push_back(CR);
@ -566,8 +581,7 @@ CoverageData CoverageMapping::getCoverageForExpansion(
return ExpansionCoverage; return ExpansionCoverage;
} }
namespace { static std::string getCoverageMapErrString(coveragemap_error Err) {
std::string getCoverageMapErrString(coveragemap_error Err) {
switch (Err) { switch (Err) {
case coveragemap_error::success: case coveragemap_error::success:
return "Success"; return "Success";
@ -585,6 +599,8 @@ std::string getCoverageMapErrString(coveragemap_error Err) {
llvm_unreachable("A value of coveragemap_error has no message."); llvm_unreachable("A value of coveragemap_error has no message.");
} }
namespace {
// FIXME: This class is only here to support the transition to llvm::Error. It // FIXME: This class is only here to support the transition to llvm::Error. It
// will be removed once this transition is complete. Clients should prefer to // will be removed once this transition is complete. Clients should prefer to
// deal with the Error value directly, rather than converting to error_code. // deal with the Error value directly, rather than converting to error_code.
@ -594,6 +610,7 @@ class CoverageMappingErrorCategoryType : public std::error_category {
return getCoverageMapErrString(static_cast<coveragemap_error>(IE)); return getCoverageMapErrString(static_cast<coveragemap_error>(IE));
} }
}; };
} // end anonymous namespace } // end anonymous namespace
std::string CoverageMapError::message() const { std::string CoverageMapError::message() const {

View File

@ -1,4 +1,4 @@
//=-- CoverageMappingReader.cpp - Code coverage mapping reader ----*- C++ -*-=// //===- CoverageMappingReader.cpp - Code coverage mapping reader -*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,15 +12,34 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ProfileData/Coverage/CoverageMappingReader.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/MachOUniversal.h" #include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"
#include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/LEB128.h" #include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <utility>
#include <vector>
using namespace llvm; using namespace llvm;
using namespace coverage; using namespace coverage;
@ -226,9 +245,8 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
} }
Error RawCoverageMappingReader::read() { Error RawCoverageMappingReader::read() {
// Read the virtual file mapping. // Read the virtual file mapping.
llvm::SmallVector<unsigned, 8> VirtualFileMapping; SmallVector<unsigned, 8> VirtualFileMapping;
uint64_t NumFileMappings; uint64_t NumFileMappings;
if (auto Err = readSize(NumFileMappings)) if (auto Err = readSize(NumFileMappings))
return Err; return Err;
@ -349,7 +367,10 @@ static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
} }
namespace { namespace {
struct CovMapFuncRecordReader { struct CovMapFuncRecordReader {
virtual ~CovMapFuncRecordReader() = default;
// The interface to read coverage mapping function records for a module. // The interface to read coverage mapping function records for a module.
// //
// \p Buf points to the buffer containing the \c CovHeader of the coverage // \p Buf points to the buffer containing the \c CovHeader of the coverage
@ -359,26 +380,24 @@ struct CovMapFuncRecordReader {
// greater than \p End if not. // greater than \p End if not.
virtual Expected<const char *> readFunctionRecords(const char *Buf, virtual Expected<const char *> readFunctionRecords(const char *Buf,
const char *End) = 0; const char *End) = 0;
virtual ~CovMapFuncRecordReader() {}
template <class IntPtrT, support::endianness Endian> template <class IntPtrT, support::endianness Endian>
static Expected<std::unique_ptr<CovMapFuncRecordReader>> static Expected<std::unique_ptr<CovMapFuncRecordReader>>
get(coverage::CovMapVersion Version, InstrProfSymtab &P, get(CovMapVersion Version, InstrProfSymtab &P,
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
std::vector<StringRef> &F); std::vector<StringRef> &F);
}; };
// A class for reading coverage mapping function records for a module. // A class for reading coverage mapping function records for a module.
template <coverage::CovMapVersion Version, class IntPtrT, template <CovMapVersion Version, class IntPtrT, support::endianness Endian>
support::endianness Endian>
class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
typedef typename coverage::CovMapTraits< typedef typename CovMapTraits<
Version, IntPtrT>::CovMapFuncRecordType FuncRecordType; Version, IntPtrT>::CovMapFuncRecordType FuncRecordType;
typedef typename coverage::CovMapTraits<Version, IntPtrT>::NameRefType typedef typename CovMapTraits<Version, IntPtrT>::NameRefType NameRefType;
NameRefType;
// Maps function's name references to the indexes of their records // Maps function's name references to the indexes of their records
// in \c Records. // in \c Records.
llvm::DenseMap<NameRefType, size_t> FunctionRecords; DenseMap<NameRefType, size_t> FunctionRecords;
InstrProfSymtab &ProfileNames; InstrProfSymtab &ProfileNames;
std::vector<StringRef> &Filenames; std::vector<StringRef> &Filenames;
std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
@ -432,14 +451,16 @@ public:
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
std::vector<StringRef> &F) std::vector<StringRef> &F)
: ProfileNames(P), Filenames(F), Records(R) {} : ProfileNames(P), Filenames(F), Records(R) {}
~VersionedCovMapFuncRecordReader() override {}
~VersionedCovMapFuncRecordReader() override = default;
Expected<const char *> readFunctionRecords(const char *Buf, Expected<const char *> readFunctionRecords(const char *Buf,
const char *End) override { const char *End) override {
using namespace support; using namespace support;
if (Buf + sizeof(CovMapHeader) > End) if (Buf + sizeof(CovMapHeader) > End)
return make_error<CoverageMapError>(coveragemap_error::malformed); return make_error<CoverageMapError>(coveragemap_error::malformed);
auto CovHeader = reinterpret_cast<const coverage::CovMapHeader *>(Buf); auto CovHeader = reinterpret_cast<const CovMapHeader *>(Buf);
uint32_t NRecords = CovHeader->getNRecords<Endian>(); uint32_t NRecords = CovHeader->getNRecords<Endian>();
uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
@ -490,14 +511,16 @@ public:
return Buf; return Buf;
} }
}; };
} // end anonymous namespace } // end anonymous namespace
template <class IntPtrT, support::endianness Endian> template <class IntPtrT, support::endianness Endian>
Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
coverage::CovMapVersion Version, InstrProfSymtab &P, CovMapVersion Version, InstrProfSymtab &P,
std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
std::vector<StringRef> &F) { std::vector<StringRef> &F) {
using namespace coverage; using namespace coverage;
switch (Version) { switch (Version) {
case CovMapVersion::Version1: case CovMapVersion::Version1:
return llvm::make_unique<VersionedCovMapFuncRecordReader< return llvm::make_unique<VersionedCovMapFuncRecordReader<
@ -518,11 +541,12 @@ static Error readCoverageMappingData(
std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
std::vector<StringRef> &Filenames) { std::vector<StringRef> &Filenames) {
using namespace coverage; using namespace coverage;
// Read the records in the coverage data section. // Read the records in the coverage data section.
auto CovHeader = auto CovHeader =
reinterpret_cast<const coverage::CovMapHeader *>(Data.data()); reinterpret_cast<const CovMapHeader *>(Data.data());
CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
if (Version > coverage::CovMapVersion::CurrentVersion) if (Version > CovMapVersion::CurrentVersion)
return make_error<CoverageMapError>(coveragemap_error::unsupported_version); return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
@ -538,6 +562,7 @@ static Error readCoverageMappingData(
} }
return Error::success(); return Error::success();
} }
static const char *TestingFormatMagic = "llvmcovmtestdata"; static const char *TestingFormatMagic = "llvmcovmtestdata";
static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames, static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames,
@ -595,21 +620,21 @@ static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer,
StringRef &CoverageMapping, StringRef &CoverageMapping,
uint8_t &BytesInAddress, uint8_t &BytesInAddress,
support::endianness &Endian, StringRef Arch) { support::endianness &Endian, StringRef Arch) {
auto BinOrErr = object::createBinary(ObjectBuffer); auto BinOrErr = createBinary(ObjectBuffer);
if (!BinOrErr) if (!BinOrErr)
return BinOrErr.takeError(); return BinOrErr.takeError();
auto Bin = std::move(BinOrErr.get()); auto Bin = std::move(BinOrErr.get());
std::unique_ptr<ObjectFile> OF; std::unique_ptr<ObjectFile> OF;
if (auto *Universal = dyn_cast<object::MachOUniversalBinary>(Bin.get())) { if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
// If we have a universal binary, try to look up the object for the // If we have a universal binary, try to look up the object for the
// appropriate architecture. // appropriate architecture.
auto ObjectFileOrErr = Universal->getObjectForArch(Arch); auto ObjectFileOrErr = Universal->getObjectForArch(Arch);
if (!ObjectFileOrErr) if (!ObjectFileOrErr)
return ObjectFileOrErr.takeError(); return ObjectFileOrErr.takeError();
OF = std::move(ObjectFileOrErr.get()); OF = std::move(ObjectFileOrErr.get());
} else if (isa<object::ObjectFile>(Bin.get())) { } else if (isa<ObjectFile>(Bin.get())) {
// For any other object file, upcast and take ownership. // For any other object file, upcast and take ownership.
OF.reset(cast<object::ObjectFile>(Bin.release())); OF.reset(cast<ObjectFile>(Bin.release()));
// If we've asked for a particular arch, make sure they match. // If we've asked for a particular arch, make sure they match.
if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
return errorCodeToError(object_error::arch_not_found); return errorCodeToError(object_error::arch_not_found);

View File

@ -1,4 +1,4 @@
//=-- CoverageMappingWriter.cpp - Code coverage mapping writer -------------=// //===- CoverageMappingWriter.cpp - Code coverage mapping writer -----------===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,8 +12,15 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
#include "llvm/Support/LEB128.h" #include "llvm/Support/LEB128.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <limits>
#include <vector>
using namespace llvm; using namespace llvm;
using namespace coverage; using namespace coverage;
@ -27,14 +34,25 @@ void CoverageFilenamesSectionWriter::write(raw_ostream &OS) {
} }
namespace { namespace {
/// \brief Gather only the expressions that are used by the mapping /// \brief Gather only the expressions that are used by the mapping
/// regions in this function. /// regions in this function.
class CounterExpressionsMinimizer { class CounterExpressionsMinimizer {
ArrayRef<CounterExpression> Expressions; ArrayRef<CounterExpression> Expressions;
llvm::SmallVector<CounterExpression, 16> UsedExpressions; SmallVector<CounterExpression, 16> UsedExpressions;
std::vector<unsigned> AdjustedExpressionIDs; std::vector<unsigned> AdjustedExpressionIDs;
public: public:
CounterExpressionsMinimizer(ArrayRef<CounterExpression> Expressions,
ArrayRef<CounterMappingRegion> MappingRegions)
: Expressions(Expressions) {
AdjustedExpressionIDs.resize(Expressions.size(), 0);
for (const auto &I : MappingRegions)
mark(I.Count);
for (const auto &I : MappingRegions)
gatherUsed(I.Count);
}
void mark(Counter C) { void mark(Counter C) {
if (!C.isExpression()) if (!C.isExpression())
return; return;
@ -54,16 +72,6 @@ public:
gatherUsed(E.RHS); gatherUsed(E.RHS);
} }
CounterExpressionsMinimizer(ArrayRef<CounterExpression> Expressions,
ArrayRef<CounterMappingRegion> MappingRegions)
: Expressions(Expressions) {
AdjustedExpressionIDs.resize(Expressions.size(), 0);
for (const auto &I : MappingRegions)
mark(I.Count);
for (const auto &I : MappingRegions)
gatherUsed(I.Count);
}
ArrayRef<CounterExpression> getExpressions() const { return UsedExpressions; } ArrayRef<CounterExpression> getExpressions() const { return UsedExpressions; }
/// \brief Adjust the given counter to correctly transition from the old /// \brief Adjust the given counter to correctly transition from the old
@ -74,7 +82,8 @@ public:
return C; return C;
} }
}; };
}
} // end anonymous namespace
/// \brief Encode the counter. /// \brief Encode the counter.
/// ///

View File

@ -1,4 +1,4 @@
//=-- InstrProf.cpp - Instrumented profiling format support -----------------=// //===- InstrProf.cpp - Instrumented profiling format support --------------===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,19 +12,46 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ProfileData/InstrProf.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h" #include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h" #include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Compression.h" #include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h" #include "llvm/Support/LEB128.h"
#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "llvm/Support/SwapByteOrder.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <cstdint>
#include <memory>
#include <string>
#include <system_error>
#include <utility>
#include <vector>
using namespace llvm; using namespace llvm;
@ -46,8 +73,7 @@ static cl::opt<unsigned> StaticFuncStripDirNamePrefix(
cl::desc("Strip specified level of directory name from source path in " cl::desc("Strip specified level of directory name from source path in "
"the profile counter name for static functions.")); "the profile counter name for static functions."));
namespace { static std::string getInstrProfErrString(instrprof_error Err) {
std::string getInstrProfErrString(instrprof_error Err) {
switch (Err) { switch (Err) {
case instrprof_error::success: case instrprof_error::success:
return "Success"; return "Success";
@ -89,15 +115,19 @@ std::string getInstrProfErrString(instrprof_error Err) {
llvm_unreachable("A value of instrprof_error has no message."); llvm_unreachable("A value of instrprof_error has no message.");
} }
namespace {
// FIXME: This class is only here to support the transition to llvm::Error. It // FIXME: This class is only here to support the transition to llvm::Error. It
// will be removed once this transition is complete. Clients should prefer to // will be removed once this transition is complete. Clients should prefer to
// deal with the Error value directly, rather than converting to error_code. // deal with the Error value directly, rather than converting to error_code.
class InstrProfErrorCategoryType : public std::error_category { class InstrProfErrorCategoryType : public std::error_category {
const char *name() const noexcept override { return "llvm.instrprof"; } const char *name() const noexcept override { return "llvm.instrprof"; }
std::string message(int IE) const override { std::string message(int IE) const override {
return getInstrProfErrString(static_cast<instrprof_error>(IE)); return getInstrProfErrString(static_cast<instrprof_error>(IE));
} }
}; };
} // end anonymous namespace } // end anonymous namespace
static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory; static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory;
@ -231,7 +261,6 @@ std::string getPGOFuncNameVarName(StringRef FuncName,
GlobalVariable *createPGOFuncNameVar(Module &M, GlobalVariable *createPGOFuncNameVar(Module &M,
GlobalValue::LinkageTypes Linkage, GlobalValue::LinkageTypes Linkage,
StringRef PGOFuncName) { StringRef PGOFuncName) {
// We generally want to match the function's linkage, but available_externally // We generally want to match the function's linkage, but available_externally
// and extern_weak both have the wrong semantics, and anything that doesn't // and extern_weak both have the wrong semantics, and anything that doesn't
// need to link across compilation units doesn't need to be visible at all. // need to link across compilation units doesn't need to be visible at all.
@ -276,7 +305,7 @@ void InstrProfSymtab::create(Module &M, bool InLTO) {
Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs, Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
bool doCompression, std::string &Result) { bool doCompression, std::string &Result) {
assert(NameStrs.size() && "No name data to emit"); assert(!NameStrs.empty() && "No name data to emit");
uint8_t Header[16], *P = Header; uint8_t Header[16], *P = Header;
std::string UncompressedNameStrings = std::string UncompressedNameStrings =
@ -589,6 +618,7 @@ void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
void ValueProfRecord::swapBytes(support::endianness Old, void ValueProfRecord::swapBytes(support::endianness Old,
support::endianness New) { support::endianness New) {
using namespace support; using namespace support;
if (Old == New) if (Old == New)
return; return;
@ -625,6 +655,7 @@ void ValueProfData::deserializeTo(InstrProfRecord &Record,
template <class T> template <class T>
static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) { static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
using namespace support; using namespace support;
if (Orig == little) if (Orig == little)
return endian::readNext<T, little, unaligned>(D); return endian::readNext<T, little, unaligned>(D);
else else
@ -659,6 +690,7 @@ ValueProfData::getValueProfData(const unsigned char *D,
const unsigned char *const BufferEnd, const unsigned char *const BufferEnd,
support::endianness Endianness) { support::endianness Endianness) {
using namespace support; using namespace support;
if (D + sizeof(ValueProfData) > BufferEnd) if (D + sizeof(ValueProfData) > BufferEnd)
return make_error<InstrProfError>(instrprof_error::truncated); return make_error<InstrProfError>(instrprof_error::truncated);
@ -681,6 +713,7 @@ ValueProfData::getValueProfData(const unsigned char *D,
void ValueProfData::swapBytesToHost(support::endianness Endianness) { void ValueProfData::swapBytesToHost(support::endianness Endianness) {
using namespace support; using namespace support;
if (Endianness == getHostEndianness()) if (Endianness == getHostEndianness())
return; return;
@ -696,6 +729,7 @@ void ValueProfData::swapBytesToHost(support::endianness Endianness) {
void ValueProfData::swapBytesFromHost(support::endianness Endianness) { void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
using namespace support; using namespace support;
if (Endianness == getHostEndianness()) if (Endianness == getHostEndianness())
return; return;
@ -890,4 +924,5 @@ bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken) {
} }
return true; return true;
} }
} // end namespace llvm } // end namespace llvm

View File

@ -1,4 +1,4 @@
//=-- InstrProfReader.cpp - Instrumented profiling reader -------------------=// //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,9 +12,27 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include <cassert> #include "llvm/ADT/StringRef.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SwapByteOrder.h"
#include <algorithm>
#include <cctype>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <system_error>
#include <utility>
#include <vector>
using namespace llvm; using namespace llvm;
@ -78,7 +96,6 @@ IndexedInstrProfReader::create(const Twine &Path) {
return IndexedInstrProfReader::create(std::move(BufferOrError.get())); return IndexedInstrProfReader::create(std::move(BufferOrError.get()));
} }
Expected<std::unique_ptr<IndexedInstrProfReader>> Expected<std::unique_ptr<IndexedInstrProfReader>>
IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) { IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
// Sanity check the buffer. // Sanity check the buffer.
@ -399,7 +416,6 @@ Error RawInstrProfReader<IntPtrT>::readRawCounts(
template <class IntPtrT> template <class IntPtrT>
Error RawInstrProfReader<IntPtrT>::readValueProfilingData( Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
InstrProfRecord &Record) { InstrProfRecord &Record) {
Record.clearValueData(); Record.clearValueData();
CurValueDataSize = 0; CurValueDataSize = 0;
// Need to match the logic in value profile dumper code in compiler-rt: // Need to match the logic in value profile dumper code in compiler-rt:
@ -455,9 +471,11 @@ Error RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) {
} }
namespace llvm { namespace llvm {
template class RawInstrProfReader<uint32_t>; template class RawInstrProfReader<uint32_t>;
template class RawInstrProfReader<uint64_t>; template class RawInstrProfReader<uint64_t>;
}
} // end namespace llvm
InstrProfLookupTrait::hash_value_type InstrProfLookupTrait::hash_value_type
InstrProfLookupTrait::ComputeHash(StringRef K) { InstrProfLookupTrait::ComputeHash(StringRef K) {
@ -483,6 +501,8 @@ bool InstrProfLookupTrait::readValueProfilingData(
data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
offset_type N) { offset_type N) {
using namespace support;
// Check if the data is corrupt. If so, don't try to read it. // Check if the data is corrupt. If so, don't try to read it.
if (N % sizeof(uint64_t)) if (N % sizeof(uint64_t))
return data_type(); return data_type();
@ -490,7 +510,6 @@ data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
DataBuffer.clear(); DataBuffer.clear();
std::vector<uint64_t> CounterBuffer; std::vector<uint64_t> CounterBuffer;
using namespace support;
const unsigned char *End = D + N; const unsigned char *End = D + N;
while (D < End) { while (D < End) {
// Read hash. // Read hash.
@ -568,9 +587,10 @@ InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
} }
bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
using namespace support;
if (DataBuffer.getBufferSize() < 8) if (DataBuffer.getBufferSize() < 8)
return false; return false;
using namespace support;
uint64_t Magic = uint64_t Magic =
endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart()); endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
// Verify that it's magical. // Verify that it's magical.
@ -582,6 +602,7 @@ IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
const unsigned char *Cur) { const unsigned char *Cur) {
using namespace IndexedInstrProf; using namespace IndexedInstrProf;
using namespace support; using namespace support;
if (Version >= IndexedInstrProf::Version4) { if (Version >= IndexedInstrProf::Version4) {
const IndexedInstrProf::Summary *SummaryInLE = const IndexedInstrProf::Summary *SummaryInLE =
reinterpret_cast<const IndexedInstrProf::Summary *>(Cur); reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
@ -618,6 +639,7 @@ IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
} else { } else {
// For older version of profile data, we need to compute on the fly: // For older version of profile data, we need to compute on the fly:
using namespace IndexedInstrProf; using namespace IndexedInstrProf;
InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
// FIXME: This only computes an empty summary. Need to call addRecord for // FIXME: This only computes an empty summary. Need to call addRecord for
// all InstrProfRecords to get the correct summary. // all InstrProfRecords to get the correct summary.
@ -627,14 +649,14 @@ IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
} }
Error IndexedInstrProfReader::readHeader() { Error IndexedInstrProfReader::readHeader() {
using namespace support;
const unsigned char *Start = const unsigned char *Start =
(const unsigned char *)DataBuffer->getBufferStart(); (const unsigned char *)DataBuffer->getBufferStart();
const unsigned char *Cur = Start; const unsigned char *Cur = Start;
if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
return error(instrprof_error::truncated); return error(instrprof_error::truncated);
using namespace support;
auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur); auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur);
Cur += sizeof(IndexedInstrProf::Header); Cur += sizeof(IndexedInstrProf::Header);

View File

@ -1,4 +1,4 @@
//=-- InstrProfWriter.cpp - Instrumented profiling writer -------------------=// //===- InstrProfWriter.cpp - Instrumented profiling writer ----------------===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -12,15 +12,21 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ProfileData/InstrProfWriter.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/IR/ProfileSummary.h" #include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/ProfileData/InstrProfWriter.h"
#include "llvm/ProfileData/ProfileCommon.h" #include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h" #include "llvm/Support/EndianStream.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <memory>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <utility> #include <utility>
@ -41,10 +47,9 @@ namespace llvm {
// A wrapper class to abstract writer stream with support of bytes // A wrapper class to abstract writer stream with support of bytes
// back patching. // back patching.
class ProfOStream { class ProfOStream {
public: public:
ProfOStream(llvm::raw_fd_ostream &FD) : IsFDOStream(true), OS(FD), LE(FD) {} ProfOStream(raw_fd_ostream &FD) : IsFDOStream(true), OS(FD), LE(FD) {}
ProfOStream(llvm::raw_string_ostream &STR) ProfOStream(raw_string_ostream &STR)
: IsFDOStream(false), OS(STR), LE(STR) {} : IsFDOStream(false), OS(STR), LE(STR) {}
uint64_t tell() { return OS.tell(); } uint64_t tell() { return OS.tell(); }
@ -55,15 +60,16 @@ public:
// directly and it won't be reflected in the stream's internal buffer. // directly and it won't be reflected in the stream's internal buffer.
void patch(PatchItem *P, int NItems) { void patch(PatchItem *P, int NItems) {
using namespace support; using namespace support;
if (IsFDOStream) { if (IsFDOStream) {
llvm::raw_fd_ostream &FDOStream = static_cast<llvm::raw_fd_ostream &>(OS); raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);
for (int K = 0; K < NItems; K++) { for (int K = 0; K < NItems; K++) {
FDOStream.seek(P[K].Pos); FDOStream.seek(P[K].Pos);
for (int I = 0; I < P[K].N; I++) for (int I = 0; I < P[K].N; I++)
write(P[K].D[I]); write(P[K].D[I]);
} }
} else { } else {
llvm::raw_string_ostream &SOStream = raw_string_ostream &SOStream =
static_cast<llvm::raw_string_ostream &>(OS); static_cast<llvm::raw_string_ostream &>(OS);
std::string &Data = SOStream.str(); // with flush std::string &Data = SOStream.str(); // with flush
for (int K = 0; K < NItems; K++) { for (int K = 0; K < NItems; K++) {
@ -94,17 +100,19 @@ public:
typedef uint64_t hash_value_type; typedef uint64_t hash_value_type;
typedef uint64_t offset_type; typedef uint64_t offset_type;
support::endianness ValueProfDataEndianness; support::endianness ValueProfDataEndianness = support::little;
InstrProfSummaryBuilder *SummaryBuilder; InstrProfSummaryBuilder *SummaryBuilder;
InstrProfRecordWriterTrait() : ValueProfDataEndianness(support::little) {} InstrProfRecordWriterTrait() = default;
static hash_value_type ComputeHash(key_type_ref K) { static hash_value_type ComputeHash(key_type_ref K) {
return IndexedInstrProf::ComputeHash(K); return IndexedInstrProf::ComputeHash(K);
} }
static std::pair<offset_type, offset_type> static std::pair<offset_type, offset_type>
EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V) { EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V) {
using namespace llvm::support; using namespace support;
endian::Writer<little> LE(Out); endian::Writer<little> LE(Out);
offset_type N = K.size(); offset_type N = K.size();
@ -130,7 +138,8 @@ public:
} }
void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type) { void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type) {
using namespace llvm::support; using namespace support;
endian::Writer<little> LE(Out); endian::Writer<little> LE(Out);
for (const auto &ProfileData : *V) { for (const auto &ProfileData : *V) {
const InstrProfRecord &ProfRecord = ProfileData.second; const InstrProfRecord &ProfRecord = ProfileData.second;
@ -154,8 +163,7 @@ public:
} // end namespace llvm } // end namespace llvm
InstrProfWriter::InstrProfWriter(bool Sparse) InstrProfWriter::InstrProfWriter(bool Sparse)
: Sparse(Sparse), FunctionData(), ProfileKind(PF_Unknown), : Sparse(Sparse), InfoObj(new InstrProfRecordWriterTrait()) {}
InfoObj(new InstrProfRecordWriterTrait()) {}
InstrProfWriter::~InstrProfWriter() { delete InfoObj; } InstrProfWriter::~InstrProfWriter() { delete InfoObj; }
@ -208,7 +216,7 @@ bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {
return true; return true;
for (const auto &Func : PD) { for (const auto &Func : PD) {
const InstrProfRecord &IPR = Func.second; const InstrProfRecord &IPR = Func.second;
if (any_of(IPR.Counts, [](uint64_t Count) { return Count > 0; })) if (llvm::any_of(IPR.Counts, [](uint64_t Count) { return Count > 0; }))
return true; return true;
} }
return false; return false;
@ -217,6 +225,7 @@ bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {
static void setSummary(IndexedInstrProf::Summary *TheSummary, static void setSummary(IndexedInstrProf::Summary *TheSummary,
ProfileSummary &PS) { ProfileSummary &PS) {
using namespace IndexedInstrProf; using namespace IndexedInstrProf;
std::vector<ProfileSummaryEntry> &Res = PS.getDetailedSummary(); std::vector<ProfileSummaryEntry> &Res = PS.getDetailedSummary();
TheSummary->NumSummaryFields = Summary::NumKinds; TheSummary->NumSummaryFields = Summary::NumKinds;
TheSummary->NumCutoffEntries = Res.size(); TheSummary->NumCutoffEntries = Res.size();
@ -231,9 +240,10 @@ static void setSummary(IndexedInstrProf::Summary *TheSummary,
} }
void InstrProfWriter::writeImpl(ProfOStream &OS) { void InstrProfWriter::writeImpl(ProfOStream &OS) {
using namespace IndexedInstrProf;
OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> Generator; OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> Generator;
using namespace IndexedInstrProf;
InstrProfSummaryBuilder ISB(ProfileSummaryBuilder::DefaultCutoffs); InstrProfSummaryBuilder ISB(ProfileSummaryBuilder::DefaultCutoffs);
InfoObj->SummaryBuilder = &ISB; InfoObj->SummaryBuilder = &ISB;
@ -301,7 +311,7 @@ void InstrProfWriter::write(raw_fd_ostream &OS) {
std::unique_ptr<MemoryBuffer> InstrProfWriter::writeBuffer() { std::unique_ptr<MemoryBuffer> InstrProfWriter::writeBuffer() {
std::string Data; std::string Data;
llvm::raw_string_ostream OS(Data); raw_string_ostream OS(Data);
ProfOStream POS(OS); ProfOStream POS(OS);
// Write the hash table. // Write the hash table.
writeImpl(POS); writeImpl(POS);

View File

@ -13,18 +13,25 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ProfileData/SampleProf.h" #include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
#include <system_error>
using namespace llvm::sampleprof;
using namespace llvm; using namespace llvm;
using namespace sampleprof;
namespace { namespace {
// FIXME: This class is only here to support the transition to llvm::Error. It // FIXME: This class is only here to support the transition to llvm::Error. It
// will be removed once this transition is complete. Clients should prefer to // will be removed once this transition is complete. Clients should prefer to
// deal with the Error value directly, rather than converting to error_code. // deal with the Error value directly, rather than converting to error_code.
class SampleProfErrorCategoryType : public std::error_category { class SampleProfErrorCategoryType : public std::error_category {
const char *name() const noexcept override { return "llvm.sampleprof"; } const char *name() const noexcept override { return "llvm.sampleprof"; }
std::string message(int IE) const override { std::string message(int IE) const override {
sampleprof_error E = static_cast<sampleprof_error>(IE); sampleprof_error E = static_cast<sampleprof_error>(IE);
switch (E) { switch (E) {
@ -54,7 +61,8 @@ class SampleProfErrorCategoryType : public std::error_category {
llvm_unreachable("A value of sampleprof_error has no message."); llvm_unreachable("A value of sampleprof_error has no message.");
} }
}; };
}
} // end anonymous namespace
static ManagedStatic<SampleProfErrorCategoryType> ErrorCategory; static ManagedStatic<SampleProfErrorCategoryType> ErrorCategory;
@ -105,7 +113,7 @@ void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const {
<< " sampled lines\n"; << " sampled lines\n";
OS.indent(Indent); OS.indent(Indent);
if (BodySamples.size() > 0) { if (!BodySamples.empty()) {
OS << "Samples collected in the function's body {\n"; OS << "Samples collected in the function's body {\n";
SampleSorter<LineLocation, SampleRecord> SortedBodySamples(BodySamples); SampleSorter<LineLocation, SampleRecord> SortedBodySamples(BodySamples);
for (const auto &SI : SortedBodySamples.get()) { for (const auto &SI : SortedBodySamples.get()) {
@ -119,7 +127,7 @@ void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const {
} }
OS.indent(Indent); OS.indent(Indent);
if (CallsiteSamples.size() > 0) { if (!CallsiteSamples.empty()) {
OS << "Samples collected in inlined callsites {\n"; OS << "Samples collected in inlined callsites {\n";
SampleSorter<LineLocation, FunctionSamples> SortedCallsiteSamples( SampleSorter<LineLocation, FunctionSamples> SortedCallsiteSamples(
CallsiteSamples); CallsiteSamples);
@ -141,5 +149,5 @@ raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
} }
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void FunctionSamples::dump(void) const { print(dbgs(), 0); } LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); }
#endif #endif

View File

@ -23,14 +23,25 @@
#include "llvm/ProfileData/SampleProfReader.h" #include "llvm/ProfileData/SampleProfReader.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h" #include "llvm/ADT/StringRef.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/ErrorOr.h" #include "llvm/Support/ErrorOr.h"
#include "llvm/Support/LEB128.h" #include "llvm/Support/LEB128.h"
#include "llvm/Support/LineIterator.h" #include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <system_error>
#include <vector>
using namespace llvm::sampleprof;
using namespace llvm; using namespace llvm;
using namespace sampleprof;
/// \brief Dump the function profile for \p FName. /// \brief Dump the function profile for \p FName.
/// ///

View File

@ -18,16 +18,23 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ADT/StringRef.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/ProfileData/SampleProfWriter.h" #include "llvm/ProfileData/SampleProfWriter.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h" #include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LEB128.h" #include "llvm/Support/LEB128.h"
#include "llvm/Support/LineIterator.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Support/MemoryBuffer.h" #include <algorithm>
#include "llvm/Support/Regex.h" #include <cstdint>
#include <memory>
#include <system_error>
#include <utility>
#include <vector>
using namespace llvm::sampleprof;
using namespace llvm; using namespace llvm;
using namespace sampleprof;
/// \brief Write samples to a text file. /// \brief Write samples to a text file.
/// ///