Skip to content

Commit 6f7c19a

Browse files
committedNov 23, 2015
[PGO] Add --text option for llvm-profdata show|merge commands
The new option is similar to the SampleProfile dump option. - dump raw/indexed format into text profile format - merge the profile and output into text profile format. Note that Value Profiling data text format is not yet designed. That functionality will be added later. Differential Revision: http://reviews.llvm.org/D14894 llvm-svn: 253913
1 parent 243ea6a commit 6f7c19a

File tree

6 files changed

+169
-38
lines changed

6 files changed

+169
-38
lines changed
 

‎llvm/docs/CommandGuide/llvm-profdata.rst

+18-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,17 @@ OPTIONS
5151

5252
.. option:: -instr (default)
5353

54-
Specify that the input profile is an instrumentation-based profile.
54+
Specify that the input profile is an instrumentation-based profile. When
55+
using instrumentation-based profiles, the format of the generated file
56+
can be generated in one of the two ways:
57+
58+
.. option:: -binary (default)
59+
60+
Emit the profile using a binary encoding in indexed profile format.
61+
62+
.. option:: -text
63+
64+
Emit the profile in text format.
5565

5666
.. option:: -sample
5767

@@ -121,6 +131,13 @@ OPTIONS
121131

122132
Specify that the input profile is an instrumentation-based profile.
123133

134+
.. option:: -text
135+
136+
Instruct the profile dumper to show profile counts in the text format of the
137+
instrumentation-based profile data representation. By default, the profile
138+
information is dumped in a more human readable form (also in text) with
139+
annotations.
140+
124141
.. option:: -sample
125142

126143
Specify that the input profile is a sample-based profile.

‎llvm/include/llvm/ProfileData/InstrProfWriter.h

