summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Profile/ProfileData.h56
-rw-r--r--include/llvm/Profile/ProfileDataReader.h91
-rw-r--r--include/llvm/Profile/ProfileDataWriter.h47
-rw-r--r--include/llvm/Support/LineIterator.h1
-rw-r--r--lib/CMakeLists.txt1
-rw-r--r--lib/LLVMBuild.txt2
-rw-r--r--lib/Makefile2
-rw-r--r--lib/Profile/CMakeLists.txt5
-rw-r--r--lib/Profile/LLVMBuild.txt21
-rw-r--r--lib/Profile/Makefile14
-rw-r--r--lib/Profile/ProfileData.cpp54
-rw-r--r--lib/Profile/ProfileDataReader.cpp167
-rw-r--r--lib/Profile/ProfileDataWriter.cpp71
-rw-r--r--test/tools/llvm-profdata/Inputs/bad-function-count.profdata2
-rw-r--r--test/tools/llvm-profdata/Inputs/bad-hash.profdata.input4
-rw-r--r--test/tools/llvm-profdata/Inputs/bar3-1.profdata4
-rw-r--r--test/tools/llvm-profdata/Inputs/bar3-1.profdata.input6
-rw-r--r--test/tools/llvm-profdata/Inputs/empty.profdata (renamed from test/tools/llvm-profdata/Inputs/empty.profdata.input)0
-rw-r--r--test/tools/llvm-profdata/Inputs/extra-word.profdata (renamed from test/tools/llvm-profdata/Inputs/extra-word.profdata.input)0
-rw-r--r--test/tools/llvm-profdata/Inputs/foo3-1.profdata4
-rw-r--r--test/tools/llvm-profdata/Inputs/foo3-1.profdata.input6
-rw-r--r--test/tools/llvm-profdata/Inputs/foo3-2.profdata4
-rw-r--r--test/tools/llvm-profdata/Inputs/foo3-2.profdata.input6
-rw-r--r--test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata9
-rw-r--r--test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata.input13
-rw-r--r--test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata (renamed from test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata.input)8
-rw-r--r--test/tools/llvm-profdata/Inputs/foo4-1.profdata (renamed from test/tools/llvm-profdata/Inputs/foo4-1.profdata.input)4
-rw-r--r--test/tools/llvm-profdata/Inputs/foo4-2.profdata (renamed from test/tools/llvm-profdata/Inputs/foo4-2.profdata.input)4
-rw-r--r--test/tools/llvm-profdata/Inputs/invalid-count-later.profdata2
-rw-r--r--test/tools/llvm-profdata/Inputs/invalid-count-later.profdata.input4
-rw-r--r--test/tools/llvm-profdata/Inputs/overflow.profdata (renamed from test/tools/llvm-profdata/Inputs/overflow.profdata.input)4
-rw-r--r--test/tools/llvm-profdata/Inputs/three-words-long.profdata (renamed from test/tools/llvm-profdata/Inputs/three-words-long.profdata.input)0
-rw-r--r--test/tools/llvm-profdata/Inputs/wrong-count.profdata.input4
-rw-r--r--test/tools/llvm-profdata/errors.test22
-rw-r--r--test/tools/llvm-profdata/generate.test38
-rw-r--r--test/tools/llvm-profdata/merge-errors.test21
-rw-r--r--test/tools/llvm-profdata/simple-merges.test33
-rw-r--r--test/tools/llvm-profdata/simple.test25
-rw-r--r--tools/llvm-profdata/CMakeLists.txt2
-rw-r--r--tools/llvm-profdata/LLVMBuild.txt2
-rw-r--r--tools/llvm-profdata/Makefile2
-rw-r--r--tools/llvm-profdata/llvm-profdata.cpp380
42 files changed, 199 insertions, 946 deletions
diff --git a/include/llvm/Profile/ProfileData.h b/include/llvm/Profile/ProfileData.h
deleted file mode 100644
index 72cc840e80..0000000000
--- a/include/llvm/Profile/ProfileData.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//=-- 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 uint32_t PROFILEDATA_HEADER_SIZE = 24;
-
-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__
diff --git a/include/llvm/Profile/ProfileDataReader.h b/include/llvm/Profile/ProfileDataReader.h
deleted file mode 100644
index 0f771f23fd..0000000000
--- a/include/llvm/Profile/ProfileDataReader.h
+++ /dev/null
@@ -1,91 +0,0 @@
-//=-- 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; }
- };
-
- /// 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);
- /// Return the maximum of all known function counts.
- uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
-
- static error_code create(std::string Path,
- std::unique_ptr<ProfileDataReader> &Result);
-};
-
-} // end namespace llvm
-
-#endif // LLVM_PROFILE_PROFILEDATA_READER_H__
diff --git a/include/llvm/Profile/ProfileDataWriter.h b/include/llvm/Profile/ProfileDataWriter.h
deleted file mode 100644
index 3498d2eca3..0000000000
--- a/include/llvm/Profile/ProfileDataWriter.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//=-- 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/Profile/ProfileData.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <vector>
-
-namespace llvm {
-
-/// 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(PROFILEDATA_HEADER_SIZE), MaxFunctionCount(0) {}
-
- void addFunctionCounts(StringRef FuncName, uint64_t FunctionHash,
- uint64_t NumCounters, const uint64_t *Counters);
- void write(raw_ostream &OS);
-};
-
-} // end namespace llvm
-
-#endif // LLVM_PROFILE_PROFILEDATA_WRITER_H__
diff --git a/include/llvm/Support/LineIterator.h b/include/llvm/Support/LineIterator.h
index 92a9cc5c57..861c19881f 100644
--- a/include/llvm/Support/LineIterator.h
+++ b/include/llvm/Support/LineIterator.h
@@ -56,7 +56,6 @@ public:
/// \brief Get the current line as a \c StringRef.
StringRef operator*() const { return CurrentLine; }
- const StringRef *operator->() const { return &CurrentLine; }
friend bool operator==(const line_iterator &LHS, const line_iterator &RHS) {
return LHS.Buffer == RHS.Buffer &&
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index a4496f9e58..9367f55313 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -16,4 +16,3 @@ add_subdirectory(ExecutionEngine)
add_subdirectory(Target)
add_subdirectory(AsmParser)
add_subdirectory(LineEditor)
-add_subdirectory(Profile)
diff --git a/lib/LLVMBuild.txt b/lib/LLVMBuild.txt
index c75ca4e903..a0984d410c 100644
--- a/lib/LLVMBuild.txt
+++ b/lib/LLVMBuild.txt
@@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine LineEditor Linker IR IRReader LTO MC Object Option Profile Support TableGen Target Transforms
+subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine LineEditor Linker IR IRReader LTO MC Object Option Support TableGen Target Transforms
[component_0]
type = Group
diff --git a/lib/Makefile b/lib/Makefile
index 1f55dd7f96..a97f71aded 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -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 Profile
+ IRReader LineEditor
include $(LEVEL)/Makefile.common
diff --git a/lib/Profile/CMakeLists.txt b/lib/Profile/CMakeLists.txt
deleted file mode 100644
index e0a4f0a1ba..0000000000
--- a/lib/Profile/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-add_llvm_library(LLVMProfile
- ProfileData.cpp
- ProfileDataReader.cpp
- ProfileDataWriter.cpp
- )
diff --git a/lib/Profile/LLVMBuild.txt b/lib/Profile/LLVMBuild.txt
deleted file mode 100644
index ae1fdd61c7..0000000000
--- a/lib/Profile/LLVMBuild.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-;===- ./lib/Profile/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 = Profile
-parent = Libraries
diff --git a/lib/Profile/Makefile b/lib/Profile/Makefile
deleted file mode 100644
index fb80a12097..0000000000
--- a/lib/Profile/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- lib/Profile/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 = LLVMProfile
-BUILD_ARCHIVE := 1
-
-include $(LEVEL)/Makefile.common
diff --git a/lib/Profile/ProfileData.cpp b/lib/Profile/ProfileData.cpp
deleted file mode 100644
index 65dca9db2b..0000000000
--- a/lib/Profile/ProfileData.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//=-- 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;
-}
diff --git a/lib/Profile/ProfileDataReader.cpp b/lib/Profile/ProfileDataReader.cpp
deleted file mode 100644
index e679d9eec0..0000000000
--- a/lib/Profile/ProfileDataReader.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-//=-- 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;
- 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;
- StringRef Magic;
- uint32_t Version, IndexEnd, DataStart;
-
- if ((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;
-
- 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;
- // 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;
- 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;
-}
diff --git a/lib/Profile/ProfileDataWriter.cpp b/lib/Profile/ProfileDataWriter.cpp
deleted file mode 100644
index b5993dd45e..0000000000
--- a/lib/Profile/ProfileDataWriter.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//=-- 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());
- }
-
- 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);
-}
diff --git a/test/tools/llvm-profdata/Inputs/bad-function-count.profdata b/test/tools/llvm-profdata/Inputs/bad-function-count.profdata
new file mode 100644
index 0000000000..7d247626e5
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/bad-function-count.profdata
@@ -0,0 +1,2 @@
+function_count_not 1count
+1
diff --git a/test/tools/llvm-profdata/Inputs/bad-hash.profdata.input b/test/tools/llvm-profdata/Inputs/bad-hash.profdata.input
deleted file mode 100644
index faa6f40152..0000000000
--- a/test/tools/llvm-profdata/Inputs/bad-hash.profdata.input
+++ /dev/null
@@ -1,4 +0,0 @@
-function_count_not
-badhash
-1
-1
diff --git a/test/tools/llvm-profdata/Inputs/bar3-1.profdata b/test/tools/llvm-profdata/Inputs/bar3-1.profdata
new file mode 100644
index 0000000000..cb8b409891
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/bar3-1.profdata
@@ -0,0 +1,4 @@
+bar 3
+1
+2
+3
diff --git a/test/tools/llvm-profdata/Inputs/bar3-1.profdata.input b/test/tools/llvm-profdata/Inputs/bar3-1.profdata.input
deleted file mode 100644
index 5486e9d84d..0000000000
--- a/test/tools/llvm-profdata/Inputs/bar3-1.profdata.input
+++ /dev/null
@@ -1,6 +0,0 @@
-bar
-3
-3
-1
-2
-3
diff --git a/test/tools/llvm-profdata/Inputs/empty.profdata.input b/test/tools/llvm-profdata/Inputs/empty.profdata
index e69de29bb2..e69de29bb2 100644
--- a/test/tools/llvm-profdata/Inputs/empty.profdata.input
+++ b/test/tools/llvm-profdata/Inputs/empty.profdata
diff --git a/test/tools/llvm-profdata/Inputs/extra-word.profdata.input b/test/tools/llvm-profdata/Inputs/extra-word.profdata
index 67a662909c..67a662909c 100644
--- a/test/tools/llvm-profdata/Inputs/extra-word.profdata.input
+++ b/test/tools/llvm-profdata/Inputs/extra-word.profdata
diff --git a/test/tools/llvm-profdata/Inputs/foo3-1.profdata b/test/tools/llvm-profdata/Inputs/foo3-1.profdata
new file mode 100644
index 0000000000..d6f9f648b7
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/foo3-1.profdata
@@ -0,0 +1,4 @@
+foo 3
+1
+2
+3
diff --git a/test/tools/llvm-profdata/Inputs/foo3-1.profdata.input b/test/tools/llvm-profdata/Inputs/foo3-1.profdata.input
deleted file mode 100644
index 14a6200435..0000000000
--- a/test/tools/llvm-profdata/Inputs/foo3-1.profdata.input
+++ /dev/null
@@ -1,6 +0,0 @@
-foo
-3
-3
-1
-2
-3
diff --git a/test/tools/llvm-profdata/Inputs/foo3-2.profdata b/test/tools/llvm-profdata/Inputs/foo3-2.profdata
new file mode 100644
index 0000000000..94fd034391
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/foo3-2.profdata
@@ -0,0 +1,4 @@
+foo 3
+7
+5
+3
diff --git a/test/tools/llvm-profdata/Inputs/foo3-2.profdata.input b/test/tools/llvm-profdata/Inputs/foo3-2.profdata.input
deleted file mode 100644
index 801846e440..0000000000
--- a/test/tools/llvm-profdata/Inputs/foo3-2.profdata.input
+++ /dev/null
@@ -1,6 +0,0 @@
-foo
-3
-3
-7
-5
-3
diff --git a/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata b/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata
new file mode 100644
index 0000000000..85b702d497
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata
@@ -0,0 +1,9 @@
+foo 3
+2
+3
+5
+
+bar 3
+7
+11
+13
diff --git a/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata.input b/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata.input
deleted file mode 100644
index 12157b9f9a..0000000000
--- a/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata.input
+++ /dev/null
@@ -1,13 +0,0 @@
-foo
-3
-3
-2
-3
-5
-
-bar
-3
-3
-7
-11
-13
diff --git a/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata.input b/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata
index f1f10bd6f3..d652781a35 100644
--- a/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata.input
+++ b/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata
@@ -1,13 +1,9 @@
-foo
-3
-3
+foo 3
17
19
23
-bar
-3
-3
+bar 3
29
31
37
diff --git a/test/tools/llvm-profdata/Inputs/foo4-1.profdata.input b/test/tools/llvm-profdata/Inputs/foo4-1.profdata
index 31d2a2ce75..4d694080bf 100644
--- a/test/tools/llvm-profdata/Inputs/foo4-1.profdata.input
+++ b/test/tools/llvm-profdata/Inputs/foo4-1.profdata
@@ -1,6 +1,4 @@
-foo
-4
-4
+foo 4
11
22
33
diff --git a/test/tools/llvm-profdata/Inputs/foo4-2.profdata.input b/test/tools/llvm-profdata/Inputs/foo4-2.profdata
index 01d8309b5c..8d91d8bbef 100644
--- a/test/tools/llvm-profdata/Inputs/foo4-2.profdata.input
+++ b/test/tools/llvm-profdata/Inputs/foo4-2.profdata
@@ -1,6 +1,4 @@
-foo
-4
-4
+foo 4
7
6
5
diff --git a/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata b/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata
new file mode 100644
index 0000000000..5575df3fda
--- /dev/null
+++ b/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata
@@ -0,0 +1,2 @@
+invalid_count 1
+1later
diff --git a/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata.input b/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata.input
deleted file mode 100644
index 2b61c55a67..0000000000
--- a/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata.input
+++ /dev/null
@@ -1,4 +0,0 @@
-invalid_count
-1
-1
-1later
diff --git a/test/tools/llvm-profdata/Inputs/overflow.profdata.input b/test/tools/llvm-profdata/Inputs/overflow.profdata
index c9a9d697ec..bfb9a52d2e 100644
--- a/test/tools/llvm-profdata/Inputs/overflow.profdata.input
+++ b/test/tools/llvm-profdata/Inputs/overflow.profdata
@@ -1,4 +1,2 @@
-overflow
-1
-1
+overflow 1
9223372036854775808
diff --git a/test/tools/llvm-profdata/Inputs/three-words-long.profdata.input b/test/tools/llvm-profdata/Inputs/three-words-long.profdata
index a4d45fb3bf..a4d45fb3bf 100644
--- a/test/tools/llvm-profdata/Inputs/three-words-long.profdata.input
+++ b/test/tools/llvm-profdata/Inputs/three-words-long.profdata
diff --git a/test/tools/llvm-profdata/Inputs/wrong-count.profdata.input b/test/tools/llvm-profdata/Inputs/wrong-count.profdata.input
deleted file mode 100644
index 129db626d1..0000000000
--- a/test/tools/llvm-profdata/Inputs/wrong-count.profdata.input
+++ /dev/null
@@ -1,4 +0,0 @@
-wrong_count
-3
-3
-1
diff --git a/test/tools/llvm-profdata/errors.test b/test/tools/llvm-profdata/errors.test
new file mode 100644
index 0000000000..6335ea95f9
--- /dev/null
+++ b/test/tools/llvm-profdata/errors.test
@@ -0,0 +1,22 @@
+RUN: not llvm-profdata %p/Inputs/empty.profdata %p/Inputs/foo3-1.profdata 2>&1 | FileCheck %s --check-prefix=LENGTH
+RUN: not llvm-profdata %p/Inputs/foo3-1.profdata %p/Inputs/foo3bar3-1.profdata 2>&1 | FileCheck %s --check-prefix=LENGTH
+RUN: not llvm-profdata %p/Inputs/foo4-1.profdata %p/Inputs/empty.profdata 2>&1 | FileCheck %s --check-prefix=LENGTH
+LENGTH: error: {{.*}}: truncated file
+
+RUN: not llvm-profdata %p/Inputs/foo3-1.profdata %p/Inputs/bar3-1.profdata 2>&1 | FileCheck %s --check-prefix=NAME
+NAME: error: {{.*}}: function name mismatch
+
+RUN: not llvm-profdata %p/Inputs/foo3-1.profdata %p/Inputs/foo4-1.profdata 2>&1 | FileCheck %s --check-prefix=COUNT
+COUNT: error: {{.*}}: function count mismatch
+
+RUN: not llvm-profdata %p/Inputs/overflow.profdata %p/Inputs/overflow.profdata 2>&1 | FileCheck %s --check-prefix=OVERFLOW
+OVERFLOW: error: {{.*}}: counter overflow
+
+RUN: not llvm-profdata %p/Inputs/invalid-count-later.profdata %p/Inputs/invalid-count-later.profdata 2>&1 | FileCheck %s --check-prefix=INVALID-COUNT-LATER
+INVALID-COUNT-LATER: error: {{.*}}: invalid counter
+
+RUN: not llvm-profdata %p/Inputs/bad-function-count.profdata %p/Inputs/bad-function-count.profdata 2>&1 | FileCheck %s --check-prefix=BAD-FUNCTION-COUNT
+BAD-FUNCTION-COUNT: error: {{.*}}: bad function count
+
+RUN: not llvm-profdata %p/Inputs/three-words-long.profdata %p/Inputs/three-words-long.profdata 2>&1 | FileCheck %s --check-prefix=INVALID-DATA
+INVALID-DATA: error: {{.*}}: invalid data
diff --git a/test/tools/llvm-profdata/generate.test b/test/tools/llvm-profdata/generate.test
deleted file mode 100644
index 71e8b50fca..0000000000
--- a/test/tools/llvm-profdata/generate.test
+++ /dev/null
@@ -1,38 +0,0 @@
-RUN: llvm-profdata generate %p/Inputs/empty.profdata.input | llvm-profdata show -all-functions -counts - | FileCheck %s --check-prefix=EMPTY
-
-EMPTY: Total functions: 0
-EMPTY: Maximum function count: 0
-EMPTY: Maximum internal block count: 0
-
-RUN: llvm-profdata generate %p/Inputs/foo3-1.profdata.input | llvm-profdata show -all-functions -counts - | FileCheck %s --check-prefix=FOO3
-
-FOO3: foo:
-FOO3: Counters: 3
-FOO3: Function count: 1
-FOO3: Block counts: [2, 3]
-FOO3: Total functions: 1
-FOO3: Maximum function count: 1
-FOO3: Maximum internal block count: 3
-
-RUN: llvm-profdata generate %p/Inputs/foo3bar3-1.profdata.input | llvm-profdata show -all-functions -counts - | FileCheck %s --check-prefix=FOO3BAR3
-
-FOO3BAR3: foo:
-FOO3BAR3: Counters: 3
-FOO3BAR3: Function count: 2
-FOO3BAR3: Block counts: [3, 5]
-FOO3BAR3: bar:
-FOO3BAR3: Counters: 3
-FOO3BAR3: Function count: 7
-FOO3BAR3: Block counts: [11, 13]
-FOO3BAR3: Total functions: 2
-FOO3BAR3: Maximum function count: 7
-FOO3BAR3: Maximum internal block count: 13
-
-RUN: not llvm-profdata generate %p/Inputs/invalid-count-later.profdata.input -o /dev/null 2>&1 | FileCheck %s --check-prefix=INVALID-COUNT-LATER
-INVALID-COUNT-LATER: error: {{.*}}: Failed to read counter
-
-RUN: not llvm-profdata generate %p/Inputs/bad-hash.profdata.input -o /dev/null 2>&1 | FileCheck %s --check-prefix=BAD-HASH
-BAD-HASH: error: {{.*}}: Failed to read hash
-
-RUN: not llvm-profdata generate %p/Inputs/wrong-count.profdata.input -o /dev/null 2>&1 | FileCheck %s --check-prefix=BAD-FUNCTION-COUNT
-BAD-FUNCTION-COUNT: error: {{.*}}: Truncated file
diff --git a/test/tools/llvm-profdata/merge-errors.test b/test/tools/llvm-profdata/merge-errors.test
deleted file mode 100644
index 1ab08be9f1..0000000000
--- a/test/tools/llvm-profdata/merge-errors.test
+++ /dev/null
@@ -1,21 +0,0 @@
-RUN: llvm-profdata generate %p/Inputs/empty.profdata.input > %t-empty.profdata
-RUN: llvm-profdata generate %p/Inputs/foo3-1.profdata.input > %t-foo3-1.profdata
-RUN: llvm-profdata generate %p/Inputs/bar3-1.profdata.input > %t-bar3-1.profdata
-RUN: llvm-profdata generate %p/Inputs/foo3bar3-1.profdata.input > %t-foo3bar3-1.profdata
-RUN: llvm-profdata generate %p/Inputs/foo4-1.profdata.input > %t-foo4-1.profdata
-
-RUN: not llvm-profdata merge %t-empty.profdata %t-foo3-1.profdata -o /dev/null 2>&1 | FileCheck %s --check-prefix=LENGTH
-RUN: not llvm-profdata merge %t-foo3-1.profdata %t-foo3bar3-1.profdata -o /dev/null 2>&1 | FileCheck %s --check-prefix=LENGTH
-RUN: not llvm-profdata merge %t-foo4-1.profdata %t-empty.profdata -o /dev/null 2>&1 | FileCheck %s --check-prefix=LENGTH
-LENGTH: error: {{.*}}: Truncated file
-
-RUN: not llvm-profdata merge %t-foo3-1.profdata %t-bar3-1.profdata -o /dev/null 2>&1 | FileCheck %s --check-prefix=NAME
-NAME: error: {{.*}}: Function name mismatch
-
-RUN: not llvm-profdata merge %t-foo3-1.profdata %t-foo4-1.profdata -o /dev/null 2>&1 | FileCheck %s --check-prefix=COUNT
-COUNT: error: {{.*}}: Function count mismatch
-
-RUN: llvm-profdata generate %p/Inputs/overflow.profdata.input > %t-overflow.profdata
-
-RUN: not llvm-profdata merge %t-overflow.profdata %t-overflow.profdata -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW
-OVERFLOW: error: {{.*}}: Counter overflow
diff --git a/test/tools/llvm-profdata/simple-merges.test b/test/tools/llvm-profdata/simple-merges.test
deleted file mode 100644
index 401ae6b58e..0000000000
--- a/test/tools/llvm-profdata/simple-merges.test
+++ /dev/null
@@ -1,33 +0,0 @@
-RUN: llvm-profdata generate %p/Inputs/foo3-1.profdata.input > %t-foo3-1.profdata
-RUN: llvm-profdata generate %p/Inputs/foo3-2.profdata.input > %t-foo3-2.profdata
-
-RUN: llvm-profdata merge %t-foo3-1.profdata %t-foo3-2.profdata 2>&1 | llvm-profdata show -all-functions -counts - | FileCheck %s --check-prefix=FOO3
-RUN: llvm-profdata merge %t-foo3-2.profdata %t-foo3-1.profdata 2>&1 | llvm-profdata show -all-functions -counts - | FileCheck %s --check-prefix=FOO3
-FOO3: foo:
-FOO3: Counters: 3
-FOO3: Function count: 8
-FOO3: Block counts: [7, 6]
-
-RUN: llvm-profdata generate %p/Inputs/foo4-1.profdata.input > %t-foo4-1.profdata
-RUN: llvm-profdata generate %p/Inputs/foo4-2.profdata.input > %t-foo4-2.profdata
-
-RUN: llvm-profdata merge %t-foo4-1.profdata %t-foo4-2.profdata 2>&1 | llvm-profdata show -all-functions -counts - | FileCheck %s --check-prefix=FOO4
-RUN: llvm-profdata merge %t-foo4-2.profdata %t-foo4-1.profdata 2>&1 | llvm-profdata show -all-functions -counts - | FileCheck %s --check-prefix=FOO4
-FOO4: foo:
-FOO4: Counters: 4
-FOO4: Function count: 18
-FOO4: Block counts: [28, 38, 48]
-
-RUN: llvm-profdata generate %p/Inputs/foo3bar3-1.profdata.input > %t-foo3bar3-1.profdata
-RUN: llvm-profdata generate %p/Inputs/foo3bar3-2.profdata.input > %t-foo3bar3-2.profdata
-
-RUN: llvm-profdata merge %t-foo3bar3-1.profdata %t-foo3bar3-2.profdata 2>&1 | llvm-profdata show -all-functions -counts - | FileCheck %s --check-prefix=FOO3BAR3
-RUN: llvm-profdata merge %t-foo3bar3-2.profdata %t-foo3bar3-1.profdata 2>&1 | llvm-profdata show -all-functions -counts - | FileCheck %s --check-prefix=FOO3BAR3
-FOO3BAR3: foo:
-FOO3BAR3: Counters: 3
-FOO3BAR3: Function count: 19
-FOO3BAR3: Block counts: [22, 28]
-FOO3BAR3: bar:
-FOO3BAR3: Counters: 3
-FOO3BAR3: Function count: 36
-FOO3BAR3: Block counts: [42, 50]
diff --git a/test/tools/llvm-profdata/simple.test b/test/tools/llvm-profdata/simple.test
new file mode 100644
index 0000000000..87073fad9c
--- /dev/null
+++ b/test/tools/llvm-profdata/simple.test
@@ -0,0 +1,25 @@
+RUN: llvm-profdata %p/Inputs/foo3-1.profdata %p/Inputs/foo3-2.profdata 2>&1 | FileCheck %s --check-prefix=FOO3
+RUN: llvm-profdata %p/Inputs/foo3-2.profdata %p/Inputs/foo3-1.profdata 2>&1 | FileCheck %s --check-prefix=FOO3
+FOO3: {{^foo 3$}}
+FOO3-NEXT: {{^8$}}
+FOO3-NEXT: {{^7$}}
+FOO3-NEXT: {{^6$}}
+
+RUN: llvm-profdata %p/Inputs/foo4-1.profdata %p/Inputs/foo4-2.profdata 2>&1 | FileCheck %s --check-prefix=FOO4
+RUN: llvm-profdata %p/Inputs/foo4-2.profdata %p/Inputs/foo4-1.profdata 2>&1 | FileCheck %s --check-prefix=FOO4
+FOO4: {{^foo 4$}}
+FOO4-NEXT: {{^18$}}
+FOO4-NEXT: {{^28$}}
+FOO4-NEXT: {{^38$}}
+FOO4-NEXT: {{^48$}}
+
+RUN: llvm-profdata %p/Inputs/foo3bar3-1.profdata %p/Inputs/foo3bar3-2.profdata 2>&1 | FileCheck %s --check-prefix=FOO3BAR3
+RUN: llvm-profdata %p/Inputs/foo3bar3-2.profdata %p/Inputs/foo3bar3-1.profdata 2>&1 | FileCheck %s --check-prefix=FOO3BAR3
+FOO3BAR3: {{^foo 3$}}
+FOO3BAR3-NEXT: {{^19$}}
+FOO3BAR3-NEXT: {{^22$}}
+FOO3BAR3-NEXT: {{^28$}}
+FOO3BAR3: {{^bar 3$}}
+FOO3BAR3-NEXT: {{^36$}}
+FOO3BAR3-NEXT: {{^42$}}
+FOO3BAR3-NEXT: {{^50$}}
diff --git a/tools/llvm-profdata/CMakeLists.txt b/tools/llvm-profdata/CMakeLists.txt
index f0667f16f9..4b1357d87e 100644
--- a/tools/llvm-profdata/CMakeLists.txt
+++ b/tools/llvm-profdata/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS core profile support)
+set(LLVM_LINK_COMPONENTS core support )
add_llvm_tool(llvm-profdata
llvm-profdata.cpp
diff --git a/tools/llvm-profdata/LLVMBuild.txt b/tools/llvm-profdata/LLVMBuild.txt
index f6492da26c..fc9e469199 100644
--- a/tools/llvm-profdata/LLVMBuild.txt
+++ b/tools/llvm-profdata/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Tool
name = llvm-profdata
parent = Tools
-required_libraries = Profile Support
+required_libraries = Support
diff --git a/tools/llvm-profdata/Makefile b/tools/llvm-profdata/Makefile
index 11276e25b9..9d7ad527b1 100644
--- a/tools/llvm-profdata/Makefile
+++ b/tools/llvm-profdata/Makefile
@@ -9,7 +9,7 @@
LEVEL := ../..
TOOLNAME := llvm-profdata
-LINK_COMPONENTS := core profile support
+LINK_COMPONENTS := core support
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp
index 989c4281f8..b338efd27e 100644
--- a/tools/llvm-profdata/llvm-profdata.cpp
+++ b/tools/llvm-profdata/llvm-profdata.cpp
@@ -12,10 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringRef.h"
-#include "llvm/Profile/ProfileDataReader.h"
-#include "llvm/Profile/ProfileDataWriter.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/LineIterator.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -24,211 +21,91 @@
using namespace llvm;
-static void exitWithError(const std::string &Message,
- const std::string &Filename, int64_t Line = -1) {
- errs() << "error: " << Filename;
- if (Line >= 0)
- errs() << ":" << Line;
- errs() << ": " << Message << "\n";
- ::exit(1);
-}
-
-int merge_main(int argc, const char *argv[]) {
- cl::opt<std::string> Filename1(cl::Positional, cl::Required,
- cl::desc("file1"));
- cl::opt<std::string> Filename2(cl::Positional, cl::Required,
- cl::desc("file2"));
-
- cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
- cl::init("-"),
- cl::desc("Output file"));
- cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
- cl::aliasopt(OutputFilename));
-
- cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
-
- std::unique_ptr<ProfileDataReader> Reader1, Reader2;
- if (error_code EC = ProfileDataReader::create(Filename1, Reader1))
- exitWithError(EC.message(), Filename1);
- if (error_code EC = ProfileDataReader::create(Filename2, Reader2))
- exitWithError(EC.message(), Filename2);
-
- if (OutputFilename.empty())
- OutputFilename = "-";
-
- std::string ErrorInfo;
- raw_fd_ostream Output(OutputFilename.data(), ErrorInfo, sys::fs::F_Text);
- if (!ErrorInfo.empty())
- exitWithError(ErrorInfo, OutputFilename);
-
- if (Output.is_displayed())
- exitWithError("Refusing to write a binary file to stdout", OutputFilename);
-
- StringRef Name1, Name2;
- std::vector<uint64_t> Counts1, Counts2, NewCounts;
- uint64_t Hash1, Hash2;
- ProfileDataWriter Writer;
- ProfileDataReader::name_iterator I1 = Reader1->begin(),
- E1 = Reader1->end(),
- I2 = Reader2->begin(),
- E2 = Reader2->end();
- for (; I1 != E1 && I2 != E2; ++I1, ++I2) {
- Name1 = *I1;
- Name2 = *I2;
- if (Name1 != Name2)
- exitWithError("Function name mismatch", Filename2); // ???
-
- if (error_code EC = Reader1->getFunctionCounts(Name1, Hash1, Counts1))
- exitWithError(EC.message(), Filename1);
- if (error_code EC = Reader2->getFunctionCounts(Name2, Hash2, Counts2))
- exitWithError(EC.message(), Filename2);
-
- if (Counts1.size() != Counts2.size())
- exitWithError("Function count mismatch", Filename2); // ???
- if (Hash1 != Hash2)
- exitWithError("Function hash mismatch", Filename2); // ???
-
- for (size_t II = 0, EE = Counts1.size(); II < EE; ++II) {
- uint64_t Sum = Counts1[II] + Counts2[II];
- if (Sum < Counts1[II])
- exitWithError("Counter overflow", Filename2); // ???
- NewCounts.push_back(Sum);
+static cl::opt<std::string> Filename1(cl::Positional, cl::Required,
+ cl::desc("file1"));
+static cl::opt<std::string> Filename2(cl::Positional, cl::Required,
+ cl::desc("file2"));
+
+static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
+ cl::init("-"),
+ cl::desc("Output file"));
+static cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
+ cl::aliasopt(OutputFilename));
+
+static bool readLine(const char *&Start, const char *End, StringRef &S) {
+ if (Start == End)
+ return false;
+
+ for (const char *I = Start; I != End; ++I) {
+ assert(*I && "unexpected binary data");
+ if (*I == '\n') {
+ S = StringRef(Start, I - Start);
+ Start = I + 1;
+ return true;
}
-
- Writer.addFunctionCounts(Name1, Hash1, NewCounts.size(), NewCounts.data());
-
- Counts1.clear();
- Counts2.clear();
- NewCounts.clear();
}
- if (I1 != E1 || I2 != E2)
- exitWithError("Truncated file", Filename2);
-
- Writer.write(Output);
- return 0;
+ S = StringRef(Start, End - Start);
+ Start = End;
+ return true;
}
-struct HashPrinter {
- uint64_t Hash;
- HashPrinter(uint64_t Hash) : Hash(Hash) {}
- void print(raw_ostream &OS) const {
- char Buf[18], *Cur = Buf;
- *Cur++ = '0'; *Cur++ = 'x';
- for (unsigned I = 16; I;) {
- char Digit = 0xF & (Hash >> (--I * 4));
- *Cur++ = (Digit < 10 ? '0' + Digit : 'A' + Digit - 10);
+static StringRef getWord(const char *&Start, const char *End) {
+ for (const char *I = Start; I != End; ++I)
+ if (*I == ' ') {
+ StringRef S(Start, I - Start);
+ Start = I + 1;
+ return S;
}
- OS.write(Buf, 18);
- }
-};
-static raw_ostream &operator<<(raw_ostream &OS, const HashPrinter &Hash) {
- Hash.print(OS);
- return OS;
+ StringRef S(Start, End - Start);
+ Start = End;
+ return S;
}
-struct FreqPrinter {
- double Freq;
- FreqPrinter(double Freq) : Freq(Freq) {}
- void print(raw_ostream &OS) const {
- OS << (unsigned)(Freq * 100) << "." << ((unsigned)(Freq * 1000) % 10)
- << ((unsigned)(Freq * 10000) % 10) << "%";
- }
-};
-static raw_ostream &operator<<(raw_ostream &OS, const FreqPrinter &Freq) {
- Freq.print(OS);
- return OS;
+static size_t splitWords(const StringRef &Line, std::vector<StringRef> &Words) {
+ const char *Start = Line.data();
+ const char *End = Line.data() + Line.size();
+ Words.clear();
+ while (Start != End)
+ Words.push_back(getWord(Start, End));
+ return Words.size();
}
-int show_main(int argc, const char *argv[]) {
- cl::opt<std::string> Filename(cl::Positional, cl::Required,
- cl::desc("<profdata-file>"));
-
- cl::opt<bool> ShowCounts("counts", cl::init(false));
- cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false));
- cl::opt<std::string> ShowFunction("function");
-
- cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
- cl::init("-"),
- cl::desc("Output file"));
- cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
- cl::aliasopt(OutputFilename));
-
- cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n");
-
- std::unique_ptr<ProfileDataReader> Reader;
- if (error_code EC = ProfileDataReader::create(Filename, Reader))
- exitWithError(EC.message(), Filename);
-
- if (OutputFilename.empty())
- OutputFilename = "-";
-
- std::string ErrorInfo;
- raw_fd_ostream OS(OutputFilename.data(), ErrorInfo, sys::fs::F_Text);
- if (!ErrorInfo.empty())
- exitWithError(ErrorInfo, OutputFilename);
-
- if (ShowAllFunctions && !ShowFunction.empty())
- errs() << "warning: -function argument ignored: showing all functions\n";
-
- uint64_t MaxFunctionCount = Reader->getMaximumFunctionCount();
-
- uint64_t MaxBlockCount = 0;
- uint64_t Hash;
- size_t ShownFunctions = false;
- std::vector<uint64_t> Counts;
- for (const auto &Name : *Reader) {
- bool Show = ShowAllFunctions || Name.find(ShowFunction) != Name.npos;
- if (error_code EC = Reader->getFunctionCounts(Name, Hash, Counts))
- exitWithError(EC.message(), Filename);
-
- if (Show) {
- double CallFreq = Counts[0] / (double)MaxFunctionCount;
-
- if (!ShownFunctions)
- OS << "Counters:\n";
- ++ShownFunctions;
+static bool getNumber(const StringRef &S, uint64_t &N) {
+ N = 0;
+ for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I)
+ if (*I >= '0' && *I <= '9')
+ N = N * 10 + (*I - '0');
+ else
+ return false;
- OS << " " << Name << ":\n"
- << " Hash: " << HashPrinter(Hash) << "\n"
- << " Relative call frequency: " << FreqPrinter(CallFreq) << "\n"
- << " Counters: " << Counts.size() << "\n"
- << " Function count: " << Counts[0] << "\n";
- }
-
- if (Show && ShowCounts)
- OS << " Block counts: [";
- for (size_t I = 1, E = Counts.size(); I < E; ++I) {
- if (Counts[I] > MaxBlockCount)
- MaxBlockCount = Counts[I];
- if (Show && ShowCounts)
- OS << (I == 1 ? "" : ", ") << Counts[I];
- }
- if (Show && ShowCounts)
- OS << "]\n";
-
- Counts.clear();
- }
+ return true;
+}
- if (ShowAllFunctions || !ShowFunction.empty())
- OS << "Functions shown: " << ShownFunctions << "\n";
- OS << "Total functions: " << Reader->numProfiledFunctions() << "\n";
- OS << "Maximum function count: " << MaxFunctionCount << "\n";
- OS << "Maximum internal block count: " << MaxBlockCount << "\n";
- return 0;
+static void exitWithError(const std::string &Message,
+ const std::string &Filename, int64_t Line = -1) {
+ errs() << "error: " << Filename;
+ if (Line >= 0)
+ errs() << ":" << Line;
+ errs() << ": " << Message << "\n";
+ ::exit(1);
}
-int generate_main(int argc, const char *argv[]) {
- cl::opt<std::string> InputName(cl::Positional, cl::Required,
- cl::desc("<input-file>"));
+//===----------------------------------------------------------------------===//
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
- cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
- cl::init("-"),
- cl::desc("Output file"));
- cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
- cl::aliasopt(OutputFilename));
+ cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
- cl::ParseCommandLineOptions(argc, argv, "LLVM profile data generator\n");
+ std::unique_ptr<MemoryBuffer> File1;
+ std::unique_ptr<MemoryBuffer> File2;
+ if (error_code ec = MemoryBuffer::getFile(Filename1, File1))
+ exitWithError(ec.message(), Filename1);
+ if (error_code ec = MemoryBuffer::getFile(Filename2, File2))
+ exitWithError(ec.message(), Filename2);
if (OutputFilename.empty())
OutputFilename = "-";
@@ -238,86 +115,63 @@ int generate_main(int argc, const char *argv[]) {
if (!ErrorInfo.empty())
exitWithError(ErrorInfo, OutputFilename);
- if (Output.is_displayed())
- exitWithError("Refusing to write a binary file to stdout", OutputFilename);
-
- std::unique_ptr<MemoryBuffer> Buffer;
- if (error_code EC = MemoryBuffer::getFile(InputName, Buffer))
- exitWithError(EC.message(), InputName);
-
- ProfileDataWriter Writer;
- StringRef Name;
- uint64_t Hash, NumCounters;
- std::vector<uint64_t> Counters;
- for (line_iterator I(*Buffer, '#'); !I.is_at_end(); ++I) {
- if (I->empty())
+ const char *Start1 = File1->getBufferStart();
+ const char *Start2 = File2->getBufferStart();
+ const char *End1 = File1->getBufferEnd();
+ const char *End2 = File2->getBufferEnd();
+ const char *P1 = Start1;
+ const char *P2 = Start2;
+
+ StringRef Line1, Line2;
+ int64_t Num = 0;
+ while (readLine(P1, End1, Line1)) {
+ ++Num;
+ if (!readLine(P2, End2, Line2))
+ exitWithError("truncated file", Filename2, Num);
+
+ std::vector<StringRef> Words1, Words2;
+ if (splitWords(Line1, Words1) != splitWords(Line2, Words2))
+ exitWithError("data mismatch", Filename2, Num);
+
+ if (Words1.size() > 2)
+ exitWithError("invalid data", Filename1, Num);
+
+ if (Words1.empty()) {
+ Output << "\n";
continue;
- Name = *I;
- if ((++I).is_at_end())
- exitWithError("Truncated file", InputName, I.line_number());
- if (I->getAsInteger(10, Hash))
- exitWithError("Failed to read hash", InputName, I.line_number());
- if ((++I).is_at_end())
- exitWithError("Truncated file", InputName, I.line_number());
- if (I->getAsInteger(10, NumCounters))
- exitWithError("Failed to read num counters", InputName, I.line_number());
- for (uint64_t CurCounter = 0; CurCounter < NumCounters; ++CurCounter) {
- uint64_t Counter;
- if ((++I).is_at_end())
- exitWithError("Truncated file", InputName, I.line_number());
- if (I->getAsInteger(10, Counter))
- exitWithError("Failed to read counter", InputName, I.line_number());
- Counters.push_back(Counter);
}
- Writer.addFunctionCounts(Name, Hash, NumCounters, Counters.data());
- Counters.clear();
- }
- Writer.write(Output);
+ if (Words1.size() == 2) {
+ if (Words1[0] != Words2[0])
+ exitWithError("function name mismatch", Filename2, Num);
- return 0;
-}
+ uint64_t N1, N2;
+ if (!getNumber(Words1[1], N1))
+ exitWithError("bad function count", Filename1, Num);
+ if (!getNumber(Words2[1], N2))
+ exitWithError("bad function count", Filename2, Num);
-int main(int argc, const char *argv[]) {
- // Print a stack trace if we signal out.
- sys::PrintStackTraceOnErrorSignal();
- PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
-
- StringRef ProgName(sys::path::filename(argv[0]));
- if (argc > 1) {
- int (*func)(int, const char *[]) = 0;
-
- if (strcmp(argv[1], "merge") == 0)
- func = merge_main;
- else if (strcmp(argv[1], "show") == 0)
- func = show_main;
- else if (strcmp(argv[1], "generate") == 0)
- func = generate_main;
+ if (N1 != N2)
+ exitWithError("function count mismatch", Filename2, Num);
- if (func) {
- std::string Invocation(ProgName.str() + " " + argv[1]);
- argv[1] = Invocation.c_str();
- return func(argc - 1, argv + 1);
+ Output << Line1 << "\n";
+ continue;
}
- if (strcmp(argv[1], "-h") == 0 ||
- strcmp(argv[1], "-help") == 0 ||
- strcmp(argv[1], "--help") == 0) {
+ uint64_t N1, N2;
+ if (!getNumber(Words1[0], N1))
+ exitWithError("invalid counter", Filename1, Num);
+ if (!getNumber(Words2[0], N2))
+ exitWithError("invalid counter", Filename2, Num);
- errs() << "OVERVIEW: LLVM profile data tools\n\n"
- << "USAGE: " << ProgName << " <command> [args...]\n"
- << "USAGE: " << ProgName << " <command> -help\n\n"
- << "Available commands: merge, show, generate\n";
- return 0;
- }
- }
+ uint64_t Sum = N1 + N2;
+ if (Sum < N1)
+ exitWithError("counter overflow", Filename2, Num);
- if (argc < 2)
- errs() << ProgName << ": No command specified!\n";
- else
- errs() << ProgName << ": Unknown command!\n";
+ Output << N1 + N2 << "\n";
+ }
+ if (readLine(P2, End2, Line2))
+ exitWithError("truncated file", Filename1, Num + 1);
- errs() << "USAGE: " << ProgName << " <merge|show|generate> [args...]\n";
- return 1;
+ return 0;
}