summaryrefslogtreecommitdiff
path: root/tools/llvm-profdata
diff options
context:
space:
mode:
authorJustin Bogner <mail@justinbogner.com>2014-03-12 22:00:57 +0000
committerJustin Bogner <mail@justinbogner.com>2014-03-12 22:00:57 +0000
commitefa9416a21d7cac98996b92a805321ad061f54c0 (patch)
treea69da4d26ec90b29ec8aa9fea0a40cfb6c13474e /tools/llvm-profdata
parent4a0593ccd38cf01419e957e3947ed24cb3e06a07 (diff)
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
Diffstat (limited to 'tools/llvm-profdata')
-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
4 files changed, 120 insertions, 266 deletions
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<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;
}