diff --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc --- a/compiler-rt/include/profile/InstrProfData.inc +++ b/compiler-rt/include/profile/InstrProfData.inc @@ -129,6 +129,8 @@ #endif INSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic()) INSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version()) +INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdSize, + __llvm_get_binary_ids_size_or_write(NULL)) INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize) INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters) INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize) diff --git a/compiler-rt/lib/profile/InstrProfilingInternal.h b/compiler-rt/lib/profile/InstrProfilingInternal.h --- a/compiler-rt/lib/profile/InstrProfilingInternal.h +++ b/compiler-rt/lib/profile/InstrProfilingInternal.h @@ -197,4 +197,12 @@ COMPILER_RT_VISIBILITY extern ValueProfNode *EndVNode; extern void (*VPMergeHook)(struct ValueProfData *, __llvm_profile_data *); +/* + * This function is used for two purposes: + * 1) If Writer is NULL, return the number of binary ids. + * 2) If Writer is given, write binary ids into profiles. + */ +COMPILER_RT_VISIBILITY COMPILER_RT_WEAK int +__llvm_get_binary_ids_size_or_write(ProfDataWriter *Writer); + #endif diff --git a/compiler-rt/lib/profile/InstrProfilingInternal.c b/compiler-rt/lib/profile/InstrProfilingInternal.c --- a/compiler-rt/lib/profile/InstrProfilingInternal.c +++ b/compiler-rt/lib/profile/InstrProfilingInternal.c @@ -33,4 +33,13 @@ RuntimeCounterRelocation = Value; } +/* + * The runtime provides the default definition of this function + * for the platforms that do not yet support binary id. + */ +COMPILER_RT_VISIBILITY COMPILER_RT_WEAK int +__llvm_get_binary_ids_size_or_write(ProfDataWriter *Writer) { + return 0; +} + #endif diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c --- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -9,9 +9,13 @@ #if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ (defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) +#include +#include #include +#include #include "InstrProfiling.h" +#include "InstrProfilingInternal.h" #define PROF_DATA_START INSTR_PROF_SECT_START(INSTR_PROF_DATA_COMMON) #define PROF_DATA_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_DATA_COMMON) @@ -72,4 +76,75 @@ COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = &PROF_VNODES_START; COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = &PROF_VNODES_STOP; +static size_t RoundUp(size_t size, size_t align) { + return (size + align - 1) & ~(align - 1); +} + +/* + * This helper function iterates through notes section and find build ids. + * 1) If Writer is NULL, return the number of binary ids. + * 2) If Writer is given, write binary ids into profiles. + */ +static int BinaryIdsHelper(ProfDataWriter *Writer, const ElfW(Nhdr) * Note, + const ElfW(Nhdr) * NotesEnd) { + int NumOfBinaryIds = 0; + while (Note < NotesEnd) { + /* + * Each note in notes section starts with a struct which includes + * n_namesz, n_descsz, and n_type members. It is followed by the name + * (whose length is defined in n_namesz) and then by the descriptor + * (whose length is defined in n_descsz). + * + * Look for the note that has the name "GNU\0" and type NT_GNU_BUILD_ID + * to check whether build id exists. + */ + const char *NoteName = (char *)Note + sizeof(*Note); + if (Note->n_type == NT_GNU_BUILD_ID && Note->n_namesz == 4 && + memcmp(NoteName, "GNU\0", 4) == 0) { + if (Writer == NULL) + NumOfBinaryIds++; + else { + uint64_t Size = Note->n_descsz; + uint8_t *Data = + (uint8_t *)((uintptr_t)Note + sizeof(ElfW(Nhdr)) + Note->n_namesz); + + ProfDataIOVec BinaryIdIOVec[] = {{&Size, sizeof(uint64_t), 1, 0}, + {Data, sizeof(uint8_t), Size, 0}}; + + if (Writer->Write(Writer, BinaryIdIOVec, + sizeof(BinaryIdIOVec) / sizeof(*BinaryIdIOVec))) + return -1; + } + } + + Note = Note + sizeof(ElfW(Nhdr)) + RoundUp(Note->n_namesz, 4) + + RoundUp(Note->n_descsz, 4); + } + + return NumOfBinaryIds; +} + +COMPILER_RT_VISIBILITY COMPILER_RT_WEAK int +__llvm_get_binary_ids_size_or_write(ProfDataWriter *Writer) { + extern const ElfW(Ehdr) __ehdr_start __attribute__((visibility("hidden"))); + const ElfW(Ehdr) *ElfHeader = &__ehdr_start; + const ElfW(Phdr) *ProgramHeader = + (const ElfW(Phdr) *)((uintptr_t)ElfHeader + ElfHeader->e_phoff); + + uint32_t I; + /* Iterate through entries in the program header. */ + for (I = 0; I < ElfHeader->e_phnum; I++) { + /* Look for the note section in program header entries. */ + if (ProgramHeader[I].p_type != PT_NOTE) + continue; + + const ElfW(Nhdr) *Note = + (const ElfW(Nhdr) *)((uintptr_t)ElfHeader + ProgramHeader[I].p_offset); + const ElfW(Nhdr) *NotesEnd = Note + ProgramHeader[I].p_filesz; + return BinaryIdsHelper(Writer, Note, NotesEnd); + } + + return 0; +} + #endif diff --git a/compiler-rt/lib/profile/InstrProfilingWriter.c b/compiler-rt/lib/profile/InstrProfilingWriter.c --- a/compiler-rt/lib/profile/InstrProfilingWriter.c +++ b/compiler-rt/lib/profile/InstrProfilingWriter.c @@ -299,5 +299,9 @@ if (__llvm_profile_is_continuous_mode_enabled()) return 0; - return writeValueProfData(Writer, VPDataReader, DataBegin, DataEnd); + if (writeValueProfData(Writer, VPDataReader, DataBegin, DataEnd)) + return -1; + + /* Write binary id length and its data. */ + return __llvm_get_binary_ids_size_or_write(Writer); } diff --git a/compiler-rt/test/profile/binary-id.c b/compiler-rt/test/profile/binary-id.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/profile/binary-id.c @@ -0,0 +1,58 @@ +// RUN: %clang_profgen -Wl,--build-id=none -O2 -o %t %s +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata show --binary-ids %t.profraw > %t.out +// RUN: FileCheck %s --check-prefix=NO-BINARY-ID < %t.out +// RUN: llvm-profdata merge -o %t.profdata %t.profraw + +// RUN: %clang_profgen -Wl,--build-id -O2 -o %t %s +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata show --binary-ids %t.profraw > %t.profraw.out +// RUN: FileCheck %s --check-prefix=BINARY-ID-RAW-PROF < %t.profraw.out +// RUN: llvm-profdata merge -o %t.profdata %t.profraw +// RUN: llvm-profdata show --binary-ids %t.profdata > %t.profdata.out +// RUN: FileCheck %s --check-prefix=BINARY-ID-INDEXED-PROF < %t.profdata.out + +// RUN: llvm-profdata merge -o %t.profdata %t.profraw %t.profraw +// RUN: llvm-profdata show --binary-ids %t.profdata > %t.profdata.out +// RUN: FileCheck %s --check-prefix=MULTIPLE-BINARY-ID < %t.profdata.out + +void foo() { +} + +void bar() { +} + +int main() { + foo(); + bar(); + + return 0; +} + +// NO-BINARY-ID: Instrumentation level: Front-end +// NO-BINARY-ID-NEXT: Total functions: 3 +// NO-BINARY-ID-NEXT: Maximum function count: 1 +// NO-BINARY-ID-NEXT: Maximum internal block count: 0 +// NO-BINARY-ID-NOT: Binary IDs: + +// BINARY-ID-RAW-PROF: Instrumentation level: Front-end +// BINARY-ID-RAW-PROF-NEXT: Total functions: 3 +// BINARY-ID-RAW-PROF-NEXT: Maximum function count: 1 +// BINARY-ID-RAW-PROF-NEXT: Maximum internal block count: 0 +// BINARY-ID-RAW-PROF-NEXT: Binary IDs: +// BINARY-ID-RAW-PROF-NEXT: {{[0-9a-f]+}} + +// BINARY-ID-INDEXED-PROF: Instrumentation level: Front-end +// BINARY-ID-INDEXED-PROF-NEXT: Total functions: 3 +// BINARY-ID-INDEXED-PROF-NEXT: Maximum function count: 1 +// BINARY-ID-INDEXED-PROF-NEXT: Maximum internal block count: 0 +// BINARY-ID-INDEXED-PROF-NEXT: Binary IDs: +// BINARY-ID-INDEXED-PROF-NEXT: {{[0-9a-f]+}} + +// MULTIPLE-BINARY-ID: Instrumentation level: Front-end +// MULTIPLE-BINARY-ID-NEXT: Total functions: 3 +// MULTIPLE-BINARY-ID-NEXT: Maximum function count: 2 +// MULTIPLE-BINARY-ID-NEXT: Maximum internal block count: 0 +// MULTIPLE-BINARY-ID-NEXT: Binary IDs: +// MULTIPLE-BINARY-ID-NEXT: {{[0-9a-f]+}} +// MULTIPLE-BINARY-ID-NEXT: {{[0-9a-f]+}} diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -592,6 +592,17 @@ return PGOName.drop_front(S + 1); } +// Binary id type that consists of number of binary ids and data. +struct BinaryIdTy { + uint64_t NumOfBinaryIds; + const uint8_t *Data; + + BinaryIdTy(uint64_t BinaryIdsCount, const uint8_t *BinaryIdsStart) { + NumOfBinaryIds = BinaryIdsCount; + Data = BinaryIdsStart; + } +}; + // To store the sums of profile count values, or the percentage of // the sums of the total count values. struct CountSumOrPercent { @@ -999,6 +1010,7 @@ struct Header { uint64_t Magic; uint64_t Version; + uint64_t BinaryIdSize; uint64_t Unused; // Becomes unused since version 4 uint64_t HashType; uint64_t HashOffset; diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc --- a/llvm/include/llvm/ProfileData/InstrProfData.inc +++ b/llvm/include/llvm/ProfileData/InstrProfData.inc @@ -129,6 +129,8 @@ #endif INSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic()) INSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version()) +INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdSize, + __llvm_get_binary_ids_size_or_write(NULL)) INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize) INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters) INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize) diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h --- a/llvm/include/llvm/ProfileData/InstrProfReader.h +++ b/llvm/include/llvm/ProfileData/InstrProfReader.h @@ -82,6 +82,14 @@ /// Read a single record. virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0; + // Get binary ids. + /// TODO: Can we implement the following three functions in InstrProfReader + /// class. + virtual const BinaryIdTy *getBinaryIds() { return nullptr; }; + + /// Print binary ids on stream OS. + virtual void printBinaryIds(raw_ostream &OS){}; + /// Iterator over profile data. InstrProfIterator begin() { return InstrProfIterator(this); } InstrProfIterator end() { return InstrProfIterator(); } @@ -222,6 +230,9 @@ 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 +242,10 @@ static bool hasFormat(const MemoryBuffer &DataBuffer); Error readHeader() override; Error readNextRecord(NamedInstrProfRecord &Record) override; + Error readBinaryIds(); + + const BinaryIdTy *getBinaryIds() override; + void printBinaryIds(raw_ostream &OS) override; bool isIRLevelProfile() const override { return (Version & VARIANT_MASK_IR_PROF) != 0; @@ -465,12 +480,20 @@ // Index to the current record in the record array. unsigned RecordIndex; + uint64_t BinaryIdsSize; + const uint8_t *BinaryIdsStart; + // Read the profile summary. Return a pointer pointing to one byte past the // end of the summary data if it exists or the input \c Cur. // \c UseCS indicates whether to use the context-sensitive profile summary. const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version, const unsigned char *Cur, bool UseCS); + // Read binary ids. + // If binary ids exists, return a pointer pointing next to binary ids. + // Otherwise, returns the input \c Cur + const unsigned char *readBinaryIds(const unsigned char *Cur); + public: IndexedInstrProfReader( std::unique_ptr DataBuffer, @@ -548,6 +571,9 @@ return *(Summary.get()); } } + + const BinaryIdTy *getBinaryIds() override; + void printBinaryIds(raw_ostream &OS) override; }; } // end namespace llvm diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h --- a/llvm/include/llvm/ProfileData/InstrProfWriter.h +++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h @@ -44,6 +44,8 @@ // Use raw pointer here for the incomplete type object. InstrProfRecordWriterTrait *InfoObj; + std::vector BinaryIds; + public: InstrProfWriter(bool Sparse = false, bool InstrEntryBBEnabled = false); ~InstrProfWriter(); @@ -112,6 +114,8 @@ OverlapStats &FuncLevelOverlap, const OverlapFuncFilters &FuncFilter); + void addBinaryIds(const BinaryIdTy *BI); + private: void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I, uint64_t Weight, function_ref Warn); diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/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 @@ -366,6 +366,7 @@ if (GET_VERSION(Version) != RawInstrProf::Version) return error(instrprof_error::unsupported_version); + BinaryIdsSize = swap(Header.BinaryIdSize); CountersDelta = swap(Header.CountersDelta); NamesDelta = swap(Header.NamesDelta); auto DataSize = swap(Header.DataSize); @@ -478,12 +479,34 @@ return success(); } +template Error RawInstrProfReader::readBinaryIds() { + BinaryIdsStart = reinterpret_cast(ValueDataStart); + + for (uint64_t I = 0; I < BinaryIdsSize; I++) { + // Read binary id length. + uint64_t BinaryIdLen = + swap(*reinterpret_cast(ValueDataStart)); + + // Increment ValueDataStart by binary id length and its data. + ValueDataStart += sizeof(BinaryIdLen); + ValueDataStart += BinaryIdLen; + } + + return success(); +} + template Error RawInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { - if (atEnd()) + if (atEnd()) { + // Read binary ids that starts after record. + // TODO: In which cases there are multiple headers? + if (Error E = readBinaryIds()) + return error(std::move(E)); + // At this point, ValueDataStart field points to the next header. if (Error E = readNextHeader(getNextHeaderPos())) return error(std::move(E)); + } // Read name ad set it in Record. if (Error E = readName(Record)) @@ -506,6 +529,31 @@ return success(); } +template +const BinaryIdTy *RawInstrProfReader::getBinaryIds() { + return new BinaryIdTy(BinaryIdsSize, BinaryIdsStart); +} + +template +void RawInstrProfReader::printBinaryIds(raw_ostream &OS) { + if (BinaryIdsSize == 0) + return; + + OS << "Binary IDs: \n"; + const uint8_t *BinaryId = BinaryIdsStart; + + for (uint64_t I = 0; I < BinaryIdsSize; I++) { + uint64_t BinaryIdLen = swap(*reinterpret_cast(BinaryId)); + BinaryId += sizeof(BinaryIdLen); + + for (uint64_t J = 0; J < BinaryIdLen; J++) + OS << format("%02x", BinaryId[J]); + OS << "\n"; + + BinaryId += BinaryIdLen; + } +} + namespace llvm { template class RawInstrProfReader; @@ -805,6 +853,24 @@ } } +const unsigned char * +IndexedInstrProfReader::readBinaryIds(const unsigned char *Cur) { + using namespace support; + + if (BinaryIdsSize == 0) + return Cur; + + BinaryIdsStart = Cur; + for (uint64_t I = 0; I < BinaryIdsSize; I++) { + uint64_t BinaryIdLen = endian::byte_swap( + *reinterpret_cast(Cur)); + Cur += sizeof(BinaryIdLen); + Cur += BinaryIdLen; + } + + return Cur; +} + Error IndexedInstrProfReader::readHeader() { using namespace support; @@ -828,12 +894,18 @@ IndexedInstrProf::ProfVersion::CurrentVersion) return error(instrprof_error::unsupported_version); + // Read number of binary ids. + BinaryIdsSize = endian::byte_swap(Header->BinaryIdSize); + Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur, /* UseCS */ false); if (FormatVersion & VARIANT_MASK_CSIR_PROF) Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur, /* UseCS */ true); + // Read binary ids. + Cur = readBinaryIds(Cur); + // Read the hash type and start offset. IndexedInstrProf::HashT HashType = static_cast( endian::byte_swap(Header->HashType)); @@ -931,3 +1003,29 @@ } Sum.NumEntries = NumFuncs; } + +const BinaryIdTy *IndexedInstrProfReader::getBinaryIds() { + return new BinaryIdTy(BinaryIdsSize, BinaryIdsStart); +} + +void IndexedInstrProfReader::printBinaryIds(raw_ostream &OS) { + using namespace support; + + if (BinaryIdsSize == 0) + return; + + OS << "Binary IDs: \n"; + const uint8_t *BinaryId = BinaryIdsStart; + + for (uint64_t I = 0; I < BinaryIdsSize; I++) { + uint64_t BinaryIdLen = endian::byte_swap( + *reinterpret_cast(BinaryId)); + BinaryId += sizeof(BinaryIdLen); + + for (uint64_t J = 0; J < BinaryIdLen; J++) + OS << format("%02x", BinaryId[J]); + OS << "\n"; + + BinaryId += BinaryIdLen; + } +} diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -54,6 +54,7 @@ uint64_t tell() { return OS.tell(); } void write(uint64_t V) { LE.write(V); } + void writeByte(uint8_t V) { LE.write(V); } // \c patch can only be called when all data is written and flushed. // For raw_string_ostream, the patch is done on the target string @@ -287,6 +288,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { using namespace IndexedInstrProf; + using namespace support; OnDiskChainedHashTableGenerator Generator; @@ -312,6 +314,11 @@ if (InstrEntryBBEnabled) Header.Version |= VARIANT_MASK_INSTR_ENTRY; + uint64_t TotalBinaryIdSizes = 0; + for (const BinaryIdTy *BI : BinaryIds) + TotalBinaryIdSizes += BI->NumOfBinaryIds; + + Header.BinaryIdSize = TotalBinaryIdSizes; Header.Unused = 0; Header.HashType = static_cast(IndexedInstrProf::HashType); Header.HashOffset = 0; @@ -344,6 +351,22 @@ OS.write(0); } + // Write binary id lengths and data. + for (const BinaryIdTy *BI : BinaryIds) { + const uint8_t *Ptr = BI->Data; + for (uint64_t J = 0; J < BI->NumOfBinaryIds; J++) { + uint64_t BinaryIdLen = endian::byte_swap( + *reinterpret_cast(Ptr)); + OS.write(BinaryIdLen); + Ptr += sizeof(BinaryIdLen); + + for (uint64_t K = 0; K < BinaryIdLen; K++) + OS.writeByte(Ptr[K]); + + Ptr += BinaryIdLen; + } + } + // Write the hash table. uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj); @@ -510,3 +533,7 @@ return Error::success(); } + +void InstrProfWriter::addBinaryIds(const BinaryIdTy *BI) { + BinaryIds.push_back(BI); +} diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -281,6 +281,10 @@ FuncName, firstTime); }); } + + // TODO: Can we have multiple Writer Contexts? + WC->Writer.addBinaryIds(Reader->getBinaryIds()); + if (Reader->hasError()) if (Error E = Reader->getError()) WC->Errors.emplace_back(std::move(E), Filename); @@ -2040,7 +2044,7 @@ 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()) { @@ -2222,6 +2226,10 @@ OS << "Total count: " << PS->getTotalCount() << "\n"; PS->printDetailedSummary(OS); } + + if (ShowBinaryIds) + Reader->printBinaryIds(OS); + return 0; } @@ -2472,6 +2480,9 @@ 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 instruction profile. ")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); @@ -2493,11 +2504,11 @@ 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,