From: Xinliang David Li Date: Mon, 14 Dec 2015 18:44:01 +0000 (+0000) Subject: [PGO] Value profiling text format reader/writer support X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ea0570fdaf61c451e0b4003b30701bd6b95ada26;p=oota-llvm.git [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 --- diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 304606de679..7056057e50f 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -106,8 +106,13 @@ private: /// Iterator over the profile data. line_iterator Line; + // String table for holding a unique copy of all the strings in the profile. + InstrProfStringTable StringTable; + TextInstrProfReader(const TextInstrProfReader &) = delete; TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; + std::error_code readValueProfileData(InstrProfRecord &Record); + public: TextInstrProfReader(std::unique_ptr DataBuffer_) : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} diff --git a/lib/ProfileData/InstrProfReader.cpp b/lib/ProfileData/InstrProfReader.cpp index da68242b461..aca43544145 100644 --- a/lib/ProfileData/InstrProfReader.cpp +++ b/lib/ProfileData/InstrProfReader.cpp @@ -109,6 +109,68 @@ bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) { [](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 CurrentValues; + for (uint32_t V = 0; V < NumValueData; V++) { + CHECK_LINE_END(Line); + std::pair 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) { // Skip empty lines and comments. 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); } + // Check if value profile data exists and read it if so. + if (std::error_code EC = readValueProfileData(Record)) + return EC; + return success(); } diff --git a/lib/ProfileData/InstrProfWriter.cpp b/lib/ProfileData/InstrProfWriter.cpp index 78bec012eeb..026912006b7 100644 --- a/lib/ProfileData/InstrProfWriter.cpp +++ b/lib/ProfileData/InstrProfWriter.cpp @@ -172,15 +172,47 @@ void InstrProfWriter::write(raw_fd_ostream &OS) { endian::Writer(OS).write(TableStart.second); } +static const char *ValueProfKindStr[] = { +#define VALUE_PROF_KIND(Enumerator, Value) #Enumerator, +#include "llvm/ProfileData/InstrProfData.inc" +}; + void InstrProfWriter::writeRecordInText(const InstrProfRecord &Func, raw_fd_ostream &OS) { OS << Func.Name << "\n"; OS << "# Func Hash:\n" << Func.Hash << "\n"; - OS << "# Num Counters:\n" < VD = Func.getValueForSite(VK, S); + for (uint32_t I = 0; I < ND; I++) { + if (VK == IPVK_IndirectCallTarget) + OS << reinterpret_cast(VD[I].Value) << ":" + << VD[I].Count << "\n"; + else + OS << VD[I].Value << ":" << VD[I].Count << "\n"; + } + } + } + OS << "\n"; } diff --git a/test/tools/llvm-profdata/Inputs/vp-malform.proftext b/test/tools/llvm-profdata/Inputs/vp-malform.proftext new file mode 100644 index 00000000000..2db3096cecf --- /dev/null +++ b/test/tools/llvm-profdata/Inputs/vp-malform.proftext @@ -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 diff --git a/test/tools/llvm-profdata/Inputs/vp-malform2.proftext b/test/tools/llvm-profdata/Inputs/vp-malform2.proftext new file mode 100644 index 00000000000..02ed5a968d8 --- /dev/null +++ b/test/tools/llvm-profdata/Inputs/vp-malform2.proftext @@ -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 diff --git a/test/tools/llvm-profdata/Inputs/vp-truncate.proftext b/test/tools/llvm-profdata/Inputs/vp-truncate.proftext new file mode 100644 index 00000000000..98b4b572b65 --- /dev/null +++ b/test/tools/llvm-profdata/Inputs/vp-truncate.proftext @@ -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 diff --git a/test/tools/llvm-profdata/text-format-errors.test b/test/tools/llvm-profdata/text-format-errors.test index c8500bfac76..b300586d102 100644 --- a/test/tools/llvm-profdata/text-format-errors.test +++ b/test/tools/llvm-profdata/text-format-errors.test @@ -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 BINARY: error: {{.+}}: Unrecognized instrumentation profile encoding format 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 diff --git a/test/tools/llvm-profdata/value-prof.proftext b/test/tools/llvm-profdata/value-prof.proftext new file mode 100644 index 00000000000..effa6d5754a --- /dev/null +++ b/test/tools/llvm-profdata/value-prof.proftext @@ -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