+5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ class InstrProfWriter {
4343
std::error_code addRecord(InstrProfRecord &&I);
4444
/// Write the profile to \c OS
4545
void write(raw_fd_ostream &OS);
46+
/// Write the profile in text format to \c OS
47+
void writeText(raw_fd_ostream &OS);
48+
/// Write \c Record in text format to \c OS
49+
static void writeRecordInText(const InstrProfRecord &Record,
50+
raw_fd_ostream &OS);
4651
/// Write the profile, returning the raw data. For testing.
4752
std::unique_ptr<MemoryBuffer> writeBuffer();
4853

‎llvm/lib/ProfileData/InstrProfWriter.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,21 @@ void InstrProfWriter::write(raw_fd_ostream &OS) {
171171
endian::Writer<little>(OS).write<uint64_t>(TableStart.second);
172172
}
173173

174+
void InstrProfWriter::writeRecordInText(const InstrProfRecord &Func,
175+
raw_fd_ostream &OS) {
176+
OS << Func.Name << "\n" << Func.Hash << "\n" << Func.Counts.size() << "\n";
177+
for (uint64_t Count : Func.Counts)
178+
OS << Count << "\n";
179+
180+
OS << "\n";
181+
}
182+
183+
void InstrProfWriter::writeText(raw_fd_ostream &OS) {
184+
for (const auto &I : FunctionData)
185+
for (const auto &Func : I.getValue())
186+
writeRecordInText(Func.second, OS);
187+
}
188+
174189
std::unique_ptr<MemoryBuffer> InstrProfWriter::writeBuffer() {
175190
std::string Data;
176191
llvm::raw_string_ostream OS(Data);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
foo
2+
10
3+
2
4+
499500
5+
179900
6+
7+
main
8+
16650
9+
4
10+
1
11+
1000
12+
1000000
13+
499500
14+
15+
foo2
16+
10
17+
2
18+
500500
19+
180100
20+
21+
foo
22+
10
23+
2
24+
499500
25+
179900
26+
27+
main
28+
16650
29+
4
30+
1
31+
1000
32+
1000000
33+
499500
34+
35+
foo2
36+
10
37+
2
38+
500500
39+
180100
40+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Basic tests for testing text dump functions.
2+
3+
RUN: llvm-profdata show --all-functions -counts --text %p/Inputs/basic.proftext > %t-basic.proftext1
4+
RUN: llvm-profdata merge -o %t-basic.proftext2 --text %p/Inputs/basic.proftext
5+
6+
RUN: llvm-profdata merge -binary -o %t-basic.profdata1 %t-basic.proftext1
7+
RUN: llvm-profdata merge -o %t-basic.profdata2 %t-basic.proftext2
8+
9+
RUN: llvm-profdata show --all-functions -counts %t-basic.profdata1 > %t-basic.dump3
10+
RUN: llvm-profdata show --all-functions -counts %t-basic.profdata2 > %t-basic.dump4
11+
12+
RUN: llvm-profdata merge -text -o %t-basic.proftext5 %t-basic.profdata1
13+
RUN: llvm-profdata merge -text -o %t-basic.proftext6 %t-basic.profdata2
14+
15+
RUN: diff %t-basic.dump3 %t-basic.dump4
16+
RUN: diff %t-basic.proftext5 %t-basic.proftext6
17+
18+
RUN: not llvm-profdata merge -gcc -o %t-basic-profdata3 %t-basic.proftext2 2>&1 | FileCheck %s --check-prefix=UNKNOWN
19+
UNKNOWN: Unknown
20+
21+

‎llvm/tools/llvm-profdata/llvm-profdata.cpp

+70-37
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
using namespace llvm;
3232

33+
enum ProfileFormat { PF_None = 0, PF_Text, PF_Binary, PF_GCC };
34+
3335
static void exitWithError(const Twine &Message,
3436
StringRef Whence = "",
3537
StringRef Hint = "") {
@@ -92,10 +94,14 @@ static void handleMergeWriterError(std::error_code &Error,
9294
}
9395

9496
static void mergeInstrProfile(const cl::list<std::string> &Inputs,
95-
StringRef OutputFilename) {
97+
StringRef OutputFilename,
98+
ProfileFormat OutputFormat) {
9699
if (OutputFilename.compare("-") == 0)
97100
exitWithError("Cannot write indexed profdata format to stdout.");
98101

102+
if (OutputFormat != PF_Binary && OutputFormat != PF_Text)
103+
exitWithError("Unknown format is specified.");
104+
99105
std::error_code EC;
100106
raw_fd_ostream Output(OutputFilename.data(), EC, sys::fs::F_None);
101107
if (EC)
@@ -119,14 +125,22 @@ static void mergeInstrProfile(const cl::list<std::string> &Inputs,
119125
if (Reader->hasError())
120126
exitWithErrorCode(Reader->getError(), Filename);
121127
}
122-
Writer.write(Output);
128+
if (OutputFormat == PF_Text)
129+
Writer.writeText(Output);
130+
else
131+
Writer.write(Output);
123132
}
124133

134+
static sampleprof::SampleProfileFormat FormatMap[] = {
135+
sampleprof::SPF_None, sampleprof::SPF_Text, sampleprof::SPF_Binary,
136+
sampleprof::SPF_GCC};
137+
125138
static void mergeSampleProfile(const cl::list<std::string> &Inputs,
126139
StringRef OutputFilename,
127-
sampleprof::SampleProfileFormat OutputFormat) {
140+
ProfileFormat OutputFormat) {
128141
using namespace sampleprof;
129-
auto WriterOrErr = SampleProfileWriter::create(OutputFilename, OutputFormat);
142+
auto WriterOrErr =
143+
SampleProfileWriter::create(OutputFilename, FormatMap[OutputFormat]);
130144
if (std::error_code EC = WriterOrErr.getError())
131145
exitWithErrorCode(EC, OutputFilename);
132146

@@ -174,19 +188,18 @@ static int merge_main(int argc, const char *argv[]) {
174188
cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
175189
clEnumVal(sample, "Sample profile"), clEnumValEnd));
176190

177-
cl::opt<sampleprof::SampleProfileFormat> OutputFormat(
178-
cl::desc("Format of output profile (only meaningful with --sample)"),
179-
cl::init(sampleprof::SPF_Binary),
180-
cl::values(clEnumValN(sampleprof::SPF_Binary, "binary",
181-
"Binary encoding (default)"),
182-
clEnumValN(sampleprof::SPF_Text, "text", "Text encoding"),
183-
clEnumValN(sampleprof::SPF_GCC, "gcc", "GCC encoding"),
191+
cl::opt<ProfileFormat> OutputFormat(
192+
cl::desc("Format of output profile"), cl::init(PF_Binary),
193+
cl::values(clEnumValN(PF_Binary, "binary", "Binary encoding (default)"),
194+
clEnumValN(PF_Text, "text", "Text encoding"),
195+
clEnumValN(PF_GCC, "gcc",
196+
"GCC encoding (only meaningful for -sample)"),
184197
clEnumValEnd));
185198

186199
cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
187200

188201
if (ProfileKind == instr)
189-
mergeInstrProfile(Inputs, OutputFilename);
202+
mergeInstrProfile(Inputs, OutputFilename, OutputFormat);
190203
else
191204
mergeSampleProfile(Inputs, OutputFilename, OutputFormat);
192205

@@ -195,7 +208,8 @@ static int merge_main(int argc, const char *argv[]) {
195208

196209
static int showInstrProfile(std::string Filename, bool ShowCounts,
197210
bool ShowIndirectCallTargets, bool ShowAllFunctions,
198-
std::string ShowFunction, raw_fd_ostream &OS) {
211+
std::string ShowFunction, bool TextFormat,
212+
raw_fd_ostream &OS) {
199213
auto ReaderOrErr = InstrProfReader::create(Filename);
200214
if (std::error_code EC = ReaderOrErr.getError())
201215
exitWithErrorCode(EC, Filename);
@@ -208,53 +222,69 @@ static int showInstrProfile(std::string Filename, bool ShowCounts,
208222
ShowAllFunctions || (!ShowFunction.empty() &&
209223
Func.Name.find(ShowFunction) != Func.Name.npos);
210224

225+
bool doTextFormatDump = (Show && ShowCounts && TextFormat);
226+
227+
if (doTextFormatDump) {
228+
InstrProfWriter::writeRecordInText(Func, OS);
229+
continue;
230+
}
231+
211232
++TotalFunctions;
212233
assert(Func.Counts.size() > 0 && "function missing entry counter");
213234
if (Func.Counts[0] > MaxFunctionCount)
214235
MaxFunctionCount = Func.Counts[0];
215236

237+
for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
238+
if (Func.Counts[I] > MaxBlockCount)
239+
MaxBlockCount = Func.Counts[I];
240+
}
241+
216242
if (Show) {
243+
217244
if (!ShownFunctions)
218245
OS << "Counters:\n";
246+
219247
++ShownFunctions;
220248

221249
OS << " " << Func.Name << ":\n"
222250
<< " Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"
223251
<< " Counters: " << Func.Counts.size() << "\n"
224252
<< " Function count: " << Func.Counts[0] << "\n";
253+
225254
if (ShowIndirectCallTargets)
226255
OS << " Indirect Call Site Count: "
227256
<< Func.getNumValueSites(IPVK_IndirectCallTarget) << "\n";
228-
}
229257

230-
if (Show && ShowCounts)
231-
OS << " Block counts: [";
232-
for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
233-
if (Func.Counts[I] > MaxBlockCount)
234-
MaxBlockCount = Func.Counts[I];
235-
if (Show && ShowCounts)
236-
OS << (I == 1 ? "" : ", ") << Func.Counts[I];
237-
}
238-
if (Show && ShowCounts)
239-
OS << "]\n";
240-
241-
if (Show && ShowIndirectCallTargets) {
242-
uint32_t NS = Func.getNumValueSites(IPVK_IndirectCallTarget);
243-
OS << " Indirect Target Results: \n";
244-
for (size_t I = 0; I < NS; ++I) {
245-
uint32_t NV = Func.getNumValueDataForSite(IPVK_IndirectCallTarget, I);
246-
std::unique_ptr<InstrProfValueData[]> VD =
247-
Func.getValueForSite(IPVK_IndirectCallTarget, I);
248-
for (uint32_t V = 0; V < NV; V++) {
249-
OS << "\t[ " << I << ", ";
250-
OS << (const char *)VD[V].Value << ", " << VD[V].Count << " ]\n";
258+
if (ShowCounts) {
259+
OS << " Block counts: [";
260+
for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
261+
OS << (I == 1 ? "" : ", ") << Func.Counts[I];
262+
}
263+
OS << "]\n";
264+
}
265+
266+
if (ShowIndirectCallTargets) {
267+
uint32_t NS = Func.getNumValueSites(IPVK_IndirectCallTarget);
268+
OS << " Indirect Target Results: \n";
269+
for (size_t I = 0; I < NS; ++I) {
270+
uint32_t NV = Func.getNumValueDataForSite(IPVK_IndirectCallTarget, I);
271+
std::unique_ptr<InstrProfValueData[]> VD =
272+
Func.getValueForSite(IPVK_IndirectCallTarget, I);
273+
for (uint32_t V = 0; V < NV; V++) {
274+
OS << "\t[ " << I << ", ";
275+
OS << (const char *)VD[V].Value << ", " << VD[V].Count << " ]\n";
276+
}
251277
}
252278
}
253279
}
254280
}
281+
255282
if (Reader->hasError())
256283
exitWithErrorCode(Reader->getError(), Filename);
257284

285+
if (ShowCounts && TextFormat)
286+
return 0;
287+
258288
if (ShowAllFunctions || !ShowFunction.empty())
259289
OS << "Functions shown: " << ShownFunctions << "\n";
260290
OS << "Total functions: " << TotalFunctions << "\n";
@@ -289,6 +319,9 @@ static int show_main(int argc, const char *argv[]) {
289319

290320
cl::opt<bool> ShowCounts("counts", cl::init(false),
291321
cl::desc("Show counter values for shown functions"));
322+
cl::opt<bool> TextFormat(
323+
"text", cl::init(false),
324+
cl::desc("Show instr profile data in text dump format"));
292325
cl::opt<bool> ShowIndirectCallTargets(
293326
"ic-targets", cl::init(false),
294327
cl::desc("Show indirect call site target values for shown functions"));
@@ -314,14 +347,14 @@ static int show_main(int argc, const char *argv[]) {
314347
std::error_code EC;
315348
raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::F_Text);
316349
if (EC)
317-
exitWithErrorCode(EC, OutputFilename);
350+
exitWithErrorCode(EC, OutputFilename);
318351

319352
if (ShowAllFunctions && !ShowFunction.empty())
320353
errs() << "warning: -function argument ignored: showing all functions\n";
321354

322355
if (ProfileKind == instr)
323356
return showInstrProfile(Filename, ShowCounts, ShowIndirectCallTargets,
324-
ShowAllFunctions, ShowFunction, OS);
357+
ShowAllFunctions, ShowFunction, TextFormat, OS);
325358
else
326359
return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
327360
ShowFunction, OS);

0 commit comments

Comments
 (0)
Please sign in to comment.