Skip to content

Commit

Permalink
ProfileData: Introduce the InstrProfReader interface and a text reader
Browse files Browse the repository at this point in the history
This introduces the ProfileData library and updates llvm-profdata to
use this library for reading profiles. InstrProfReader is an abstract
base class that will be subclassed for both the raw instrprof data
from compiler-rt and the efficient instrprof format that will be used
for PGO.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204482 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
bogner committed Mar 21, 2014
1 parent 6c22b04 commit c0f3b72
Show file tree
Hide file tree
Showing 15 changed files with 400 additions and 79 deletions.
52 changes: 52 additions & 0 deletions include/llvm/ProfileData/InstrProf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//=-- InstrProf.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.
//
//===----------------------------------------------------------------------===//
//
// Instrumentation-based profiling data is generated by instrumented
// binaries through library functions in compiler-rt, and read by the clang
// frontend to feed PGO.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_PROFILEDATA_INSTRPROF_H__
#define LLVM_PROFILEDATA_INSTRPROF_H__

#include "llvm/Support/system_error.h"

namespace llvm {

const error_category &instrprof_category();

struct instrprof_error {
enum ErrorType {
success = 0,
eof,
bad_magic,
unsupported_version,
too_large,
truncated,
malformed,
unknown_function
};
ErrorType V;

instrprof_error(ErrorType V) : V(V) {}
operator ErrorType() const { return V; }
};

inline error_code make_error_code(instrprof_error E) {
return error_code(static_cast<int>(E), instrprof_category());
}

template <> struct is_error_code_enum<instrprof_error> : std::true_type {};
template <> struct is_error_code_enum<instrprof_error::ErrorType>
: std::true_type {};

} // end namespace llvm

#endif // LLVM_PROFILEDATA_INSTRPROF_H__
119 changes: 119 additions & 0 deletions include/llvm/ProfileData/InstrProfReader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//=-- InstrProfReader.h - Instrumented profiling readers ----------*- 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_PROFILEDATA_INSTRPROF_READER_H__
#define LLVM_PROFILEDATA_INSTRPROF_READER_H__

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"

#include <iterator>

namespace llvm {

class InstrProfReader;

/// Profiling information for a single function.
struct InstrProfRecord {
StringRef Name;
uint64_t Hash;
ArrayRef<uint64_t> Counts;
};

/// A file format agnostic iterator over profiling data.
class InstrProfIterator : public std::iterator<std::input_iterator_tag,
InstrProfRecord> {
InstrProfReader *Reader;
InstrProfRecord Record;

void Increment();
public:
InstrProfIterator() : Reader(nullptr) {}
InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }

InstrProfIterator &operator++() { Increment(); return *this; }
bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; }
bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; }
InstrProfRecord &operator*() { return Record; }
InstrProfRecord *operator->() { return &Record; }
};

/// Base class and interface for reading profiling data of any known instrprof
/// format. Provides an iterator over InstrProfRecords.
class InstrProfReader {
error_code LastError;
public:
InstrProfReader() : LastError(instrprof_error::success) {}
virtual ~InstrProfReader() {}

/// Read a single record.
virtual error_code readNextRecord(InstrProfRecord &Record) = 0;
/// Iterator over profile data.
InstrProfIterator begin() { return InstrProfIterator(this); }
InstrProfIterator end() { return InstrProfIterator(); }

/// Set the current error_code and return same.
error_code error(error_code EC) {
LastError = EC;
return EC;
}
/// Clear the current error code and return a successful one.
error_code success() { return error(instrprof_error::success); }

/// 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 && !isEOF(); }
/// Get the current error code.
error_code getError() { return LastError; }

/// Factory method to create an appropriately typed reader for the given
/// instrprof file.
static error_code create(std::string Path,
std::unique_ptr<InstrProfReader> &Result);
};

/// Reader for the simple text based instrprof format.
///
/// This format is a simple text format that's suitable for test data. Records
/// are separated by one or more blank lines, and record fields are separated by
/// new lines.
///
/// Each record consists of a function name, a function hash, a number of
/// counters, and then each counter value, in that order.
class TextInstrProfReader : public InstrProfReader {
private:
/// The profile data file contents.
std::unique_ptr<MemoryBuffer> DataBuffer;
/// Iterator over the profile data.
line_iterator Line;
/// The current set of counter values.
std::vector<uint64_t> Counts;

TextInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION;
TextInstrProfReader &operator=(const TextInstrProfReader &)
LLVM_DELETED_FUNCTION;
public:
TextInstrProfReader(std::unique_ptr<MemoryBuffer> &DataBuffer_)
: DataBuffer(DataBuffer_.release()), Line(*DataBuffer, '#') {}

/// Read a single record.
error_code readNextRecord(InstrProfRecord &Record) override;
};

} // end namespace llvm

