1 //===- llvm-profdata.cpp - LLVM profile data tool -------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // llvm-profdata merges .profdata files.
12 //===----------------------------------------------------------------------===//
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/PrettyStackTrace.h"
26 #include "llvm/Support/Signals.h"
27 #include "llvm/Support/raw_ostream.h"
31 static void exitWithError(const Twine
&Message
, StringRef Whence
= "") {
34 errs() << Whence
<< ": ";
35 errs() << Message
<< "\n";
39 enum ProfileKinds
{ instr
, sample
};
41 void mergeInstrProfile(cl::list
<std::string
> Inputs
, StringRef OutputFilename
) {
42 if (OutputFilename
.compare("-") == 0)
43 exitWithError("Cannot write indexed profdata format to stdout.");
46 raw_fd_ostream
Output(OutputFilename
.data(), EC
, sys::fs::F_None
);
48 exitWithError(EC
.message(), OutputFilename
);
50 InstrProfWriter Writer
;
51 for (const auto &Filename
: Inputs
) {
52 auto ReaderOrErr
= InstrProfReader::create(Filename
);
53 if (std::error_code ec
= ReaderOrErr
.getError())
54 exitWithError(ec
.message(), Filename
);
56 auto Reader
= std::move(ReaderOrErr
.get());
57 for (const auto &I
: *Reader
)
58 if (std::error_code EC
=
59 Writer
.addFunctionCounts(I
.Name
, I
.Hash
, I
.Counts
))
60 errs() << Filename
<< ": " << I
.Name
<< ": " << EC
.message() << "\n";
61 if (Reader
->hasError())
62 exitWithError(Reader
->getError().message(), Filename
);
67 void mergeSampleProfile(cl::list
<std::string
> Inputs
, StringRef OutputFilename
,
68 sampleprof::SampleProfileFormat OutputFormat
) {
69 using namespace sampleprof
;
70 auto WriterOrErr
= SampleProfileWriter::create(OutputFilename
, OutputFormat
);
71 if (std::error_code EC
= WriterOrErr
.getError())
72 exitWithError(EC
.message(), OutputFilename
);
74 auto Writer
= std::move(WriterOrErr
.get());
75 StringMap
<FunctionSamples
> ProfileMap
;
76 for (const auto &Filename
: Inputs
) {
78 SampleProfileReader::create(Filename
, getGlobalContext());
79 if (std::error_code EC
= ReaderOrErr
.getError())
80 exitWithError(EC
.message(), Filename
);
82 auto Reader
= std::move(ReaderOrErr
.get());
83 if (std::error_code EC
= Reader
->read())
84 exitWithError(EC
.message(), Filename
);
86 StringMap
<FunctionSamples
> &Profiles
= Reader
->getProfiles();
87 for (StringMap
<FunctionSamples
>::iterator I
= Profiles
.begin(),
90 StringRef FName
= I
->first();
91 FunctionSamples
&Samples
= I
->second
;
92 ProfileMap
[FName
].merge(Samples
);
95 Writer
->write(ProfileMap
);
98 int merge_main(int argc
, const char *argv
[]) {
99 cl::list
<std::string
> Inputs(cl::Positional
, cl::Required
, cl::OneOrMore
,
100 cl::desc("<filenames...>"));
102 cl::opt
<std::string
> OutputFilename("output", cl::value_desc("output"),
103 cl::init("-"), cl::Required
,
104 cl::desc("Output file"));
105 cl::alias
OutputFilenameA("o", cl::desc("Alias for --output"),
106 cl::aliasopt(OutputFilename
));
107 cl::opt
<ProfileKinds
> ProfileKind(
108 cl::desc("Profile kind:"), cl::init(instr
),
109 cl::values(clEnumVal(instr
, "Instrumentation profile (default)"),
110 clEnumVal(sample
, "Sample profile"), clEnumValEnd
));
112 cl::opt
<sampleprof::SampleProfileFormat
> OutputFormat(
113 cl::desc("Format of output profile (only meaningful with --sample)"),
114 cl::init(sampleprof::SPF_Binary
),
115 cl::values(clEnumValN(sampleprof::SPF_Binary
, "binary",
116 "Binary encoding (default)"),
117 clEnumValN(sampleprof::SPF_Text
, "text", "Text encoding"),
118 clEnumValN(sampleprof::SPF_GCC
, "gcc", "GCC encoding"),
121 cl::ParseCommandLineOptions(argc
, argv
, "LLVM profile data merger\n");
123 if (ProfileKind
== instr
)
124 mergeInstrProfile(Inputs
, OutputFilename
);
126 mergeSampleProfile(Inputs
, OutputFilename
, OutputFormat
);
131 int showInstrProfile(std::string Filename
, bool ShowCounts
,
132 bool ShowAllFunctions
, std::string ShowFunction
,
133 raw_fd_ostream
&OS
) {
134 auto ReaderOrErr
= InstrProfReader::create(Filename
);
135 if (std::error_code EC
= ReaderOrErr
.getError())
136 exitWithError(EC
.message(), Filename
);
138 auto Reader
= std::move(ReaderOrErr
.get());
139 uint64_t MaxFunctionCount
= 0, MaxBlockCount
= 0;
140 size_t ShownFunctions
= 0, TotalFunctions
= 0;
141 for (const auto &Func
: *Reader
) {
143 ShowAllFunctions
|| (!ShowFunction
.empty() &&
144 Func
.Name
.find(ShowFunction
) != Func
.Name
.npos
);
147 assert(Func
.Counts
.size() > 0 && "function missing entry counter");
148 if (Func
.Counts
[0] > MaxFunctionCount
)
149 MaxFunctionCount
= Func
.Counts
[0];
156 OS
<< " " << Func
.Name
<< ":\n"
157 << " Hash: " << format("0x%016" PRIx64
, Func
.Hash
) << "\n"
158 << " Counters: " << Func
.Counts
.size() << "\n"
159 << " Function count: " << Func
.Counts
[0] << "\n";
162 if (Show
&& ShowCounts
)
163 OS
<< " Block counts: [";
164 for (size_t I
= 1, E
= Func
.Counts
.size(); I
< E
; ++I
) {
165 if (Func
.Counts
[I
] > MaxBlockCount
)
166 MaxBlockCount
= Func
.Counts
[I
];
167 if (Show
&& ShowCounts
)
168 OS
<< (I
== 1 ? "" : ", ") << Func
.Counts
[I
];
170 if (Show
&& ShowCounts
)
173 if (Reader
->hasError())
174 exitWithError(Reader
->getError().message(), Filename
);
176 if (ShowAllFunctions
|| !ShowFunction
.empty())
177 OS
<< "Functions shown: " << ShownFunctions
<< "\n";
178 OS
<< "Total functions: " << TotalFunctions
<< "\n";
179 OS
<< "Maximum function count: " << MaxFunctionCount
<< "\n";
180 OS
<< "Maximum internal block count: " << MaxBlockCount
<< "\n";
184 int showSampleProfile(std::string Filename
, bool ShowCounts
,
185 bool ShowAllFunctions
, std::string ShowFunction
,
186 raw_fd_ostream
&OS
) {
187 using namespace sampleprof
;
188 auto ReaderOrErr
= SampleProfileReader::create(Filename
, getGlobalContext());
189 if (std::error_code EC
= ReaderOrErr
.getError())
190 exitWithError(EC
.message(), Filename
);
192 auto Reader
= std::move(ReaderOrErr
.get());
194 if (ShowAllFunctions
|| ShowFunction
.empty())
197 Reader
->dumpFunctionProfile(ShowFunction
, OS
);
202 int show_main(int argc
, const char *argv
[]) {
203 cl::opt
<std::string
> Filename(cl::Positional
, cl::Required
,
204 cl::desc("<profdata-file>"));
206 cl::opt
<bool> ShowCounts("counts", cl::init(false),
207 cl::desc("Show counter values for shown functions"));
208 cl::opt
<bool> ShowAllFunctions("all-functions", cl::init(false),
209 cl::desc("Details for every function"));
210 cl::opt
<std::string
> ShowFunction("function",
211 cl::desc("Details for matching functions"));
213 cl::opt
<std::string
> OutputFilename("output", cl::value_desc("output"),
214 cl::init("-"), cl::desc("Output file"));
215 cl::alias
OutputFilenameA("o", cl::desc("Alias for --output"),
216 cl::aliasopt(OutputFilename
));
217 cl::opt
<ProfileKinds
> ProfileKind(
218 cl::desc("Profile kind:"), cl::init(instr
),
219 cl::values(clEnumVal(instr
, "Instrumentation profile (default)"),
220 clEnumVal(sample
, "Sample profile"), clEnumValEnd
));
222 cl::ParseCommandLineOptions(argc
, argv
, "LLVM profile data summary\n");
224 if (OutputFilename
.empty())
225 OutputFilename
= "-";
228 raw_fd_ostream
OS(OutputFilename
.data(), EC
, sys::fs::F_Text
);
230 exitWithError(EC
.message(), OutputFilename
);
232 if (ShowAllFunctions
&& !ShowFunction
.empty())
233 errs() << "warning: -function argument ignored: showing all functions\n";
235 if (ProfileKind
== instr
)
236 return showInstrProfile(Filename
, ShowCounts
, ShowAllFunctions
,
239 return showSampleProfile(Filename
, ShowCounts
, ShowAllFunctions
,
243 int main(int argc
, const char *argv
[]) {
244 // Print a stack trace if we signal out.
245 sys::PrintStackTraceOnErrorSignal();
246 PrettyStackTraceProgram
X(argc
, argv
);
247 llvm_shutdown_obj Y
; // Call llvm_shutdown() on exit.
249 StringRef
ProgName(sys::path::filename(argv
[0]));
251 int (*func
)(int, const char *[]) = nullptr;
253 if (strcmp(argv
[1], "merge") == 0)
255 else if (strcmp(argv
[1], "show") == 0)
259 std::string
Invocation(ProgName
.str() + " " + argv
[1]);
260 argv
[1] = Invocation
.c_str();
261 return func(argc
- 1, argv
+ 1);
264 if (strcmp(argv
[1], "-h") == 0 ||
265 strcmp(argv
[1], "-help") == 0 ||
266 strcmp(argv
[1], "--help") == 0) {
268 errs() << "OVERVIEW: LLVM profile data tools\n\n"
269 << "USAGE: " << ProgName
<< " <command> [args...]\n"
270 << "USAGE: " << ProgName
<< " <command> -help\n\n"
271 << "Available commands: merge, show\n";
277 errs() << ProgName
<< ": No command specified!\n";
279 errs() << ProgName
<< ": Unknown command!\n";
281 errs() << "USAGE: " << ProgName
<< " <merge|show> [args...]\n";