diff options
Diffstat (limited to 'include/llvm/ProfileData')
-rw-r--r-- | include/llvm/ProfileData/CoverageMapping.h | 109 | ||||
-rw-r--r-- | include/llvm/ProfileData/CoverageMappingReader.h | 80 | ||||
-rw-r--r-- | include/llvm/ProfileData/InstrProfReader.h | 25 | ||||
-rw-r--r-- | include/llvm/ProfileData/InstrProfWriter.h | 8 | ||||
-rw-r--r-- | include/llvm/ProfileData/SampleProf.h | 34 |
5 files changed, 151 insertions, 105 deletions
diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index 38fc8ca7c77c..94e655c3edcb 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -18,16 +18,19 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/raw_ostream.h" #include <system_error> +#include <tuple> namespace llvm { class IndexedInstrProfReader; namespace coverage { -class ObjectFileCoverageMappingReader; +class CoverageMappingReader; class CoverageMapping; struct CounterExpressions; @@ -62,8 +65,12 @@ public: unsigned getExpressionID() const { return ID; } - bool operator==(const Counter &Other) const { - return Kind == Other.Kind && ID == Other.ID; + friend bool operator==(const Counter &LHS, const Counter &RHS) { + return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; + } + + friend bool operator!=(const Counter &LHS, const Counter &RHS) { + return !(LHS == RHS); } friend bool operator<(const Counter &LHS, const Counter &RHS) { @@ -153,24 +160,40 @@ struct CounterMappingRegion { SkippedRegion }; - static const unsigned EncodingHasCodeBeforeBits = 1; - Counter Count; unsigned FileID, ExpandedFileID; unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; RegionKind Kind; - /// \brief A flag that is set to true when there is already code before - /// this region on the same line. - /// This is useful to accurately compute the execution counts for a line. - bool HasCodeBefore; - - CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart, - unsigned ColumnStart, unsigned LineEnd, - unsigned ColumnEnd, bool HasCodeBefore = false, - RegionKind Kind = CodeRegion) - : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart), - ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), - Kind(Kind), HasCodeBefore(HasCodeBefore) {} + + CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, + unsigned LineStart, unsigned ColumnStart, + unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) + : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), + LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), + ColumnEnd(ColumnEnd), Kind(Kind) {} + + static CounterMappingRegion + makeRegion(Counter Count, unsigned FileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, + LineEnd, ColumnEnd, CodeRegion); + } + + static CounterMappingRegion + makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, + ColumnStart, LineEnd, ColumnEnd, + ExpansionRegion); + } + + static CounterMappingRegion + makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, + unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, + LineEnd, ColumnEnd, SkippedRegion); + } + inline std::pair<unsigned, unsigned> startLoc() const { return std::pair<unsigned, unsigned>(LineStart, ColumnStart); @@ -216,8 +239,10 @@ public: ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>()) : Expressions(Expressions), CounterValues(CounterValues) {} + void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; } + void dump(const Counter &C, llvm::raw_ostream &OS) const; - void dump(const Counter &C) const { dump(C, llvm::outs()); } + void dump(const Counter &C) const { dump(C, dbgs()); } /// \brief Return the number of times that a region of code associated with /// this counter was executed. @@ -235,10 +260,14 @@ struct FunctionRecord { /// \brief The number of times this function was executed. uint64_t ExecutionCount; - FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames, - uint64_t ExecutionCount) - : Name(Name), Filenames(Filenames.begin(), Filenames.end()), - ExecutionCount(ExecutionCount) {} + FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames) + : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} + + void pushRegion(CounterMappingRegion Region, uint64_t Count) { + if (CountedRegions.empty()) + ExecutionCount = Count; + CountedRegions.emplace_back(Region, Count); + } }; /// \brief Iterator over Functions, optionally filtered to a single file. @@ -312,10 +341,22 @@ struct CoverageSegment { CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) : Line(Line), Col(Col), Count(0), HasCount(false), IsRegionEntry(IsRegionEntry) {} + + CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, + bool IsRegionEntry) + : Line(Line), Col(Col), Count(Count), HasCount(true), + IsRegionEntry(IsRegionEntry) {} + + friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { + return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry) == + std::tie(R.Line, R.Col, R.Count, R.HasCount, R.IsRegionEntry); + } + void setCount(uint64_t NewCount) { Count = NewCount; HasCount = true; } + void addCount(uint64_t NewCount) { setCount(Count + NewCount); } }; @@ -363,12 +404,13 @@ class CoverageMapping { public: /// \brief Load the coverage mapping using the given readers. static ErrorOr<std::unique_ptr<CoverageMapping>> - load(ObjectFileCoverageMappingReader &CoverageReader, + load(CoverageMappingReader &CoverageReader, IndexedInstrProfReader &ProfileReader); /// \brief Load the coverage mapping from the given files. static ErrorOr<std::unique_ptr<CoverageMapping>> - load(StringRef ObjectFilename, StringRef ProfileFilename); + load(StringRef ObjectFilename, StringRef ProfileFilename, + Triple::ArchType Arch = Triple::ArchType::UnknownArch); /// \brief The number of functions that couldn't have their profiles mapped. /// @@ -442,7 +484,26 @@ template<> struct DenseMapInfo<coverage::CounterExpression> { } }; +const std::error_category &coveragemap_category(); + +enum class coveragemap_error { + success = 0, + eof, + no_data_found, + unsupported_version, + truncated, + malformed +}; + +inline std::error_code make_error_code(coveragemap_error E) { + return std::error_code(static_cast<int>(E), coveragemap_category()); +} } // end namespace llvm +namespace std { +template <> +struct is_error_code_enum<llvm::coveragemap_error> : std::true_type {}; +} + #endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_ diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h index 5a6b44b8d9ef..020edbd3e6c1 100644 --- a/include/llvm/ProfileData/CoverageMappingReader.h +++ b/include/llvm/ProfileData/CoverageMappingReader.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/Object/ObjectFile.h" #include "llvm/ProfileData/CoverageMapping.h" #include "llvm/ProfileData/InstrProf.h" @@ -27,7 +28,7 @@ namespace llvm { namespace coverage { -class ObjectFileCoverageMappingReader; +class CoverageMappingReader; /// \brief Coverage mapping information for a single function. struct CoverageMappingRecord { @@ -41,15 +42,14 @@ struct CoverageMappingRecord { /// \brief A file format agnostic iterator over coverage mapping data. class CoverageMappingIterator : public std::iterator<std::input_iterator_tag, CoverageMappingRecord> { - ObjectFileCoverageMappingReader *Reader; + CoverageMappingReader *Reader; CoverageMappingRecord Record; void increment(); public: CoverageMappingIterator() : Reader(nullptr) {} - CoverageMappingIterator(ObjectFileCoverageMappingReader *Reader) - : Reader(Reader) { + CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) { increment(); } @@ -67,17 +67,19 @@ public: CoverageMappingRecord *operator->() { return &Record; } }; +class CoverageMappingReader { +public: + virtual std::error_code 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. class RawCoverageReader { protected: StringRef Data; - /// \brief Return the error code. - std::error_code error(std::error_code EC) { return EC; } - - /// \brief Clear the current error code and return a successful one. - std::error_code success() { return error(instrprof_error::success); } - RawCoverageReader(StringRef Data) : Data(Data) {} std::error_code readULEB128(uint64_t &Result); @@ -90,10 +92,9 @@ protected: class RawCoverageFilenamesReader : public RawCoverageReader { std::vector<StringRef> &Filenames; - RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) - LLVM_DELETED_FUNCTION; + RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete; RawCoverageFilenamesReader & - operator=(const RawCoverageFilenamesReader &) LLVM_DELETED_FUNCTION; + operator=(const RawCoverageFilenamesReader &) = delete; public: RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames) @@ -104,29 +105,27 @@ public: /// \brief Reader for the raw coverage mapping data. class RawCoverageMappingReader : public RawCoverageReader { - StringRef FunctionName; ArrayRef<StringRef> TranslationUnitFilenames; std::vector<StringRef> &Filenames; std::vector<CounterExpression> &Expressions; std::vector<CounterMappingRegion> &MappingRegions; - RawCoverageMappingReader(const RawCoverageMappingReader &) - LLVM_DELETED_FUNCTION; + RawCoverageMappingReader(const RawCoverageMappingReader &) = delete; RawCoverageMappingReader & - operator=(const RawCoverageMappingReader &) LLVM_DELETED_FUNCTION; + operator=(const RawCoverageMappingReader &) = delete; public: - RawCoverageMappingReader(StringRef FunctionName, StringRef MappingData, + RawCoverageMappingReader(StringRef MappingData, ArrayRef<StringRef> TranslationUnitFilenames, std::vector<StringRef> &Filenames, std::vector<CounterExpression> &Expressions, std::vector<CounterMappingRegion> &MappingRegions) - : RawCoverageReader(MappingData), FunctionName(FunctionName), + : RawCoverageReader(MappingData), TranslationUnitFilenames(TranslationUnitFilenames), Filenames(Filenames), Expressions(Expressions), MappingRegions(MappingRegions) {} - std::error_code read(CoverageMappingRecord &Record); + std::error_code read(); private: std::error_code decodeCounter(unsigned Value, Counter &C); @@ -138,7 +137,7 @@ private: /// \brief Reader for the coverage mapping data that is emitted by the /// frontend and stored in an object file. -class ObjectFileCoverageMappingReader { +class BinaryCoverageReader : public CoverageMappingReader { public: struct ProfileMappingRecord { CoverageMappingVersion Version; @@ -157,8 +156,6 @@ public: }; private: - std::error_code LastError; - object::OwningBinary<object::ObjectFile> Object; std::vector<StringRef> Filenames; std::vector<ProfileMappingRecord> MappingRecords; size_t CurrentRecord; @@ -166,40 +163,17 @@ private: std::vector<CounterExpression> Expressions; std::vector<CounterMappingRegion> MappingRegions; - ObjectFileCoverageMappingReader(const ObjectFileCoverageMappingReader &) - LLVM_DELETED_FUNCTION; - ObjectFileCoverageMappingReader & - operator=(const ObjectFileCoverageMappingReader &) LLVM_DELETED_FUNCTION; - - /// \brief Set the current error_code and return same. - std::error_code error(std::error_code EC) { - LastError = EC; - return EC; - } + BinaryCoverageReader(const BinaryCoverageReader &) = delete; + BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; - /// \brief Clear the current error code and return a successful one. - std::error_code success() { return error(instrprof_error::success); } + BinaryCoverageReader() : CurrentRecord(0) {} public: - ObjectFileCoverageMappingReader(StringRef FileName); - ObjectFileCoverageMappingReader( - std::unique_ptr<MemoryBuffer> &ObjectBuffer, - sys::fs::file_magic Type = sys::fs::file_magic::unknown); - - std::error_code readHeader(); - std::error_code readNextRecord(CoverageMappingRecord &Record); - - /// Iterator over profile data. - CoverageMappingIterator begin() { return CoverageMappingIterator(this); } - CoverageMappingIterator end() { return CoverageMappingIterator(); } + static ErrorOr<std::unique_ptr<BinaryCoverageReader>> + create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, + Triple::ArchType Arch = Triple::ArchType::UnknownArch); - /// \brief Return true if the reader has finished reading the profile data. - bool isEOF() { return LastError == instrprof_error::eof; } - /// \brief Return true if the reader encountered an error reading profiling - /// data. - bool hasError() { return LastError && !isEOF(); } - /// \brief Get the current error code. - std::error_code getError() { return LastError; } + std::error_code readNextRecord(CoverageMappingRecord &Record) override; }; } // end namespace coverage diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 9655d66edc92..63a6ac671f2b 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -95,6 +95,9 @@ public: /// Factory method to create an appropriately typed reader for the given /// instrprof file. static ErrorOr<std::unique_ptr<InstrProfReader>> create(std::string Path); + + static ErrorOr<std::unique_ptr<InstrProfReader>> + create(std::unique_ptr<MemoryBuffer> Buffer); }; /// Reader for the simple text based instrprof format. @@ -114,9 +117,8 @@ private: /// The current set of counter values. std::vector<uint64_t> Counts; - TextInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION; - TextInstrProfReader &operator=(const TextInstrProfReader &) - LLVM_DELETED_FUNCTION; + TextInstrProfReader(const TextInstrProfReader &) = delete; + TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; public: TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_) : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} @@ -167,9 +169,8 @@ private: const char *NamesStart; const char *ProfileEnd; - RawInstrProfReader(const RawInstrProfReader &) LLVM_DELETED_FUNCTION; - RawInstrProfReader &operator=(const RawInstrProfReader &) - LLVM_DELETED_FUNCTION; + RawInstrProfReader(const RawInstrProfReader &) = delete; + RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; public: RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) : DataBuffer(std::move(DataBuffer)) { } @@ -273,9 +274,8 @@ private: /// The maximal execution count among all functions. uint64_t MaxFunctionCount; - IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION; - IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) - LLVM_DELETED_FUNCTION; + IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; + IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; public: IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) : DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {} @@ -295,8 +295,11 @@ public: uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } /// Factory method to create an indexed reader. - static std::error_code - create(std::string Path, std::unique_ptr<IndexedInstrProfReader> &Result); + static ErrorOr<std::unique_ptr<IndexedInstrProfReader>> + create(std::string Path); + + static ErrorOr<std::unique_ptr<IndexedInstrProfReader>> + create(std::unique_ptr<MemoryBuffer> Buffer); }; } // end namespace llvm diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index a23c56772a2f..ce0bb5242498 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -20,6 +20,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include <vector> @@ -41,8 +42,13 @@ public: std::error_code addFunctionCounts(StringRef FunctionName, uint64_t FunctionHash, ArrayRef<uint64_t> Counters); - /// Ensure that all data is written to disk. + /// Write the profile to \c OS void write(raw_fd_ostream &OS); + /// Write the profile, returning the raw data. For testing. + std::unique_ptr<MemoryBuffer> writeBuffer(); + +private: + std::pair<uint64_t, uint64_t> writeImpl(raw_ostream &OS); }; } // end namespace llvm diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index df0a055c2a79..1b82e55aa77a 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -59,7 +59,7 @@ static inline uint64_t SPMagic() { static inline uint64_t SPVersion() { return 100; } -/// \brief Represents the relative location of an instruction. +/// Represents the relative location of an instruction. /// /// Instruction locations are specified by the line offset from the /// beginning of the function (marked by the line where the function @@ -100,7 +100,7 @@ template <> struct DenseMapInfo<sampleprof::LineLocation> { namespace sampleprof { -/// \brief Representation of a single sample record. +/// Representation of a single sample record. /// /// A sample record is represented by a positive integer value, which /// indicates how frequently was the associated line location executed. @@ -116,7 +116,7 @@ public: SampleRecord() : NumSamples(0), CallTargets() {} - /// \brief Increment the number of samples for this record by \p S. + /// Increment the number of samples for this record by \p S. /// /// Sample counts accumulate using saturating arithmetic, to avoid wrapping /// around unsigned integers. @@ -127,7 +127,7 @@ public: NumSamples = std::numeric_limits<unsigned>::max(); } - /// \brief Add called function \p F with samples \p S. + /// Add called function \p F with samples \p S. /// /// Sample counts accumulate using saturating arithmetic, to avoid wrapping /// around unsigned integers. @@ -139,13 +139,13 @@ public: TargetSamples = std::numeric_limits<unsigned>::max(); } - /// \brief 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; } unsigned getSamples() const { return NumSamples; } const CallTargetMap &getCallTargets() const { return CallTargets; } - /// \brief Merge the samples in \p Other into this record. + /// Merge the samples in \p Other into this record. void merge(const SampleRecord &Other) { addSamples(Other.getSamples()); for (const auto &I : Other.getCallTargets()) @@ -159,7 +159,7 @@ private: typedef DenseMap<LineLocation, SampleRecord> BodySampleMap; -/// \brief Representation of the samples collected for a function. +/// Representation of the samples collected for a function. /// /// This data structure contains all the collected samples for the body /// of a function. Each sample corresponds to a LineLocation instance @@ -187,13 +187,13 @@ public: Num); } - /// \brief Return the sample record at the given location. + /// Return the sample record at the given location. /// Each location is specified by \p LineOffset and \p Discriminator. SampleRecord &sampleRecordAt(const LineLocation &Loc) { return BodySamples[Loc]; } - /// \brief Return the number of samples collected at the given location. + /// Return the number of samples collected at the given location. /// Each location is specified by \p LineOffset and \p Discriminator. unsigned samplesAt(int LineOffset, unsigned Discriminator) { return sampleRecordAt(LineLocation(LineOffset, Discriminator)).getSamples(); @@ -201,17 +201,17 @@ public: bool empty() const { return BodySamples.empty(); } - /// \brief Return the total number of samples collected inside the function. + /// Return the total number of samples collected inside the function. unsigned getTotalSamples() const { return TotalSamples; } - /// \brief Return the total number of samples collected at the head of the + /// Return the total number of samples collected at the head of the /// function. unsigned getHeadSamples() const { return TotalHeadSamples; } - /// \brief Return all the samples collected in the body of the function. + /// Return all the samples collected in the body of the function. const BodySampleMap &getBodySamples() const { return BodySamples; } - /// \brief Merge the samples in \p Other into this one. + /// Merge the samples in \p Other into this one. void merge(const FunctionSamples &Other) { addTotalSamples(Other.getTotalSamples()); addHeadSamples(Other.getHeadSamples()); @@ -223,16 +223,18 @@ public: } private: - /// \brief Total number of samples collected inside this function. + /// Total number of samples collected inside this function. /// /// Samples are cumulative, they include all the samples collected /// inside this function and all its inlined callees. unsigned TotalSamples; - /// \brief 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 + /// at runtime. unsigned TotalHeadSamples; - /// \brief Map instruction locations to collected samples. + /// Map instruction locations to collected samples. /// /// Each entry in this map contains the number of samples /// collected at the corresponding line offset. All line locations |