#endif // LLVM_PROFILEDATA_INSTRPROF_READER_H__
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ add_subdirectory(ExecutionEngine)
add_subdirectory(Target)
add_subdirectory(AsmParser)
add_subdirectory(LineEditor)
add_subdirectory(ProfileData)
2 changes: 1 addition & 1 deletion lib/LLVMBuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 ProfileData Support TableGen Target Transforms

[component_0]
type = Group
Expand Down
2 changes: 1 addition & 1 deletion lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 ProfileData

include $(LEVEL)/Makefile.common
7 changes: 7 additions & 0 deletions lib/ProfileData/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
add_llvm_library(LLVMProfileData
InstrProf.cpp
InstrProfReader.cpp

LINK_LIBS
LLVMSupport
)
56 changes: 56 additions & 0 deletions lib/ProfileData/InstrProf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//=-- InstrProf.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/ProfileData/InstrProf.h"
#include "llvm/Support/ErrorHandling.h"

using namespace llvm;

namespace {
class InstrProfErrorCategoryType : public error_category {
const char *name() const override { return "llvm.instrprof"; }
std::string message(int IE) const override {
instrprof_error::ErrorType E = static_cast<instrprof_error::ErrorType>(IE);
switch (E) {
case instrprof_error::success:
return "Success";
case instrprof_error::eof:
return "End of File";
case instrprof_error::bad_magic:
return "Invalid file format (bad magic)";
case instrprof_error::unsupported_version:
return "Unsupported format version";
case instrprof_error::too_large:
return "Too much profile data";
case instrprof_error::truncated:
return "Truncated profile data";
case instrprof_error::malformed:
return "Malformed profile data";
case instrprof_error::unknown_function:
return "No profile data available for function";
}
llvm_unreachable("A value of instrprof_error has no message.");
}
error_condition default_error_condition(int EV) const {
if (EV == instrprof_error::success)
return errc::success;
return errc::invalid_argument;
}
};
}

const error_category &llvm::instrprof_category() {
static InstrProfErrorCategoryType C;
return C;
}
84 changes: 84 additions & 0 deletions lib/ProfileData/InstrProfReader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//=-- InstrProfReader.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/ProfileData/InstrProfReader.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Endian.h"

#include <cassert>

using namespace llvm;

error_code InstrProfReader::create(std::string Path,
std::unique_ptr<InstrProfReader> &Result) {
std::unique_ptr<MemoryBuffer> Buffer;
if (error_code EC = MemoryBuffer::getFileOrSTDIN(Path, Buffer))
return EC;

// Sanity check the file.
if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max())
return instrprof_error::too_large;

// FIXME: This needs to determine which format the file is and construct the
// correct subclass.
Result.reset(new TextInstrProfReader(Buffer));

return instrprof_error::success;
}

void InstrProfIterator::Increment() {
if (Reader->readNextRecord(Record))
*this = InstrProfIterator();
}

error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) {
// Skip empty lines.
while (!Line.is_at_end() && Line->empty())
++Line;
// If we hit EOF while looking for a name, we're done.
if (Line.is_at_end())
return error(instrprof_error::eof);

// Read the function name.
Record.Name = *Line++;

// Read the function hash.
if (Line.is_at_end())
return error(instrprof_error::truncated);
if ((Line++)->getAsInteger(10, Record.Hash))
return error(instrprof_error::malformed);

// Read the number of counters.
uint64_t NumCounters;
if (Line.is_at_end())
return error(instrprof_error::truncated);
if ((Line++)->getAsInteger(10, NumCounters))
return error(instrprof_error::malformed);

// Read each counter and fill our internal storage with the values.
Counts.clear();
Counts.reserve(NumCounters);
for (uint64_t I = 0; I < NumCounters; ++I) {
if (Line.is_at_end())
return error(instrprof_error::truncated);
uint64_t Count;
if ((Line++)->getAsInteger(10, Count))
return error(instrprof_error::malformed);
Counts.push_back(Count);
}
// Give the record a reference to our internal counter storage.
Record.Counts = Counts;

return success();
}
22 changes: 22 additions & 0 deletions lib/ProfileData/LLVMBuild.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
;===- ./lib/ProfileData/LLVMBuild.txt --------------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[component_0]
type = Library
name = ProfileData
parent = Libraries
required_libraries = Support
14 changes: 14 additions & 0 deletions lib/ProfileData/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
##===- lib/ProfileData/Makefile ----------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##

LEVEL = ../..
LIBRARYNAME = LLVMProfileData
BUILD_ARCHIVE := 1

include $(LEVEL)/Makefile.common
Loading

0 comments on commit c0f3b72

Please sign in to comment.