[llvm-profdata] Show hint for other mismatch errors when merging instr profdata
[oota-llvm.git] / tools / llvm-profdata / llvm-profdata.cpp
1 //===- llvm-profdata.cpp - LLVM profile data tool -------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // llvm-profdata merges .profdata files.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/IR/LLVMContext.h"
16 #include "llvm/ProfileData/InstrProfReader.h"
17 #include "llvm/ProfileData/InstrProfWriter.h"
18 #include "llvm/ProfileData/SampleProfReader.h"
19 #include "llvm/ProfileData/SampleProfWriter.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/FileSystem.h"
22 #include "llvm/Support/Format.h"
23 #include "llvm/Support/ManagedStatic.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/Path.h"
26 #include "llvm/Support/PrettyStackTrace.h"
27 #include "llvm/Support/Signals.h"
28 #include "llvm/Support/raw_ostream.h"
29
30 #include <set>
31
32 using namespace llvm;
33
34 static void exitWithError(const Twine &Message,
35                           StringRef Whence = "",
36                           StringRef Hint = "") {
37   errs() << "error: ";
38   if (!Whence.empty())
39     errs() << Whence << ": ";
40   errs() << Message << "\n";
41   if (!Hint.empty())
42     errs() << Hint << "\n";
43   ::exit(1);
44 }
45
46 static void exitWithErrorCode(const std::error_code &Error,
47                               StringRef Whence = "") {
48   if (Error.category() == instrprof_category()) {
49     instrprof_error instrError = static_cast<instrprof_error>(Error.value());
50     if (instrError == instrprof_error::unrecognized_format) {
51       // Hint for common error of forgetting -sample for sample profiles.
52       exitWithError(Error.message(), Whence,
53                     "Perhaps you forgot to use the -sample option?");
54     }
55   }
56   exitWithError(Error.message(), Whence);
57 }
58
59 namespace {
60     enum ProfileKinds { instr, sample };
61 }
62
63 static void handleMergeWriterError(std::error_code &Error,
64                                    StringRef WhenceFile = "",
65                                    StringRef WhenceFunction = "",
66                                    bool ShowHint = true)
67 {
68   if (!WhenceFile.empty())
69     errs() << WhenceFile << ": ";
70   if (!WhenceFunction.empty())
71     errs() << WhenceFunction << ": ";
72   errs() << Error.message() << "\n";
73
74   if (ShowHint) {
75     StringRef Hint = "";
76     if (Error.category() == instrprof_category()) {
77       instrprof_error instrError = static_cast<instrprof_error>(Error.value());
78       switch (instrError) {
79       case instrprof_error::hash_mismatch:
80       case instrprof_error::count_mismatch:
81       case instrprof_error::value_site_count_mismatch:
82         Hint = "Make sure that all profile data to be merged is generated " \
83                "from the same binary.";
84         break;
85       }
86     }
87
88     if (!Hint.empty())
89       errs() << Hint << "\n";
90   }
91 }
92
93 static void mergeInstrProfile(const cl::list<std::string> &Inputs,
94                               StringRef OutputFilename) {
95   if (OutputFilename.compare("-") == 0)
96     exitWithError("Cannot write indexed profdata format to stdout.");
97
98   std::error_code EC;
99   raw_fd_ostream Output(OutputFilename.data(), EC, sys::fs::F_None);
100   if (EC)
101     exitWithErrorCode(EC, OutputFilename);
102
103   InstrProfWriter Writer;
104   std::set<std::error_code> WriterErrorCodes;
105   for (const auto &Filename : Inputs) {
106     auto ReaderOrErr = InstrProfReader::create(Filename);
107     if (std::error_code ec = ReaderOrErr.getError())
108       exitWithErrorCode(ec, Filename);
109
110     auto Reader = std::move(ReaderOrErr.get());
111     for (auto &I : *Reader) {
112       if (std::error_code EC = Writer.addRecord(std::move(I))) {
113         // Only show hint the first time an error occurs.
114         bool firstTime = WriterErrorCodes.insert(EC).second;
115         handleMergeWriterError(EC, Filename, I.Name, firstTime);
116       }
117     }
118     if (Reader->hasError())
119       exitWithErrorCode(Reader->getError(), Filename);
120   }
121   Writer.write(Output);
122 }
123
124 static void mergeSampleProfile(const cl::list<std::string> &Inputs,
125                                StringRef OutputFilename,
126                                sampleprof::SampleProfileFormat OutputFormat) {
127   using namespace sampleprof;
128   auto WriterOrErr = SampleProfileWriter::create(OutputFilename, OutputFormat);
129   if (std::error_code EC = WriterOrErr.getError())
130     exitWithErrorCode(EC, OutputFilename);
131
132   auto Writer = std::move(WriterOrErr.get());
133   StringMap<FunctionSamples> ProfileMap;
134   SmallVector<std::unique_ptr<sampleprof::SampleProfileReader>, 5> Readers;
135   for (const auto &Filename : Inputs) {
136     auto ReaderOrErr =
137         SampleProfileReader::create(Filename, getGlobalContext());
138     if (std::error_code EC = ReaderOrErr.getError())
139       exitWithErrorCode(EC, Filename);
140
141     // We need to keep the readers around until after all the files are
142     // read so that we do not lose the function names stored in each
143     // reader's memory. The function names are needed to write out the
144     // merged profile map.
145     Readers.push_back(std::move(ReaderOrErr.get()));
146     const auto Reader = Readers.back().get();
147     if (std::error_code EC = Reader->read())
148       exitWithErrorCode(EC, Filename);
149
150     StringMap<FunctionSamples> &Profiles = Reader->getProfiles();
151     for (StringMap<FunctionSamples>::iterator I = Profiles.begin(),
152                                               E = Profiles.end();
153          I != E; ++I) {
154       StringRef FName = I->first();
155       FunctionSamples &Samples = I->second;
156       ProfileMap[FName].merge(Samples);
157     }
158   }
159   Writer->write(ProfileMap);
160 }
161
162 static int merge_main(int argc, const char *argv[]) {
163   cl::list<std::string> Inputs(cl::Positional, cl::Required, cl::OneOrMore,
164                                cl::desc("<filenames...>"));
165
166   cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
167                                       cl::init("-"), cl::Required,
168                                       cl::desc("Output file"));
169   cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
170                             cl::aliasopt(OutputFilename));
171   cl::opt<ProfileKinds> ProfileKind(
172       cl::desc("Profile kind:"), cl::init(instr),
173       cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
174                  clEnumVal(sample, "Sample profile"), clEnumValEnd));
175
176   cl::opt<sampleprof::SampleProfileFormat> OutputFormat(
177       cl::desc("Format of output profile (only meaningful with --sample)"),
178       cl::init(sampleprof::SPF_Binary),
179       cl::values(clEnumValN(sampleprof::SPF_Binary, "binary",
180                             "Binary encoding (default)"),
181                  clEnumValN(sampleprof::SPF_Text, "text", "Text encoding"),
182                  clEnumValN(sampleprof::SPF_GCC, "gcc", "GCC encoding"),
183                  clEnumValEnd));
184
185   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
186
187   if (ProfileKind == instr)
188     mergeInstrProfile(Inputs, OutputFilename);
189   else
190     mergeSampleProfile(Inputs, OutputFilename, OutputFormat);
191
192   return 0;
193 }
194
195 static int showInstrProfile(std::string Filename, bool ShowCounts,
196                             bool ShowIndirectCallTargets, bool ShowAllFunctions,
197                             std::string ShowFunction, raw_fd_ostream &OS) {
198   auto ReaderOrErr = InstrProfReader::create(Filename);
199   if (std::error_code EC = ReaderOrErr.getError())
200     exitWithErrorCode(EC, Filename);
201
202   auto Reader = std::move(ReaderOrErr.get());
203   uint64_t MaxFunctionCount = 0, MaxBlockCount = 0;
204   size_t ShownFunctions = 0, TotalFunctions = 0;
205   for (const auto &Func : *Reader) {
206     bool Show =
207         ShowAllFunctions || (!ShowFunction.empty() &&
208                              Func.Name.find(ShowFunction) != Func.Name.npos);
209
210     ++TotalFunctions;
211     assert(Func.Counts.size() > 0 && "function missing entry counter");
212     if (Func.Counts[0] > MaxFunctionCount)
213       MaxFunctionCount = Func.Counts[0];
214
215     if (Show) {
216       if (!ShownFunctions)
217         OS << "Counters:\n";
218       ++ShownFunctions;
219
220       OS << "  " << Func.Name << ":\n"
221          << "    Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"
222          << "    Counters: " << Func.Counts.size() << "\n"
223          << "    Function count: " << Func.Counts[0] << "\n";
224       if (ShowIndirectCallTargets)
225         OS << "    Indirect Call Site Count: "
226            << Func.getNumValueSites(IPVK_IndirectCallTarget) << "\n";
227     }
228
229     if (Show && ShowCounts)
230       OS << "    Block counts: [";
231     for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
232       if (Func.Counts[I] > MaxBlockCount)
233         MaxBlockCount = Func.Counts[I];
234       if (Show && ShowCounts)
235         OS << (I == 1 ? "" : ", ") << Func.Counts[I];
236     }
237     if (Show && ShowCounts)
238       OS << "]\n";
239
240     if (Show && ShowIndirectCallTargets) {
241       uint32_t NS = Func.getNumValueSites(IPVK_IndirectCallTarget);
242       OS << "    Indirect Target Results: \n";
243       for (size_t I = 0; I < NS; ++I) {
244         uint32_t NV = Func.getNumValueDataForSite(IPVK_IndirectCallTarget, I);
245         std::unique_ptr<InstrProfValueData[]> VD =
246             Func.getValueForSite(IPVK_IndirectCallTarget, I);
247         for (uint32_t V = 0; V < NV; V++) {
248           OS << "\t[ " << I << ", ";
249           OS << (const char *)VD[V].Value << ", " << VD[V].Count << " ]\n";
250         }
251       }
252     }
253   }
254   if (Reader->hasError())
255     exitWithErrorCode(Reader->getError(), Filename);
256
257   if (ShowAllFunctions || !ShowFunction.empty())
258     OS << "Functions shown: " << ShownFunctions << "\n";
259   OS << "Total functions: " << TotalFunctions << "\n";
260   OS << "Maximum function count: " << MaxFunctionCount << "\n";
261   OS << "Maximum internal block count: " << MaxBlockCount << "\n";
262   return 0;
263 }
264
265 static int showSampleProfile(std::string Filename, bool ShowCounts,
266                              bool ShowAllFunctions, std::string ShowFunction,
267                              raw_fd_ostream &OS) {
268   using namespace sampleprof;
269   auto ReaderOrErr = SampleProfileReader::create(Filename, getGlobalContext());
270   if (std::error_code EC = ReaderOrErr.getError())
271     exitWithErrorCode(EC, Filename);
272
273   auto Reader = std::move(ReaderOrErr.get());
274   if (std::error_code EC = Reader->read())
275     exitWithErrorCode(EC, Filename);
276
277   if (ShowAllFunctions || ShowFunction.empty())
278     Reader->dump(OS);
279   else
280     Reader->dumpFunctionProfile(ShowFunction, OS);
281
282   return 0;
283 }
284
285 static int show_main(int argc, const char *argv[]) {
286   cl::opt<std::string> Filename(cl::Positional, cl::Required,
287                                 cl::desc("<profdata-file>"));
288
289   cl::opt<bool> ShowCounts("counts", cl::init(false),
290                            cl::desc("Show counter values for shown functions"));
291   cl::opt<bool> ShowIndirectCallTargets(
292       "ic-targets", cl::init(false),
293       cl::desc("Show indirect call site target values for shown functions"));
294   cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
295                                  cl::desc("Details for every function"));
296   cl::opt<std::string> ShowFunction("function",
297                                     cl::desc("Details for matching functions"));
298
299   cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
300                                       cl::init("-"), cl::desc("Output file"));
301   cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
302                             cl::aliasopt(OutputFilename));
303   cl::opt<ProfileKinds> ProfileKind(
304       cl::desc("Profile kind:"), cl::init(instr),
305       cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
306                  clEnumVal(sample, "Sample profile"), clEnumValEnd));
307
308   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n");
309
310   if (OutputFilename.empty())
311     OutputFilename = "-";
312
313   std::error_code EC;
314   raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::F_Text);
315   if (EC)
316       exitWithErrorCode(EC, OutputFilename);
317
318   if (ShowAllFunctions && !ShowFunction.empty())
319     errs() << "warning: -function argument ignored: showing all functions\n";
320
321   if (ProfileKind == instr)
322     return showInstrProfile(Filename, ShowCounts, ShowIndirectCallTargets,
323                             ShowAllFunctions, ShowFunction, OS);
324   else
325     return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
326                              ShowFunction, OS);
327 }
328
329 int main(int argc, const char *argv[]) {
330   // Print a stack trace if we signal out.
331   sys::PrintStackTraceOnErrorSignal();
332   PrettyStackTraceProgram X(argc, argv);
333   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
334
335   StringRef ProgName(sys::path::filename(argv[0]));
336   if (argc > 1) {
337     int (*func)(int, const char *[]) = nullptr;
338
339     if (strcmp(argv[1], "merge") == 0)
340       func = merge_main;
341     else if (strcmp(argv[1], "show") == 0)
342       func = show_main;
343
344     if (func) {
345       std::string Invocation(ProgName.str() + " " + argv[1]);
346       argv[1] = Invocation.c_str();
347       return func(argc - 1, argv + 1);
348     }
349
350     if (strcmp(argv[1], "-h") == 0 ||
351         strcmp(argv[1], "-help") == 0 ||
352         strcmp(argv[1], "--help") == 0) {
353
354       errs() << "OVERVIEW: LLVM profile data tools\n\n"
355              << "USAGE: " << ProgName << " <command> [args...]\n"
356              << "USAGE: " << ProgName << " <command> -help\n\n"
357              << "Available commands: merge, show\n";
358       return 0;
359     }
360   }
361
362   if (argc < 2)
363     errs() << ProgName << ": No command specified!\n";
364   else
365     errs() << ProgName << ": Unknown command!\n";
366
367   errs() << "USAGE: " << ProgName << " <merge|show> [args...]\n";
368   return 1;
369 }