[llvm] r203703 - Profile: Add a library for the instrumentation based profiling format
Duncan P. N. Exon Smith
dexonsmith at apple.com
Wed Mar 12 14:11:34 PDT 2014
On Mar 12, 2014, at 1:14 PM, Justin Bogner <mail at justinbogner.com> wrote:
> Author: bogner
> Date: Wed Mar 12 15:14:05 2014
> New Revision: 203703
>
> URL: http://llvm.org/viewvc/llvm-project?rev=203703&view=rev
> Log:
> Profile: Add a library for the instrumentation based profiling format
>
> This provides a library to work with the instrumentation based
> profiling format that is used by clang's -fprofile-instr-* options and
> by the llvm-profdata tool. This is a binary format, rather than the
> textual one that's currently in use.
>
> The tests are in the subsequent commits that use this.
>
> Added:
> llvm/trunk/include/llvm/Profile/
> llvm/trunk/include/llvm/Profile/ProfileData.h
> llvm/trunk/include/llvm/Profile/ProfileDataReader.h
> llvm/trunk/include/llvm/Profile/ProfileDataWriter.h
> llvm/trunk/lib/Profile/
> llvm/trunk/lib/Profile/CMakeLists.txt
> llvm/trunk/lib/Profile/LLVMBuild.txt
> - copied, changed from r203701, llvm/trunk/lib/LLVMBuild.txt
> llvm/trunk/lib/Profile/Makefile
> - copied, changed from r203701, llvm/trunk/lib/Makefile
> llvm/trunk/lib/Profile/ProfileData.cpp
> llvm/trunk/lib/Profile/ProfileDataReader.cpp
> llvm/trunk/lib/Profile/ProfileDataWriter.cpp
> Modified:
> llvm/trunk/lib/CMakeLists.txt
> llvm/trunk/lib/LLVMBuild.txt
> llvm/trunk/lib/Makefile
>
> Added: llvm/trunk/include/llvm/Profile/ProfileData.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Profile/ProfileData.h?rev=203703&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Profile/ProfileData.h (added)
> +++ llvm/trunk/include/llvm/Profile/ProfileData.h Wed Mar 12 15:14:05 2014
> @@ -0,0 +1,55 @@
> +//=-- ProfileData.h - Instrumented profiling format support -------*- C++ -*-=//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains support for instrumentation based PGO and coverage.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_PROFILE_PROFILEDATA_H__
> +#define LLVM_PROFILE_PROFILEDATA_H__
> +
> +#include "llvm/Support/DataTypes.h"
> +#include "llvm/Support/system_error.h"
> +
> +#include <vector>
> +
> +namespace llvm {
> +
> +const char PROFILEDATA_MAGIC[4] = {'L', 'P', 'R', 'F'};
> +const uint32_t PROFILEDATA_VERSION = 1;
> +
> +const error_category &profiledata_category();
> +
> +struct profiledata_error {
> + enum ErrorType {
> + success = 0,
> + bad_magic,
> + unsupported_version,
> + too_large,
> + truncated,
> + malformed,
> + unknown_function
> + };
> + ErrorType V;
> +
> + profiledata_error(ErrorType V) : V(V) {}
> + operator ErrorType() const { return V; }
> +};
> +
> +inline error_code make_error_code(profiledata_error E) {
> + return error_code(static_cast<int>(E), profiledata_category());
> +}
> +
> +template <> struct is_error_code_enum<profiledata_error> : std::true_type {};
> +template <> struct is_error_code_enum<profiledata_error::ErrorType>
> + : std::true_type {};
> +
> +} // end namespace llvm
> +
> +#endif // LLVM_PROFILE_PROFILEDATA_H__
>
> Added: llvm/trunk/include/llvm/Profile/ProfileDataReader.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Profile/ProfileDataReader.h?rev=203703&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Profile/ProfileDataReader.h (added)
> +++ llvm/trunk/include/llvm/Profile/ProfileDataReader.h Wed Mar 12 15:14:05 2014
> @@ -0,0 +1,93 @@
> +//=-- ProfileDataReader.h - Instrumented profiling reader ---------*- C++ -*-=//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains support for reading profiling data for instrumentation
> +// based PGO and coverage.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_PROFILE_PROFILEDATA_READER_H__
> +#define LLVM_PROFILE_PROFILEDATA_READER_H__
> +
> +#include "llvm/ADT/StringMap.h"
> +#include "llvm/Support/Compiler.h"
> +#include "llvm/Support/DataTypes.h"
> +#include "llvm/Support/ErrorOr.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +#include <vector>
> +
> +namespace llvm {
> +
> +class ProfileDataCursor;
> +
> +/// Reader for the profile data that is used for instrumentation based PGO.
> +class ProfileDataReader {
> +private:
> + /// The profile data file contents.
> + std::unique_ptr<MemoryBuffer> DataBuffer;
> + /// Offsets into DataBuffer for each function's counters.
> + StringMap<uint32_t> DataOffsets;
> + /// The maximal execution count among all functions.
> + uint64_t MaxFunctionCount;
> +
> + ProfileDataReader(const ProfileDataReader &) LLVM_DELETED_FUNCTION;
> + ProfileDataReader &operator=(const ProfileDataReader &) LLVM_DELETED_FUNCTION;
> +protected:
> + ProfileDataReader(std::unique_ptr<MemoryBuffer> &DataBuffer)
> + : DataBuffer(DataBuffer.release()) {}
> +
> + /// Populate internal state using the profile data's index
> + error_code readIndex();
> +public:
> +
> + class name_iterator {
> + typedef StringMap<unsigned>::const_iterator IterTy;
> + IterTy Ix;
> + public:
> + explicit name_iterator(const IterTy &Ix) : Ix(Ix) {}
> +
> + StringRef operator*() const { return Ix->getKey(); }
> +
> + bool operator==(const name_iterator &RHS) const { return Ix == RHS.Ix; }
> + bool operator!=(const name_iterator &RHS) const { return Ix != RHS.Ix; }
> +
> + inline name_iterator& operator++() { ++Ix; return *this; }
- Is the explicit inline necessary here? I think functions defined
inline are already inlined.
- & should be attached to operator++ instead of name_iterator.
- Might be nice to provide a post-increment operator as well.
> + };
> +
> + /// Iterators over the names of indexed items
> + name_iterator begin() const {
> + return name_iterator(DataOffsets.begin());
> + }
> + name_iterator end() const {
> + return name_iterator(DataOffsets.end());
> + }
> +
> +private:
> + error_code findFunctionCounts(StringRef FuncName, uint64_t &FunctionHash,
> + ProfileDataCursor &Cursor);
> +public:
> + /// The number of profiled functions
> + size_t numProfiledFunctions() { return DataOffsets.size(); }
> + /// Fill Counts with the profile data for the given function name.
> + error_code getFunctionCounts(StringRef FuncName, uint64_t &FunctionHash,
> + std::vector<uint64_t> &Counts);
> + /// Get the frequency with which a function is called relative to the function
> + /// that is called most often in the program.
> + error_code getCallFrequency(StringRef FuncName, uint64_t &FunctionHash,
> + double &F);
> +
> + static error_code create(std::string Path,
> + std::unique_ptr<ProfileDataReader> &Result);
> +};
> +
> +} // end namespace llvm
> +
> +#endif // LLVM_PROFILE_PROFILEDATA_READER_H__
>
> Added: llvm/trunk/include/llvm/Profile/ProfileDataWriter.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Profile/ProfileDataWriter.h?rev=203703&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Profile/ProfileDataWriter.h (added)
> +++ llvm/trunk/include/llvm/Profile/ProfileDataWriter.h Wed Mar 12 15:14:05 2014
> @@ -0,0 +1,54 @@
> +//=-- ProfileDataWriter.h - Instrumented profiling writer ---------*- C++ -*-=//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains support for writing profiling data for instrumentation
> +// based PGO and coverage.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_PROFILE_PROFILEDATA_WRITER_H__
> +#define LLVM_PROFILE_PROFILEDATA_WRITER_H__
> +
> +#include "llvm/ADT/StringMap.h"
> +#include "llvm/Support/DataTypes.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +#include <vector>
> +
> +namespace llvm {
> +
> +struct __attribute__((packed)) ProfileDataHeader {
> + char Magic[4];
> + uint32_t Version;
> + uint32_t DataStart;
> + uint32_t Padding;
> + uint64_t MaxFunctionCount;
> +};
> +
> +/// Writer for instrumentation based profile data
> +class ProfileDataWriter {
> + StringMap<size_t> FunctionOffsets;
> + std::vector<uint64_t> FunctionData;
> + uint32_t DataStart;
> + uint64_t MaxFunctionCount;
> +
> + void write32(raw_ostream &OS, uint32_t Value);
> + void write64(raw_ostream &OS, uint64_t Value);
> +public:
> + ProfileDataWriter()
> + : DataStart(sizeof(ProfileDataHeader)), MaxFunctionCount(0) {}
> +
> + void addFunctionCounts(StringRef FuncName, uint64_t FunctionHash,
> + uint64_t NumCounters, const uint64_t *Counters);
Can this be an ArrayRef<uint64_t>?
> + void write(raw_ostream &OS);
> +};
> +
> +} // end namespace llvm
> +
> +#endif // LLVM_PROFILE_PROFILEDATA_WRITER_H__
>
> Modified: llvm/trunk/lib/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CMakeLists.txt?rev=203703&r1=203702&r2=203703&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CMakeLists.txt (original)
> +++ llvm/trunk/lib/CMakeLists.txt Wed Mar 12 15:14:05 2014
> @@ -16,3 +16,4 @@ add_subdirectory(ExecutionEngine)
> add_subdirectory(Target)
> add_subdirectory(AsmParser)
> add_subdirectory(LineEditor)
> +add_subdirectory(Profile)
>
> Modified: llvm/trunk/lib/LLVMBuild.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LLVMBuild.txt?rev=203703&r1=203702&r2=203703&view=diff
> ==============================================================================
> --- llvm/trunk/lib/LLVMBuild.txt (original)
> +++ llvm/trunk/lib/LLVMBuild.txt Wed Mar 12 15:14:05 2014
> @@ -16,7 +16,7 @@
> ;===------------------------------------------------------------------------===;
>
> [common]
> -subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine LineEditor Linker IR IRReader LTO MC Object Option Support TableGen Target Transforms
> +subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine LineEditor Linker IR IRReader LTO MC Object Option Profile Support TableGen Target Transforms
>
> [component_0]
> type = Group
>
> Modified: llvm/trunk/lib/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Makefile?rev=203703&r1=203702&r2=203703&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Makefile (original)
> +++ llvm/trunk/lib/Makefile Wed Mar 12 15:14:05 2014
> @@ -12,6 +12,6 @@ include $(LEVEL)/Makefile.config
>
> PARALLEL_DIRS := IR AsmParser Bitcode Analysis Transforms CodeGen Target \
> ExecutionEngine Linker LTO MC Object Option DebugInfo \
> - IRReader LineEditor
> + IRReader LineEditor Profile
>
> include $(LEVEL)/Makefile.common
>
> Added: llvm/trunk/lib/Profile/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Profile/CMakeLists.txt?rev=203703&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Profile/CMakeLists.txt (added)
> +++ llvm/trunk/lib/Profile/CMakeLists.txt Wed Mar 12 15:14:05 2014
> @@ -0,0 +1,5 @@
> +add_llvm_library(LLVMProfile
> + ProfileData.cpp
> + ProfileDataReader.cpp
> + ProfileDataWriter.cpp
> + )
>
> Copied: llvm/trunk/lib/Profile/LLVMBuild.txt (from r203701, llvm/trunk/lib/LLVMBuild.txt)
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Profile/LLVMBuild.txt?p2=llvm/trunk/lib/Profile/LLVMBuild.txt&p1=llvm/trunk/lib/LLVMBuild.txt&r1=203701&r2=203703&rev=203703&view=diff
> ==============================================================================
> --- llvm/trunk/lib/LLVMBuild.txt (original)
> +++ llvm/trunk/lib/Profile/LLVMBuild.txt Wed Mar 12 15:14:05 2014
> @@ -1,4 +1,4 @@
> -;===- ./lib/LLVMBuild.txt --------------------------------------*- Conf -*--===;
> +;===- ./lib/Profile/LLVMBuild.txt ------------------------------*- Conf -*--===;
> ;
> ; The LLVM Compiler Infrastructure
> ;
> @@ -15,10 +15,7 @@
> ;
> ;===------------------------------------------------------------------------===;
>
> -[common]
> -subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine LineEditor Linker IR IRReader LTO MC Object Option Support TableGen Target Transforms
> -
> [component_0]
> -type = Group
> -name = Libraries
> -parent = $ROOT
> +type = Library
> +name = Profile
> +parent = Libraries
>
> Copied: llvm/trunk/lib/Profile/Makefile (from r203701, llvm/trunk/lib/Makefile)
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Profile/Makefile?p2=llvm/trunk/lib/Profile/Makefile&p1=llvm/trunk/lib/Makefile&r1=203701&r2=203703&rev=203703&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Makefile (original)
> +++ llvm/trunk/lib/Profile/Makefile Wed Mar 12 15:14:05 2014
> @@ -1,4 +1,4 @@
> -##===- lib/Makefile ----------------------------------------*- Makefile -*-===##
> +##===- lib/Profile/Makefile --------------------------------*- Makefile -*-===##
> #
> # The LLVM Compiler Infrastructure
> #
> @@ -6,12 +6,9 @@
> # License. See LICENSE.TXT for details.
> #
> ##===----------------------------------------------------------------------===##
> -LEVEL = ..
>
> -include $(LEVEL)/Makefile.config
> -
> -PARALLEL_DIRS := IR AsmParser Bitcode Analysis Transforms CodeGen Target \
> - ExecutionEngine Linker LTO MC Object Option DebugInfo \
> - IRReader LineEditor
> +LEVEL = ../..
> +LIBRARYNAME = LLVMProfile
> +BUILD_ARCHIVE := 1
>
> include $(LEVEL)/Makefile.common
>
> Added: llvm/trunk/lib/Profile/ProfileData.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Profile/ProfileData.cpp?rev=203703&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Profile/ProfileData.cpp (added)
> +++ llvm/trunk/lib/Profile/ProfileData.cpp Wed Mar 12 15:14:05 2014
> @@ -0,0 +1,54 @@
> +//=-- ProfileData.cpp - Instrumented profiling format support ---------------=//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains support for clang's instrumentation based PGO and
> +// coverage.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Profile/ProfileData.h"
> +#include "llvm/Support/ErrorHandling.h"
> +
> +using namespace llvm;
> +
> +namespace {
> +class ProfileDataErrorCategoryType : public _do_message {
> + const char *name() const override { return "llvm.profiledata"; }
> + std::string message(int IE) const {
> + profiledata_error::ErrorType E =
> + static_cast<profiledata_error::ErrorType>(IE);
> + switch (E) {
> + case profiledata_error::success: return "Success";
> + case profiledata_error::bad_magic:
> + return "Invalid file format (bad magic)";
> + case profiledata_error::unsupported_version:
> + return "Unsupported format version";
> + case profiledata_error::too_large:
> + return "Too much profile data";
> + case profiledata_error::truncated:
> + return "Truncated profile data";
> + case profiledata_error::malformed:
> + return "Malformed profile data";
> + case profiledata_error::unknown_function:
> + return "No profile data available for function";
> + }
> + llvm_unreachable("A value of profiledata_error has no message.");
> + }
> + error_condition default_error_condition(int EV) const {
> + if (EV == profiledata_error::success)
> + return errc::success;
> + return errc::invalid_argument;
> + }
> +};
> +}
> +
> +const error_category &llvm::profiledata_category() {
> + static ProfileDataErrorCategoryType C;
> + return C;
> +}
>
> Added: llvm/trunk/lib/Profile/ProfileDataReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Profile/ProfileDataReader.cpp?rev=203703&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Profile/ProfileDataReader.cpp (added)
> +++ llvm/trunk/lib/Profile/ProfileDataReader.cpp Wed Mar 12 15:14:05 2014
> @@ -0,0 +1,183 @@
> +//=-- ProfileDataReader.cpp - Instrumented profiling reader -----------------=//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains support for reading profiling data for clang's
> +// instrumentation based PGO and coverage.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Profile/ProfileDataReader.h"
> +#include "llvm/Profile/ProfileData.h"
> +#include "llvm/Support/Endian.h"
> +
> +#include <cassert>
> +
> +using namespace llvm;
> +
> +error_code ProfileDataReader::create(
> + std::string Path, std::unique_ptr<ProfileDataReader> &Result) {
> + std::unique_ptr<MemoryBuffer> Buffer;
> + if (error_code EC = MemoryBuffer::getFileOrSTDIN(Path, Buffer))
> + return EC;
> +
> + if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max())
> + return profiledata_error::too_large;
> +
> + Result.reset(new ProfileDataReader(Buffer));
> + if (error_code EC = Result->readIndex())
> + return EC;
> + return profiledata_error::success;
> +}
> +
> +class llvm::ProfileDataCursor {
> + const char *Start;
> + const char *Next;
> + const char *End;
> +
> + error_code skip(unsigned bytes) {
> + if (Next + bytes > End)
> + return profiledata_error::malformed;
> + Next += bytes;
> + return profiledata_error::success;
> + }
> +
> + template <typename T>
> + error_code read(T &Result) {
> + typedef support::detail::packed_endian_specific_integral
> + <T, support::little, support::unaligned> Endian_t;
> + const char *Prev = Next;
> + if (error_code EC = skip(sizeof(T)))
> + return EC;
> + Result = *reinterpret_cast<const Endian_t*>(Prev);
> + return profiledata_error::success;
> + }
> +public:
> + ProfileDataCursor(const MemoryBuffer *Buf)
> + : Start(Buf->getBufferStart()), Next(Start), End(Buf->getBufferEnd()) {}
> + bool offsetReached(size_t Offset) { return Start + Offset <= Next; }
> + bool offsetInBounds(size_t Offset) { return Start + Offset < End; }
> +
> + error_code skipToOffset(size_t Offset) {
> + if (!offsetInBounds(Offset))
> + return profiledata_error::malformed;
> + Next = Start + Offset;
> + return profiledata_error::success;
> + }
> +
> + error_code skip32() { return skip(4); }
> + error_code skip64() { return skip(8); }
> + error_code read32(uint32_t &Result) { return read<uint32_t>(Result); }
> + error_code read64(uint64_t &Result) { return read<uint64_t>(Result); }
> +
> + error_code readChars(StringRef &Result, uint32_t Len) {
> + error_code EC;
Unused variable, I think.
> + const char *Prev = Next;
> + if (error_code EC = skip(Len))
> + return EC;
> + Result = StringRef(Prev, Len);
> + return profiledata_error::success;
> + }
> + error_code readString(StringRef &Result) {
> + uint32_t Len;
> + if (error_code EC = read32(Len))
> + return EC;
> + return readChars(Result, Len);
> + }
> +};
> +
> +error_code ProfileDataReader::readIndex() {
> + ProfileDataCursor Cursor(DataBuffer.get());
> + error_code EC;
Since you never use EC except to return it after it’s set, I think the
code is clearer without the local variable. I’d suggest deleting it
here, and then...
> + StringRef Magic;
> + uint32_t Version, IndexEnd, DataStart;
> +
> + if ((EC = Cursor.readChars(Magic, 4)))
> + return EC;
...declaring it for each if that uses it, e.g.:
if (error_code EC = Cursor.readChars(Magic, 4))
return EC;
> + if (StringRef(PROFILEDATA_MAGIC, 4) != Magic)
> + return profiledata_error::bad_magic;
> + if ((EC = Cursor.read32(Version)))
> + return EC;
> + if (Version != PROFILEDATA_VERSION)
> + return profiledata_error::unsupported_version;
> + if ((EC = Cursor.read32(IndexEnd)))
> + return EC;
> + if ((EC = Cursor.skip32()))
> + return EC;
> + if ((EC = Cursor.read64(MaxFunctionCount)))
> + return EC;
> +
A comment here would be nice. Something like:
// DataStart is 8B aligned, whereas IndexEnd is not.
(Or otherwise explain what this math is about.)
> + DataStart = IndexEnd + (sizeof(uint64_t) - IndexEnd % sizeof(uint64_t));
> + while (!Cursor.offsetReached(IndexEnd)) {
> + StringRef FuncName;
> + uint32_t Offset, TotalOffset;
> + if ((EC = Cursor.readString(FuncName)))
> + return EC;
> + if ((EC = Cursor.read32(Offset)))
> + return EC;
> + TotalOffset = DataStart + Offset;
> + if (!Cursor.offsetInBounds(TotalOffset))
> + return profiledata_error::truncated;
> + DataOffsets[FuncName] = TotalOffset;
> + }
> +
> + return profiledata_error::success;
> +}
> +
> +error_code ProfileDataReader::findFunctionCounts(StringRef FuncName,
> + uint64_t &FunctionHash,
> + ProfileDataCursor &Cursor) {
> + error_code EC;
Same comment here.
> + // Find the relevant section of the pgo-data file.
> + const auto &OffsetIter = DataOffsets.find(FuncName);
> + if (OffsetIter == DataOffsets.end())
> + return profiledata_error::unknown_function;
> + // Go there and read the function data
> + if ((EC = Cursor.skipToOffset(OffsetIter->getValue())))
> + return EC;
> + if ((EC = Cursor.read64(FunctionHash)))
> + return EC;
> + return profiledata_error::success;
> +}
> +
> +error_code ProfileDataReader::getFunctionCounts(StringRef FuncName,
> + uint64_t &FunctionHash,
> + std::vector<uint64_t> &Counts) {
> + ProfileDataCursor Cursor(DataBuffer.get());
> + error_code EC;
And here.
> + if ((EC = findFunctionCounts(FuncName, FunctionHash, Cursor)))
> + return EC;
> +
> + uint64_t NumCounters;
> + if ((EC = Cursor.read64(NumCounters)))
> + return EC;
> + for (uint64_t I = 0; I < NumCounters; ++I) {
> + uint64_t Count;
> + if ((EC = Cursor.read64(Count)))
> + return EC;
> + Counts.push_back(Count);
> + }
> +
> + return profiledata_error::success;
> +}
> +
> +error_code ProfileDataReader::getCallFrequency(StringRef FuncName,
> + uint64_t &FunctionHash,
> + double &Frequency) {
> + ProfileDataCursor Cursor(DataBuffer.get());
> + error_code EC;
And here.
> + if ((EC = findFunctionCounts(FuncName, FunctionHash, Cursor)))
> + return EC;
> + if ((EC = Cursor.skip64()))
> + return EC;
> + uint64_t CallCount;
> + if ((EC = Cursor.read64(CallCount)))
> + return EC;
> + Frequency = CallCount / (double)MaxFunctionCount;
> + return profiledata_error::success;
> +}
>
> Added: llvm/trunk/lib/Profile/ProfileDataWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Profile/ProfileDataWriter.cpp?rev=203703&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Profile/ProfileDataWriter.cpp (added)
> +++ llvm/trunk/lib/Profile/ProfileDataWriter.cpp Wed Mar 12 15:14:05 2014
> @@ -0,0 +1,71 @@
> +//=-- ProfileDataWriter.cpp - Instrumented profiling writer -----------------=//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains support for writing profiling data for clang's
> +// instrumentation based PGO and coverage.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Profile/ProfileDataWriter.h"
> +#include "llvm/Profile/ProfileData.h"
> +#include "llvm/Support/Endian.h"
> +
> +using namespace llvm;
> +
> +template <typename T>
> +struct LEBytes {
> + const T &Data;
> + LEBytes(const T &Data) : Data(Data) {}
> + void print(raw_ostream &OS) const {
> + for (uint32_t Shift = 0; Shift < sizeof(Data); ++Shift)
> + OS << (char)((Data >> (8 * Shift)) & 0xFF);
> + }
> +};
> +template <typename T>
> +static raw_ostream &operator<<(raw_ostream &OS, const LEBytes<T> &Bytes) {
> + Bytes.print(OS);
> + return OS;
> +}
> +
> +void ProfileDataWriter::addFunctionCounts(StringRef FuncName,
> + uint64_t FunctionHash,
> + uint64_t NumCounters,
> + const uint64_t *Counters) {
> + DataStart += 2 * sizeof(uint32_t) + FuncName.size();
> + FunctionOffsets[FuncName] = FunctionData.size() * sizeof(uint64_t);
> + FunctionData.push_back(FunctionHash);
> + FunctionData.push_back(NumCounters);
> + assert(NumCounters > 0 && "Function call counter missing!");
> + if (Counters[0] > MaxFunctionCount)
> + MaxFunctionCount = Counters[0];
> + for (uint64_t I = 0; I < NumCounters; ++I)
> + FunctionData.push_back(Counters[I]);
> +}
> +
> +void ProfileDataWriter::write(raw_ostream &OS) {
> + for (char C : PROFILEDATA_MAGIC)
> + OS << C;
> + OS << LEBytes<uint32_t>(PROFILEDATA_VERSION);
> + OS << LEBytes<uint32_t>(DataStart);
> + OS << LEBytes<uint32_t>(0);
> + OS << LEBytes<uint64_t>(MaxFunctionCount);
> +
> + for (const auto &I : FunctionOffsets) {
> + StringRef Name = I.getKey();
> + OS << LEBytes<uint32_t>(Name.size());
> + OS << Name;
> + OS << LEBytes<uint32_t>(I.getValue());
> + }
> +
I think a comment about alignment would be helpful here, too.
> + for (unsigned I = 0; I < sizeof(uint64_t) - DataStart % sizeof(uint64_t); ++I)
> + OS << '\0';
> +
> + for (uint64_t Value : FunctionData)
> + OS << LEBytes<uint64_t>(Value);
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list