From 4e540995b12e3599cdb5a23f936a87a5c037cdae Mon Sep 17 00:00:00 2001 From: Gulfem Savrun Yeniceri Date: Thu, 6 May 2021 16:09:12 +0000 Subject: [PATCH] [profile] Add binary id into profiles This patch adds binary id into profiles to easily associate binaries with the corresponding profiles. There is an RFC that discusses the motivation, design and implementation in more detail: https://lists.llvm.org/pipermail/llvm-dev/2021-June/151154.html Differential Revision: https://reviews.llvm.org/D102039 --- include/llvm/ProfileData/InstrProf.h | 1 + include/llvm/ProfileData/InstrProfData.inc | 3 +- include/llvm/ProfileData/InstrProfReader.h | 7 ++++ lib/ProfileData/InstrProfReader.cpp | 37 +++++++++++++++++- .../llvm-profdata/Inputs/c-general.profraw | Bin 1696 -> 1800 bytes .../llvm-profdata/Inputs/compressed.profraw | Bin 1648 -> 1752 bytes test/tools/llvm-profdata/c-general.test | 2 +- .../malformed-ptr-to-counter-array.test | 4 +- test/tools/llvm-profdata/raw-32-bits-be.test | 3 +- test/tools/llvm-profdata/raw-32-bits-le.test | 3 +- test/tools/llvm-profdata/raw-64-bits-be.test | 3 +- test/tools/llvm-profdata/raw-64-bits-le.test | 3 +- .../tools/llvm-profdata/raw-two-profiles.test | 6 ++- tools/llvm-profdata/llvm-profdata.cpp | 19 ++++++--- 14 files changed, 74 insertions(+), 17 deletions(-) diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index 1681c048070..08a934e6985 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -1103,6 +1103,7 @@ namespace RawInstrProf { // raw header. // Version 5: Bit 60 of FuncHash is reserved for the flag for the context // sensitive records. +// Version 6: Added binary id. const uint64_t Version = INSTR_PROF_RAW_VERSION; template inline uint64_t getMagic(); diff --git a/include/llvm/ProfileData/InstrProfData.inc b/include/llvm/ProfileData/InstrProfData.inc index bd625457260..08a64246962 100644 --- a/include/llvm/ProfileData/InstrProfData.inc +++ b/include/llvm/ProfileData/InstrProfData.inc @@ -137,6 +137,7 @@ INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize) INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin) INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin) INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) +INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL)) #undef INSTR_PROF_RAW_HEADER /* INSTR_PROF_RAW_HEADER end */ @@ -645,7 +646,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129 /* Raw profile format version (start from 1). */ -#define INSTR_PROF_RAW_VERSION 5 +#define INSTR_PROF_RAW_VERSION 6 /* Indexed profile format version (start from 1). */ #define INSTR_PROF_INDEX_VERSION 7 /* Coverage mapping format version (start from 0). */ diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 6746f0c2e55..501c6f011d5 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -82,6 +82,9 @@ public: /// Read a single record. virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0; + /// Print binary ids on stream OS. + virtual Error printBinaryIds(raw_ostream &OS) { return success(); }; + /// Iterator over profile data. InstrProfIterator begin() { return InstrProfIterator(this); } InstrProfIterator end() { return InstrProfIterator(); } @@ -222,6 +225,9 @@ private: uint32_t ValueKindLast; uint32_t CurValueDataSize; + uint64_t BinaryIdsSize; + const uint8_t *BinaryIdsStart; + public: RawInstrProfReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)) {} @@ -231,6 +237,7 @@ public: static bool hasFormat(const MemoryBuffer &DataBuffer); Error readHeader() override; Error readNextRecord(NamedInstrProfRecord &Record) override; + Error printBinaryIds(raw_ostream &OS) override; bool isIRLevelProfile() const override { return (Version & VARIANT_MASK_IR_PROF) != 0; diff --git a/lib/ProfileData/InstrProfReader.cpp b/lib/ProfileData/InstrProfReader.cpp index fa7610c4200..8a4470ae207 100644 --- a/lib/ProfileData/InstrProfReader.cpp +++ b/lib/ProfileData/InstrProfReader.cpp @@ -24,8 +24,8 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SymbolRemappingReader.h" #include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/SymbolRemappingReader.h" #include #include #include @@ -374,11 +374,13 @@ Error RawInstrProfReader::readHeader( auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters); NamesSize = swap(Header.NamesSize); ValueKindLast = swap(Header.ValueKindLast); + BinaryIdsSize = swap(Header.BinaryIdsSize); auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData); auto PaddingSize = getNumPaddingBytes(NamesSize); - ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); + // Profile data starts after profile header and binary ids if exist. + ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdsSize; ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes + PaddingBytesBeforeCounters; ptrdiff_t NamesOffset = CountersOffset + (sizeof(uint64_t) * CountersSize) + @@ -392,6 +394,10 @@ Error RawInstrProfReader::readHeader( Data = reinterpret_cast *>( Start + DataOffset); DataEnd = Data + DataSize; + + // Binary ids start just after the header. + BinaryIdsStart = + reinterpret_cast(&Header) + sizeof(RawInstrProf::Header); CountersStart = reinterpret_cast(Start + CountersOffset); NamesStart = Start + NamesOffset; ValueDataStart = reinterpret_cast(Start + ValueDataOffset); @@ -506,6 +512,33 @@ Error RawInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) return success(); } +template +Error RawInstrProfReader::printBinaryIds(raw_ostream &OS) { + if (BinaryIdsSize == 0) + return success(); + + OS << "Binary IDs: \n"; + const uint8_t *BI = BinaryIdsStart; + while (BI < BinaryIdsStart + BinaryIdsSize) { + uint64_t BinaryIdLen = swap(*reinterpret_cast(BI)); + // Increment by binary id length data type size. + BI += sizeof(BinaryIdLen); + if (BI > (const uint8_t *)DataBuffer->getBufferEnd()) + return make_error(instrprof_error::malformed); + + for (uint64_t I = 0; I < BinaryIdLen; I++) + OS << format("%02x", BI[I]); + OS << "\n"; + + // Increment by binary id data length. + BI += BinaryIdLen; + if (BI > (const uint8_t *)DataBuffer->getBufferEnd()) + return make_error(instrprof_error::malformed); + } + + return success(); +} + namespace llvm { template class RawInstrProfReader; diff --git a/test/tools/llvm-profdata/Inputs/c-general.profraw b/test/tools/llvm-profdata/Inputs/c-general.profraw index c453d806770d82b673e80e0b66f20f73d07ab419..249f22b518e8a7778c7d5101bd85e111665923bd 100644 GIT binary patch delta 539 zcmZ3$+rg*USd^AuRFLzZjR699pfrrCoTw;n8F0t}%;)Ta(2QUng1Fw^Df0W}Z1#(0 zE^`EOSr}mI873#Ph)-6wz&s+GX z`i(;lP#GXK@vO9{^c>GvljMgN6b>Ux{FN59%V=&sxnL&41!RfIx{T7I*Zzm?Xp73+ zmT?40%j8%_<@yiEA_#jJ_@L~sQ*Bwi17d~aFB*mEKbKpRa1_Y|B=s=YD?B}%x%XpC z<%Mey$rCu#Gee{&|7YYBob>9$jHLDt6%Sx)K|wazfJuOp;TY7m$&Sq8lM|Q(csXDq zApMhTnVKiRU=o;of>~g*0J8=YCoEQ+CL6MfE5dk65X%?@p|m25o_vrAXe_J3Sd^AuRFLzZl>q{Hpfrriov0`-$e*hg^Eivf(c(<)v+rik;@MhM0af4d z2~|BOM14I&=#&ag*7>S&Z_j=+jeF^K=Kxg0h0mxO#Gn=wYM!!DYnrtGsrR~xpV_&V z7AQh|6YvdHy)ab0y{}AOLc3!%Gk<>PIf?(TIFumj5BvbBpPa_141ds-4m6&Y6b^`!aEM`9d diff --git a/test/tools/llvm-profdata/Inputs/compressed.profraw b/test/tools/llvm-profdata/Inputs/compressed.profraw index dabb8cb4d4c7adfbbe6c927b10c340e315d35758..c096cbff812a42016830f161101255d0f169f5ab 100644 GIT binary patch delta 539 zcmeysbAwm0u_!ISs37M*8v_LJKxr6NIZ;vEGT@K{n9tb-p&7wE1aZB+Q{?x{+3Xk1 zT;>SmvM|8ZGfYlo5uez=;Tm+=G(yZq(52uI!~ld=2#Xggz~XtFMdN63rfrNapSSQ& z^&5vApfW&e;#p}?={cUUCdm&kC>%zX_$w`Hm(kpOa=}c73&;|abs42aul*0((H51t zE#nB1mdUY<%Jm8=wGBr)0RXf!XPE#1 delta 573 zcmcb?`+-NXu_!ISs37M*D+2`ZKxr72J5froERux4-@=Q4-tgv zV1Y84*Rn4C=-ihvtH&mp(MrQg0cyyC22}OjQ1vXH$5}Lv7H4XoeK&I!&(@*}sCtDa zRP~$?_4N#)Qz|rB=c~rOJ^Rfx?xowE15gbG&8Qm0pcWKrp0ZJEnza9^_qvIn*}0Y$ zY=o%$(2A;F7^>dhS0*o^-LaaPKfm*w#Q#?un;_~EIzaT~G)5)Q2~eR6U8qKIK#ll1 z)t1FOAXeD)vz~q!Q^uSNQ1ugfP}OrzzQ`zUE3p}BK_99tGt{)&7tfCrOndEQdx2$U zMD*Tx1E_k2exUlvs!Ynf0Z@?*V3AOuNCZ?wVFE}^D^v4i0cL^83CtXu4VV>}6rG?( j3qolnD6I&kjV3Q-RiAu;m1FV-RtX>t(ke08fNcc;dCPHv diff --git a/test/tools/llvm-profdata/c-general.test b/test/tools/llvm-profdata/c-general.test index ae4bc0a34d2..7c48f7b04a0 100644 --- a/test/tools/llvm-profdata/c-general.test +++ b/test/tools/llvm-profdata/c-general.test @@ -14,7 +14,7 @@ RUN: llvm-profdata show %p/Inputs/c-general.profraw -o - --function=switches | F SWITCHES-LABEL: Counters: SWITCHES-NEXT: switches: -SWITCHES-NEXT: Hash: 0xa50a07f391ae4be5 +SWITCHES-NEXT: Hash: 0x0099a0c98383683e SWITCHES-NEXT: Counters: 19 SWITCHES-NEXT: Function count: 1 SWITCHES-LABEL: Functions shown: 1 diff --git a/test/tools/llvm-profdata/malformed-ptr-to-counter-array.test b/test/tools/llvm-profdata/malformed-ptr-to-counter-array.test index 5df43f4b9f9..c60188236f8 100644 --- a/test/tools/llvm-profdata/malformed-ptr-to-counter-array.test +++ b/test/tools/llvm-profdata/malformed-ptr-to-counter-array.test @@ -8,9 +8,10 @@ // INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin) // INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin) // INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) +// INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL)) RUN: printf '\201rforpl\377' > %t.profraw -RUN: printf '\5\0\0\0\0\0\0\0' >> %t.profraw +RUN: printf '\6\0\0\0\0\0\0\0' >> %t.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw RUN: printf '\2\0\0\0\0\0\0\0' >> %t.profraw @@ -19,6 +20,7 @@ RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw RUN: printf '\0\0\6\0\1\0\0\0' >> %t.profraw RUN: printf '\0\0\6\0\2\0\0\0' >> %t.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw // Data Section // diff --git a/test/tools/llvm-profdata/raw-32-bits-be.test b/test/tools/llvm-profdata/raw-32-bits-be.test index cebd25a07f4..3f8e8427da3 100644 --- a/test/tools/llvm-profdata/raw-32-bits-be.test +++ b/test/tools/llvm-profdata/raw-32-bits-be.test @@ -1,5 +1,5 @@ RUN: printf '\377lprofR\201' > %t -RUN: printf '\0\0\0\0\0\0\0\5' >> %t +RUN: printf '\0\0\0\0\0\0\0\6' >> %t RUN: printf '\0\0\0\0\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\3' >> %t @@ -8,6 +8,7 @@ RUN: printf '\0\0\0\0\0\0\0\20' >> %t RUN: printf '\0\0\0\0\1\0\0\0' >> %t RUN: printf '\0\0\0\0\2\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\134\370\302\114\333\030\275\254' >> %t RUN: printf '\0\0\0\0\0\0\0\1' >> %t diff --git a/test/tools/llvm-profdata/raw-32-bits-le.test b/test/tools/llvm-profdata/raw-32-bits-le.test index a176f80ec95..04a6e817543 100644 --- a/test/tools/llvm-profdata/raw-32-bits-le.test +++ b/test/tools/llvm-profdata/raw-32-bits-le.test @@ -1,5 +1,5 @@ RUN: printf '\201Rforpl\377' > %t -RUN: printf '\5\0\0\0\0\0\0\0' >> %t +RUN: printf '\6\0\0\0\0\0\0\0' >> %t RUN: printf '\2\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\3\0\0\0\0\0\0\0' >> %t @@ -8,6 +8,7 @@ RUN: printf '\20\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\1\0\0\0\0' >> %t RUN: printf '\0\0\0\2\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\254\275\030\333\114\302\370\134' >> %t RUN: printf '\1\0\0\0\0\0\0\0' >> %t diff --git a/test/tools/llvm-profdata/raw-64-bits-be.test b/test/tools/llvm-profdata/raw-64-bits-be.test index c679207102e..ec624ea4be2 100644 --- a/test/tools/llvm-profdata/raw-64-bits-be.test +++ b/test/tools/llvm-profdata/raw-64-bits-be.test @@ -1,5 +1,5 @@ RUN: printf '\377lprofr\201' > %t -RUN: printf '\0\0\0\0\0\0\0\5' >> %t +RUN: printf '\0\0\0\0\0\0\0\6' >> %t RUN: printf '\0\0\0\0\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\3' >> %t @@ -8,6 +8,7 @@ RUN: printf '\0\0\0\0\0\0\0\20' >> %t RUN: printf '\0\0\0\1\0\4\0\0' >> %t RUN: printf '\0\0\0\2\0\4\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\134\370\302\114\333\030\275\254' >> %t RUN: printf '\0\0\0\0\0\0\0\1' >> %t diff --git a/test/tools/llvm-profdata/raw-64-bits-le.test b/test/tools/llvm-profdata/raw-64-bits-le.test index 8e179a87162..80564458d37 100644 --- a/test/tools/llvm-profdata/raw-64-bits-le.test +++ b/test/tools/llvm-profdata/raw-64-bits-le.test @@ -1,5 +1,5 @@ RUN: printf '\201rforpl\377' > %t -RUN: printf '\5\0\0\0\0\0\0\0' >> %t +RUN: printf '\6\0\0\0\0\0\0\0' >> %t RUN: printf '\2\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\3\0\0\0\0\0\0\0' >> %t @@ -8,6 +8,7 @@ RUN: printf '\20\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\4\0\1\0\0\0' >> %t RUN: printf '\0\0\4\0\2\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\254\275\030\333\114\302\370\134' >> %t RUN: printf '\1\0\0\0\0\0\0\0' >> %t diff --git a/test/tools/llvm-profdata/raw-two-profiles.test b/test/tools/llvm-profdata/raw-two-profiles.test index 9cd8a8c7b00..a4f97a582d2 100644 --- a/test/tools/llvm-profdata/raw-two-profiles.test +++ b/test/tools/llvm-profdata/raw-two-profiles.test @@ -1,5 +1,5 @@ RUN: printf '\201rforpl\377' > %t-foo.profraw -RUN: printf '\5\0\0\0\0\0\0\0' >> %t-foo.profraw +RUN: printf '\6\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw @@ -8,6 +8,7 @@ RUN: printf '\10\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\4\0\1\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\4\0\2\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\254\275\030\333\114\302\370\134' >> %t-foo.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw @@ -20,7 +21,7 @@ RUN: printf '\023\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\3\0foo\0\0\0' >> %t-foo.profraw RUN: printf '\201rforpl\377' > %t-bar.profraw -RUN: printf '\5\0\0\0\0\0\0\0' >> %t-bar.profraw +RUN: printf '\6\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\2\0\0\0\0\0\0\0' >> %t-bar.profraw @@ -29,6 +30,7 @@ RUN: printf '\10\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\6\0\1\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\6\0\2\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\067\265\035\031\112\165\023\344' >> %t-bar.profraw RUN: printf '\02\0\0\0\0\0\0\0' >> %t-bar.profraw diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp index b61df6eacdc..66d70120ac9 100644 --- a/tools/llvm-profdata/llvm-profdata.cpp +++ b/tools/llvm-profdata/llvm-profdata.cpp @@ -2069,7 +2069,7 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts, bool ShowAllFunctions, bool ShowCS, uint64_t ValueCutoff, bool OnlyListBelow, const std::string &ShowFunction, bool TextFormat, - raw_fd_ostream &OS) { + bool ShowBinaryIds, raw_fd_ostream &OS) { auto ReaderOrErr = InstrProfReader::create(Filename); std::vector Cutoffs = std::move(DetailedSummaryCutoffs); if (ShowDetailedSummary && Cutoffs.empty()) { @@ -2251,6 +2251,11 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts, OS << "Total count: " << PS->getTotalCount() << "\n"; PS->printDetailedSummary(OS); } + + if (ShowBinaryIds) + if (Error E = Reader->printBinaryIds(OS)) + exitWithError(std::move(E), Filename); + return 0; } @@ -2501,6 +2506,8 @@ static int show_main(int argc, const char *argv[]) { cl::desc("Show the information of each section in the sample profile. " "The flag is only usable when the sample profile is in " "extbinary format")); + cl::opt ShowBinaryIds("binary-ids", cl::init(false), + cl::desc("Show binary ids in the profile. ")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); @@ -2519,11 +2526,11 @@ static int show_main(int argc, const char *argv[]) { WithColor::warning() << "-function argument ignored: showing all functions\n"; if (ProfileKind == instr) - return showInstrProfile(Filename, ShowCounts, TopNFunctions, - ShowIndirectCallTargets, ShowMemOPSizes, - ShowDetailedSummary, DetailedSummaryCutoffs, - ShowAllFunctions, ShowCS, ValueCutoff, - OnlyListBelow, ShowFunction, TextFormat, OS); + return showInstrProfile( + Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets, + ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs, + ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction, + TextFormat, ShowBinaryIds, OS); else return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, ShowDetailedSummary, ShowFunction,