From: Justin Bogner Date: Wed, 12 Mar 2014 22:00:57 +0000 (+0000) Subject: Back out Profile library and dependent commits X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=efa9416a21d7cac98996b92a805321ad061f54c0;p=oota-llvm.git Back out Profile library and dependent commits Chandler voiced some concern with checking this in without some discussion first. Reverting for now. This reverts r203703, r203704, r203708, and 203709. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203723 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Profile/ProfileData.h b/include/llvm/Profile/ProfileData.h deleted file mode 100644 index 72cc840e803..00000000000 --- 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 - -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(E), profiledata_category()); -} - -template <> struct is_error_code_enum : std::true_type {}; -template <> struct is_error_code_enum - : 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 0f771f23fd9..00000000000 --- 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 - -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 DataBuffer; - /// Offsets into DataBuffer for each function's counters. - StringMap 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 &DataBuffer) - : DataBuffer(DataBuffer.release()) {} - - /// Populate internal state using the profile data's index - error_code readIndex(); -public: - - class name_iterator { - typedef StringMap::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 &Counts); - /// Return the maximum of all known function counts. - uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } - - static error_code create(std::string Path, - std::unique_ptr &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 3498d2eca3e..00000000000 --- 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 - -namespace llvm { - -/// Writer for instrumentation based profile data -class ProfileDataWriter { - StringMap FunctionOffsets; - std::vector 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 92a9cc5c574..861c19881fe 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 a4496f9e58b..9367f553134 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 c75ca4e9030..a0984d410c6 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 1f55dd7f960..a97f71aded0 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 e0a4f0a1bac..00000000000 --- 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 ae1fdd61c7a..00000000000 --- 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 fb80a12097f..00000000000 --- 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 65dca9db2b7..00000000000 --- 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(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 e679d9eec0d..00000000000 --- 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 - -using namespace llvm; - -error_code ProfileDataReader::create( - std::string Path, std::unique_ptr &Result) { - std::unique_ptr Buffer; - if (error_code EC = MemoryBuffer::getFileOrSTDIN(Path, Buffer)) - return EC; - - if (Buffer->getBufferSize() > std::numeric_limits::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 - error_code read(T &Result) { - typedef support::detail::packed_endian_specific_integral - Endian_t; - const char *Prev = Next; - if (error_code EC = skip(sizeof(T))) - return EC; - Result = *reinterpret_cast(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(Result); } - error_code read64(uint64_t &Result) { return read(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 &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 b5993dd45ed..00000000000 --- 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 -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 -static raw_ostream &operator<<(raw_ostream &OS, const LEBytes &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(PROFILEDATA_VERSION); - OS << LEBytes(DataStart); - OS << LEBytes(0); - OS << LEBytes(MaxFunctionCount); - - for (const auto &I : FunctionOffsets) { - StringRef Name = I.getKey(); - OS << LEBytes(Name.size()); - OS << Name; - OS << LEBytes(I.getValue()); - } - - for (unsigned I = 0; I < sizeof(uint64_t) - DataStart % sizeof(uint64_t); ++I) - OS << '\0'; - - for (uint64_t Value : FunctionData) - OS << LEBytes(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 00000000000..7d247626e5a --- /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 faa6f401525..00000000000 --- 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 00000000000..cb8b409891a --- /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 5486e9d84d7..00000000000 --- 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 b/test/tools/llvm-profdata/Inputs/empty.profdata new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/tools/llvm-profdata/Inputs/empty.profdata.input b/test/tools/llvm-profdata/Inputs/empty.profdata.input deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test/tools/llvm-profdata/Inputs/extra-word.profdata b/test/tools/llvm-profdata/Inputs/extra-word.profdata new file mode 100644 index 00000000000..67a662909cf --- /dev/null +++ b/test/tools/llvm-profdata/Inputs/extra-word.profdata @@ -0,0 +1,2 @@ +extra 1 word +1 diff --git a/test/tools/llvm-profdata/Inputs/extra-word.profdata.input b/test/tools/llvm-profdata/Inputs/extra-word.profdata.input deleted file mode 100644 index 67a662909cf..00000000000 --- a/test/tools/llvm-profdata/Inputs/extra-word.profdata.input +++ /dev/null @@ -1,2 +0,0 @@ -extra 1 word -1 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 00000000000..d6f9f648b7b --- /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 14a62004357..00000000000 --- 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 00000000000..94fd0343915 --- /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 801846e4404..00000000000 --- 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 00000000000..85b702d4977 --- /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 12157b9f9ad..00000000000 --- 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 b/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata new file mode 100644 index 00000000000..d652781a35c --- /dev/null +++ b/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata @@ -0,0 +1,9 @@ +foo 3 +17 +19 +23 + +bar 3 +29 +31 +37 diff --git a/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata.input b/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata.input deleted file mode 100644 index f1f10bd6f3d..00000000000 --- a/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata.input +++ /dev/null @@ -1,13 +0,0 @@ -foo -3 -3 -17 -19 -23 - -bar -3 -3 -29 -31 -37 diff --git a/test/tools/llvm-profdata/Inputs/foo4-1.profdata b/test/tools/llvm-profdata/Inputs/foo4-1.profdata new file mode 100644 index 00000000000..4d694080bff --- /dev/null +++ b/test/tools/llvm-profdata/Inputs/foo4-1.profdata @@ -0,0 +1,5 @@ +foo 4 +11 +22 +33 +44 diff --git a/test/tools/llvm-profdata/Inputs/foo4-1.profdata.input b/test/tools/llvm-profdata/Inputs/foo4-1.profdata.input deleted file mode 100644 index 31d2a2ce756..00000000000 --- a/test/tools/llvm-profdata/Inputs/foo4-1.profdata.input +++ /dev/null @@ -1,7 +0,0 @@ -foo -4 -4 -11 -22 -33 -44 diff --git a/test/tools/llvm-profdata/Inputs/foo4-2.profdata b/test/tools/llvm-profdata/Inputs/foo4-2.profdata new file mode 100644 index 00000000000..8d91d8bbef0 --- /dev/null +++ b/test/tools/llvm-profdata/Inputs/foo4-2.profdata @@ -0,0 +1,5 @@ +foo 4 +7 +6 +5 +4 diff --git a/test/tools/llvm-profdata/Inputs/foo4-2.profdata.input b/test/tools/llvm-profdata/Inputs/foo4-2.profdata.input deleted file mode 100644 index 01d8309b5ce..00000000000 --- a/test/tools/llvm-profdata/Inputs/foo4-2.profdata.input +++ /dev/null @@ -1,7 +0,0 @@ -foo -4 -4 -7 -6 -5 -4 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 00000000000..5575df3fda6 --- /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 2b61c55a676..00000000000 --- 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 b/test/tools/llvm-profdata/Inputs/overflow.profdata new file mode 100644 index 00000000000..bfb9a52d2ec --- /dev/null +++ b/test/tools/llvm-profdata/Inputs/overflow.profdata @@ -0,0 +1,2 @@ +overflow 1 +9223372036854775808 diff --git a/test/tools/llvm-profdata/Inputs/overflow.profdata.input b/test/tools/llvm-profdata/Inputs/overflow.profdata.input deleted file mode 100644 index c9a9d697ecf..00000000000 --- a/test/tools/llvm-profdata/Inputs/overflow.profdata.input +++ /dev/null @@ -1,4 +0,0 @@ -overflow -1 -1 -9223372036854775808 diff --git a/test/tools/llvm-profdata/Inputs/three-words-long.profdata b/test/tools/llvm-profdata/Inputs/three-words-long.profdata new file mode 100644 index 00000000000..a4d45fb3bfa --- /dev/null +++ b/test/tools/llvm-profdata/Inputs/three-words-long.profdata @@ -0,0 +1 @@ +three words long diff --git a/test/tools/llvm-profdata/Inputs/three-words-long.profdata.input b/test/tools/llvm-profdata/Inputs/three-words-long.profdata.input deleted file mode 100644 index a4d45fb3bfa..00000000000 --- a/test/tools/llvm-profdata/Inputs/three-words-long.profdata.input +++ /dev/null @@ -1 +0,0 @@ -three words long 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 129db626d14..00000000000 --- 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 00000000000..6335ea95f9e --- /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 71e8b50fcad..00000000000 --- 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 1ab08be9f14..00000000000 --- 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 401ae6b58e3..00000000000 --- 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 00000000000..87073fad9cf --- /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 f0667f16f9c..4b1357d87e1 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 f6492da26ca..fc9e4691997 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 11276e25b95..9d7ad527b16 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 989c4281f82..b338efd27e3 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 Filename1(cl::Positional, cl::Required, - cl::desc("file1")); - cl::opt Filename2(cl::Positional, cl::Required, - cl::desc("file2")); - - cl::opt 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 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 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 Filename1(cl::Positional, cl::Required, + cl::desc("file1")); +static cl::opt Filename2(cl::Positional, cl::Required, + cl::desc("file2")); + +static cl::opt 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 &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 Filename(cl::Positional, cl::Required, - cl::desc("")); - - cl::opt ShowCounts("counts", cl::init(false)); - cl::opt ShowAllFunctions("all-functions", cl::init(false)); - cl::opt ShowFunction("function"); - - cl::opt 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 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 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 InputName(cl::Positional, cl::Required, - cl::desc("")); +//===----------------------------------------------------------------------===// +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 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 File1; + std::unique_ptr 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 Buffer; - if (error_code EC = MemoryBuffer::getFile(InputName, Buffer)) - exitWithError(EC.message(), InputName); - - ProfileDataWriter Writer; - StringRef Name; - uint64_t Hash, NumCounters; - std::vector 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 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 << " [args...]\n" - << "USAGE: " << ProgName << " -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 << " [args...]\n"; - return 1; + return 0; }