mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-13 17:20:28 +00:00
[PGO] Value profiling text format reader/writer support
This patch adds the missing functionality in parsable text format support for value profiling. Differential Revision: http://reviews.llvm.org/D15212 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255523 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
868145efb0
commit
ea0570fdaf
@ -106,8 +106,13 @@ private:
|
|||||||
/// Iterator over the profile data.
|
/// Iterator over the profile data.
|
||||||
line_iterator Line;
|
line_iterator Line;
|
||||||
|
|
||||||
|
// String table for holding a unique copy of all the strings in the profile.
|
||||||
|
InstrProfStringTable StringTable;
|
||||||
|
|
||||||
TextInstrProfReader(const TextInstrProfReader &) = delete;
|
TextInstrProfReader(const TextInstrProfReader &) = delete;
|
||||||
TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
|
TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
|
||||||
|
std::error_code readValueProfileData(InstrProfRecord &Record);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
|
TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
|
||||||
: DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
|
: DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
|
||||||
|
@ -109,6 +109,68 @@ bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
|
|||||||
[](char c) { return ::isprint(c) || ::isspace(c); });
|
[](char c) { return ::isprint(c) || ::isspace(c); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::error_code
|
||||||
|
TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
|
||||||
|
|
||||||
|
#define CHECK_LINE_END(Line) \
|
||||||
|
if (Line.is_at_end()) \
|
||||||
|
return error(instrprof_error::truncated);
|
||||||
|
#define READ_NUM(Str, Dst) \
|
||||||
|
if ((Str).getAsInteger(10, (Dst))) \
|
||||||
|
return error(instrprof_error::malformed);
|
||||||
|
#define VP_READ_ADVANCE(Val) \
|
||||||
|
CHECK_LINE_END(Line); \
|
||||||
|
uint32_t Val; \
|
||||||
|
READ_NUM((*Line), (Val)); \
|
||||||
|
Line++;
|
||||||
|
|
||||||
|
if (Line.is_at_end())
|
||||||
|
return success();
|
||||||
|
uint32_t NumValueKinds;
|
||||||
|
if (Line->getAsInteger(10, NumValueKinds)) {
|
||||||
|
// No value profile data
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
|
||||||
|
return error(instrprof_error::malformed);
|
||||||
|
Line++;
|
||||||
|
|
||||||
|
for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
|
||||||
|
VP_READ_ADVANCE(ValueKind);
|
||||||
|
if (ValueKind > IPVK_Last)
|
||||||
|
return error(instrprof_error::malformed);
|
||||||
|
VP_READ_ADVANCE(NumValueSites);
|
||||||
|
if (!NumValueSites)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Record.reserveSites(VK, NumValueSites);
|
||||||
|
for (uint32_t S = 0; S < NumValueSites; S++) {
|
||||||
|
VP_READ_ADVANCE(NumValueData);
|
||||||
|
|
||||||
|
std::vector<InstrProfValueData> CurrentValues;
|
||||||
|
for (uint32_t V = 0; V < NumValueData; V++) {
|
||||||
|
CHECK_LINE_END(Line);
|
||||||
|
std::pair<StringRef, StringRef> VD = Line->split(':');
|
||||||
|
uint64_t TakenCount, Value;
|
||||||
|
READ_NUM(VD.second, TakenCount);
|
||||||
|
if (VK == IPVK_IndirectCallTarget)
|
||||||
|
Value = (uint64_t)StringTable.insertString(VD.first);
|
||||||
|
else {
|
||||||
|
READ_NUM(VD.first, Value);
|
||||||
|
}
|
||||||
|
CurrentValues.push_back({Value, TakenCount});
|
||||||
|
Line++;
|
||||||
|
}
|
||||||
|
Record.addValueData(VK, S, CurrentValues.data(), NumValueData, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success();
|
||||||
|
|
||||||
|
#undef CHECK_LINE_END
|
||||||
|
#undef READ_NUM
|
||||||
|
#undef VP_READ_ADVANCE
|
||||||
|
}
|
||||||
|
|
||||||
std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) {
|
std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) {
|
||||||
// Skip empty lines and comments.
|
// Skip empty lines and comments.
|
||||||
while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
|
while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
|
||||||
@ -147,6 +209,10 @@ std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) {
|
|||||||
Record.Counts.push_back(Count);
|
Record.Counts.push_back(Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if value profile data exists and read it if so.
|
||||||
|
if (std::error_code EC = readValueProfileData(Record))
|
||||||
|
return EC;
|
||||||
|
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,15 +172,47 @@ void InstrProfWriter::write(raw_fd_ostream &OS) {
|
|||||||
endian::Writer<little>(OS).write<uint64_t>(TableStart.second);
|
endian::Writer<little>(OS).write<uint64_t>(TableStart.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *ValueProfKindStr[] = {
|
||||||
|
#define VALUE_PROF_KIND(Enumerator, Value) #Enumerator,
|
||||||
|
#include "llvm/ProfileData/InstrProfData.inc"
|
||||||
|
};
|
||||||
|
|
||||||
void InstrProfWriter::writeRecordInText(const InstrProfRecord &Func,
|
void InstrProfWriter::writeRecordInText(const InstrProfRecord &Func,
|
||||||
raw_fd_ostream &OS) {
|
raw_fd_ostream &OS) {
|
||||||
OS << Func.Name << "\n";
|
OS << Func.Name << "\n";
|
||||||
OS << "# Func Hash:\n" << Func.Hash << "\n";
|
OS << "# Func Hash:\n" << Func.Hash << "\n";
|
||||||
OS << "# Num Counters:\n" <<Func.Counts.size() << "\n";
|
OS << "# Num Counters:\n" << Func.Counts.size() << "\n";
|
||||||
OS << "# Counter Values:\n";
|
OS << "# Counter Values:\n";
|
||||||
for (uint64_t Count : Func.Counts)
|
for (uint64_t Count : Func.Counts)
|
||||||
OS << Count << "\n";
|
OS << Count << "\n";
|
||||||
|
|
||||||
|
uint32_t NumValueKinds = Func.getNumValueKinds();
|
||||||
|
if (!NumValueKinds) {
|
||||||
|
OS << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OS << "# Num Value Kinds:\n" << Func.getNumValueKinds() << "\n";
|
||||||
|
for (uint32_t VK = 0; VK < IPVK_Last + 1; VK++) {
|
||||||
|
uint32_t NS = Func.getNumValueSites(VK);
|
||||||
|
if (!NS)
|
||||||
|
continue;
|
||||||
|
OS << "# ValueKind = " << ValueProfKindStr[VK] << ":\n" << VK << "\n";
|
||||||
|
OS << "# NumValueSites:\n" << NS << "\n";
|
||||||
|
for (uint32_t S = 0; S < NS; S++) {
|
||||||
|
uint32_t ND = Func.getNumValueDataForSite(VK, S);
|
||||||
|
OS << ND << "\n";
|
||||||
|
std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, S);
|
||||||
|
for (uint32_t I = 0; I < ND; I++) {
|
||||||
|
if (VK == IPVK_IndirectCallTarget)
|
||||||
|
OS << reinterpret_cast<const char *>(VD[I].Value) << ":"
|
||||||
|
<< VD[I].Count << "\n";
|
||||||
|
else
|
||||||
|
OS << VD[I].Value << ":" << VD[I].Count << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OS << "\n";
|
OS << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
test/tools/llvm-profdata/Inputs/vp-malform.proftext
Normal file
42
test/tools/llvm-profdata/Inputs/vp-malform.proftext
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
foo
|
||||||
|
# Func Hash:
|
||||||
|
10
|
||||||
|
# Num Counters:
|
||||||
|
2
|
||||||
|
# Counter Values:
|
||||||
|
999000
|
||||||
|
359800
|
||||||
|
|
||||||
|
foo2
|
||||||
|
# Func Hash:
|
||||||
|
10
|
||||||
|
# Num Counters:
|
||||||
|
2
|
||||||
|
# Counter Values:
|
||||||
|
1001000
|
||||||
|
360200
|
||||||
|
|
||||||
|
main
|
||||||
|
# Func Hash:
|
||||||
|
16650
|
||||||
|
# Num Counters:
|
||||||
|
4
|
||||||
|
# Counter Values:
|
||||||
|
2
|
||||||
|
2000
|
||||||
|
2000000
|
||||||
|
999000
|
||||||
|
# NumValueKinds
|
||||||
|
1
|
||||||
|
# Value Kind IPVK_IndirectCallTarget
|
||||||
|
0
|
||||||
|
# NumSites
|
||||||
|
3
|
||||||
|
# Values for each site
|
||||||
|
0
|
||||||
|
2
|
||||||
|
# !!!! Malformed Value/Count pair
|
||||||
|
foo+100
|
||||||
|
foo2:1000
|
||||||
|
1
|
||||||
|
foo2:20000
|
32
test/tools/llvm-profdata/Inputs/vp-malform2.proftext
Normal file
32
test/tools/llvm-profdata/Inputs/vp-malform2.proftext
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
foo
|
||||||
|
# Func Hash:
|
||||||
|
10
|
||||||
|
# Num Counters:
|
||||||
|
2
|
||||||
|
# Counter Values:
|
||||||
|
999000
|
||||||
|
359800
|
||||||
|
|
||||||
|
main
|
||||||
|
# Func Hash:
|
||||||
|
16650
|
||||||
|
# Num Counters:
|
||||||
|
4
|
||||||
|
# Counter Values:
|
||||||
|
2
|
||||||
|
2000
|
||||||
|
2000000
|
||||||
|
999000
|
||||||
|
# NumValueKinds
|
||||||
|
1
|
||||||
|
# Value Kind IPVK_IndirectCallTarget
|
||||||
|
0
|
||||||
|
# NumSites
|
||||||
|
3
|
||||||
|
# Values for each site
|
||||||
|
0
|
||||||
|
# !! Malformed value site, missing one value
|
||||||
|
2
|
||||||
|
foo:100
|
||||||
|
1
|
||||||
|
foo2:20000
|
36
test/tools/llvm-profdata/Inputs/vp-truncate.proftext
Normal file
36
test/tools/llvm-profdata/Inputs/vp-truncate.proftext
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
foo
|
||||||
|
# Func Hash:
|
||||||
|
10
|
||||||
|
# Num Counters:
|
||||||
|
2
|
||||||
|
# Counter Values:
|
||||||
|
999000
|
||||||
|
359800
|
||||||
|
|
||||||
|
foo2
|
||||||
|
# Func Hash:
|
||||||
|
10
|
||||||
|
# Num Counters:
|
||||||
|
2
|
||||||
|
# Counter Values:
|
||||||
|
1001000
|
||||||
|
360200
|
||||||
|
|
||||||
|
main
|
||||||
|
# Func Hash:
|
||||||
|
16650
|
||||||
|
# Num Counters:
|
||||||
|
4
|
||||||
|
# Counter Values:
|
||||||
|
2
|
||||||
|
2000
|
||||||
|
2000000
|
||||||
|
999000
|
||||||
|
# NumValueKinds
|
||||||
|
1
|
||||||
|
# Value Kind IPVK_IndirectCallTarget
|
||||||
|
0
|
||||||
|
# NumSites
|
||||||
|
3
|
||||||
|
# Values for each site
|
||||||
|
0
|
@ -18,3 +18,12 @@ NO-COUNTS: error: {{.*}}no-counts.proftext: Malformed instrumentation profile da
|
|||||||
RUN: not llvm-profdata show %p/Inputs/text-format-errors.text.bin 2>&1 | FileCheck %s --check-prefix=BINARY
|
RUN: not llvm-profdata show %p/Inputs/text-format-errors.text.bin 2>&1 | FileCheck %s --check-prefix=BINARY
|
||||||
BINARY: error: {{.+}}: Unrecognized instrumentation profile encoding format
|
BINARY: error: {{.+}}: Unrecognized instrumentation profile encoding format
|
||||||
BINARY: Perhaps you forgot to use the -sample option?
|
BINARY: Perhaps you forgot to use the -sample option?
|
||||||
|
|
||||||
|
5- Detect malformed value profile data
|
||||||
|
RUN: not llvm-profdata show %p/Inputs/vp-malform.proftext 2>&1 | FileCheck %s --check-prefix=VP
|
||||||
|
RUN: not llvm-profdata show %p/Inputs/vp-malform2.proftext 2>&1 | FileCheck %s --check-prefix=VP
|
||||||
|
VP: Malformed instrumentation profile data
|
||||||
|
|
||||||
|
6- Detect truncated value profile data
|
||||||
|
RUN: not llvm-profdata show %p/Inputs/vp-truncate.proftext 2>&1 | FileCheck %s --check-prefix=VPTRUNC
|
||||||
|
VPTRUNC: Truncated profile data
|
||||||
|
61
test/tools/llvm-profdata/value-prof.proftext
Normal file
61
test/tools/llvm-profdata/value-prof.proftext
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# RUN: llvm-profdata show -ic-targets -all-functions %s | FileCheck %s --check-prefix=IC
|
||||||
|
# RUN: llvm-profdata show -ic-targets -counts -text -all-functions %s | FileCheck %s --check-prefix=ICTEXT
|
||||||
|
# RUN: llvm-profdata merge -o %t.profdata %s
|
||||||
|
# RUN: llvm-profdata show -ic-targets -all-functions %t.profdata | FileCheck %s --check-prefix=IC
|
||||||
|
|
||||||
|
foo
|
||||||
|
# Func Hash:
|
||||||
|
10
|
||||||
|
# Num Counters:
|
||||||
|
2
|
||||||
|
# Counter Values:
|
||||||
|
999000
|
||||||
|
359800
|
||||||
|
|
||||||
|
foo2
|
||||||
|
# Func Hash:
|
||||||
|
10
|
||||||
|
# Num Counters:
|
||||||
|
2
|
||||||
|
# Counter Values:
|
||||||
|
1001000
|
||||||
|
360200
|
||||||
|
|
||||||
|
main
|
||||||
|
# Func Hash:
|
||||||
|
16650
|
||||||
|
# Num Counters:
|
||||||
|
4
|
||||||
|
# Counter Values:
|
||||||
|
2
|
||||||
|
2000
|
||||||
|
2000000
|
||||||
|
999000
|
||||||
|
# NumValueKinds
|
||||||
|
1
|
||||||
|
# Value Kind IPVK_IndirectCallTarget
|
||||||
|
0
|
||||||
|
# NumSites
|
||||||
|
3
|
||||||
|
# Values for each site
|
||||||
|
0
|
||||||
|
2
|
||||||
|
foo:100
|
||||||
|
foo2:1000
|
||||||
|
1
|
||||||
|
foo2:20000
|
||||||
|
|
||||||
|
#IC: Indirect Call Site Count: 3
|
||||||
|
#IC-NEXT: Indirect Target Results:
|
||||||
|
#IC-NEXT: [ 1, foo, 100 ]
|
||||||
|
#IC-NEXT: [ 1, foo2, 1000 ]
|
||||||
|
#IC-NEXT: [ 2, foo2, 20000 ]
|
||||||
|
|
||||||
|
#ICTEXT: foo:100
|
||||||
|
#ICTEXT-NEXT: foo2:1000
|
||||||
|
#ICTEXT-NEXT: 1
|
||||||
|
#ICTEXT-NEXT: foo2:20000
|
||||||
|
# RUN: llvm-profdata show -ic-targets -all-functions %s | FileCheck %s --check-prefix=IC
|
||||||
|
# RUN: llvm-profdata show -ic-targets -counts -text -all-functions %s | FileCheck %s --check-prefix=ICTEXT
|
||||||
|
# RUN: llvm-profdata merge -o %t.profdata %s
|
||||||
|
# RUN: llvm-profdata show -ic-targets -all-functions %t.profdata | FileCheck %s --check-prefix=IC
|
Loading…
x
Reference in New Issue
Block a user