summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/ProfileData/SampleProfReader.h3
-rw-r--r--llvm/lib/ProfileData/SampleProfReader.cpp112
-rw-r--r--llvm/lib/ProfileData/SampleProfWriter.cpp15
-rw-r--r--llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprofbin112 -> 115 bytes
-rw-r--r--llvm/test/tools/llvm-profdata/Inputs/inline-samples.afdo20
-rw-r--r--llvm/test/tools/llvm-profdata/inline-samples.test30
6 files changed, 137 insertions, 43 deletions
diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h
index 9f4d53902e1..e2976e2efab 100644
--- a/llvm/include/llvm/ProfileData/SampleProfReader.h
+++ b/llvm/include/llvm/ProfileData/SampleProfReader.h
@@ -157,6 +157,9 @@ protected:
/// \brief Return true if we've reached the end of file.
bool at_eof() const { return Data >= End; }
+ /// Read the contents of the given profile instance.
+ std::error_code readProfile(FunctionSamples &FProfile);
+
/// \brief Points to the current location in the buffer.
const uint8_t *Data;
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index 6d7d182e46c..c620d4ca84a 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -378,62 +378,94 @@ ErrorOr<StringRef> SampleProfileReaderBinary::readString() {
return Str;
}
-std::error_code SampleProfileReaderBinary::read() {
- while (!at_eof()) {
- auto FName(readString());
- if (std::error_code EC = FName.getError())
- return EC;
+std::error_code
+SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
+ auto Val = readNumber<unsigned>();
+ if (std::error_code EC = Val.getError())
+ return EC;
+ FProfile.addTotalSamples(*Val);
- Profiles[*FName] = FunctionSamples();
- FunctionSamples &FProfile = Profiles[*FName];
+ Val = readNumber<unsigned>();
+ if (std::error_code EC = Val.getError())
+ return EC;
+ FProfile.addHeadSamples(*Val);
+
+ // Read the samples in the body.
+ auto NumRecords = readNumber<unsigned>();
+ if (std::error_code EC = NumRecords.getError())
+ return EC;
- auto Val = readNumber<unsigned>();
- if (std::error_code EC = Val.getError())
+ for (unsigned I = 0; I < *NumRecords; ++I) {
+ auto LineOffset = readNumber<uint64_t>();
+ if (std::error_code EC = LineOffset.getError())
return EC;
- FProfile.addTotalSamples(*Val);
- Val = readNumber<unsigned>();
- if (std::error_code EC = Val.getError())
+ auto Discriminator = readNumber<uint64_t>();
+ if (std::error_code EC = Discriminator.getError())
return EC;
- FProfile.addHeadSamples(*Val);
- // Read the samples in the body.
- auto NumRecords = readNumber<unsigned>();
- if (std::error_code EC = NumRecords.getError())
+ auto NumSamples = readNumber<uint64_t>();
+ if (std::error_code EC = NumSamples.getError())
return EC;
- for (unsigned I = 0; I < *NumRecords; ++I) {
- auto LineOffset = readNumber<uint64_t>();
- if (std::error_code EC = LineOffset.getError())
- return EC;
- auto Discriminator = readNumber<uint64_t>();
- if (std::error_code EC = Discriminator.getError())
- return EC;
+ auto NumCalls = readNumber<unsigned>();
+ if (std::error_code EC = NumCalls.getError())
+ return EC;
- auto NumSamples = readNumber<uint64_t>();
- if (std::error_code EC = NumSamples.getError())
+ for (unsigned J = 0; J < *NumCalls; ++J) {
+ auto CalledFunction(readString());
+ if (std::error_code EC = CalledFunction.getError())
return EC;
- auto NumCalls = readNumber<unsigned>();
- if (std::error_code EC = NumCalls.getError())
+ auto CalledFunctionSamples = readNumber<uint64_t>();
+ if (std::error_code EC = CalledFunctionSamples.getError())
return EC;
- for (unsigned J = 0; J < *NumCalls; ++J) {
- auto CalledFunction(readString());
- if (std::error_code EC = CalledFunction.getError())
- return EC;
+ FProfile.addCalledTargetSamples(*LineOffset, *Discriminator,
+ *CalledFunction, *CalledFunctionSamples);
+ }
- auto CalledFunctionSamples = readNumber<uint64_t>();
- if (std::error_code EC = CalledFunctionSamples.getError())
- return EC;
+ FProfile.addBodySamples(*LineOffset, *Discriminator, *NumSamples);
+ }
- FProfile.addCalledTargetSamples(*LineOffset, *Discriminator,
- *CalledFunction,
- *CalledFunctionSamples);
- }
+ // Read all the samples for inlined function calls.
+ auto NumCallsites = readNumber<unsigned>();
+ if (std::error_code EC = NumCallsites.getError())
+ return EC;
- FProfile.addBodySamples(*LineOffset, *Discriminator, *NumSamples);
- }
+ for (unsigned J = 0; J < *NumCallsites; ++J) {
+ auto LineOffset = readNumber<uint64_t>();
+ if (std::error_code EC = LineOffset.getError())
+ return EC;
+
+ auto Discriminator = readNumber<uint64_t>();
+ if (std::error_code EC = Discriminator.getError())
+ return EC;
+
+ auto FName(readString());
+ if (std::error_code EC = FName.getError())
+ return EC;
+
+ FunctionSamples &CalleeProfile = FProfile.functionSamplesAt(
+ CallsiteLocation(*LineOffset, *Discriminator, *FName));
+ if (std::error_code EC = readProfile(CalleeProfile))
+ return EC;
+ }
+
+ return sampleprof_error::success;
+}
+
+std::error_code SampleProfileReaderBinary::read() {
+ while (!at_eof()) {
+ auto FName(readString());
+ if (std::error_code EC = FName.getError())
+ return EC;
+
+ Profiles[*FName] = FunctionSamples();
+ FunctionSamples &FProfile = Profiles[*FName];
+
+ if (std::error_code EC = readProfile(FProfile))
+ return EC;
}
return sampleprof_error::success;
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index e6a4d7d1321..6be884b13e0 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -84,14 +84,13 @@ SampleProfileWriterBinary::SampleProfileWriterBinary(StringRef F,
/// \returns true if the samples were written successfully, false otherwise.
bool SampleProfileWriterBinary::write(StringRef FName,
const FunctionSamples &S) {
- if (S.empty())
- return true;
-
OS << FName;
encodeULEB128(0, OS);
encodeULEB128(S.getTotalSamples(), OS);
encodeULEB128(S.getHeadSamples(), OS);
encodeULEB128(S.getBodySamples().size(), OS);
+
+ // Emit all the body samples.
for (const auto &I : S.getBodySamples()) {
LineLocation Loc = I.first;
const SampleRecord &Sample = I.second;
@@ -108,6 +107,16 @@ bool SampleProfileWriterBinary::write(StringRef FName,
}
}
+ // Recursively emit all the callsite samples.
+ encodeULEB128(S.getCallsiteSamples().size(), OS);
+ for (const auto &J : S.getCallsiteSamples()) {
+ CallsiteLocation Loc = J.first;
+ const FunctionSamples &CalleeSamples = J.second;
+ encodeULEB128(Loc.LineOffset, OS);
+ encodeULEB128(Loc.Discriminator, OS);
+ write(Loc.CalleeName, CalleeSamples);
+ }
+
return true;
}
diff --git a/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof b/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof
index 14d7fd555da..8cbe646c16e 100644
--- a/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof
+++ b/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof
Binary files differ
diff --git a/llvm/test/tools/llvm-profdata/Inputs/inline-samples.afdo b/llvm/test/tools/llvm-profdata/Inputs/inline-samples.afdo
new file mode 100644
index 00000000000..f8680d86fcb
--- /dev/null
+++ b/llvm/test/tools/llvm-profdata/Inputs/inline-samples.afdo
@@ -0,0 +1,20 @@
+main:366846:0
+ 2.1: 60401
+ 4: 0
+ 3: 0
+ 0: 0
+ 2.3: 60401
+ 1: 0
+ 2.3: _Z3fool:246044
+ 1.2: 39280
+ 1.4: 46871
+ 1: 60401
+ 1.3: _Z3bari:0
+ 1.2: 0
+ 1.1: 0
+ 1.8: _Z3bari:0
+ 1.2: 0
+ 1.1: 0
+ 1.7: _Z3bari:99492
+ 1.2: 46732
+ 1.1: 52760
diff --git a/llvm/test/tools/llvm-profdata/inline-samples.test b/llvm/test/tools/llvm-profdata/inline-samples.test
new file mode 100644
index 00000000000..b16ac488234
--- /dev/null
+++ b/llvm/test/tools/llvm-profdata/inline-samples.test
@@ -0,0 +1,30 @@
+Tests for conversion between text and binary encoded sample profiles.
+
+1- Encode the original profile into binary form. All the tests below will use
+ the binary profile.
+RUN: llvm-profdata merge --sample %p/Inputs/inline-samples.afdo -o %t.profbin
+
+2- Show all functions. This profile has a single main() function with several
+ inlined callees.
+RUN: llvm-profdata show --sample %t.profbin | FileCheck %s --check-prefix=SHOW1
+SHOW1: Function: main: 366846, 0, 6 sampled lines
+SHOW1: line offset: 2, discriminator: 3, inlined callee: _Z3fool: 246044, 0, 3 sampled lines
+SHOW1: line offset: 1, discriminator: 3, inlined callee: _Z3bari: 0, 0, 2 sampled lines
+SHOW1: line offset: 1, discriminator: 8, inlined callee: _Z3bari: 0, 0, 2 sampled lines
+SHOW1: line offset: 1, discriminator: 7, inlined callee: _Z3bari: 99492, 0, 2 sampled lines
+SHOW1: line offset: 1, discriminator: 2, number of samples: 46732
+
+3- Convert the binary profile to text encoding and check that they are both
+ identical.
+RUN: llvm-profdata merge --sample %t.profbin --text -o - | llvm-profdata show --sample - -o %t-bintext
+RUN: llvm-profdata show --sample %p/Inputs/inline-samples.afdo -o %t-text
+RUN: diff %t-bintext %t-text
+
+4- Merge the binary and text encodings of the profile and check that the
+ counters have doubled.
+RUN: llvm-profdata merge --sample --text %t.profbin %p/Inputs/inline-samples.afdo -o - | FileCheck %s --check-prefix=MERGE1
+MERGE1: main:733692:0
+MERGE1: 2.3: 120802
+MERGE1: 2.3: _Z3fool:492088
+MERGE1: 1.7: _Z3bari:198984
+MERGE1: 1.1: 105520
OpenPOWER on IntegriCloud