diff options
Diffstat (limited to 'include/llvm/ProfileData')
-rw-r--r-- | include/llvm/ProfileData/Coverage/CoverageMapping.h | 79 | ||||
-rw-r--r-- | include/llvm/ProfileData/Coverage/CoverageMappingReader.h | 46 | ||||
-rw-r--r-- | include/llvm/ProfileData/Coverage/CoverageMappingWriter.h | 15 | ||||
-rw-r--r-- | include/llvm/ProfileData/InstrProf.h | 171 | ||||
-rw-r--r-- | include/llvm/ProfileData/InstrProfData.inc | 84 | ||||
-rw-r--r-- | include/llvm/ProfileData/InstrProfReader.h | 88 | ||||
-rw-r--r-- | include/llvm/ProfileData/InstrProfWriter.h | 20 | ||||
-rw-r--r-- | include/llvm/ProfileData/ProfileCommon.h | 54 | ||||
-rw-r--r-- | include/llvm/ProfileData/SampleProf.h | 124 | ||||
-rw-r--r-- | include/llvm/ProfileData/SampleProfReader.h | 29 | ||||
-rw-r--r-- | include/llvm/ProfileData/SampleProfWriter.h | 20 |
11 files changed, 485 insertions, 245 deletions
diff --git a/include/llvm/ProfileData/Coverage/CoverageMapping.h b/include/llvm/ProfileData/Coverage/CoverageMapping.h index d6051ffb3f8d0..b9a9f53776984 100644 --- a/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -1,4 +1,4 @@ -//=-- CoverageMapping.h - Code coverage mapping support ---------*- C++ -*-=// +//===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,25 +12,42 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_COVERAGEMAPPING_H_ -#define LLVM_PROFILEDATA_COVERAGEMAPPING_H_ +#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H +#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.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_range.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> +#include <iterator> +#include <memory> +#include <string> #include <system_error> #include <tuple> +#include <utility> +#include <vector> namespace llvm { + +class IndexedInstrProfReader; + namespace coverage { +class CoverageMappingReader; +struct CoverageMappingRecord; + enum class coveragemap_error { success = 0, eof, @@ -68,19 +85,6 @@ private: 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 /// execution count for a region of code using the collected profile count data. struct Counter { @@ -91,13 +95,13 @@ struct Counter { EncodingTagBits + 1; private: - CounterKind Kind; - unsigned ID; + CounterKind Kind = Zero; + unsigned ID = 0; Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} public: - Counter() : Kind(Zero), ID(0) {} + Counter() = default; CounterKind getKind() const { return Kind; } @@ -153,8 +157,9 @@ struct CounterExpression { class CounterExpressionBuilder { /// \brief A list of all the counter expressions std::vector<CounterExpression> Expressions; + /// \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. /// @@ -238,7 +243,6 @@ struct CounterMappingRegion { LineEnd, ColumnEnd, SkippedRegion); } - inline std::pair<unsigned, unsigned> startLoc() const { return std::pair<unsigned, unsigned>(LineStart, ColumnStart); } @@ -269,7 +273,7 @@ public: 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()); } /// \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 /// list of expansions that can be further processed. class CoverageData { + friend class CoverageMapping; + std::string Filename; std::vector<CoverageSegment> Segments; std::vector<ExpansionRecord> Expansions; - friend class CoverageMapping; public: - CoverageData() {} + CoverageData() = default; CoverageData(StringRef Filename) : Filename(Filename) {} @@ -422,18 +427,17 @@ public: class CoverageMapping { StringSet<> FunctionNames; std::vector<FunctionRecord> Functions; - unsigned MismatchedFunctionCount; - - CoverageMapping() : MismatchedFunctionCount(0) {} - - CoverageMapping(const CoverageMapping &) = delete; - const CoverageMapping &operator=(const CoverageMapping &) = delete; + unsigned MismatchedFunctionCount = 0; + CoverageMapping() = default; /// \brief Add a function record corresponding to \p Record. Error loadFunctionRecord(const CoverageMappingRecord &Record, IndexedInstrProfReader &ProfileReader); public: + CoverageMapping(const CoverageMapping &) = delete; + CoverageMapping &operator=(const CoverageMapping &) = delete; + /// \brief Load the coverage mapping using the given readers. static Expected<std::unique_ptr<CoverageMapping>> load(CoverageMappingReader &CoverageReader, @@ -517,14 +521,17 @@ template <class IntPtrT> struct CovMapFunctionRecordV1 { template <support::endianness Endian> uint64_t getFuncHash() const { return support::endian::byte_swap<uint64_t, Endian>(FuncHash); } + // Return the coverage map data size for the funciton. template <support::endianness Endian> uint32_t getDataSize() const { return support::endian::byte_swap<uint32_t, Endian>(DataSize); } + // Return function lookup key. The value is consider opaque. template <support::endianness Endian> IntPtrT getFuncNameRef() const { return support::endian::byte_swap<IntPtrT, Endian>(NamePtr); } + // Return the PGO name of the function */ template <support::endianness Endian> Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { @@ -545,14 +552,17 @@ struct CovMapFunctionRecord { template <support::endianness Endian> uint64_t getFuncHash() const { return support::endian::byte_swap<uint64_t, Endian>(FuncHash); } + // Return the coverage map data size for the funciton. template <support::endianness Endian> uint32_t getDataSize() const { return support::endian::byte_swap<uint32_t, Endian>(DataSize); } + // Return function lookup key. The value is consider opaque. template <support::endianness Endian> uint64_t getFuncNameRef() const { return support::endian::byte_swap<uint64_t, Endian>(NameRef); } + // Return the PGO name of the function */ template <support::endianness Endian> Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { @@ -570,12 +580,15 @@ struct CovMapHeader { template <support::endianness Endian> uint32_t getNRecords() const { return support::endian::byte_swap<uint32_t, Endian>(NRecords); } + template <support::endianness Endian> uint32_t getFilenamesSize() const { return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize); } + template <support::endianness Endian> uint32_t getCoverageSize() const { return support::endian::byte_swap<uint32_t, Endian>(CoverageSize); } + template <support::endianness Endian> uint32_t getVersion() const { return support::endian::byte_swap<uint32_t, Endian>(Version); } @@ -635,4 +648,4 @@ template<> struct DenseMapInfo<coverage::CounterExpression> { } // end namespace llvm -#endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_ +#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H diff --git a/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h index db907f128d931..5b372252a9ac9 100644 --- a/include/llvm/ProfileData/Coverage/CoverageMappingReader.h +++ b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h @@ -1,4 +1,4 @@ -//=-- CoverageMappingReader.h - Code coverage mapping reader ------*- C++ -*-=// +//===- CoverageMappingReader.h - Code coverage mapping reader ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,18 +12,20 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H -#define LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H +#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H +#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H #include "llvm/ADT/ArrayRef.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/InstrProf.h" -#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" +#include <cstddef> +#include <cstdint> #include <iterator> +#include <memory> +#include <vector> namespace llvm { namespace coverage { @@ -42,13 +44,14 @@ struct CoverageMappingRecord { /// \brief A file format agnostic iterator over coverage mapping data. class CoverageMappingIterator : public std::iterator<std::input_iterator_tag, CoverageMappingRecord> { - CoverageMappingReader *Reader; + CoverageMappingReader *Reader = nullptr; CoverageMappingRecord Record; void increment(); public: - CoverageMappingIterator() : Reader(nullptr) {} + CoverageMappingIterator() = default; + CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) { increment(); } @@ -69,10 +72,11 @@ public: class CoverageMappingReader { public: + virtual ~CoverageMappingReader() = default; + virtual Error readNextRecord(CoverageMappingRecord &Record) = 0; CoverageMappingIterator begin() { return CoverageMappingIterator(this); } CoverageMappingIterator end() { return CoverageMappingIterator(); } - virtual ~CoverageMappingReader() {} }; /// \brief Base class for the raw coverage mapping and filenames data readers. @@ -92,13 +96,12 @@ protected: class RawCoverageFilenamesReader : public RawCoverageReader { std::vector<StringRef> &Filenames; - RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete; - RawCoverageFilenamesReader & - operator=(const RawCoverageFilenamesReader &) = delete; - public: RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames) : RawCoverageReader(Data), Filenames(Filenames) {} + RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete; + RawCoverageFilenamesReader & + operator=(const RawCoverageFilenamesReader &) = delete; Error read(); }; @@ -120,10 +123,6 @@ class RawCoverageMappingReader : public RawCoverageReader { std::vector<CounterExpression> &Expressions; std::vector<CounterMappingRegion> &MappingRegions; - RawCoverageMappingReader(const RawCoverageMappingReader &) = delete; - RawCoverageMappingReader & - operator=(const RawCoverageMappingReader &) = delete; - public: RawCoverageMappingReader(StringRef MappingData, ArrayRef<StringRef> TranslationUnitFilenames, @@ -134,6 +133,9 @@ public: TranslationUnitFilenames(TranslationUnitFilenames), Filenames(Filenames), Expressions(Expressions), MappingRegions(MappingRegions) {} + RawCoverageMappingReader(const RawCoverageMappingReader &) = delete; + RawCoverageMappingReader & + operator=(const RawCoverageMappingReader &) = delete; Error read(); @@ -169,17 +171,17 @@ private: std::vector<StringRef> Filenames; std::vector<ProfileMappingRecord> MappingRecords; InstrProfSymtab ProfileNames; - size_t CurrentRecord; + size_t CurrentRecord = 0; std::vector<StringRef> FunctionsFilenames; std::vector<CounterExpression> Expressions; std::vector<CounterMappingRegion> MappingRegions; + BinaryCoverageReader() = default; + +public: BinaryCoverageReader(const BinaryCoverageReader &) = delete; BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; - BinaryCoverageReader() : CurrentRecord(0) {} - -public: static Expected<std::unique_ptr<BinaryCoverageReader>> create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, StringRef Arch); @@ -190,4 +192,4 @@ public: } // end namespace coverage } // end namespace llvm -#endif +#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H diff --git a/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h index 24fb94647247c..b6f864ab3de38 100644 --- a/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h +++ b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h @@ -1,4 +1,4 @@ -//=-- CoverageMappingWriter.h - Code coverage mapping writer ------*- C++ -*-=// +//===- CoverageMappingWriter.h - Code coverage mapping writer ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,15 +12,17 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H -#define LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H +#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H +#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ProfileData/Coverage/CoverageMapping.h" -#include "llvm/Support/raw_ostream.h" namespace llvm { + +class raw_ostream; + namespace coverage { /// \brief Writer of the filenames section for the instrumentation @@ -54,6 +56,7 @@ public: }; } // end namespace coverage + } // end namespace llvm -#endif +#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index c7e558efa3dcc..c9828858cce3a 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -1,4 +1,4 @@ -//===-- InstrProf.h - Instrumented profiling format support -----*- C++ -*-===// +//===- InstrProf.h - Instrumented profiling format support ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,62 +16,57 @@ #ifndef LLVM_PROFILEDATA_INSTRPROF_H #define LLVM_PROFILEDATA_INSTRPROF_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/Triple.h" #include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Metadata.h" +#include "llvm/IR/ProfileSummary.h" #include "llvm/ProfileData/InstrProfData.inc" -#include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Host.h" #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> #include <cstdint> +#include <cstring> #include <list> +#include <memory> +#include <string> #include <system_error> +#include <utility> #include <vector> namespace llvm { class Function; class GlobalVariable; +struct InstrProfRecord; +class InstrProfSymtab; +class Instruction; +class MDNode; class Module; -/// Return the name of data section containing profile counter variables. -inline StringRef getInstrProfCountersSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_CNTS_SECT_NAME_STR - : INSTR_PROF_CNTS_SECT_NAME_STR; -} - -/// Return the name of data section containing names of instrumented -/// functions. -inline StringRef getInstrProfNameSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_NAME_SECT_NAME_STR - : INSTR_PROF_NAME_SECT_NAME_STR; -} - -/// Return the name of the data section containing per-function control -/// data. -inline StringRef getInstrProfDataSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_DATA_SECT_NAME_STR - ",regular,live_support" - : INSTR_PROF_DATA_SECT_NAME_STR; -} - -/// Return the name of data section containing pointers to value profile -/// counters/nodes. -inline StringRef getInstrProfValuesSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_VALS_SECT_NAME_STR - : INSTR_PROF_VALS_SECT_NAME_STR; -} +enum InstrProfSectKind { +#define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Kind, +#include "llvm/ProfileData/InstrProfData.inc" +}; -/// Return the name of data section containing nodes holdling value -/// profiling data. -inline StringRef getInstrProfVNodesSectionName(bool AddSegment) { - return AddSegment ? "__DATA," INSTR_PROF_VNODES_SECT_NAME_STR - : INSTR_PROF_VNODES_SECT_NAME_STR; -} +/// Return the name of the profile section corresponding to \p IPSK. +/// +/// The name of the section depends on the object format type \p OF. If +/// \p AddSegmentInfo is true, a segment prefix and additional linker hints may +/// be added to the section name (this is the default). +std::string getInstrProfSectionName(InstrProfSectKind IPSK, + Triple::ObjectFormatType OF, + bool AddSegmentInfo = true); /// Return the name profile runtime entry point to do value profiling /// for a given site. @@ -79,12 +74,18 @@ inline StringRef getInstrProfValueProfFuncName() { return INSTR_PROF_VALUE_PROF_FUNC_STR; } +/// Return the name profile runtime entry point to do value range profiling. +inline StringRef getInstrProfValueRangeProfFuncName() { + return INSTR_PROF_VALUE_RANGE_PROF_FUNC_STR; +} + /// Return the name of the section containing function coverage mapping /// data. -inline StringRef getInstrProfCoverageSectionName(bool AddSegment) { - return AddSegment ? "__LLVM_COV," INSTR_PROF_COVMAP_SECT_NAME_STR - : INSTR_PROF_COVMAP_SECT_NAME_STR; -} +std::string getInstrProfCoverageSectionName(const Module *M = nullptr); +/// Similar to the above, but used by host tool (e.g, coverage) which has +/// object format information. The section name returned is not prefixed +/// with segment name. +std::string getInstrProfCoverageSectionNameInObject(bool isCoff); /// Return the name prefix of variables containing instrumented function names. inline StringRef getInstrProfNameVarPrefix() { return "__profn_"; } @@ -201,6 +202,7 @@ GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName); GlobalVariable *createPGOFuncNameVar(Module &M, GlobalValue::LinkageTypes Linkage, StringRef PGOFuncName); + /// Return the initializer in string of the PGO name var \c NameVar. StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar); @@ -220,11 +222,12 @@ StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, /// second field will have value zero. Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs, bool doCompression, std::string &Result); + /// Produce \c Result string with the same format described above. The input /// is vector of PGO function name variables that are referenced. Error collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars, std::string &Result, bool doCompression = true); -class InstrProfSymtab; + /// \c NameStrings is a string composed of one of more sub-strings encoded in /// the format described above. The substrings are separated by 0 or more zero /// bytes. This method decodes the string and populates the \c Symtab. @@ -244,8 +247,6 @@ enum InstrProfValueKind : uint32_t { #include "llvm/ProfileData/InstrProfData.inc" }; -struct InstrProfRecord; - /// Get the value profile data for value site \p SiteIdx from \p InstrProfR /// and annotate the instruction \p Inst with the value profile meta data. /// Annotate up to \p MaxMDCount (default 3) number of records per value site. @@ -253,6 +254,7 @@ void annotateValueSite(Module &M, Instruction &Inst, const InstrProfRecord &InstrProfR, InstrProfValueKind ValueKind, uint32_t SiteIndx, uint32_t MaxMDCount = 3); + /// Same as the above interface but using an ArrayRef, as well as \p Sum. void annotateValueSite(Module &M, Instruction &Inst, ArrayRef<InstrProfValueData> VDs, @@ -347,25 +349,22 @@ class SoftInstrProfErrors { /// the first such error for reporting purposes. /// The first soft error encountered. - instrprof_error FirstError; + instrprof_error FirstError = instrprof_error::success; /// The number of hash mismatches. - unsigned NumHashMismatches; + unsigned NumHashMismatches = 0; /// The number of count mismatches. - unsigned NumCountMismatches; + unsigned NumCountMismatches = 0; /// The number of counter overflows. - unsigned NumCounterOverflows; + unsigned NumCounterOverflows = 0; /// The number of value site count mismatches. - unsigned NumValueSiteCountMismatches; + unsigned NumValueSiteCountMismatches = 0; public: - SoftInstrProfErrors() - : FirstError(instrprof_error::success), NumHashMismatches(0), - NumCountMismatches(0), NumCounterOverflows(0), - NumValueSiteCountMismatches(0) {} + SoftInstrProfErrors() = default; ~SoftInstrProfErrors() { assert(FirstError == instrprof_error::success && @@ -401,12 +400,16 @@ public: }; namespace object { + class SectionRef; -} + +} // end namespace object namespace IndexedInstrProf { + uint64_t ComputeHash(StringRef K); -} + +} // end namespace IndexedInstrProf /// A symbol table used for function PGO name look-up with keys /// (such as pointers, md5hash values) to the function. A function's @@ -419,7 +422,7 @@ public: private: StringRef Data; - uint64_t Address; + uint64_t Address = 0; // Unique name strings. StringSet<> NameTab; // A map from MD5 keys to function name strings. @@ -432,9 +435,7 @@ private: AddrHashMap AddrToMD5Map; public: - InstrProfSymtab() - : Data(), Address(0), NameTab(), MD5NameMap(), MD5FuncMap(), - AddrToMD5Map() {} + InstrProfSymtab() = default; /// Create InstrProfSymtab from an object file section which /// contains function PGO names. When section may contain raw @@ -443,26 +444,32 @@ public: /// the section base address. The decompression will be delayed /// until before it is used. See also \c create(StringRef) method. Error create(object::SectionRef &Section); + /// This interface is used by reader of CoverageMapping test /// format. inline Error create(StringRef D, uint64_t BaseAddr); + /// \c NameStrings is a string composed of one of more sub-strings /// encoded in the format described in \c collectPGOFuncNameStrings. /// This method is a wrapper to \c readPGOFuncNameStrings method. inline Error create(StringRef NameStrings); + /// A wrapper interface to populate the PGO symtab with functions /// decls from module \c M. This interface is used by transformation /// passes such as indirect function call promotion. Variable \c InLTO /// indicates if this is called from LTO optimization passes. void create(Module &M, bool InLTO = false); + /// Create InstrProfSymtab from a set of names iteratable from /// \p IterRange. This interface is used by IndexedProfReader. template <typename NameIterRange> void create(const NameIterRange &IterRange); + // If the symtab is created by a series of calls to \c addFuncName, \c // finalizeSymtab needs to be called before looking up function names. // This is required because the underlying map is a vector (for space // efficiency) which needs to be sorted. inline void finalizeSymtab(); + /// Update the symtab by adding \p FuncName to the table. This interface /// is used by the raw and text profile readers. void addFuncName(StringRef FuncName) { @@ -471,25 +478,32 @@ public: MD5NameMap.push_back(std::make_pair( IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey())); } + /// Map a function address to its name's MD5 hash. This interface /// is only used by the raw profiler reader. void mapAddress(uint64_t Addr, uint64_t MD5Val) { AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val)); } + AddrHashMap &getAddrHashMap() { return AddrToMD5Map; } + /// Return function's PGO name from the function name's symbol /// address in the object file. If an error occurs, return /// an empty string. StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize); + /// Return function's PGO name from the name's md5 hash value. /// If not found, return an empty string. inline StringRef getFuncName(uint64_t FuncMD5Hash); + /// Return function from the name's md5 hash. Return nullptr if not found. inline Function *getFunction(uint64_t FuncMD5Hash); + /// Return the function's original assembly name by stripping off /// the prefix attached (to symbols with priviate linkage). For /// global functions, it returns the same string as getFuncName. inline StringRef getOrigFuncName(uint64_t FuncMD5Hash); + /// Return the name section data. inline StringRef getNameData() const { return Data; } }; @@ -579,40 +593,48 @@ struct InstrProfValueSiteRecord { /// Profiling information for a single function. 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; uint64_t Hash; std::vector<uint64_t> Counts; 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; /// Return the number of value profile kinds with non-zero number /// of profile sites. inline uint32_t getNumValueKinds() const; + /// Return the number of instrumented sites for ValueKind. inline uint32_t getNumValueSites(uint32_t ValueKind) const; + /// Return the total number of ValueData for ValueKind. inline uint32_t getNumValueData(uint32_t ValueKind) const; + /// Return the number of value data collected for ValueKind at profiling /// site: Site. inline uint32_t getNumValueDataForSite(uint32_t ValueKind, uint32_t Site) const; + /// Return the array of profiled values at \p Site. If \p TotalC /// is not null, the total count of all target values at this site /// will be stored in \c *TotalC. inline std::unique_ptr<InstrProfValueData[]> getValueForSite(uint32_t ValueKind, uint32_t Site, - uint64_t *TotalC = 0) const; + uint64_t *TotalC = nullptr) const; + /// Get the target value/counts of kind \p ValueKind collected at site /// \p Site and store the result in array \p Dest. Return the total /// counts of all target values at this site. inline uint64_t getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind, uint32_t Site) const; + /// Reserve space for NumValueSites sites. inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites); + /// Add ValueData for ValueKind at value Site. void addValueData(uint32_t ValueKind, uint32_t Site, InstrProfValueData *VData, uint32_t N, @@ -635,6 +657,13 @@ struct InstrProfRecord { SR.sortByCount(); } } + + /// Clear value data entries and edge counters. + void Clear() { + Counts.clear(); + clearValueData(); + } + /// Clear value data entries void clearValueData() { for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) @@ -646,11 +675,15 @@ struct InstrProfRecord { private: std::vector<InstrProfValueSiteRecord> IndirectCallSites; + std::vector<InstrProfValueSiteRecord> MemOPSizes; const std::vector<InstrProfValueSiteRecord> & + getValueSitesForKind(uint32_t ValueKind) const { switch (ValueKind) { case IPVK_IndirectCallTarget: return IndirectCallSites; + case IPVK_MemOPSize: + return MemOPSizes; default: llvm_unreachable("Unknown value kind!"); } @@ -672,6 +705,7 @@ private: // Scale merged value counts by \p Weight. void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src, uint64_t Weight); + // Scale up value profile data count. void scaleValueProfData(uint32_t ValueKind, uint64_t Weight); }; @@ -706,7 +740,7 @@ std::unique_ptr<InstrProfValueData[]> InstrProfRecord::getValueForSite(uint32_t ValueKind, uint32_t Site, uint64_t *TotalC) const { uint64_t Dummy; - uint64_t &TotalCount = (TotalC == 0 ? Dummy : *TotalC); + uint64_t &TotalCount = (TotalC == nullptr ? Dummy : *TotalC); uint32_t N = getNumValueDataForSite(ValueKind, Site); if (N == 0) { TotalCount = 0; @@ -762,7 +796,6 @@ namespace IndexedInstrProf { enum class HashT : uint32_t { MD5, - Last = MD5 }; @@ -816,7 +849,6 @@ struct Header { // format. It is introduced in version 4. The summary data follows // right after the profile file header. struct Summary { - struct Entry { uint64_t Cutoff; ///< The required percentile of total execution count. uint64_t @@ -857,13 +889,16 @@ struct Summary { const uint64_t *getSummaryDataBase() const { return reinterpret_cast<const uint64_t *>(this + 1); } + uint64_t *getSummaryDataBase() { return reinterpret_cast<uint64_t *>(this + 1); } + const Entry *getCutoffEntryBase() const { return reinterpret_cast<const Entry *>( &getSummaryDataBase()[NumSummaryFields]); } + Entry *getCutoffEntryBase() { return reinterpret_cast<Entry *>(&getSummaryDataBase()[NumSummaryFields]); } @@ -877,6 +912,7 @@ struct Summary { } const Entry &getEntry(uint32_t I) const { return getCutoffEntryBase()[I]; } + void setEntry(uint32_t I, const ProfileSummaryEntry &E) { Entry &ER = getCutoffEntryBase()[I]; ER.Cutoff = E.Cutoff; @@ -894,6 +930,7 @@ inline std::unique_ptr<Summary> allocSummary(uint32_t TotalSize) { return std::unique_ptr<Summary>(new (::operator new(TotalSize)) Summary(TotalSize)); } + } // end namespace IndexedInstrProf namespace RawInstrProf { @@ -937,6 +974,10 @@ struct Header { } // end namespace RawInstrProf +// Parse MemOP Size range option. +void getMemOPSizeRangeFromOption(std::string Str, int64_t &RangeStart, + int64_t &RangeLast); + } // end namespace llvm #endif // LLVM_PROFILEDATA_INSTRPROF_H diff --git a/include/llvm/ProfileData/InstrProfData.inc b/include/llvm/ProfileData/InstrProfData.inc index f7c22d10763c5..be0dd4ad04bf6 100644 --- a/include/llvm/ProfileData/InstrProfData.inc +++ b/include/llvm/ProfileData/InstrProfData.inc @@ -153,7 +153,17 @@ INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) VALUE_PROF_FUNC_PARAM(uint64_t, TargetValue, Type::getInt64Ty(Ctx)) \ INSTR_PROF_COMMA VALUE_PROF_FUNC_PARAM(void *, Data, Type::getInt8PtrTy(Ctx)) INSTR_PROF_COMMA +#ifndef VALUE_RANGE_PROF VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx)) +#else /* VALUE_RANGE_PROF */ +VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx)) \ + INSTR_PROF_COMMA +VALUE_PROF_FUNC_PARAM(uint64_t, PreciseRangeStart, Type::getInt64Ty(Ctx)) \ + INSTR_PROF_COMMA +VALUE_PROF_FUNC_PARAM(uint64_t, PreciseRangeLast, Type::getInt64Ty(Ctx)) \ + INSTR_PROF_COMMA +VALUE_PROF_FUNC_PARAM(uint64_t, LargeValue, Type::getInt64Ty(Ctx)) +#endif /*VALUE_RANGE_PROF */ #undef VALUE_PROF_FUNC_PARAM #undef INSTR_PROF_COMMA /* VALUE_PROF_FUNC_PARAM end */ @@ -174,13 +184,15 @@ VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx)) * name hash and the function address. */ VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0) +/* For memory intrinsic functions size profiling. */ +VALUE_PROF_KIND(IPVK_MemOPSize, 1) /* These two kinds must be the last to be * declared. This is to make sure the string * array created with the template can be * indexed with the kind value. */ VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget) -VALUE_PROF_KIND(IPVK_Last, IPVK_IndirectCallTarget) +VALUE_PROF_KIND(IPVK_Last, IPVK_MemOPSize) #undef VALUE_PROF_KIND /* VALUE_PROF_KIND end */ @@ -234,6 +246,31 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \ /* COVMAP_HEADER end. */ +#ifdef INSTR_PROF_SECT_ENTRY +#define INSTR_PROF_DATA_DEFINED +INSTR_PROF_SECT_ENTRY(IPSK_data, \ + INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_DATA_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_cnts, \ + INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_name, \ + INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_NAME_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_vals, \ + INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_VALS_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_vnodes, \ + INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COFF), "__DATA,") +INSTR_PROF_SECT_ENTRY(IPSK_covmap, \ + INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COFF), "__LLVM_COV,") + +#undef INSTR_PROF_SECT_ENTRY +#endif + + #ifdef INSTR_PROF_VALUE_PROF_DATA #define INSTR_PROF_DATA_DEFINED @@ -610,17 +647,47 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, * specified via command line. */ #define INSTR_PROF_PROFILE_NAME_VAR __llvm_profile_filename +/* section name strings common to all targets other + than WIN32 */ +#define INSTR_PROF_DATA_COMMON __llvm_prf_data +#define INSTR_PROF_NAME_COMMON __llvm_prf_names +#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts +#define INSTR_PROF_VALS_COMMON __llvm_prf_vals +#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds +#define INSTR_PROF_COVMAP_COMMON __llvm_covmap +/* Win32 */ +#define INSTR_PROF_DATA_COFF .lprfd +#define INSTR_PROF_NAME_COFF .lprfn +#define INSTR_PROF_CNTS_COFF .lprfc +#define INSTR_PROF_VALS_COFF .lprfv +#define INSTR_PROF_VNODES_COFF .lprfnd +#define INSTR_PROF_COVMAP_COFF .lcovmap + +#ifdef _WIN32 /* Runtime section names and name strings. */ -#define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data -#define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names -#define INSTR_PROF_CNTS_SECT_NAME __llvm_prf_cnts +#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF +#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF +#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF /* Array of pointers. Each pointer points to a list * of value nodes associated with one value site. */ -#define INSTR_PROF_VALS_SECT_NAME __llvm_prf_vals +#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COFF /* Value profile nodes section. */ -#define INSTR_PROF_VNODES_SECT_NAME __llvm_prf_vnds -#define INSTR_PROF_COVMAP_SECT_NAME __llvm_covmap +#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF +#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF +#else +/* Runtime section names and name strings. */ +#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COMMON +#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COMMON +#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COMMON +/* Array of pointers. Each pointer points to a list + * of value nodes associated with one value site. + */ +#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COMMON +/* Value profile nodes section. */ +#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COMMON +#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COMMON +#endif #define INSTR_PROF_DATA_SECT_NAME_STR \ INSTR_PROF_QUOTE(INSTR_PROF_DATA_SECT_NAME) @@ -649,6 +716,9 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_VALUE_PROF_FUNC __llvm_profile_instrument_target #define INSTR_PROF_VALUE_PROF_FUNC_STR \ INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_FUNC) +#define INSTR_PROF_VALUE_RANGE_PROF_FUNC __llvm_profile_instrument_range +#define INSTR_PROF_VALUE_RANGE_PROF_FUNC_STR \ + INSTR_PROF_QUOTE(INSTR_PROF_VALUE_RANGE_PROF_FUNC) /* InstrProfile per-function control data alignment. */ #define INSTR_PROF_DATA_ALIGNMENT 8 diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 65b11f61d10bc..1d85a7149afc8 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -1,4 +1,4 @@ -//=-- InstrProfReader.h - Instrumented profiling readers ----------*- C++ -*-=// +//===- InstrProfReader.h - Instrumented profiling readers -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,14 +16,23 @@ #define LLVM_PROFILEDATA_INSTRPROFREADER_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/Support/EndianStream.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.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 <memory> +#include <utility> +#include <vector> namespace llvm { @@ -32,12 +41,13 @@ class InstrProfReader; /// A file format agnostic iterator over profiling data. class InstrProfIterator : public std::iterator<std::input_iterator_tag, InstrProfRecord> { - InstrProfReader *Reader; + InstrProfReader *Reader = nullptr; InstrProfRecord Record; void Increment(); + public: - InstrProfIterator() : Reader(nullptr) {} + InstrProfIterator() = default; InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); } InstrProfIterator &operator++() { Increment(); return *this; } @@ -50,19 +60,22 @@ public: /// Base class and interface for reading profiling data of any known instrprof /// format. Provides an iterator over InstrProfRecords. class InstrProfReader { - instrprof_error LastError; + instrprof_error LastError = instrprof_error::success; public: - InstrProfReader() : LastError(instrprof_error::success), Symtab() {} - virtual ~InstrProfReader() {} + InstrProfReader() = default; + virtual ~InstrProfReader() = default; /// Read the header. Required before reading first record. virtual Error readHeader() = 0; + /// Read a single record. virtual Error readNextRecord(InstrProfRecord &Record) = 0; + /// Iterator over profile data. InstrProfIterator begin() { return InstrProfIterator(this); } InstrProfIterator end() { return InstrProfIterator(); } + virtual bool isIRLevelProfile() const = 0; /// Return the PGO symtab. There are three different readers: @@ -86,6 +99,7 @@ protected: return Error::success(); return make_error<InstrProfError>(Err); } + Error error(Error E) { return error(InstrProfError::take(std::move(E))); } /// Clear the current error and return a successful one. @@ -94,8 +108,10 @@ protected: public: /// Return true if the reader has finished reading the profile data. bool isEOF() { return LastError == instrprof_error::eof; } + /// Return true if the reader encountered an error reading profiling data. bool hasError() { return LastError != instrprof_error::success && !isEOF(); } + /// Get the current error. Error getError() { if (hasError()) @@ -125,16 +141,15 @@ private: std::unique_ptr<MemoryBuffer> DataBuffer; /// Iterator over the profile data. line_iterator Line; - bool IsIRLevelProfile; + bool IsIRLevelProfile = false; - TextInstrProfReader(const TextInstrProfReader &) = delete; - TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; Error readValueProfileData(InstrProfRecord &Record); public: TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_) - : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#'), - IsIRLevelProfile(false) {} + : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} + TextInstrProfReader(const TextInstrProfReader &) = delete; + TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; /// Return true if the given buffer is in text instrprof format. static bool hasFormat(const MemoryBuffer &Buffer); @@ -143,6 +158,7 @@ public: /// Read the header. Error readHeader() override; + /// Read a single record. Error readNextRecord(InstrProfRecord &Record) override; @@ -184,15 +200,16 @@ private: InstrProfRecord::ValueMapType FunctionPtrToNameMap; - RawInstrProfReader(const RawInstrProfReader &) = delete; - RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; public: RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) : DataBuffer(std::move(DataBuffer)) { } + RawInstrProfReader(const RawInstrProfReader &) = delete; + RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; static bool hasFormat(const MemoryBuffer &DataBuffer); Error readHeader() override; Error readNextRecord(InstrProfRecord &Record) override; + bool isIRLevelProfile() const override { return (Version & VARIANT_MASK_IR_PROF) != 0; } @@ -206,9 +223,11 @@ private: Error createSymtab(InstrProfSymtab &Symtab); Error readNextHeader(const char *CurrentPos); Error readHeader(const RawInstrProf::Header &Header); + template <class IntT> IntT swap(IntT Int) const { return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int; } + support::endianness getDataEndianness() const { support::endianness HostEndian = getHostEndianness(); if (!ShouldSwapBytes) @@ -222,15 +241,18 @@ private: inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) { return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); } + Error readName(InstrProfRecord &Record); Error readFuncHash(InstrProfRecord &Record); Error readRawCounts(InstrProfRecord &Record); Error readValueProfilingData(InstrProfRecord &Record); bool atEnd() const { return Data == DataEnd; } + void advanceData() { Data++; ValueDataStart += CurValueDataSize; } + const char *getNextHeaderPos() const { assert(atEnd()); return (const char *)ValueDataStart; @@ -240,6 +262,7 @@ private: ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t); return CountersStart + Offset; } + StringRef getName(uint64_t NameRef) const { return Symtab->getFuncName(swap(NameRef)); } @@ -249,8 +272,10 @@ typedef RawInstrProfReader<uint32_t> RawInstrProfReader32; typedef RawInstrProfReader<uint64_t> RawInstrProfReader64; namespace IndexedInstrProf { + enum class HashT : uint32_t; -} + +} // end namespace IndexedInstrProf /// Trait for lookups into the on-disk hash table for the binary instrprof /// format. @@ -261,12 +286,11 @@ class InstrProfLookupTrait { // Endianness of the input value profile data. // It should be LE by default, but can be changed // for testing purpose. - support::endianness ValueProfDataEndianness; + support::endianness ValueProfDataEndianness = support::little; public: InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion) - : HashType(HashType), FormatVersion(FormatVersion), - ValueProfDataEndianness(support::little) {} + : HashType(HashType), FormatVersion(FormatVersion) {} typedef ArrayRef<InstrProfRecord> data_type; @@ -284,6 +308,7 @@ public: static std::pair<offset_type, offset_type> ReadKeyDataLength(const unsigned char *&D) { using namespace support; + offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D); offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D); return std::make_pair(KeyLen, DataLen); @@ -304,16 +329,18 @@ public: }; struct InstrProfReaderIndexBase { + virtual ~InstrProfReaderIndexBase() = default; + // Read all the profile records with the same key pointed to the current // iterator. virtual Error getRecords(ArrayRef<InstrProfRecord> &Data) = 0; + // Read all the profile records with the key equal to FuncName virtual Error getRecords(StringRef FuncName, ArrayRef<InstrProfRecord> &Data) = 0; virtual void advanceToNextKey() = 0; virtual bool atEnd() const = 0; virtual void setValueProfDataEndianness(support::endianness Endianness) = 0; - virtual ~InstrProfReaderIndexBase() {} virtual uint64_t getVersion() const = 0; virtual bool isIRLevelProfile() const = 0; virtual void populateSymtab(InstrProfSymtab &) = 0; @@ -335,22 +362,27 @@ public: const unsigned char *const Payload, const unsigned char *const Base, IndexedInstrProf::HashT HashType, uint64_t Version); + ~InstrProfReaderIndex() override = default; Error getRecords(ArrayRef<InstrProfRecord> &Data) override; Error getRecords(StringRef FuncName, ArrayRef<InstrProfRecord> &Data) override; void advanceToNextKey() override { RecordIterator++; } + bool atEnd() const override { return RecordIterator == HashTable->data_end(); } + void setValueProfDataEndianness(support::endianness Endianness) override { HashTable->getInfoObj().setValueProfDataEndianness(Endianness); } - ~InstrProfReaderIndex() override {} + uint64_t getVersion() const override { return GET_VERSION(FormatVersion); } + bool isIRLevelProfile() const override { return (FormatVersion & VARIANT_MASK_IR_PROF) != 0; } + void populateSymtab(InstrProfSymtab &Symtab) override { Symtab.create(HashTable->keys()); } @@ -366,20 +398,20 @@ private: /// Profile summary data. std::unique_ptr<ProfileSummary> Summary; - IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; - IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; - // Read the profile summary. Return a pointer pointing to one byte past the // end of the summary data if it exists or the input \c Cur. const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version, const unsigned char *Cur); public: + IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) + : DataBuffer(std::move(DataBuffer)) {} + IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; + IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; + /// Return the profile version. uint64_t getVersion() const { return Index->getVersion(); } bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); } - IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) - : DataBuffer(std::move(DataBuffer)), Index(nullptr) {} /// Return true if the given buffer is in an indexed instrprof format. static bool hasFormat(const MemoryBuffer &DataBuffer); @@ -422,4 +454,4 @@ public: } // end namespace llvm -#endif +#endif // LLVM_PROFILEDATA_INSTRPROFREADER_H diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index f7780fb450048..10742c0228ebe 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -1,4 +1,4 @@ -//=-- InstrProfWriter.h - Instrumented profiling writer -----------*- C++ -*-=// +//===- InstrProfWriter.h - Instrumented profiling writer --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,16 +16,19 @@ #define LLVM_PROFILEDATA_INSTRPROFWRITER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.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/raw_ostream.h" +#include <cstdint> +#include <memory> namespace llvm { /// Writer for instrumentation based profile data. -class ProfOStream; class InstrProfRecordWriterTrait; +class ProfOStream; class InstrProfWriter { public: @@ -35,7 +38,7 @@ public: private: bool Sparse; StringMap<ProfilingData> FunctionData; - ProfKind ProfileKind; + ProfKind ProfileKind = PF_Unknown; // Use raw pointer here for the incomplete type object. InstrProfRecordWriterTrait *InfoObj; @@ -47,15 +50,20 @@ public: /// for this function and the hash and number of counts match, each counter is /// summed. Optionally scale counts by \p Weight. Error addRecord(InstrProfRecord &&I, uint64_t Weight = 1); + /// Merge existing function counts from the given writer. Error mergeRecordsFromWriter(InstrProfWriter &&IPW); + /// Write the profile to \c OS void write(raw_fd_ostream &OS); + /// Write the profile in text format to \c OS void writeText(raw_fd_ostream &OS); + /// Write \c Record in text format to \c OS static void writeRecordInText(const InstrProfRecord &Record, InstrProfSymtab &Symtab, raw_fd_ostream &OS); + /// Write the profile, returning the raw data. For testing. std::unique_ptr<MemoryBuffer> writeBuffer(); @@ -82,4 +90,4 @@ private: } // end namespace llvm -#endif +#endif // LLVM_PROFILEDATA_INSTRPROFWRITER_H diff --git a/include/llvm/ProfileData/ProfileCommon.h b/include/llvm/ProfileData/ProfileCommon.h index e955755e5c9a5..987e3160ccae2 100644 --- a/include/llvm/ProfileData/ProfileCommon.h +++ b/include/llvm/ProfileData/ProfileCommon.h @@ -1,4 +1,4 @@ -//===-- ProfileCommon.h - Common profiling APIs. ----------------*- C++ -*-===// +//===- ProfileCommon.h - Common profiling APIs. -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,38 +12,33 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_PROFILE_COMMON_H -#define LLVM_PROFILEDATA_PROFILE_COMMON_H +#ifndef LLVM_PROFILEDATA_PROFILECOMMON_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 <functional> #include <map> -#include <utility> +#include <memory> #include <vector> -#include "llvm/IR/ProfileSummary.h" -#include "llvm/Support/Error.h" -#include "llvm/ADT/ArrayRef.h" - namespace llvm { -class Function; -namespace IndexedInstrProf { -struct Summary; -} + +struct InstrProfRecord; + namespace sampleprof { + class FunctionSamples; -} -struct InstrProfRecord; -class LLVMContext; -class Metadata; -class MDTuple; -class MDNode; + +} // end namespace sampleprof inline const char *getHotSectionPrefix() { return ".hot"; } inline const char *getUnlikelySectionPrefix() { return ".unlikely"; } class ProfileSummaryBuilder { - private: /// We keep track of the number of times a count (block count or samples) /// appears in the profile. The map is kept sorted in the descending order of @@ -53,13 +48,18 @@ private: protected: 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) : DetailedSummaryCutoffs(std::move(Cutoffs)) {} - inline void addCount(uint64_t Count); ~ProfileSummaryBuilder() = default; + + inline void addCount(uint64_t Count); void computeDetailedSummary(); - uint64_t TotalCount = 0, MaxCount = 0, MaxFunctionCount = 0; - uint32_t NumCounts = 0, NumFunctions = 0; public: /// \brief A vector of useful cutoff values for detailed summary. @@ -68,22 +68,24 @@ public: class InstrProfSummaryBuilder final : public ProfileSummaryBuilder { uint64_t MaxInternalBlockCount = 0; + inline void addEntryCount(uint64_t Count); inline void addInternalCount(uint64_t Count); public: InstrProfSummaryBuilder(std::vector<uint32_t> Cutoffs) : ProfileSummaryBuilder(std::move(Cutoffs)) {} + void addRecord(const InstrProfRecord &); std::unique_ptr<ProfileSummary> getSummary(); }; class SampleProfileSummaryBuilder final : public ProfileSummaryBuilder { - public: - void addRecord(const sampleprof::FunctionSamples &FS); SampleProfileSummaryBuilder(std::vector<uint32_t> Cutoffs) : ProfileSummaryBuilder(std::move(Cutoffs)) {} + + void addRecord(const sampleprof::FunctionSamples &FS); std::unique_ptr<ProfileSummary> getSummary(); }; @@ -96,6 +98,6 @@ void ProfileSummaryBuilder::addCount(uint64_t Count) { CountFrequencies[Count]++; } - } // end namespace llvm -#endif + +#endif // LLVM_PROFILEDATA_PROFILECOMMON_H diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index a96f83620f8b5..7a705ca5416da 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -1,4 +1,4 @@ -//=-- SampleProf.h - Sampling profiling format support --------------------===// +//===- SampleProf.h - Sampling profiling format support ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,20 +12,30 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H_ -#define LLVM_PROFILEDATA_SAMPLEPROF_H_ +#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H +#define LLVM_PROFILEDATA_SAMPLEPROF_H +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" -#include "llvm/Support/raw_ostream.h" - +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cstdint> #include <map> +#include <string> #include <system_error> +#include <utility> namespace llvm { +class raw_ostream; + const std::error_category &sampleprof_category(); enum class sampleprof_error { @@ -59,12 +69,13 @@ inline sampleprof_error MergeResult(sampleprof_error &Accumulator, } // end namespace llvm namespace std { + template <> struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {}; -} -namespace llvm { +} // end namespace std +namespace llvm { namespace sampleprof { static inline uint64_t SPMagic() { @@ -87,8 +98,10 @@ static inline uint64_t SPVersion() { return 103; } /// (e.g., the two post-increment instructions in "if (p) x++; else y++;"). struct LineLocation { LineLocation(uint32_t L, uint32_t D) : LineOffset(L), Discriminator(D) {} + void print(raw_ostream &OS) const; void dump() const; + bool operator<(const LineLocation &O) const { return LineOffset < O.LineOffset || (LineOffset == O.LineOffset && Discriminator < O.Discriminator); @@ -114,7 +127,7 @@ class SampleRecord { public: typedef StringMap<uint64_t> CallTargetMap; - SampleRecord() : NumSamples(0), CallTargets() {} + SampleRecord() = default; /// Increment the number of samples for this record by \p S. /// Optionally scale sample count \p S by \p Weight. @@ -144,7 +157,7 @@ public: } /// 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; } const CallTargetMap &getCallTargets() const { return CallTargets; } @@ -163,7 +176,7 @@ public: void dump() const; private: - uint64_t NumSamples; + uint64_t NumSamples = 0; CallTargetMap CallTargets; }; @@ -171,7 +184,8 @@ raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample); typedef std::map<LineLocation, SampleRecord> BodySampleMap; class FunctionSamples; -typedef std::map<LineLocation, FunctionSamples> CallsiteSampleMap; +typedef StringMap<FunctionSamples> FunctionSamplesMap; +typedef std::map<LineLocation, FunctionSamplesMap> CallsiteSampleMap; /// Representation of the samples collected for a function. /// @@ -180,9 +194,11 @@ typedef std::map<LineLocation, FunctionSamples> CallsiteSampleMap; /// within the body of the function. class FunctionSamples { public: - FunctionSamples() : Name(), TotalSamples(0), TotalHeadSamples(0) {} + FunctionSamples() = default; + void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const; void dump() const; + sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) { bool Overflowed; TotalSamples = @@ -190,6 +206,7 @@ public: return Overflowed ? sampleprof_error::counter_overflow : sampleprof_error::success; } + sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) { bool Overflowed; TotalHeadSamples = @@ -197,11 +214,13 @@ public: return Overflowed ? sampleprof_error::counter_overflow : sampleprof_error::success; } + sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num, uint64_t Weight = 1) { return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples( Num, Weight); } + sampleprof_error addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator, const std::string &FName, @@ -222,34 +241,53 @@ public: return ret->second.getSamples(); } - /// Return the total number of call target samples collected at a given - /// location. Each location is specified by \p LineOffset and - /// \p Discriminator. If the location is not found in profile, return error. - ErrorOr<uint64_t> findCallSamplesAt(uint32_t LineOffset, - uint32_t Discriminator) const { + /// Returns the call target map collected at a given location. + /// Each location is specified by \p LineOffset and \p Discriminator. + /// If the location is not found in profile, return error. + ErrorOr<SampleRecord::CallTargetMap> + findCallTargetMapAt(uint32_t LineOffset, uint32_t Discriminator) const { const auto &ret = BodySamples.find(LineLocation(LineOffset, Discriminator)); if (ret == BodySamples.end()) return std::error_code(); - uint64_t T = 0; - for (const auto &t_c : ret->second.getCallTargets()) { - T += t_c.second; - } - return T; + return ret->second.getCallTargets(); } /// Return the function samples at the given callsite location. - FunctionSamples &functionSamplesAt(const LineLocation &Loc) { + FunctionSamplesMap &functionSamplesAt(const LineLocation &Loc) { return CallsiteSamples[Loc]; } - /// Return a pointer to function samples at the given callsite location. - const FunctionSamples *findFunctionSamplesAt(const LineLocation &Loc) const { + /// Returns the FunctionSamplesMap at the given \p Loc. + const FunctionSamplesMap * + findFunctionSamplesMapAt(const LineLocation &Loc) const { auto iter = CallsiteSamples.find(Loc); - if (iter == CallsiteSamples.end()) { + if (iter == CallsiteSamples.end()) return nullptr; - } else { - return &iter->second; - } + return &iter->second; + } + + /// Returns a pointer to FunctionSamples at the given callsite location \p Loc + /// with callee \p CalleeName. If no callsite can be found, relax the + /// restriction to return the FunctionSamples at callsite location \p Loc + /// with the maximum total sample count. + const FunctionSamples *findFunctionSamplesAt(const LineLocation &Loc, + StringRef CalleeName) const { + auto iter = CallsiteSamples.find(Loc); + if (iter == CallsiteSamples.end()) + return nullptr; + auto FS = iter->second.find(CalleeName); + if (FS != iter->second.end()) + return &FS->getValue(); + // If we cannot find exact match of the callee name, return the FS with + // the max total count. + uint64_t MaxTotalSamples = 0; + const FunctionSamples *R = nullptr; + for (const auto &NameFS : iter->second) + if (NameFS.second.getTotalSamples() >= MaxTotalSamples) { + MaxTotalSamples = NameFS.second.getTotalSamples(); + R = &NameFS.second; + } + return R; } bool empty() const { return TotalSamples == 0; } @@ -283,12 +321,28 @@ public: } for (const auto &I : Other.getCallsiteSamples()) { const LineLocation &Loc = I.first; - const FunctionSamples &Rec = I.second; - MergeResult(Result, functionSamplesAt(Loc).merge(Rec, Weight)); + FunctionSamplesMap &FSMap = functionSamplesAt(Loc); + for (const auto &Rec : I.second) + MergeResult(Result, FSMap[Rec.first()].merge(Rec.second, Weight)); } return Result; } + /// Recursively traverses all children, if the corresponding function is + /// not defined in module \p M, and its total sample is no less than + /// \p Threshold, add its corresponding GUID to \p S. + void findImportedFunctions(DenseSet<GlobalValue::GUID> &S, const Module *M, + uint64_t Threshold) const { + if (TotalSamples <= Threshold) + return; + Function *F = M->getFunction(Name); + if (!F || !F->getSubprogram()) + S.insert(Function::getGUID(Name)); + for (auto CS : CallsiteSamples) + for (const auto &NameFS : CS.second) + NameFS.second.findImportedFunctions(S, M, Threshold); + } + /// Set the name of the function. void setName(StringRef FunctionName) { Name = FunctionName; } @@ -303,12 +357,12 @@ private: /// /// Samples are cumulative, they include all the samples collected /// 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. /// This is an approximation of the number of calls made to this function /// at runtime. - uint64_t TotalHeadSamples; + uint64_t TotalHeadSamples = 0; /// Map instruction locations to collected samples. /// @@ -355,6 +409,7 @@ public: return A->first < B->first; }); } + const SamplesWithLocList &get() const { return V; } private: @@ -362,7 +417,6 @@ private: }; } // end namespace sampleprof - } // end namespace llvm -#endif // LLVM_PROFILEDATA_SAMPLEPROF_H_ +#endif // LLVM_PROFILEDATA_SAMPLEPROF_H diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h index bf86721709c7b..29e3aba3e0e76 100644 --- a/include/llvm/ProfileData/SampleProfReader.h +++ b/include/llvm/ProfileData/SampleProfReader.h @@ -1,4 +1,4 @@ -//===- SampleProfReader.h - Read LLVM sample profile data -----------------===// +//===- SampleProfReader.h - Read LLVM sample profile data -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -205,26 +205,34 @@ // FUNCTION BODY // A FUNCTION BODY entry describing the inlined function. //===----------------------------------------------------------------------===// + #ifndef LLVM_PROFILEDATA_SAMPLEPROFREADER_H #define LLVM_PROFILEDATA_SAMPLEPROFREADER_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/IR/ProfileSummary.h" #include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/GCOV.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 { +class raw_ostream; + namespace sampleprof { /// \brief Sample-based profile reader. @@ -259,7 +267,7 @@ public: SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) : Profiles(0), Ctx(C), Buffer(std::move(B)) {} - virtual ~SampleProfileReader() {} + virtual ~SampleProfileReader() = default; /// \brief Read and validate the file header. virtual std::error_code readHeader() = 0; @@ -275,7 +283,12 @@ public: /// \brief Return the samples collected for function \p F. FunctionSamples *getSamplesFor(const Function &F) { - return &Profiles[F.getName()]; + // The function name may have been updated by adding suffix. In sample + // profile, the function names are all stripped, so we need to strip + // the function name suffix before matching with profile. + if (Profiles.count(F.getName().split('.').first)) + return &Profiles[(F.getName().split('.').first)]; + return nullptr; } /// \brief Return all the profiles. @@ -442,8 +455,8 @@ protected: static const uint32_t GCOVTagAFDOFunction = 0xac000000; }; -} // End namespace sampleprof +} // end namespace sampleprof -} // End namespace llvm +} // end namespace llvm #endif // LLVM_PROFILEDATA_SAMPLEPROFREADER_H diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h index f6f2e2702e316..9d69af32dd46a 100644 --- a/include/llvm/ProfileData/SampleProfWriter.h +++ b/include/llvm/ProfileData/SampleProfWriter.h @@ -1,4 +1,4 @@ -//===- SampleProfWriter.h - Write LLVM sample profile data ----------------===// +//===- SampleProfWriter.h - Write LLVM sample profile data ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,15 +14,18 @@ #define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/IR/ProfileSummary.h" #include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/ErrorOr.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cstdint> +#include <memory> +#include <system_error> namespace llvm { - namespace sampleprof { 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. class SampleProfileWriter { public: - virtual ~SampleProfileWriter() {} + virtual ~SampleProfileWriter() = default; /// Write sample profiles in \p S. /// @@ -114,7 +117,7 @@ public: protected: SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS) - : SampleProfileWriter(OS), NameTable() {} + : SampleProfileWriter(OS) {} std::error_code writeHeader(const StringMap<FunctionSamples> &ProfileMap) override; @@ -133,8 +136,7 @@ private: SampleProfileFormat Format); }; -} // End namespace sampleprof - -} // End namespace llvm +} // end namespace sampleprof +} // end namespace llvm #endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H |